Skip to content

Commit

Permalink
Nano-GPT (#1336)
Browse files Browse the repository at this point in the history
* init

* updates

* nano updates

* updates

* updates

* [skipci] wip deep link changes

* fix deep links

* minor fix

* add reminder message on buy and exchange routes

* [skip ci] font fixes

* review updates

* [skip ci] minor fix

* save

* fixes

* minor code cleanup

* minor potential fix
  • Loading branch information
fossephate authored May 8, 2024
1 parent e5be737 commit baad7f7
Show file tree
Hide file tree
Showing 46 changed files with 480 additions and 189 deletions.
1 change: 1 addition & 0 deletions .github/workflows/pr_test_build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,7 @@ jobs:
echo "const moralisApiKey = '${{ secrets.MORALIS_API_KEY }}';" >> lib/.secrets.g.dart
echo "const polygonScanApiKey = '${{ secrets.POLYGON_SCAN_API_KEY }}';" >> cw_evm/lib/.secrets.g.dart
echo "const ankrApiKey = '${{ secrets.ANKR_API_KEY }}';" >> cw_solana/lib/.secrets.g.dart
echo "const nano2ApiKey = '${{ secrets.NANO2_API_KEY }}';" >> cw_nano/lib/.secrets.g.dart
echo "const tronGridApiKey = '${{ secrets.TRON_GRID_API_KEY }}';" >> cw_tron/lib/.secrets.g.dart
- name: Rename app
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ android/app/key.jks
**/tool/.evm-secrets-config.json
**/tool/.ethereum-secrets-config.json
**/tool/.solana-secrets-config.json
**/tool/.nano-secrets-config.json
**/tool/.tron-secrets-config.json
**/lib/.secrets.g.dart
**/cw_evm/lib/.secrets.g.dart
Expand Down
7 changes: 7 additions & 0 deletions android/app/src/main/AndroidManifestBase.xml
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,13 @@
<data android:scheme="tron-wallet" />
<data android:scheme="tron_wallet" />
</intent-filter>
<!-- nano-gpt link scheme -->
<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="nano-gpt" />
</intent-filter>
</activity>
<meta-data
android:name="flutterEmbedding"
Expand Down
5 changes: 5 additions & 0 deletions assets/banano_node_list.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
-
uri: kaliumapi.appditto.com
path: /api
useSSL: true
is_default: true
6 changes: 6 additions & 0 deletions cw_core/lib/crypto_currency.dart
Original file line number Diff line number Diff line change
Expand Up @@ -259,10 +259,16 @@ class CryptoCurrency extends EnumerableItem<int> with Serializable<int> implemen
element.tag == walletCurrency?.tag));
} catch (_) {}

// search by fullName if not found by title:
try {
return CryptoCurrency.all.firstWhere((element) => element.fullName?.toLowerCase() == name);
} catch (_) {}

if (CryptoCurrency._nameCurrencyMap[name.toLowerCase()] == null) {
final s = 'Unexpected token: $name for CryptoCurrency fromString';
throw ArgumentError.value(name, 'name', s);
}

return CryptoCurrency._nameCurrencyMap[name.toLowerCase()]!;
}

Expand Down
16 changes: 16 additions & 0 deletions cw_nano/lib/banano_balance.dart
Original file line number Diff line number Diff line change
@@ -1,12 +1,28 @@
import 'package:cw_core/balance.dart';
import 'package:nanoutil/nanoutil.dart';

BigInt stringAmountToBigIntBanano(String amount) {
return BigInt.parse(NanoAmounts.getAmountAsRaw(amount, NanoAmounts.rawPerBanano));
}

class BananoBalance extends Balance {
final BigInt currentBalance;
final BigInt receivableBalance;

BananoBalance({required this.currentBalance, required this.receivableBalance}) : super(0, 0);

BananoBalance.fromFormattedString(
{required String formattedCurrentBalance, required String formattedReceivableBalance})
: currentBalance = stringAmountToBigIntBanano(formattedCurrentBalance),
receivableBalance = stringAmountToBigIntBanano(formattedReceivableBalance),
super(0, 0);

BananoBalance.fromRawString(
{required String currentBalance, required String receivableBalance})
: currentBalance = BigInt.parse(currentBalance),
receivableBalance = BigInt.parse(receivableBalance),
super(0, 0);

@override
String get formattedAvailableBalance {
return NanoAmounts.getRawAsUsableString(currentBalance.toString(), NanoAmounts.rawPerBanano);
Expand Down
6 changes: 3 additions & 3 deletions cw_nano/lib/nano_balance.dart
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import 'package:cw_core/balance.dart';
import 'package:nanoutil/nanoutil.dart';

BigInt stringAmountToBigInt(String amount) {
BigInt stringAmountToBigIntNano(String amount) {
return BigInt.parse(NanoAmounts.getAmountAsRaw(amount, NanoAmounts.rawPerNano));
}

Expand All @@ -13,8 +13,8 @@ class NanoBalance extends Balance {

NanoBalance.fromFormattedString(
{required String formattedCurrentBalance, required String formattedReceivableBalance})
: currentBalance = stringAmountToBigInt(formattedCurrentBalance),
receivableBalance = stringAmountToBigInt(formattedReceivableBalance),
: currentBalance = stringAmountToBigIntNano(formattedCurrentBalance),
receivableBalance = stringAmountToBigIntNano(formattedReceivableBalance),
super(0, 0);

NanoBalance.fromRawString(
Expand Down
26 changes: 18 additions & 8 deletions cw_nano/lib/nano_client.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import 'package:nanodart/nanodart.dart';
import 'package:cw_core/node.dart';
import 'package:nanoutil/nanoutil.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:cw_nano/.secrets.g.dart' as secrets;

class NanoClient {
static const Map<String, String> CAKE_HEADERS = {
Expand Down Expand Up @@ -52,10 +53,19 @@ class NanoClient {
}
}

Map<String, String> getHeaders() {
if (_node!.uri == "https://rpc.nano.to") {
return CAKE_HEADERS..addAll({
"key": secrets.nano2ApiKey,
});
}
return CAKE_HEADERS;
}

Future<NanoBalance> getBalance(String address) async {
final response = await http.post(
_node!.uri,
headers: CAKE_HEADERS,
headers: getHeaders(),
body: jsonEncode(
{
"action": "account_balance",
Expand All @@ -82,7 +92,7 @@ class NanoClient {
try {
final response = await http.post(
_node!.uri,
headers: CAKE_HEADERS,
headers: getHeaders(),
body: jsonEncode(
{
"action": "account_info",
Expand All @@ -94,7 +104,7 @@ class NanoClient {
final data = await jsonDecode(response.body);
return AccountInfoResponse.fromJson(data as Map<String, dynamic>);
} catch (e) {
print("error while getting account info");
print("error while getting account info $e");
return null;
}
}
Expand Down Expand Up @@ -149,7 +159,7 @@ class NanoClient {
Future<String> requestWork(String hash) async {
final response = await http.post(
_powNode!.uri,
headers: CAKE_HEADERS,
headers: getHeaders(),
body: json.encode(
{
"action": "work_generate",
Expand Down Expand Up @@ -192,7 +202,7 @@ class NanoClient {

final processResponse = await http.post(
_node!.uri,
headers: CAKE_HEADERS,
headers: getHeaders(),
body: processBody,
);

Expand Down Expand Up @@ -351,7 +361,7 @@ class NanoClient {
});
final processResponse = await http.post(
_node!.uri,
headers: CAKE_HEADERS,
headers: getHeaders(),
body: processBody,
);

Expand All @@ -367,7 +377,7 @@ class NanoClient {
required String privateKey,
}) async {
final receivableResponse = await http.post(_node!.uri,
headers: CAKE_HEADERS,
headers: getHeaders(),
body: jsonEncode({
"action": "receivable",
"account": destinationAddress,
Expand Down Expand Up @@ -417,7 +427,7 @@ class NanoClient {
Future<List<NanoTransactionModel>> fetchTransactions(String address) async {
try {
final response = await http.post(_node!.uri,
headers: CAKE_HEADERS,
headers: getHeaders(),
body: jsonEncode({
"action": "account_history",
"account": address,
Expand Down
10 changes: 10 additions & 0 deletions ios/Runner/InfoBase.plist
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,16 @@
<string>nano-wallet</string>
</array>
</dict>
<dict>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
<key>CFBundleURLName</key>
<string>nano-gpt</string>
<key>CFBundleURLSchemes</key>
<array>
<string>nano-gpt</string>
</array>
</dict>
<dict>
<key>CFBundleTypeRole</key>
<string>Editor</string>
Expand Down
133 changes: 79 additions & 54 deletions lib/di.dart
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import 'package:cake_wallet/entities/contact.dart';
import 'package:cake_wallet/entities/contact_record.dart';
import 'package:cake_wallet/entities/exchange_api_mode.dart';
import 'package:cake_wallet/entities/parse_address_from_domain.dart';
import 'package:cake_wallet/view_model/link_view_model.dart';
import 'package:cake_wallet/tron/tron.dart';
import 'package:cake_wallet/src/screens/transaction_details/rbf_details_page.dart';
import 'package:cw_core/receive_page_option.dart';
Expand Down Expand Up @@ -268,6 +269,7 @@ Future<void> setup({
required Box<UnspentCoinsInfo> unspentCoinsInfoSource,
required Box<AnonpayInvoiceInfo> anonpayInvoiceInfoSource,
required FlutterSecureStorage secureStorage,
required GlobalKey<NavigatorState> navigatorKey,
}) async {
_walletInfoSource = walletInfoSource;
_nodeSource = nodeSource;
Expand Down Expand Up @@ -429,68 +431,89 @@ Future<void> setup({
),
);

getIt.registerFactory<AuthPage>(() {
return AuthPage(getIt.get<AuthViewModel>(),
getIt.registerLazySingleton<LinkViewModel>(() {
return LinkViewModel(
appStore: getIt.get<AppStore>(),
settingsStore: getIt.get<SettingsStore>(),
authenticationStore: getIt.get<AuthenticationStore>(),
navigatorKey: navigatorKey,
);
});

getIt.registerFactory<AuthPage>(instanceName: 'login', () {
return AuthPage(getIt.get<AuthViewModel>(), closable: false,
onAuthenticationFinished: (isAuthenticated, AuthPageState authPageState) {
if (!isAuthenticated) {
return;
}
final authStore = getIt.get<AuthenticationStore>();
final appStore = getIt.get<AppStore>();
final useTotp = appStore.settingsStore.useTOTP2FA;
final shouldUseTotp2FAToAccessWallets =
appStore.settingsStore.shouldRequireTOTP2FAForAccessingWallet;
if (useTotp && shouldUseTotp2FAToAccessWallets) {
authPageState.close(
route: Routes.totpAuthCodePage,
arguments: TotpAuthArgumentsModel(
isForSetup: false,
isClosable: false,
onTotpAuthenticationFinished:
(bool isAuthenticatedSuccessfully, TotpAuthCodePageState totpAuthPageState) async {
if (!isAuthenticatedSuccessfully) {
return;
}
if (appStore.wallet != null) {
authStore.allowed();
return;
}

totpAuthPageState.changeProcessText('Loading the wallet');

if (loginError != null) {
totpAuthPageState.changeProcessText('ERROR: ${loginError.toString()}');
}

ReactionDisposer? _reaction;
_reaction = reaction((_) => appStore.wallet, (Object? _) {
_reaction?.reaction.dispose();
authStore.allowed();
});
},
),
);
} else {
final authStore = getIt.get<AuthenticationStore>();
final appStore = getIt.get<AppStore>();
final useTotp = appStore.settingsStore.useTOTP2FA;
final shouldUseTotp2FAToAccessWallets =
appStore.settingsStore.shouldRequireTOTP2FAForAccessingWallet;
if (useTotp && shouldUseTotp2FAToAccessWallets) {
authPageState.close(
route: Routes.totpAuthCodePage,
arguments: TotpAuthArgumentsModel(
isForSetup: false,
isClosable: false,
onTotpAuthenticationFinished: (bool isAuthenticatedSuccessfully,
TotpAuthCodePageState totpAuthPageState) async {
if (!isAuthenticatedSuccessfully) {
return;
}
if (appStore.wallet != null) {
authStore.allowed();
return;
}

totpAuthPageState.changeProcessText('Loading the wallet');

if (loginError != null) {
totpAuthPageState.changeProcessText('ERROR: ${loginError.toString()}');
}

ReactionDisposer? _reaction;
_reaction = reaction((_) => appStore.wallet, (Object? _) {
_reaction?.reaction.dispose();
authStore.allowed();
});
},
),
);
} else {
if (appStore.wallet != null) {
authStore.allowed();
return;
// wallet is already loaded:
if (appStore.wallet != null) {
// goes to the dashboard:
authStore.allowed();
// trigger any deep links:
final linkViewModel = getIt.get<LinkViewModel>();
if (linkViewModel.currentLink != null) {
linkViewModel.handleLink();
}
return;
}

authPageState.changeProcessText('Loading the wallet');
// load the wallet:

if (loginError != null) {
authPageState.changeProcessText('ERROR: ${loginError.toString()}');
}
authPageState.changeProcessText('Loading the wallet');

ReactionDisposer? _reaction;
_reaction = reaction((_) => appStore.wallet, (Object? _) {
_reaction?.reaction.dispose();
authStore.allowed();
});
if (loginError != null) {
authPageState.changeProcessText('ERROR: ${loginError.toString()}');
}

ReactionDisposer? _reaction;
_reaction = reaction((_) => appStore.wallet, (Object? _) {
_reaction?.reaction.dispose();
authStore.allowed();
final linkViewModel = getIt.get<LinkViewModel>();
if (linkViewModel.currentLink != null) {
linkViewModel.handleLink();
}
});
}
}, closable: false);
}, instanceName: 'login');
});
});

getIt.registerSingleton<BottomSheetService>(BottomSheetServiceImpl());

Expand Down Expand Up @@ -849,8 +872,10 @@ Future<void> setup({
tradesStore: getIt.get<TradesStore>(),
sendViewModel: getIt.get<SendViewModel>()));

getIt.registerFactory(
() => ExchangePage(getIt.get<ExchangeViewModel>(), getIt.get<AuthService>()));
getIt.registerFactoryParam<ExchangePage, PaymentRequest?, void>(
(PaymentRequest? paymentRequest, __) {
return ExchangePage(getIt.get<ExchangeViewModel>(), getIt.get<AuthService>(), paymentRequest);
});

getIt.registerFactory(() => ExchangeConfirmPage(tradesStore: getIt.get<TradesStore>()));

Expand Down
Loading

0 comments on commit baad7f7

Please sign in to comment.