This commit is contained in:
Konstantin Ullrich 2025-06-26 22:00:20 +00:00 committed by GitHub
commit 40de84fdfb
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
54 changed files with 1237 additions and 12 deletions

1
.gitignore vendored
View file

@ -135,6 +135,7 @@ lib/ethereum/ethereum.dart
lib/bitcoin_cash/bitcoin_cash.dart
lib/nano/nano.dart
lib/polygon/polygon.dart
lib/gnosis/gnosis.dart
lib/solana/solana.dart
lib/tron/tron.dart
lib/wownero/wownero.dart

View file

@ -0,0 +1,4 @@
-
uri: gnosis-rpc.publicnode.com
useSSL: true
isDefault: true

BIN
assets/images/gno.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

BIN
assets/images/xdai.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

View file

@ -1,5 +1,5 @@
@echo off
set cw_win_app_config=--monero --bitcoin --ethereum --polygon --nano --bitcoinCash --solana --tron
set cw_win_app_config=--monero --bitcoin --ethereum --polygon --gnosis --nano --bitcoinCash --solana --tron
set cw_root=%cd%
set cw_archive_name=Cake Wallet.zip
set cw_archive_path=%cw_root%\%cw_archive_name%

View file

@ -111,7 +111,9 @@ class CryptoCurrency extends EnumerableItem<int> with Serializable<int> implemen
CryptoCurrency.zano,
CryptoCurrency.ton,
CryptoCurrency.flip,
CryptoCurrency.deuro
CryptoCurrency.deuro,
CryptoCurrency.xdai,
CryptoCurrency.gno,
];
static const havenCurrencies = [
@ -233,6 +235,8 @@ class CryptoCurrency extends EnumerableItem<int> with Serializable<int> implemen
static const zano = CryptoCurrency(title: 'ZANO', tag: 'ZANO', fullName: 'Zano', raw: 96, name: 'zano', iconPath: 'assets/images/zano_icon.png', decimals: 12);
static const flip = CryptoCurrency(title: 'FLIP', tag: 'ETH', fullName: 'Chainflip', raw: 97, name: 'flip', iconPath: 'assets/images/flip_icon.png', decimals: 18);
static const deuro = CryptoCurrency(title: 'DEURO', tag: 'ETH', fullName: 'Decentralized Euro', raw: 98, name: 'deuro', iconPath: 'assets/images/deuro_icon.png', decimals: 18);
static const xdai = CryptoCurrency(title: 'XDAI', tag: 'XDAI', fullName: 'xDAI', raw: 99, name: 'xDAI', iconPath: 'assets/images/xdai.png', decimals: 18);
static const gno = CryptoCurrency(title: 'GNO', tag: 'XDAI', fullName: 'Gnosis', raw: 99, name: 'gnoxdai', iconPath: 'assets/images/gno.png', decimals: 18);
static final Map<int, CryptoCurrency> _rawCurrencyMap =
[...all, ...havenCurrencies].fold<Map<int, CryptoCurrency>>(<int, CryptoCurrency>{}, (acc, item) {

View file

@ -34,6 +34,8 @@ CryptoCurrency currencyForWalletType(WalletType type, {bool? isTestnet}) {
return CryptoCurrency.zano;
case WalletType.decred:
return CryptoCurrency.dcr;
case WalletType.gnosis:
return CryptoCurrency.xdai;
case WalletType.none:
throw Exception(
'Unexpected wallet type: ${type.toString()} for CryptoCurrency currencyForWalletType');
@ -60,6 +62,8 @@ WalletType? walletTypeForCurrency(CryptoCurrency currency) {
return WalletType.banano;
case CryptoCurrency.maticpoly:
return WalletType.polygon;
case CryptoCurrency.xdai:
return WalletType.gnosis;
case CryptoCurrency.sol:
return WalletType.solana;
case CryptoCurrency.trx:

View file

@ -70,6 +70,7 @@ class Erc20Token extends CryptoCurrency with HiveObjectMixin {
static const boxName = 'Erc20Tokens';
static const ethereumBoxName = 'EthereumErc20Tokens';
static const polygonBoxName = 'PolygonErc20Tokens';
static const gnosisBoxName = 'GnosisErc20Tokens';
@override
bool operator ==(other) =>

View file

@ -100,6 +100,7 @@ class Node extends HiveObject with Keyable {
case WalletType.banano:
case WalletType.ethereum:
case WalletType.polygon:
case WalletType.gnosis:
case WalletType.solana:
case WalletType.tron:
case WalletType.zano:
@ -163,6 +164,7 @@ class Node extends HiveObject with Keyable {
case WalletType.bitcoinCash:
case WalletType.ethereum:
case WalletType.polygon:
case WalletType.gnosis:
case WalletType.solana:
case WalletType.tron:
return requestElectrumServer();

View file

@ -10,6 +10,7 @@ const walletTypes = [
WalletType.litecoin,
WalletType.haven,
WalletType.ethereum,
WalletType.gnosis,
WalletType.bitcoinCash,
WalletType.nano,
WalletType.banano,
@ -65,7 +66,10 @@ enum WalletType {
zano,
@HiveField(14)
decred
decred,
@HiveField(15)
gnosis
}
int serializeToInt(WalletType type) {
@ -98,6 +102,8 @@ int serializeToInt(WalletType type) {
return 12;
case WalletType.decred:
return 13;
case WalletType.gnosis:
return 14;
case WalletType.none:
return -1;
}
@ -133,6 +139,8 @@ WalletType deserializeFromInt(int raw) {
return WalletType.zano;
case 13:
return WalletType.decred;
case 14:
return WalletType.gnosis;
default:
throw Exception(
'Unexpected token: $raw for WalletType deserializeFromInt');
@ -169,6 +177,8 @@ String walletTypeToString(WalletType type) {
return 'Zano';
case WalletType.decred:
return 'Decred';
case WalletType.gnosis:
return 'Gnosis';
case WalletType.none:
return '';
}
@ -204,6 +214,8 @@ String walletTypeToDisplayName(WalletType type) {
return 'Zano (ZANO)';
case WalletType.decred:
return 'Decred (DCR)';
case WalletType.gnosis:
return 'Gnosis (xDAI)';
case WalletType.none:
return '';
}
@ -242,6 +254,8 @@ CryptoCurrency walletTypeToCryptoCurrency(WalletType type, {bool isTestnet = fal
return CryptoCurrency.zano;
case WalletType.decred:
return CryptoCurrency.dcr;
case WalletType.gnosis:
return CryptoCurrency.xdai;
case WalletType.none:
throw Exception(
'Unexpected wallet type: ${type.toString()} for CryptoCurrency walletTypeToCryptoCurrency');
@ -278,6 +292,8 @@ WalletType? cryptoCurrencyToWalletType(CryptoCurrency type) {
return WalletType.zano;
case CryptoCurrency.dcr:
return WalletType.decred;
case CryptoCurrency.xdai:
return WalletType.gnosis;
default:
return null;
}

View file

@ -703,7 +703,9 @@ abstract class EVMChainWalletBase
} else {
balance.remove(token);
}
} catch (_) {}
} catch (e) {
print(e);
}
}
}

30
cw_gnosis/.gitignore vendored Normal file
View file

@ -0,0 +1,30 @@
# Miscellaneous
*.class
*.log
*.pyc
*.swp
.DS_Store
.atom/
.buildlog/
.history
.svn/
migrate_working_dir/
# IntelliJ related
*.iml
*.ipr
*.iws
.idea/
# The .vscode folder contains launch configuration and tasks you configure in
# VS Code which you may wish to be included in version control, so this line
# is commented out by default.
#.vscode/
# Flutter/Dart/Pub related
# Libraries should not include pubspec.lock, per https://dart.dev/guides/libraries/private-files#pubspeclock.
/pubspec.lock
**/doc/api/
.dart_tool/
.packages
build/

1
cw_gnosis/LICENSE Normal file
View file

@ -0,0 +1 @@
TODO: Add your license here.

View file

@ -0,0 +1,4 @@
include: package:flutter_lints/flutter.yaml
# Additional information about this file can be found at
# https://dart.dev/guides/language/analysis-options

View file

@ -0,0 +1,3 @@
description: This file stores settings for Dart & Flutter DevTools.
documentation: https://docs.flutter.dev/tools/devtools/extensions#configure-extension-enablement-states
extensions:

View file

@ -0,0 +1,54 @@
import 'package:cw_core/crypto_currency.dart';
import 'package:cw_core/erc20_token.dart';
class DefaultGnosisErc20Tokens {
final List<Erc20Token> _defaultTokens = [
Erc20Token(
name: "Wrapped Ether",
symbol: "WETH",
contractAddress: "0x6a023ccd1ff6f2045c3309768ead9e68f978f6e1",
decimal: 18,
enabled: false,
),
Erc20Token(
name: "Tether USD on xDai",
symbol: "USDT",
contractAddress: "0x4ECaBa5870353805a9F068101A40E0f32ed605C6",
decimal: 6,
enabled: true,
),
Erc20Token(
name: "USD Coin",
symbol: "USDC.e",
contractAddress: "0x2a22f9c3b484c3629090FeED35F17Ff8F88f76F0",
decimal: 6,
enabled: true,
),
Erc20Token(
name: "Gnosis",
symbol: "GNO",
contractAddress: "0x9C58BAcC331c9aa871AFD802DB6379a98e80CEdb",
decimal: 18,
enabled: true,
),
Erc20Token(
name: "Decentralized Euro",
symbol: "DEURO",
contractAddress: "0xac90f343820D8299Ac72a06A7674491b07d45f03",
decimal: 18,
enabled: true,
),
];
List<Erc20Token> get initialGnosisErc20Tokens => _defaultTokens.map((token) {
String? iconPath;
try {
iconPath = CryptoCurrency.all
.firstWhere((element) =>
element.title.toUpperCase() == token.symbol.split(".").first.toUpperCase())
.iconPath;
} catch (_) {}
return Erc20Token.copyWith(token, iconPath, 'XDAI');
}).toList();
}

View file

@ -0,0 +1,92 @@
import 'dart:convert';
import 'package:cw_evm/evm_chain_client.dart';
import 'package:cw_evm/.secrets.g.dart' as secrets;
import 'package:cw_evm/evm_chain_transaction_model.dart';
import 'package:flutter/foundation.dart';
import 'package:web3dart/web3dart.dart';
class GnosisClient extends EVMChainClient {
@override
Transaction createTransaction({
required EthereumAddress from,
required EthereumAddress to,
required EtherAmount amount,
EtherAmount? maxPriorityFeePerGas,
Uint8List? data,
int? maxGas,
EtherAmount? gasPrice,
EtherAmount? maxFeePerGas,
}) {
return Transaction(
from: from,
to: to,
value: amount,
// data: data,
maxGas: maxGas,
// gasPrice: gasPrice,
// maxFeePerGas: maxFeePerGas,
// maxPriorityFeePerGas: maxPriorityFeePerGas,
);
}
@override
Uint8List prepareSignedTransactionForSending(Uint8List signedTransaction) => signedTransaction;
@override
int get chainId => 137;
@override
Future<List<EVMChainTransactionModel>> fetchTransactions(String address,
{String? contractAddress}) async {
try {
final response = await httpClient.get(Uri.https("api.gnosisscan.io", "/v2/api", {
"chainid": "$chainId",
"module": "account",
"action": contractAddress != null ? "tokentx" : "txlist",
if (contractAddress != null) "contractaddress": contractAddress,
"address": address,
"apikey": secrets.etherScanApiKey,
}));
final jsonResponse = json.decode(response.body) as Map<String, dynamic>;
if (response.statusCode >= 200 && response.statusCode < 300 && jsonResponse['status'] != 0) {
return (jsonResponse['result'] as List)
.map(
(e) => EVMChainTransactionModel.fromJson(e as Map<String, dynamic>, 'XDAI'),
)
.toList();
}
return [];
} catch (e) {
return [];
}
}
@override
Future<List<EVMChainTransactionModel>> fetchInternalTransactions(String address) async {
try {
final response = await httpClient.get(Uri.https("api.gnosisscan.io", "/v2/api", {
"chainid": "$chainId",
"module": "account",
"action": "txlistinternal",
"address": address,
"apikey": secrets.etherScanApiKey,
}));
final jsonResponse = json.decode(response.body) as Map<String, dynamic>;
if (response.statusCode >= 200 && response.statusCode < 300 && jsonResponse['status'] != 0) {
return (jsonResponse['result'] as List)
.map((e) => EVMChainTransactionModel.fromJson(e as Map<String, dynamic>, 'XDAI'))
.toList();
}
return [];
} catch (_) {
return [];
}
}
}

View file

@ -0,0 +1,5 @@
class GnosisMnemonicIsIncorrectException implements Exception {
@override
String toString() =>
'Polygon mnemonic has incorrect format. Mnemonic should contain 12 or 24 words separated by space.';
}

View file

@ -0,0 +1,20 @@
import 'dart:core';
import 'package:cw_evm/evm_chain_transaction_history.dart';
import 'package:cw_evm/evm_chain_transaction_info.dart';
import 'package:cw_gnosis/gnosis_transaction_info.dart';
class GnosisTransactionHistory extends EVMChainTransactionHistory {
GnosisTransactionHistory({
required super.walletInfo,
required super.password,
required super.encryptionFileUtils,
});
@override
String getTransactionHistoryFileName() => 'gnosis_transactions.json';
@override
EVMChainTransactionInfo getTransactionInfo(Map<String, dynamic> val) =>
GnosisTransactionInfo.fromJson(val);
}

View file

@ -0,0 +1,39 @@
import 'package:cw_core/transaction_direction.dart';
import 'package:cw_evm/evm_chain_transaction_info.dart';
class GnosisTransactionInfo extends EVMChainTransactionInfo {
GnosisTransactionInfo({
required super.id,
required super.height,
required super.ethAmount,
required super.ethFee,
required super.tokenSymbol,
required super.direction,
required super.isPending,
required super.date,
required super.confirmations,
required super.to,
required super.from,
super.exponent,
});
factory GnosisTransactionInfo.fromJson(Map<String, dynamic> data) {
return GnosisTransactionInfo(
id: data['id'] as String,
height: data['height'] as int,
ethAmount: BigInt.parse(data['amount']),
exponent: data['exponent'] as int,
ethFee: BigInt.parse(data['fee']),
direction: parseTransactionDirectionFromInt(data['direction'] as int),
date: DateTime.fromMillisecondsSinceEpoch(data['date'] as int),
isPending: data['isPending'] as bool,
confirmations: data['confirmations'] as int,
tokenSymbol: data['tokenSymbol'] as String,
to: data['to'],
from: data['from'],
);
}
@override
String get feeCurrency => 'xDAI';
}

View file

@ -0,0 +1,163 @@
import 'dart:convert';
import 'package:cw_core/cake_hive.dart';
import 'package:cw_core/crypto_currency.dart';
import 'package:cw_core/encryption_file_utils.dart';
import 'package:cw_core/erc20_token.dart';
import 'package:cw_core/pathForWallet.dart';
import 'package:cw_core/transaction_direction.dart';
import 'package:cw_core/wallet_info.dart';
import 'package:cw_core/wallet_keys_file.dart';
import 'package:cw_evm/evm_chain_transaction_history.dart';
import 'package:cw_evm/evm_chain_transaction_info.dart';
import 'package:cw_evm/evm_chain_transaction_model.dart';
import 'package:cw_evm/evm_chain_wallet.dart';
import 'package:cw_evm/evm_erc20_balance.dart';
import 'package:cw_gnosis/default_gnosis_erc20_tokens.dart';
import 'package:cw_gnosis/gnosis_client.dart';
import 'package:cw_gnosis/gnosis_transaction_history.dart';
import 'package:cw_gnosis/gnosis_transaction_info.dart';
class GnosisWallet extends EVMChainWallet {
GnosisWallet({
required super.walletInfo,
required super.password,
super.mnemonic,
super.initialBalance,
super.privateKey,
required super.client,
required super.encryptionFileUtils,
super.passphrase,
}) : super(nativeCurrency: CryptoCurrency.xdai);
@override
Future<void> initErc20TokensBox() async {
final boxName = "${walletInfo.name.replaceAll(" ", "_")}_ ${Erc20Token.gnosisBoxName}";
if (await CakeHive.boxExists(boxName)) {
evmChainErc20TokensBox = await CakeHive.openBox<Erc20Token>(boxName);
} else {
evmChainErc20TokensBox = await CakeHive.openBox<Erc20Token>(boxName.replaceAll(" ", ""));
}
}
@override
void addInitialTokens([bool isMigration = false]) {
final initialErc20Tokens = DefaultGnosisErc20Tokens().initialGnosisErc20Tokens;
for (final token in initialErc20Tokens) {
if (!evmChainErc20TokensBox.containsKey(token.contractAddress)) {
if (isMigration) token.enabled = false;
evmChainErc20TokensBox.put(token.contractAddress, token);
}
}
}
@override
List<String> get getDefaultTokenContractAddresses =>
DefaultGnosisErc20Tokens().initialGnosisErc20Tokens.map((e) => e.contractAddress).toList();
@override
Future<bool> checkIfScanProviderIsEnabled() async {
bool isPolygonScanEnabled = (await sharedPrefs.future).getBool("use_gnosisscan") ?? true;
return isPolygonScanEnabled;
}
@override
String getTransactionHistoryFileName() => 'gnosis_transactions.json';
@override
Erc20Token createNewErc20TokenObject(Erc20Token token, String? iconPath) {
return Erc20Token(
name: token.name,
symbol: token.symbol,
contractAddress: token.contractAddress,
decimal: token.decimal,
enabled: token.enabled,
tag: token.tag ?? "XDAI",
iconPath: iconPath,
isPotentialScam: token.isPotentialScam,
);
}
@override
EVMChainTransactionInfo getTransactionInfo(
EVMChainTransactionModel transactionModel, String address) {
final model = GnosisTransactionInfo(
id: transactionModel.hash,
height: transactionModel.blockNumber,
ethAmount: transactionModel.amount,
direction: transactionModel.from == address
? TransactionDirection.outgoing
: TransactionDirection.incoming,
isPending: false,
date: transactionModel.date,
confirmations: transactionModel.confirmations,
ethFee: BigInt.from(transactionModel.gasUsed) * transactionModel.gasPrice,
exponent: transactionModel.tokenDecimal ?? 18,
tokenSymbol: transactionModel.tokenSymbol ?? "XDAI",
to: transactionModel.to,
from: transactionModel.from,
);
return model;
}
@override
EVMChainTransactionHistory setUpTransactionHistory(
WalletInfo walletInfo, String password, EncryptionFileUtils encryptionFileUtils) {
return GnosisTransactionHistory(
walletInfo: walletInfo,
password: password,
encryptionFileUtils: encryptionFileUtils,
);
}
static Future<GnosisWallet> open({
required String name,
required String password,
required WalletInfo walletInfo,
required EncryptionFileUtils encryptionFileUtils,
}) async {
final hasKeysFile = await WalletKeysFile.hasKeysFile(name, walletInfo.type);
final path = await pathForWallet(name: name, type: walletInfo.type);
Map<String, dynamic>? data;
try {
final jsonSource = await encryptionFileUtils.read(path: path, password: password);
data = json.decode(jsonSource) as Map<String, dynamic>;
} catch (e) {
if (!hasKeysFile) rethrow;
}
final balance = EVMChainERC20Balance.fromJSON(data?['balance'] as String?) ??
EVMChainERC20Balance(BigInt.zero);
final WalletKeysData keysData;
// Migrate wallet from the old scheme to then new .keys file scheme
if (!hasKeysFile) {
final mnemonic = data!['mnemonic'] as String?;
final privateKey = data['private_key'] as String?;
final passphrase = data['passphrase'] as String?;
keysData = WalletKeysData(mnemonic: mnemonic, privateKey: privateKey, passphrase: passphrase);
} else {
keysData = await WalletKeysFile.readKeysFile(
name,
walletInfo.type,
password,
encryptionFileUtils,
);
}
return GnosisWallet(
walletInfo: walletInfo,
password: password,
mnemonic: keysData.mnemonic,
privateKey: keysData.privateKey,
passphrase: keysData.passphrase,
initialBalance: balance,
client: GnosisClient(),
encryptionFileUtils: encryptionFileUtils,
);
}
}

View file

@ -0,0 +1,162 @@
import 'package:bip39/bip39.dart' as bip39;
import 'package:cw_core/encryption_file_utils.dart';
import 'package:cw_core/wallet_base.dart';
import 'package:cw_core/wallet_info.dart';
import 'package:cw_core/wallet_type.dart';
import 'package:cw_evm/evm_chain_wallet_creation_credentials.dart';
import 'package:cw_evm/evm_chain_wallet_service.dart';
import 'package:cw_gnosis/gnosis_mnemonics_exception.dart';
import 'package:cw_gnosis/gnosis_wallet.dart';
import 'package:cw_gnosis/gnosis_client.dart';
class GnosisWalletService extends EVMChainWalletService<GnosisWallet> {
GnosisWalletService(
super.walletInfoSource, super.isDirect, {
required this.client,
});
late GnosisClient client;
@override
WalletType getType() => WalletType.gnosis;
@override
Future<GnosisWallet> create(EVMChainNewWalletCredentials credentials, {bool? isTestnet}) async {
final strength = credentials.seedPhraseLength == 24 ? 256 : 128;
final mnemonic = credentials.mnemonic ?? bip39.generateMnemonic(strength: strength);
final wallet = GnosisWallet(
walletInfo: credentials.walletInfo!,
mnemonic: mnemonic,
password: credentials.password!,
passphrase: credentials.passphrase,
client: client,
encryptionFileUtils: encryptionFileUtilsFor(isDirect),
);
await wallet.init();
wallet.addInitialTokens();
await wallet.save();
return wallet;
}
@override
Future<GnosisWallet> openWallet(String name, String password) async {
final walletInfo =
walletInfoSource.values.firstWhere((info) => info.id == WalletBase.idFor(name, getType()));
try {
final wallet = await GnosisWallet.open(
name: name,
password: password,
walletInfo: walletInfo,
encryptionFileUtils: encryptionFileUtilsFor(isDirect),
);
await wallet.init();
wallet.addInitialTokens(true);
await wallet.save();
saveBackup(name);
return wallet;
} catch (_) {
await restoreWalletFilesFromBackup(name);
final wallet = await GnosisWallet.open(
name: name,
password: password,
walletInfo: walletInfo,
encryptionFileUtils: encryptionFileUtilsFor(isDirect),
);
await wallet.init();
await wallet.save();
return wallet;
}
}
@override
Future<GnosisWallet> restoreFromKeys(EVMChainRestoreWalletFromPrivateKey credentials,
{bool? isTestnet}) async {
final wallet = GnosisWallet(
password: credentials.password!,
privateKey: credentials.privateKey,
walletInfo: credentials.walletInfo!,
client: client,
encryptionFileUtils: encryptionFileUtilsFor(isDirect),
);
await wallet.init();
wallet.addInitialTokens();
await wallet.save();
return wallet;
}
@override
Future<GnosisWallet> restoreFromHardwareWallet(
EVMChainRestoreWalletFromHardware credentials) async {
credentials.walletInfo!.derivationInfo = DerivationInfo(
derivationType: DerivationType.bip39,
derivationPath: "m/44'/60'/${credentials.hwAccountData.accountIndex}'/0/0"
);
credentials.walletInfo!.hardwareWalletType = credentials.hardwareWalletType;
credentials.walletInfo!.address = credentials.hwAccountData.address;
final wallet = GnosisWallet(
walletInfo: credentials.walletInfo!,
password: credentials.password!,
client: client,
encryptionFileUtils: encryptionFileUtilsFor(isDirect),
);
await wallet.init();
wallet.addInitialTokens();
await wallet.save();
return wallet;
}
@override
Future<GnosisWallet> restoreFromSeed(EVMChainRestoreWalletFromSeedCredentials credentials,
{bool? isTestnet}) async {
if (!bip39.validateMnemonic(credentials.mnemonic)) {
throw GnosisMnemonicIsIncorrectException();
}
final wallet = GnosisWallet(
password: credentials.password!,
mnemonic: credentials.mnemonic,
walletInfo: credentials.walletInfo!,
passphrase: credentials.passphrase,
client: client,
encryptionFileUtils: encryptionFileUtilsFor(isDirect),
);
await wallet.init();
wallet.addInitialTokens();
await wallet.save();
return wallet;
}
@override
Future<void> rename(String currentName, String password, String newName) async {
final currentWalletInfo = walletInfoSource.values
.firstWhere((info) => info.id == WalletBase.idFor(currentName, getType()));
final currentWallet = await GnosisWallet.open(
password: password,
name: currentName,
walletInfo: currentWalletInfo,
encryptionFileUtils: encryptionFileUtilsFor(isDirect),
);
await currentWallet.renameWalletFiles(newName);
await saveBackup(newName);
final newWalletInfo = currentWalletInfo;
newWalletInfo.id = WalletBase.idFor(newName, getType());
newWalletInfo.name = newName;
await walletInfoSource.put(currentWalletInfo.key, newWalletInfo);
}
}

74
cw_gnosis/pubspec.yaml Normal file
View file

@ -0,0 +1,74 @@
name: cw_gnosis
description: A new Flutter package project.
version: 0.0.1
publish_to: none
homepage: https://cakewallet.com
environment:
sdk: '>=3.0.6 <4.0.0'
flutter: ">=1.17.0"
dependencies:
flutter:
sdk: flutter
cw_core:
path: ../cw_core
cw_ethereum:
path: ../cw_ethereum
cw_evm:
path: ../cw_evm
web3dart: ^2.7.1
hive: ^2.2.3
bip39: ^1.0.6
collection: ^1.17.1
dependency_overrides:
web3dart:
git:
url: https://github.com/cake-tech/web3dart.git
ref: cake
watcher: ^1.1.0
dev_dependencies:
flutter_test:
sdk: flutter
flutter_lints: ^2.0.0
build_runner: ^2.4.15
# For information on the generic Dart part of this file, see the
# following page: https://dart.dev/tools/pub/pubspec
# The following section is specific to Flutter packages.
flutter:
# To add assets to your package, add an assets section, like this:
# assets:
# - images/a_dot_burr.jpeg
# - images/a_dot_ham.jpeg
#
# For details regarding assets in packages, see
# https://flutter.dev/assets-and-images/#from-packages
#
# An image asset can refer to one or more resolution-specific "variants", see
# https://flutter.dev/assets-and-images/#resolution-aware
# To add custom fonts to your package, add a fonts section here,
# in this "flutter" section. Each entry in this list should have a
# "family" key with the font family name, and a "fonts" key with a
# list giving the asset and other descriptors for the font. For
# example:
# fonts:
# - family: Schyler
# fonts:
# - asset: fonts/Schyler-Regular.ttf
# - asset: fonts/Schyler-Italic.ttf
# style: italic
# - family: Trajan Pro
# fonts:
# - asset: fonts/TrajanPro.ttf
# - asset: fonts/TrajanPro_Bold.ttf
# weight: 700
#
# For details regarding fonts in packages, see
# https://flutter.dev/custom-fonts/#from-packages

View file

@ -2,6 +2,7 @@ import 'package:cake_wallet/bitcoin/bitcoin.dart';
import 'package:cake_wallet/core/validator.dart';
import 'package:cake_wallet/entities/mnemonic_item.dart';
import 'package:cake_wallet/ethereum/ethereum.dart';
import 'package:cake_wallet/gnosis/gnosis.dart';
import 'package:cake_wallet/monero/monero.dart';
import 'package:cake_wallet/nano/nano.dart';
import 'package:cake_wallet/polygon/polygon.dart';
@ -40,6 +41,8 @@ class SeedValidator extends Validator<MnemonicItem> {
return nano!.getNanoWordList(language);
case WalletType.polygon:
return polygon!.getPolygonWordList(language);
case WalletType.gnosis:
return gnosis!.getGnosisWordList(language);
case WalletType.solana:
return solana!.getSolanaWordList(language);
case WalletType.tron:

View file

@ -80,6 +80,7 @@ class WalletCreationService {
case WalletType.bitcoinCash:
case WalletType.ethereum:
case WalletType.polygon:
case WalletType.gnosis:
case WalletType.solana:
case WalletType.tron:
return true;

View file

@ -30,6 +30,7 @@ import 'package:cake_wallet/entities/exchange_api_mode.dart';
import 'package:cake_wallet/entities/hardware_wallet/require_hardware_wallet_connection.dart';
import 'package:cake_wallet/entities/parse_address_from_domain.dart';
import 'package:cake_wallet/exchange/provider/trocador_exchange_provider.dart';
import 'package:cake_wallet/gnosis/gnosis.dart';
import 'package:cake_wallet/haven/cw_haven.dart';
import 'package:cake_wallet/src/screens/dev/monero_background_sync.dart';
import 'package:cake_wallet/src/screens/dev/moneroc_call_profiler.dart';
@ -1143,6 +1144,9 @@ Future<void> setup({
case WalletType.polygon:
return polygon!.createPolygonWalletService(
_walletInfoSource, SettingsStoreBase.walletPasswordDirectInput);
case WalletType.gnosis:
return gnosis!.createGnosisWalletService(
_walletInfoSource, SettingsStoreBase.walletPasswordDirectInput);
case WalletType.solana:
return solana!.createSolanaWalletService(
_walletInfoSource, SettingsStoreBase.walletPasswordDirectInput);

View file

@ -36,6 +36,7 @@ const cakeWalletLitecoinElectrumUri = 'ltc-electrum.cakewallet.com:50002';
const havenDefaultNodeUri = 'nodes.havenprotocol.org:443';
const ethereumDefaultNodeUri = 'ethereum-rpc.publicnode.com';
const polygonDefaultNodeUri = 'polygon-bor-rpc.publicnode.com';
const gnosisDefaultNodeUri = 'gnosis-rpc.publicnode.com';
const cakeWalletBitcoinCashDefaultNodeUri = 'bitcoincash.stackwallet.com:50002';
const nanoDefaultNodeUri = 'nano.nownodes.io';
const nanoDefaultPowNodeUri = 'rpc.nano.to';
@ -511,6 +512,15 @@ Future<void> defaultSettingsMigration(
enabled: true,
);
break;
case 50:
await addWalletNodeList(nodes: nodes, type: WalletType.gnosis);
await _changeDefaultNode(
nodes: nodes,
sharedPreferences: sharedPreferences,
type: WalletType.gnosis,
currentNodePreferenceKey: PreferencesKey.currentGnosisNodeIdKey,
);
break;
default:
break;
}
@ -607,6 +617,8 @@ String _getDefaultNodeUri(WalletType type) {
return cakeWalletBitcoinCashDefaultNodeUri;
case WalletType.polygon:
return polygonDefaultNodeUri;
case WalletType.gnosis:
return gnosisDefaultNodeUri;
case WalletType.solana:
return solanaDefaultNodeUri;
case WalletType.tron:
@ -1042,6 +1054,7 @@ Future<void> checkCurrentNodes(
final currentHavenNodeId = sharedPreferences.getInt(PreferencesKey.currentHavenNodeIdKey);
final currentEthereumNodeId = sharedPreferences.getInt(PreferencesKey.currentEthereumNodeIdKey);
final currentPolygonNodeId = sharedPreferences.getInt(PreferencesKey.currentPolygonNodeIdKey);
final currentGnosisNodeId = sharedPreferences.getInt(PreferencesKey.currentGnosisNodeIdKey);
final currentNanoNodeId = sharedPreferences.getInt(PreferencesKey.currentNanoNodeIdKey);
final currentNanoPowNodeId = sharedPreferences.getInt(PreferencesKey.currentNanoPowNodeIdKey);
final currentDecredNodeId = sharedPreferences.getInt(PreferencesKey.currentDecredNodeIdKey);
@ -1063,6 +1076,8 @@ Future<void> checkCurrentNodes(
nodeSource.values.firstWhereOrNull((node) => node.key == currentEthereumNodeId);
final currentPolygonNodeServer =
nodeSource.values.firstWhereOrNull((node) => node.key == currentPolygonNodeId);
final currentGnosisNodeServer =
nodeSource.values.firstWhereOrNull((node) => node.key == currentGnosisNodeId);
final currentNanoNodeServer =
nodeSource.values.firstWhereOrNull((node) => node.key == currentNanoNodeId);
final currentDecredNodeServer =
@ -1146,6 +1161,12 @@ Future<void> checkCurrentNodes(
await sharedPreferences.setInt(PreferencesKey.currentPolygonNodeIdKey, node.key as int);
}
if (currentGnosisNodeServer == null) {
final node = Node(uri: gnosisDefaultNodeUri, type: WalletType.gnosis);
await nodeSource.add(node);
await sharedPreferences.setInt(PreferencesKey.currentGnosisNodeIdKey, node.key as int);
}
if (currentSolanaNodeServer == null) {
final node = Node(uri: solanaDefaultNodeUri, type: WalletType.solana);
await nodeSource.add(node);

View file

@ -31,6 +31,9 @@ Future<List<Node>> loadDefaultNodes(WalletType type) async {
case WalletType.polygon:
path = 'assets/polygon_node_list.yml';
break;
case WalletType.gnosis:
path = 'assets/gnosis_node_list.yml';
break;
case WalletType.solana:
path = 'assets/solana_node_list.yml';
break;

View file

@ -8,6 +8,7 @@ class PreferencesKey {
static const currentZanoNodeIdKey = 'current_node_id_zano';
static const currentEthereumNodeIdKey = 'current_node_id_eth';
static const currentPolygonNodeIdKey = 'current_node_id_matic';
static const currentGnosisNodeIdKey = 'current_node_id_gnosis';
static const currentNanoNodeIdKey = 'current_node_id_nano';
static const currentNanoPowNodeIdKey = 'current_node_id_nano_pow';
static const currentDecredNodeIdKey = 'current_node_id_decred';
@ -48,6 +49,7 @@ class PreferencesKey {
static const litecoinTransactionPriority = 'current_fee_priority_litecoin';
static const ethereumTransactionPriority = 'current_fee_priority_ethereum';
static const polygonTransactionPriority = 'current_fee_priority_polygon';
static const gnosisTransactionPriority = 'current_fee_priority_gnosis';
static const bitcoinCashTransactionPriority = 'current_fee_priority_bitcoin_cash';
static const zanoTransactionPriority = 'current_fee_priority_zano';
static const wowneroTransactionPriority = 'current_fee_priority_wownero';
@ -73,6 +75,7 @@ class PreferencesKey {
static const pinNativeTokenAtTop = 'pin_native_token_at_top';
static const useEtherscan = 'use_etherscan';
static const usePolygonScan = 'use_polygonscan';
static const useGnosisScan = 'use_gnosisscan';
static const useTronGrid = 'use_trongrid';
static const useMempoolFeeAPI = 'use_mempool_fee_api';
static const defaultNanoRep = 'default_nano_representative';

View file

@ -1,6 +1,7 @@
import 'package:cake_wallet/bitcoin/bitcoin.dart';
import 'package:cake_wallet/bitcoin_cash/bitcoin_cash.dart';
import 'package:cake_wallet/ethereum/ethereum.dart';
import 'package:cake_wallet/gnosis/gnosis.dart';
import 'package:cake_wallet/monero/monero.dart';
import 'package:cake_wallet/polygon/polygon.dart';
import 'package:cake_wallet/wownero/wownero.dart';
@ -25,6 +26,8 @@ List<TransactionPriority> priorityForWalletType(WalletType type) {
return bitcoinCash!.getTransactionPriorities();
case WalletType.polygon:
return polygon!.getTransactionPriorities();
case WalletType.gnosis:
return gnosis!.getTransactionPriorities();
// no such thing for nano/banano/solana/tron:
case WalletType.nano:
case WalletType.banano:

214
lib/gnosis/cw_gnosis.dart Normal file
View file

@ -0,0 +1,214 @@
part of 'gnosis.dart';
class CWGnosis extends Gnosis {
@override
List<String> getGnosisWordList(String language) => EVMChainMnemonics.englishWordlist;
WalletService createGnosisWalletService(Box<WalletInfo> walletInfoSource, bool isDirect) =>
GnosisWalletService(walletInfoSource, isDirect, client: GnosisClient());
@override
WalletCredentials createGnosisNewWalletCredentials({
required String name,
String? mnemonic,
WalletInfo? walletInfo,
String? password,
String? passphrase,
}) =>
EVMChainNewWalletCredentials(
name: name,
walletInfo: walletInfo,
password: password,
mnemonic: mnemonic,
passphrase: passphrase,
);
@override
WalletCredentials createGnosisRestoreWalletFromSeedCredentials({
required String name,
required String mnemonic,
required String password,
String? passphrase,
}) =>
EVMChainRestoreWalletFromSeedCredentials(
name: name,
password: password,
mnemonic: mnemonic,
passphrase: passphrase,
);
@override
WalletCredentials createGnosisRestoreWalletFromPrivateKey({
required String name,
required String privateKey,
required String password,
}) =>
EVMChainRestoreWalletFromPrivateKey(name: name, password: password, privateKey: privateKey);
@override
WalletCredentials createGnosisHardwareWalletCredentials({
required String name,
required HardwareAccountData hwAccountData,
WalletInfo? walletInfo,
}) =>
EVMChainRestoreWalletFromHardware(
name: name, hwAccountData: hwAccountData, walletInfo: walletInfo);
@override
String getAddress(WalletBase wallet) => (wallet as GnosisWallet).walletAddresses.address;
@override
String getPrivateKey(WalletBase wallet) {
final privateKeyHolder = (wallet as GnosisWallet).evmChainPrivateKey;
if (privateKeyHolder is EthPrivateKey) return bytesToHex(privateKeyHolder.privateKey);
return "";
}
@override
String getPublicKey(WalletBase wallet) {
final privateKeyInUnitInt = (wallet as GnosisWallet).evmChainPrivateKey;
final publicKey = privateKeyInUnitInt.address.hex;
return publicKey;
}
@override
TransactionPriority getDefaultTransactionPriority() => EVMChainTransactionPriority.medium;
@override
TransactionPriority getGnosisTransactionPrioritySlow() => EVMChainTransactionPriority.slow;
@override
List<TransactionPriority> getTransactionPriorities() => EVMChainTransactionPriority.all;
@override
TransactionPriority deserializeGnosisTransactionPriority(int raw) =>
EVMChainTransactionPriority.deserialize(raw: raw);
Object createGnosisTransactionCredentials(
List<Output> outputs, {
required TransactionPriority priority,
required CryptoCurrency currency,
int? feeRate,
}) =>
EVMChainTransactionCredentials(
outputs
.map((out) => OutputInfo(
fiatAmount: out.fiatAmount,
cryptoAmount: out.cryptoAmount,
address: out.address,
note: out.note,
sendAll: out.sendAll,
extractedAddress: out.extractedAddress,
isParsedAddress: out.isParsedAddress,
formattedCryptoAmount: out.formattedCryptoAmount))
.toList(),
priority: priority as EVMChainTransactionPriority,
currency: currency,
feeRate: feeRate,
);
Object createGnosisTransactionCredentialsRaw(
List<OutputInfo> outputs, {
TransactionPriority? priority,
required CryptoCurrency currency,
required int feeRate,
}) =>
EVMChainTransactionCredentials(
outputs,
priority: priority as EVMChainTransactionPriority?,
currency: currency,
feeRate: feeRate,
);
@override
int formatterGnosisParseAmount(String amount) => EVMChainFormatter.parseEVMChainAmount(amount);
@override
double formatterGnosisAmountToDouble(
{TransactionInfo? transaction, BigInt? amount, int exponent = 18}) {
assert(transaction != null || amount != null);
if (transaction != null) {
transaction as EVMChainTransactionInfo;
return transaction.ethAmount / BigInt.from(10).pow(transaction.exponent);
} else {
return (amount!) / BigInt.from(10).pow(exponent);
}
}
@override
List<Erc20Token> getERC20Currencies(WalletBase wallet) {
final polygonWallet = wallet as GnosisWallet;
return polygonWallet.erc20Currencies;
}
@override
Future<void> addErc20Token(WalletBase wallet, CryptoCurrency token) async =>
await (wallet as GnosisWallet).addErc20Token(token as Erc20Token);
@override
Future<void> deleteErc20Token(WalletBase wallet, CryptoCurrency token) async =>
await (wallet as GnosisWallet).deleteErc20Token(token as Erc20Token);
@override
Future<void> removeTokenTransactionsInHistory(WalletBase wallet, CryptoCurrency token) async =>
await (wallet as GnosisWallet).removeTokenTransactionsInHistory(token as Erc20Token);
@override
Future<Erc20Token?> getErc20Token(WalletBase wallet, String contractAddress) async {
final polygonWallet = wallet as GnosisWallet;
return await polygonWallet.getErc20Token(contractAddress, 'polygon');
}
@override
CryptoCurrency assetOfTransaction(WalletBase wallet, TransactionInfo transaction) {
transaction as EVMChainTransactionInfo;
if (transaction.tokenSymbol == CryptoCurrency.maticpoly.title ||
transaction.tokenSymbol == "MATIC") {
return CryptoCurrency.maticpoly;
}
wallet as GnosisWallet;
return wallet.erc20Currencies.firstWhere(
(element) => transaction.tokenSymbol.toLowerCase() == element.symbol.toLowerCase(),
);
}
@override
void updateGnosisScanUsageState(WalletBase wallet, bool isEnabled) {
(wallet as GnosisWallet).updateScanProviderUsageState(isEnabled);
}
@override
Web3Client? getWeb3Client(WalletBase wallet) {
return (wallet as GnosisWallet).getWeb3Client();
}
String getTokenAddress(CryptoCurrency asset) => (asset as Erc20Token).contractAddress;
@override
void setLedgerConnection(
WalletBase wallet, ledger.LedgerConnection connection) {
((wallet as EVMChainWallet).evmChainPrivateKey as EvmLedgerCredentials)
.setLedgerConnection(
connection, wallet.walletInfo.derivationInfo?.derivationPath);
}
@override
Future<List<HardwareAccountData>> getHardwareWalletAccounts(LedgerViewModel ledgerVM,
{int index = 0, int limit = 5}) async {
final hardwareWalletService = EVMChainHardwareWalletService(ledgerVM.connection);
try {
return await hardwareWalletService.getAvailableAccounts(index: index, limit: limit);
} catch (err) {
printV(err);
throw err;
}
}
@override
List<String> getDefaultTokenContractAddresses() {
return DefaultGnosisErc20Tokens().initialGnosisErc20Tokens.map((e) => e.contractAddress).toList();
}
}

View file

@ -4,6 +4,7 @@ bool isBIP39Wallet(WalletType walletType) {
switch (walletType) {
case WalletType.ethereum:
case WalletType.polygon:
case WalletType.gnosis:
case WalletType.solana:
case WalletType.tron:
case WalletType.bitcoin:

View file

@ -6,8 +6,9 @@ import 'package:cw_core/wallet_type.dart';
bool isEVMCompatibleChain(WalletType walletType) {
switch (walletType) {
case WalletType.polygon:
case WalletType.ethereum:
case WalletType.polygon:
case WalletType.gnosis:
return true;
default:
return false;
@ -16,8 +17,9 @@ bool isEVMCompatibleChain(WalletType walletType) {
bool isNFTACtivatedChain(WalletType walletType) {
switch (walletType) {
case WalletType.polygon:
case WalletType.ethereum:
case WalletType.polygon:
case WalletType.gnosis:
case WalletType.solana:
return true;
default:
@ -27,8 +29,9 @@ bool isNFTACtivatedChain(WalletType walletType) {
bool isWalletConnectCompatibleChain(WalletType walletType) {
switch (walletType) {
case WalletType.polygon:
case WalletType.ethereum:
case WalletType.polygon:
case WalletType.gnosis:
case WalletType.solana:
return true;
default:

View file

@ -33,6 +33,7 @@ class MenuWidgetState extends State<MenuWidget> {
this.bananoIcon = Image.asset('assets/images/nano_icon.png'),
this.bitcoinCashIcon = Image.asset('assets/images/bch_icon.png'),
this.polygonIcon = Image.asset('assets/images/matic_icon.png'),
this.gnosisIcon = Image.asset('assets/images/gnosis_icon.png'),
this.solanaIcon = Image.asset('assets/images/sol_icon.png'),
this.tronIcon = Image.asset('assets/images/trx_icon.png'),
this.wowneroIcon = Image.asset('assets/images/wownero_icon.png'),
@ -59,6 +60,7 @@ class MenuWidgetState extends State<MenuWidget> {
Image nanoIcon;
Image bananoIcon;
Image polygonIcon;
Image gnosisIcon;
Image solanaIcon;
Image tronIcon;
Image wowneroIcon;
@ -245,6 +247,8 @@ class MenuWidgetState extends State<MenuWidget> {
return bananoIcon;
case WalletType.polygon:
return polygonIcon;
case WalletType.gnosis:
return gnosisIcon;
case WalletType.solana:
return solanaIcon;
case WalletType.tron:

View file

@ -26,6 +26,7 @@ import 'package:cake_wallet/entities/seed_type.dart';
import 'package:cake_wallet/entities/sort_balance_types.dart';
import 'package:cake_wallet/entities/wallet_list_order_types.dart';
import 'package:cake_wallet/ethereum/ethereum.dart';
import 'package:cake_wallet/gnosis/gnosis.dart';
import 'package:cake_wallet/wownero/wownero.dart';
import 'package:cake_wallet/zano/zano.dart';
import 'package:cw_core/transaction_priority.dart';
@ -106,6 +107,7 @@ abstract class SettingsStoreBase with Store {
required this.pinNativeTokenAtTop,
required this.useEtherscan,
required this.usePolygonScan,
required this.useGnosisScan,
required this.useTronGrid,
required this.useMempoolFeeAPI,
required this.defaultNanoRep,
@ -135,6 +137,7 @@ abstract class SettingsStoreBase with Store {
TransactionPriority? initialLitecoinTransactionPriority,
TransactionPriority? initialEthereumTransactionPriority,
TransactionPriority? initialPolygonTransactionPriority,
TransactionPriority? initialGnosisTransactionPriority,
TransactionPriority? initialBitcoinCashTransactionPriority,
TransactionPriority? initialZanoTransactionPriority,
TransactionPriority? initialDecredTransactionPriority,
@ -217,6 +220,10 @@ abstract class SettingsStoreBase with Store {
priority[WalletType.polygon] = initialPolygonTransactionPriority;
}
if (initialGnosisTransactionPriority != null) {
priority[WalletType.gnosis] = initialGnosisTransactionPriority;
}
if (initialBitcoinCashTransactionPriority != null) {
priority[WalletType.bitcoinCash] = initialBitcoinCashTransactionPriority;
}
@ -279,6 +286,9 @@ abstract class SettingsStoreBase with Store {
case WalletType.polygon:
key = PreferencesKey.polygonTransactionPriority;
break;
case WalletType.gnosis:
key = PreferencesKey.gnosisTransactionPriority;
break;
case WalletType.zano:
key = PreferencesKey.zanoTransactionPriority;
break;
@ -436,6 +446,11 @@ abstract class SettingsStoreBase with Store {
(bool usePolygonScan) =>
_sharedPreferences.setBool(PreferencesKey.usePolygonScan, usePolygonScan));
reaction(
(_) => useGnosisScan,
(bool useGnosisScan) =>
_sharedPreferences.setBool(PreferencesKey.useGnosisScan, useGnosisScan));
reaction((_) => useTronGrid,
(bool useTronGrid) => _sharedPreferences.setBool(PreferencesKey.useTronGrid, useTronGrid));
@ -780,6 +795,9 @@ abstract class SettingsStoreBase with Store {
@observable
bool usePolygonScan;
@observable
bool useGnosisScan;
@observable
bool useTronGrid;
@ -918,6 +936,7 @@ abstract class SettingsStoreBase with Store {
TransactionPriority? litecoinTransactionPriority;
TransactionPriority? ethereumTransactionPriority;
TransactionPriority? polygonTransactionPriority;
TransactionPriority? gnosisTransactionPriority;
TransactionPriority? bitcoinCashTransactionPriority;
TransactionPriority? wowneroTransactionPriority;
TransactionPriority? zanoTransactionPriority;
@ -939,6 +958,10 @@ abstract class SettingsStoreBase with Store {
polygonTransactionPriority = polygon?.deserializePolygonTransactionPriority(
sharedPreferences.getInt(PreferencesKey.polygonTransactionPriority)!);
}
if (sharedPreferences.getInt(PreferencesKey.gnosisTransactionPriority) != null) {
gnosisTransactionPriority = gnosis?.deserializeGnosisTransactionPriority(
sharedPreferences.getInt(PreferencesKey.gnosisTransactionPriority)!);
}
if (sharedPreferences.getInt(PreferencesKey.bitcoinCashTransactionPriority) != null) {
bitcoinCashTransactionPriority = bitcoinCash?.deserializeBitcoinCashTransactionPriority(
sharedPreferences.getInt(PreferencesKey.bitcoinCashTransactionPriority)!);
@ -965,6 +988,7 @@ abstract class SettingsStoreBase with Store {
wowneroTransactionPriority ??= wownero?.getDefaultTransactionPriority();
decredTransactionPriority ??= decred?.getDecredTransactionPriorityMedium();
polygonTransactionPriority ??= polygon?.getDefaultTransactionPriority();
gnosisTransactionPriority ??= gnosis?.getDefaultTransactionPriority();
zanoTransactionPriority ??= zano?.getDefaultTransactionPriority();
final currentBalanceDisplayMode = BalanceDisplayMode.deserialize(
@ -1009,6 +1033,7 @@ abstract class SettingsStoreBase with Store {
: defaultSeedPhraseLength;
final useEtherscan = sharedPreferences.getBool(PreferencesKey.useEtherscan) ?? true;
final usePolygonScan = sharedPreferences.getBool(PreferencesKey.usePolygonScan) ?? true;
final useGnosisScan = sharedPreferences.getBool(PreferencesKey.useGnosisScan) ?? true;
final useTronGrid = sharedPreferences.getBool(PreferencesKey.useTronGrid) ?? true;
final useMempoolFeeAPI = sharedPreferences.getBool(PreferencesKey.useMempoolFeeAPI) ?? true;
final defaultNanoRep = sharedPreferences.getString(PreferencesKey.defaultNanoRep) ?? "";
@ -1053,6 +1078,7 @@ abstract class SettingsStoreBase with Store {
sharedPreferences.getInt(PreferencesKey.currentBitcoinCashNodeIdKey);
final ethereumNodeId = sharedPreferences.getInt(PreferencesKey.currentEthereumNodeIdKey);
final polygonNodeId = sharedPreferences.getInt(PreferencesKey.currentPolygonNodeIdKey);
final gnosisNodeId = sharedPreferences.getInt(PreferencesKey.currentGnosisNodeIdKey);
final nanoNodeId = sharedPreferences.getInt(PreferencesKey.currentNanoNodeIdKey);
final nanoPowNodeId = sharedPreferences.getInt(PreferencesKey.currentNanoPowNodeIdKey);
final solanaNodeId = sharedPreferences.getInt(PreferencesKey.currentSolanaNodeIdKey);
@ -1072,6 +1098,8 @@ abstract class SettingsStoreBase with Store {
nodeSource.values.firstWhereOrNull((e) => e.uriRaw == ethereumDefaultNodeUri);
final polygonNode = nodeSource.get(polygonNodeId) ??
nodeSource.values.firstWhereOrNull((e) => e.uriRaw == polygonDefaultNodeUri);
final gnosisNode = nodeSource.get(gnosisNodeId) ??
nodeSource.values.firstWhereOrNull((e) => e.uriRaw == gnosisDefaultNodeUri);
final bitcoinCashElectrumServer = nodeSource.get(bitcoinCashElectrumServerId) ??
nodeSource.values.firstWhereOrNull((e) => e.uriRaw == cakeWalletBitcoinCashDefaultNodeUri);
final nanoNode = nodeSource.get(nanoNodeId) ??
@ -1142,6 +1170,10 @@ abstract class SettingsStoreBase with Store {
nodes[WalletType.polygon] = polygonNode;
}
if (gnosisNode != null) {
nodes[WalletType.gnosis] = gnosisNode;
}
if (bitcoinCashElectrumServer != null) {
nodes[WalletType.bitcoinCash] = bitcoinCashElectrumServer;
}
@ -1315,6 +1347,7 @@ abstract class SettingsStoreBase with Store {
pinNativeTokenAtTop: pinNativeTokenAtTop,
useEtherscan: useEtherscan,
usePolygonScan: usePolygonScan,
useGnosisScan: useGnosisScan,
useTronGrid: useTronGrid,
useMempoolFeeAPI: useMempoolFeeAPI,
defaultNanoRep: defaultNanoRep,
@ -1360,6 +1393,7 @@ abstract class SettingsStoreBase with Store {
shouldRequireTOTP2FAForAllSecurityAndBackupSettings,
initialEthereumTransactionPriority: ethereumTransactionPriority,
initialPolygonTransactionPriority: polygonTransactionPriority,
initialGnosisTransactionPriority: gnosisTransactionPriority,
initialSyncMode: savedSyncMode,
initialSyncAll: savedSyncAll,
shouldShowYatPopup: shouldShowYatPopup,
@ -1410,6 +1444,11 @@ abstract class SettingsStoreBase with Store {
priority[WalletType.polygon] = polygon!.deserializePolygonTransactionPriority(
sharedPreferences.getInt(PreferencesKey.polygonTransactionPriority)!);
}
if (gnosis != null &&
sharedPreferences.getInt(PreferencesKey.gnosisTransactionPriority) != null) {
priority[WalletType.gnosis] = gnosis!.deserializeGnosisTransactionPriority(
sharedPreferences.getInt(PreferencesKey.gnosisTransactionPriority)!);
}
if (bitcoinCash != null &&
sharedPreferences.getInt(PreferencesKey.bitcoinCashTransactionPriority) != null) {
priority[WalletType.bitcoinCash] = bitcoinCash!.deserializeBitcoinCashTransactionPriority(
@ -1496,6 +1535,7 @@ abstract class SettingsStoreBase with Store {
pinNativeTokenAtTop = sharedPreferences.getBool(PreferencesKey.pinNativeTokenAtTop) ?? true;
useEtherscan = sharedPreferences.getBool(PreferencesKey.useEtherscan) ?? true;
usePolygonScan = sharedPreferences.getBool(PreferencesKey.usePolygonScan) ?? true;
useGnosisScan = sharedPreferences.getBool(PreferencesKey.usePolygonScan) ?? true;
useTronGrid = sharedPreferences.getBool(PreferencesKey.useTronGrid) ?? true;
useMempoolFeeAPI = sharedPreferences.getBool(PreferencesKey.useMempoolFeeAPI) ?? true;
defaultNanoRep = sharedPreferences.getString(PreferencesKey.defaultNanoRep) ?? "";
@ -1528,6 +1568,7 @@ abstract class SettingsStoreBase with Store {
final havenNodeId = sharedPreferences.getInt(PreferencesKey.currentHavenNodeIdKey);
final ethereumNodeId = sharedPreferences.getInt(PreferencesKey.currentEthereumNodeIdKey);
final polygonNodeId = sharedPreferences.getInt(PreferencesKey.currentPolygonNodeIdKey);
final gnosisNodeId = sharedPreferences.getInt(PreferencesKey.currentGnosisNodeIdKey);
final nanoNodeId = sharedPreferences.getInt(PreferencesKey.currentNanoNodeIdKey);
final solanaNodeId = sharedPreferences.getInt(PreferencesKey.currentSolanaNodeIdKey);
final tronNodeId = sharedPreferences.getInt(PreferencesKey.currentTronNodeIdKey);
@ -1540,6 +1581,7 @@ abstract class SettingsStoreBase with Store {
final havenNode = nodeSource.get(havenNodeId);
final ethereumNode = nodeSource.get(ethereumNodeId);
final polygonNode = nodeSource.get(polygonNodeId);
final gnosisNode = nodeSource.get(gnosisNodeId);
final bitcoinCashNode = nodeSource.get(bitcoinCashElectrumServerId);
final nanoNode = nodeSource.get(nanoNodeId);
final solanaNode = nodeSource.get(solanaNodeId);
@ -1572,6 +1614,10 @@ abstract class SettingsStoreBase with Store {
nodes[WalletType.polygon] = polygonNode;
}
if (gnosisNode != null) {
nodes[WalletType.gnosis] = gnosisNode;
}
if (bitcoinCashNode != null) {
nodes[WalletType.bitcoinCash] = bitcoinCashNode;
}
@ -1728,6 +1774,9 @@ abstract class SettingsStoreBase with Store {
case WalletType.polygon:
await _sharedPreferences.setInt(PreferencesKey.currentPolygonNodeIdKey, node.key as int);
break;
case WalletType.gnosis:
await _sharedPreferences.setInt(PreferencesKey.currentGnosisNodeIdKey, node.key as int);
break;
case WalletType.solana:
await _sharedPreferences.setInt(PreferencesKey.currentSolanaNodeIdKey, node.key as int);
break;

View file

@ -35,9 +35,10 @@ abstract class AdvancedPrivacySettingsViewModelBase with Store {
// convert to switch case so that it give a syntax error when adding a new wallet type
// thus we don't forget about it
switch (type) {
case WalletType.ethereum:
case WalletType.bitcoinCash:
case WalletType.ethereum:
case WalletType.polygon:
case WalletType.gnosis:
case WalletType.solana:
case WalletType.tron:
return true;

View file

@ -854,6 +854,7 @@ abstract class DashboardViewModelBase with Store {
case WalletType.bitcoinCash:
case WalletType.ethereum:
case WalletType.polygon:
case WalletType.gnosis:
case WalletType.solana:
case WalletType.nano:
case WalletType.banano:

View file

@ -7,6 +7,7 @@ import 'package:cake_wallet/entities/fiat_api_mode.dart';
import 'package:cake_wallet/entities/erc20_token_info_moralis.dart';
import 'package:cake_wallet/entities/sort_balance_types.dart';
import 'package:cake_wallet/ethereum/ethereum.dart';
import 'package:cake_wallet/gnosis/gnosis.dart';
import 'package:cake_wallet/polygon/polygon.dart';
import 'package:cake_wallet/reactions/wallet_connect.dart';
import 'package:cake_wallet/solana/solana.dart';
@ -225,6 +226,9 @@ abstract class HomeSettingsViewModelBase with Store {
case WalletType.polygon:
defaultTokenAddresses = polygon!.getDefaultTokenContractAddresses();
break;
case WalletType.gnosis:
defaultTokenAddresses = gnosis!.getDefaultTokenContractAddresses();
break;
case WalletType.solana:
defaultTokenAddresses = solana!.getDefaultTokenContractAddresses();
break;

View file

@ -3,6 +3,7 @@ import 'package:cake_wallet/entities/balance_display_mode.dart';
import 'package:cake_wallet/entities/fiat_currency.dart';
import 'package:cake_wallet/ethereum/ethereum.dart';
import 'package:cake_wallet/generated/i18n.dart';
import 'package:cake_wallet/gnosis/gnosis.dart';
import 'package:cake_wallet/nano/nano.dart';
import 'package:cake_wallet/polygon/polygon.dart';
import 'package:cake_wallet/reactions/wallet_connect.dart';
@ -185,6 +186,13 @@ class TransactionListItem extends ActionListItem with Keyable {
cryptoAmount: polygon!.formatterPolygonAmountToDouble(transaction: transaction),
price: price);
break;
case WalletType.gnosis:
final asset = gnosis!.assetOfTransaction(balanceViewModel.wallet, transaction);
final price = balanceViewModel.fiatConvertationStore.prices[asset];
amount = calculateFiatAmountRaw(
cryptoAmount: gnosis!.formatterGnosisAmountToDouble(transaction: transaction),
price: price);
break;
case WalletType.nano:
amount = calculateFiatAmountRaw(
cryptoAmount: double.parse(nanoUtil!.getRawAsUsableString(

View file

@ -779,6 +779,10 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with
depositCurrency = CryptoCurrency.dcr;
receiveCurrency = CryptoCurrency.xmr;
break;
case WalletType.gnosis:
depositCurrency = CryptoCurrency.xdai;
receiveCurrency = CryptoCurrency.xmr;
break;
case WalletType.none:
break;
}

View file

@ -77,6 +77,7 @@ abstract class NodeCreateOrEditViewModelBase with Store {
switch (_walletType) {
case WalletType.ethereum:
case WalletType.polygon:
case WalletType.gnosis:
case WalletType.solana:
case WalletType.banano:
case WalletType.nano:

View file

@ -3,6 +3,7 @@ import 'package:cake_wallet/decred/decred.dart';
import 'package:cake_wallet/entities/priority_for_wallet_type.dart';
import 'package:cake_wallet/core/wallet_change_listener_view_model.dart';
import 'package:cake_wallet/ethereum/ethereum.dart';
import 'package:cake_wallet/gnosis/gnosis.dart';
import 'package:cake_wallet/monero/monero.dart';
import 'package:cake_wallet/polygon/polygon.dart';
import 'package:cake_wallet/store/app_store.dart';
@ -89,6 +90,8 @@ abstract class FeesViewModelBase extends WalletChangeListenerViewModel with Stor
return transactionPriority == bitcoinCash!.getBitcoinCashTransactionPrioritySlow();
case WalletType.polygon:
return transactionPriority == polygon!.getPolygonTransactionPrioritySlow();
case WalletType.gnosis:
return transactionPriority == gnosis!.getGnosisTransactionPrioritySlow();
case WalletType.decred:
return transactionPriority == decred!.getDecredTransactionPrioritySlow();
case WalletType.none:

View file

@ -4,6 +4,7 @@ import 'package:cake_wallet/entities/calculate_fiat_amount_raw.dart';
import 'package:cake_wallet/entities/parse_address_from_domain.dart';
import 'package:cake_wallet/entities/parsed_address.dart';
import 'package:cake_wallet/ethereum/ethereum.dart';
import 'package:cake_wallet/gnosis/gnosis.dart';
import 'package:cake_wallet/polygon/polygon.dart';
import 'package:cake_wallet/reactions/wallet_connect.dart';
import 'package:cake_wallet/solana/solana.dart';
@ -110,6 +111,9 @@ abstract class OutputBase with Store {
case WalletType.polygon:
_amount = polygon!.formatterPolygonParseAmount(_cryptoAmount);
break;
case WalletType.gnosis:
_amount = gnosis!.formatterGnosisParseAmount(_cryptoAmount);
break;
case WalletType.wownero:
_amount = wownero!.formatterWowneroParseAmount(amount: _cryptoAmount);
break;
@ -186,6 +190,10 @@ abstract class OutputBase with Store {
return polygon!.formatterPolygonAmountToDouble(amount: BigInt.from(fee));
}
if (_wallet.type == WalletType.gnosis) {
return gnosis!.formatterGnosisAmountToDouble(amount: BigInt.from(fee));
}
if (_wallet.type == WalletType.zano) {
return zano!.formatterIntAmountToDouble(amount: fee, currency: cryptoCurrencyHandler(), forFee: true);
}
@ -296,6 +304,7 @@ abstract class OutputBase with Store {
case WalletType.monero:
case WalletType.ethereum:
case WalletType.polygon:
case WalletType.gnosis:
case WalletType.solana:
case WalletType.tron:
case WalletType.haven:

View file

@ -73,6 +73,9 @@ abstract class TransactionDetailsViewModelBase with Store {
case WalletType.polygon:
_addPolygonListItems(tx, dateFormat);
break;
case WalletType.gnosis:
_addGnosisListItems(tx, dateFormat);
break;
case WalletType.solana:
_addSolanaListItems(tx, dateFormat);
break;
@ -183,6 +186,8 @@ abstract class TransactionDetailsViewModelBase with Store {
return 'https://nanexplorer.com/banano/block/${txId}';
case WalletType.polygon:
return 'https://polygonscan.com/tx/${txId}';
case WalletType.gnosis:
return 'https://gnosisscan.io/tx/${txId}';
case WalletType.solana:
return 'https://solscan.io/tx/${txId}';
case WalletType.tron:
@ -217,6 +222,8 @@ abstract class TransactionDetailsViewModelBase with Store {
return S.current.view_transaction_on + 'nanexplorer.com';
case WalletType.polygon:
return S.current.view_transaction_on + 'polygonscan.com';
case WalletType.gnosis:
return S.current.view_transaction_on + 'gnosisscan.io';
case WalletType.solana:
return S.current.view_transaction_on + 'solscan.io';
case WalletType.tron:
@ -522,6 +529,56 @@ abstract class TransactionDetailsViewModelBase with Store {
items.addAll(_items);
}
void _addGnosisListItems(TransactionInfo tx, DateFormat dateFormat) {
final _items = [
StandartListItem(
title: S.current.transaction_details_transaction_id,
value: tx.txHash,
key: ValueKey('standard_list_item_transaction_details_id_key'),
),
StandartListItem(
title: S.current.transaction_details_date,
value: dateFormat.format(tx.date),
key: ValueKey('standard_list_item_transaction_details_date_key'),
),
StandartListItem(
title: S.current.confirmations,
value: tx.confirmations.toString(),
key: ValueKey('standard_list_item_transaction_confirmations_key'),
),
StandartListItem(
title: S.current.transaction_details_height,
value: '${tx.height}',
key: ValueKey('standard_list_item_transaction_details_height_key'),
),
StandartListItem(
title: S.current.transaction_details_amount,
value: tx.amountFormatted(),
key: ValueKey('standard_list_item_transaction_details_amount_key'),
),
if (tx.feeFormatted()?.isNotEmpty ?? false)
StandartListItem(
title: S.current.transaction_details_fee,
value: tx.feeFormatted()!,
key: ValueKey('standard_list_item_transaction_details_fee_key'),
),
if (showRecipientAddress && tx.to != null && tx.direction == TransactionDirection.outgoing)
StandartListItem(
title: S.current.transaction_details_recipient_address,
value: tx.to!,
key: ValueKey('standard_list_item_transaction_details_recipient_address_key'),
),
if (tx.direction == TransactionDirection.incoming && tx.from != null)
StandartListItem(
title: S.current.transaction_details_source_address,
value: tx.from!,
key: ValueKey('standard_list_item_transaction_details_source_address_key'),
),
];
items.addAll(_items);
}
void _addSolanaListItems(TransactionInfo tx, DateFormat dateFormat) {
final _items = [
StandartListItem(

View file

@ -340,6 +340,8 @@ abstract class WalletAddressListViewModelBase extends WalletChangeListenerViewMo
return NanoURI(amount: amount, address: address.address);
case WalletType.polygon:
return PolygonURI(amount: amount, address: address.address);
case WalletType.gnosis:
return EthereumURI(amount: amount, address: address.address); // ToDo: ?
case WalletType.solana:
return SolanaURI(amount: amount, address: address.address);
case WalletType.tron:

View file

@ -124,6 +124,7 @@ abstract class WalletKeysViewModelBase with Store {
break;
case WalletType.ethereum:
case WalletType.polygon:
case WalletType.gnosis:
case WalletType.solana:
case WalletType.tron:
items.addAll([

View file

@ -1,5 +1,6 @@
import 'package:cake_wallet/core/new_wallet_arguments.dart';
import 'package:cake_wallet/ethereum/ethereum.dart';
import 'package:cake_wallet/gnosis/gnosis.dart';
import 'package:cake_wallet/zano/zano.dart';
import 'package:cake_wallet/bitcoin_cash/bitcoin_cash.dart';
import 'package:cake_wallet/solana/solana.dart';
@ -111,6 +112,13 @@ abstract class WalletNewVMBase extends WalletCreationVM with Store {
mnemonic: newWalletArguments!.mnemonic,
passphrase: passphrase,
);
case WalletType.gnosis:
return gnosis!.createGnosisNewWalletCredentials(
name: name,
password: walletPassword,
mnemonic: newWalletArguments!.mnemonic,
passphrase: passphrase,
);
case WalletType.solana:
return solana!.createSolanaNewWalletCredentials(
name: name,

View file

@ -4,6 +4,7 @@ import 'package:cake_wallet/core/generate_wallet_password.dart';
import 'package:cake_wallet/core/wallet_creation_service.dart';
import 'package:cake_wallet/di.dart';
import 'package:cake_wallet/ethereum/ethereum.dart';
import 'package:cake_wallet/gnosis/gnosis.dart';
import 'package:cake_wallet/monero/monero.dart';
import 'package:cake_wallet/nano/nano.dart';
import 'package:cake_wallet/polygon/polygon.dart';
@ -38,6 +39,7 @@ abstract class WalletRestoreViewModelBase extends WalletCreationVM with Store {
type == WalletType.monero || type == WalletType.haven || type == WalletType.wownero,
hasRestoreFromPrivateKey = type == WalletType.ethereum ||
type == WalletType.polygon ||
type == WalletType.gnosis ||
type == WalletType.nano ||
type == WalletType.banano ||
type == WalletType.solana ||
@ -59,6 +61,7 @@ abstract class WalletRestoreViewModelBase extends WalletCreationVM with Store {
case WalletType.haven:
case WalletType.ethereum:
case WalletType.polygon:
case WalletType.gnosis:
case WalletType.decred:
availableModes = [WalletRestoreMode.seed, WalletRestoreMode.keys];
break;
@ -150,6 +153,13 @@ abstract class WalletRestoreViewModelBase extends WalletCreationVM with Store {
password: password,
passphrase: passphrase,
);
case WalletType.gnosis:
return gnosis!.createGnosisRestoreWalletFromSeedCredentials(
name: name,
mnemonic: seed,
password: password,
passphrase: passphrase,
);
case WalletType.solana:
return solana!.createSolanaRestoreWalletFromSeedCredentials(
name: name,

View file

@ -10,7 +10,7 @@ case $APP_ANDROID_TYPE in
CONFIG_ARGS="--monero"
;;
$CAKEWALLET)
CONFIG_ARGS="--monero --bitcoin --ethereum --polygon --nano --bitcoinCash --solana --tron --wownero --zano --decred"
CONFIG_ARGS="--monero --bitcoin --ethereum --polygon --gnosis --nano --bitcoinCash --solana --tron --wownero --zano --decred"
;;
esac

View file

@ -31,7 +31,7 @@ case $APP_IOS_TYPE in
;;
$CAKEWALLET)
CONFIG_ARGS="--monero --bitcoin --ethereum --polygon --nano --bitcoinCash --solana --tron --wownero --zano --decred"
CONFIG_ARGS="--monero --bitcoin --ethereum --polygon --gnosis --nano --bitcoinCash --solana --tron --wownero --zano --decred"
;;
esac

View file

@ -13,7 +13,7 @@ CONFIG_ARGS=""
case $APP_LINUX_TYPE in
$CAKEWALLET)
CONFIG_ARGS="--monero --bitcoin --ethereum --polygon --nano --bitcoinCash --solana --tron --wownero --excludeFlutterSecureStorage";;
CONFIG_ARGS="--monero --bitcoin --ethereum --polygon --gnosis --nano --bitcoinCash --solana --tron --wownero --excludeFlutterSecureStorage";;
esac
cp -rf pubspec_description.yaml pubspec.yaml

View file

@ -36,7 +36,7 @@ case $APP_MACOS_TYPE in
$MONERO_COM)
CONFIG_ARGS="--monero";;
$CAKEWALLET)
CONFIG_ARGS="--monero --bitcoin --ethereum --polygon --nano --bitcoinCash --solana --tron --wownero";;
CONFIG_ARGS="--monero --bitcoin --ethereum --polygon --gnosis --nano --bitcoinCash --solana --tron --wownero";;
esac
cp -rf pubspec_description.yaml pubspec.yaml

View file

@ -6,6 +6,7 @@ const ethereumOutputPath = 'lib/ethereum/ethereum.dart';
const bitcoinCashOutputPath = 'lib/bitcoin_cash/bitcoin_cash.dart';
const nanoOutputPath = 'lib/nano/nano.dart';
const polygonOutputPath = 'lib/polygon/polygon.dart';
const gnosisOutputPath = 'lib/gnosis/gnosis.dart';
const solanaOutputPath = 'lib/solana/solana.dart';
const tronOutputPath = 'lib/tron/tron.dart';
const wowneroOutputPath = 'lib/wownero/wownero.dart';
@ -25,6 +26,7 @@ Future<void> main(List<String> args) async {
final hasNano = args.contains('${prefix}nano');
final hasBanano = args.contains('${prefix}banano');
final hasPolygon = args.contains('${prefix}polygon');
final hasGnosis = args.contains('${prefix}gnosis');
final hasSolana = args.contains('${prefix}solana');
final hasTron = args.contains('${prefix}tron');
final hasWownero = args.contains('${prefix}wownero');
@ -38,6 +40,7 @@ Future<void> main(List<String> args) async {
await generateBitcoinCash(hasBitcoinCash);
await generateNano(hasNano);
await generatePolygon(hasPolygon);
await generateGnosis(hasGnosis);
await generateSolana(hasSolana);
await generateTron(hasTron);
await generateWownero(hasWownero);
@ -54,6 +57,7 @@ Future<void> main(List<String> args) async {
hasBitcoinCash: hasBitcoinCash,
hasFlutterSecureStorage: !excludeFlutterSecureStorage,
hasPolygon: hasPolygon,
hasGnosis: hasGnosis,
hasSolana: hasSolana,
hasTron: hasTron,
hasWownero: hasWownero,
@ -68,6 +72,7 @@ Future<void> main(List<String> args) async {
hasBanano: hasBanano,
hasBitcoinCash: hasBitcoinCash,
hasPolygon: hasPolygon,
hasGnosis: hasGnosis,
hasSolana: hasSolana,
hasTron: hasTron,
hasWownero: hasWownero,
@ -892,6 +897,113 @@ abstract class Polygon {
await outputFile.writeAsString(output);
}
Future<void> generateGnosis(bool hasImplementation) async {
final outputFile = File(gnosisOutputPath);
const gnosisCommonHeaders = """
import 'package:cake_wallet/view_model/hardware_wallet/ledger_view_model.dart';
import 'package:cake_wallet/view_model/send/output.dart';
import 'package:cw_core/crypto_currency.dart';
import 'package:cw_core/erc20_token.dart';
import 'package:cw_core/hardware/hardware_account_data.dart';
import 'package:cw_core/output_info.dart';
import 'package:cw_core/transaction_info.dart';
import 'package:cw_core/transaction_priority.dart';
import 'package:cw_core/wallet_base.dart';
import 'package:cw_core/wallet_credentials.dart';
import 'package:cw_core/wallet_info.dart';
import 'package:cw_core/wallet_service.dart';
import 'package:cw_core/utils/print_verbose.dart';
import 'package:hive/hive.dart';
import 'package:ledger_flutter_plus/ledger_flutter_plus.dart' as ledger;
import 'package:web3dart/web3dart.dart';
""";
const gnosisCWHeaders = """
import 'package:cw_evm/evm_chain_formatter.dart';
import 'package:cw_evm/evm_chain_mnemonics.dart';
import 'package:cw_evm/evm_chain_transaction_credentials.dart';
import 'package:cw_evm/evm_chain_transaction_info.dart';
import 'package:cw_evm/evm_chain_transaction_priority.dart';
import 'package:cw_evm/evm_chain_wallet_creation_credentials.dart';
import 'package:cw_evm/evm_chain_hardware_wallet_service.dart';
import 'package:cw_evm/evm_ledger_credentials.dart';
import 'package:cw_evm/evm_chain_wallet.dart';
import 'package:cw_gnosis/gnosis_client.dart';
import 'package:cw_gnosis/gnosis_wallet.dart';
import 'package:cw_gnosis/gnosis_wallet_service.dart';
import 'package:cw_gnosis/default_gnosis_erc20_tokens.dart';
import 'package:eth_sig_util/util/utils.dart';
""";
const gnosisCwPart = "part 'cw_gnosis.dart';";
const gnosisContent = """
abstract class Gnosis {
List<String> getGnosisWordList(String language);
WalletService createGnosisWalletService(Box<WalletInfo> walletInfoSource, bool isDirect);
WalletCredentials createGnosisNewWalletCredentials({required String name, WalletInfo? walletInfo, String? password, String? mnemonic, String? passphrase});
WalletCredentials createGnosisRestoreWalletFromSeedCredentials({required String name, required String mnemonic, required String password, String? passphrase});
WalletCredentials createGnosisRestoreWalletFromPrivateKey({required String name, required String privateKey, required String password});
WalletCredentials createGnosisHardwareWalletCredentials({required String name, required HardwareAccountData hwAccountData, WalletInfo? walletInfo});
String getAddress(WalletBase wallet);
String getPrivateKey(WalletBase wallet);
String getPublicKey(WalletBase wallet);
TransactionPriority getDefaultTransactionPriority();
TransactionPriority getGnosisTransactionPrioritySlow();
List<TransactionPriority> getTransactionPriorities();
TransactionPriority deserializeGnosisTransactionPriority(int raw);
Object createGnosisTransactionCredentials(
List<Output> outputs, {
required TransactionPriority priority,
required CryptoCurrency currency,
int? feeRate,
});
Object createGnosisTransactionCredentialsRaw(
List<OutputInfo> outputs, {
TransactionPriority? priority,
required CryptoCurrency currency,
required int feeRate,
});
int formatterGnosisParseAmount(String amount);
double formatterGnosisAmountToDouble({TransactionInfo? transaction, BigInt? amount, int exponent = 18});
List<Erc20Token> getERC20Currencies(WalletBase wallet);
Future<void> addErc20Token(WalletBase wallet, CryptoCurrency token);
Future<void> deleteErc20Token(WalletBase wallet, CryptoCurrency token);
Future<void> removeTokenTransactionsInHistory(WalletBase wallet, CryptoCurrency token);
Future<Erc20Token?> getErc20Token(WalletBase wallet, String contractAddress);
CryptoCurrency assetOfTransaction(WalletBase wallet, TransactionInfo transaction);
void updateGnosisScanUsageState(WalletBase wallet, bool isEnabled);
Web3Client? getWeb3Client(WalletBase wallet);
String getTokenAddress(CryptoCurrency asset);
void setLedgerConnection(WalletBase wallet, ledger.LedgerConnection connection);
Future<List<HardwareAccountData>> getHardwareWalletAccounts(LedgerViewModel ledgerVM, {int index = 0, int limit = 5});
List<String> getDefaultTokenContractAddresses();
}
""";
const gnosisEmptyDefinition = 'Gnosis? gnosis;\n';
const gnosisCWDefinition = 'Gnosis? gnosis = CWGnosis();\n';
final output = '$gnosisCommonHeaders\n' +
(hasImplementation ? '$gnosisCWHeaders\n' : '\n') +
(hasImplementation ? '$gnosisCwPart\n\n' : '\n') +
(hasImplementation ? gnosisCWDefinition : gnosisEmptyDefinition) +
'\n' +
gnosisContent;
if (outputFile.existsSync()) {
await outputFile.delete();
}
await outputFile.writeAsString(output);
}
Future<void> generateBitcoinCash(bool hasImplementation) async {
final outputFile = File(bitcoinCashOutputPath);
const bitcoinCashCommonHeaders = """
@ -1420,6 +1532,7 @@ Future<void> generatePubspec({
required bool hasBitcoinCash,
required bool hasFlutterSecureStorage,
required bool hasPolygon,
required bool hasGnosis,
required bool hasSolana,
required bool hasTron,
required bool hasWownero,
@ -1465,6 +1578,10 @@ Future<void> generatePubspec({
cw_polygon:
path: ./cw_polygon
""";
const cwGnosis = """
cw_gnosis:
path: ./cw_gnosis
""";
const cwSolana = """
cw_solana:
path: ./cw_solana
@ -1526,6 +1643,10 @@ Future<void> generatePubspec({
output += '\n$cwPolygon';
}
if (hasGnosis) {
output += '\n$cwGnosis';
}
if (hasSolana) {
output += '\n$cwSolana';
}
@ -1574,6 +1695,7 @@ Future<void> generateWalletTypes({
required bool hasBanano,
required bool hasBitcoinCash,
required bool hasPolygon,
required bool hasGnosis,
required bool hasSolana,
required bool hasTron,
required bool hasWownero,
@ -1614,6 +1736,10 @@ Future<void> generateWalletTypes({
outputContent += '\tWalletType.polygon,\n';
}
if (hasGnosis) {
outputContent += '\tWalletType.gnosis,\n';
}
if (hasSolana) {
outputContent += '\tWalletType.solana,\n';
}