mirror of
https://github.com/cake-tech/cake_wallet.git
synced 2025-06-29 04:49:51 +00:00
Solana Wallet New Implementation (#2011)
* Feat: Implement Solana wallet using on_chain * v4.23.0 release candidate (#1974) * v4.23.0 release candidate * - Fix restoring zano from QR - Fix Zano confirmations count - Fix birdpay - Fix balance display * Fix Zano assets showing amount before they are added * - handle fetching token data while the API is busy - potential fix for duplicate transactions * fix receive confirmations, maybe * revert onChangeWallet cleanup * Fix confirmations not updating * improve zano wallet opening, fix CI commands and messages on slack (#1979) Co-authored-by: Omar Hatem <omarh.ismail1@gmail.com> * Cache wallet when creating/restoring as well * - hardcode Trocador Maximum limit for Zano temporarily - Configure Cake Zano node to use SSL * reformatting [skip ci] * revert to non-ssl * update build numbers [skip ci] * disable zano for desktop [skip ci] --------- Co-authored-by: cyan <cyjan@mrcyjanek.net> * CW-711 passphrase for XMR/WOWcreation (#1992) * add monero passphrase add wownero passphrase add passphrase to seed screen * obscure passphrase by default disable passphrase create for zano * Update lib/view_model/wallet_keys_view_model.dart [skip ci] * Update lib/src/screens/wallet_keys/wallet_keys_page.dart [skip ci] * Update lib/view_model/advanced_privacy_settings_view_model.dart * dynamic passphrase icon * fix polyseed not being encrypted by passphrase --------- Co-authored-by: Omar Hatem <omarh.ismail1@gmail.com> * show Zano keys properly in the keys tab (#2004) * fix: Switch private key hex encoding * Modified existing implementation to use older version of packages * fix: Fetch direct transaction history amounts instead of decimals, and add Create Account Instructions to Transaction History List * fix: Remove Create Account entries in Transaction History and disable activating token accounts of selected tokens * feat: Add passphrase support to Solana * fix: Issues with transaction amount and dissappearing transaction history items (very annoying bug) * fix: Issue with flipping transactions and incorrect transaction status * PR Review fixes --------- Co-authored-by: Omar Hatem <omarh.ismail1@gmail.com> Co-authored-by: cyan <cyjan@mrcyjanek.net>
This commit is contained in:
parent
1c29be7993
commit
1b5be705f6
19 changed files with 716 additions and 561 deletions
26
cw_core/lib/solana_rpc_http_service.dart
Normal file
26
cw_core/lib/solana_rpc_http_service.dart
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
import 'dart:convert';
|
||||||
|
import 'package:http/http.dart';
|
||||||
|
import 'package:on_chain/solana/solana.dart';
|
||||||
|
|
||||||
|
class SolanaRPCHTTPService implements SolanaJSONRPCService {
|
||||||
|
SolanaRPCHTTPService(
|
||||||
|
{required this.url, Client? client, this.defaultRequestTimeout = const Duration(seconds: 30)})
|
||||||
|
: client = client ?? Client();
|
||||||
|
@override
|
||||||
|
final String url;
|
||||||
|
final Client client;
|
||||||
|
final Duration defaultRequestTimeout;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<Map<String, dynamic>> call(SolanaRequestDetails params, [Duration? timeout]) async {
|
||||||
|
final response = await client.post(
|
||||||
|
Uri.parse(url),
|
||||||
|
body: params.toRequestBody(),
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
).timeout(timeout ?? defaultRequestTimeout);
|
||||||
|
final data = json.decode(response.body) as Map<String, dynamic>;
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
|
@ -27,6 +27,10 @@ dependencies:
|
||||||
version: 1.0.0
|
version: 1.0.0
|
||||||
socks5_proxy: ^1.0.4
|
socks5_proxy: ^1.0.4
|
||||||
unorm_dart: ^0.3.0
|
unorm_dart: ^0.3.0
|
||||||
|
on_chain:
|
||||||
|
git:
|
||||||
|
url: https://github.com/cake-tech/on_chain.git
|
||||||
|
ref: cake-update-v2
|
||||||
# tor:
|
# tor:
|
||||||
# git:
|
# git:
|
||||||
# url: https://github.com/cake-tech/tor.git
|
# url: https://github.com/cake-tech/tor.git
|
||||||
|
|
|
@ -26,7 +26,7 @@ class DefaultSPLTokens {
|
||||||
decimal: 5,
|
decimal: 5,
|
||||||
mint: 'Bonk',
|
mint: 'Bonk',
|
||||||
iconPath: 'assets/images/bonk_icon.png',
|
iconPath: 'assets/images/bonk_icon.png',
|
||||||
enabled: true,
|
enabled: false,
|
||||||
),
|
),
|
||||||
SPLToken(
|
SPLToken(
|
||||||
name: 'Raydium',
|
name: 'Raydium',
|
||||||
|
@ -35,7 +35,7 @@ class DefaultSPLTokens {
|
||||||
decimal: 6,
|
decimal: 6,
|
||||||
mint: 'ray',
|
mint: 'ray',
|
||||||
iconPath: 'assets/images/ray_icon.png',
|
iconPath: 'assets/images/ray_icon.png',
|
||||||
enabled: true,
|
enabled: false,
|
||||||
),
|
),
|
||||||
SPLToken(
|
SPLToken(
|
||||||
name: 'Wrapped Ethereum (Sollet)',
|
name: 'Wrapped Ethereum (Sollet)',
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
import 'package:cw_core/pending_transaction.dart';
|
import 'package:cw_core/pending_transaction.dart';
|
||||||
import 'package:solana/encoder.dart';
|
|
||||||
|
|
||||||
class PendingSolanaTransaction with PendingTransaction {
|
class PendingSolanaTransaction with PendingTransaction {
|
||||||
final double amount;
|
final double amount;
|
||||||
final SignedTx signedTransaction;
|
final String serializedTransaction;
|
||||||
final String destinationAddress;
|
final String destinationAddress;
|
||||||
final Function sendTransaction;
|
final Function sendTransaction;
|
||||||
final double fee;
|
final double fee;
|
||||||
|
@ -11,7 +10,7 @@ class PendingSolanaTransaction with PendingTransaction {
|
||||||
PendingSolanaTransaction({
|
PendingSolanaTransaction({
|
||||||
required this.fee,
|
required this.fee,
|
||||||
required this.amount,
|
required this.amount,
|
||||||
required this.signedTransaction,
|
required this.serializedTransaction,
|
||||||
required this.destinationAddress,
|
required this.destinationAddress,
|
||||||
required this.sendTransaction,
|
required this.sendTransaction,
|
||||||
});
|
});
|
||||||
|
@ -36,7 +35,7 @@ class PendingSolanaTransaction with PendingTransaction {
|
||||||
String get feeFormatted => fee.toString();
|
String get feeFormatted => fee.toString();
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get hex => signedTransaction.encode();
|
String get hex => serializedTransaction;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get id => '';
|
String get id => '';
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -34,7 +34,9 @@ class SolanaTransactionInfo extends TransactionInfo {
|
||||||
@override
|
@override
|
||||||
String amountFormatted() {
|
String amountFormatted() {
|
||||||
String stringBalance = solAmount.toString();
|
String stringBalance = solAmount.toString();
|
||||||
|
if (stringBalance.toString().length >= 12) {
|
||||||
|
stringBalance = stringBalance.substring(0, 12);
|
||||||
|
}
|
||||||
return '$stringBalance $tokenSymbol';
|
return '$stringBalance $tokenSymbol';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -30,9 +30,9 @@ import 'package:hex/hex.dart';
|
||||||
import 'package:hive/hive.dart';
|
import 'package:hive/hive.dart';
|
||||||
import 'package:mobx/mobx.dart';
|
import 'package:mobx/mobx.dart';
|
||||||
import 'package:shared_preferences/shared_preferences.dart';
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
import 'package:solana/base58.dart';
|
import 'package:on_chain/solana/solana.dart' hide Store;
|
||||||
import 'package:solana/metaplex.dart' as metaplex;
|
import 'package:bip39/bip39.dart' as bip39;
|
||||||
import 'package:solana/solana.dart';
|
import 'package:blockchain_utils/blockchain_utils.dart';
|
||||||
|
|
||||||
part 'solana_wallet.g.dart';
|
part 'solana_wallet.g.dart';
|
||||||
|
|
||||||
|
@ -77,14 +77,6 @@ abstract class SolanaWalletBase
|
||||||
final String? _hexPrivateKey;
|
final String? _hexPrivateKey;
|
||||||
final EncryptionFileUtils encryptionFileUtils;
|
final EncryptionFileUtils encryptionFileUtils;
|
||||||
|
|
||||||
// The Solana WalletPair
|
|
||||||
Ed25519HDKeyPair? _walletKeyPair;
|
|
||||||
|
|
||||||
Ed25519HDKeyPair? get walletKeyPair => _walletKeyPair;
|
|
||||||
|
|
||||||
// To access the privateKey bytes.
|
|
||||||
Ed25519HDKeyPairData? _keyPairData;
|
|
||||||
|
|
||||||
late final SolanaWalletClient _client;
|
late final SolanaWalletClient _client;
|
||||||
|
|
||||||
@observable
|
@observable
|
||||||
|
@ -108,29 +100,23 @@ abstract class SolanaWalletBase
|
||||||
final Completer<SharedPreferences> _sharedPrefs = Completer();
|
final Completer<SharedPreferences> _sharedPrefs = Completer();
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Ed25519HDKeyPairData get keys {
|
Object get keys => throw UnimplementedError("keys");
|
||||||
if (_keyPairData == null) {
|
|
||||||
return Ed25519HDKeyPairData([], publicKey: const Ed25519HDPublicKey([]));
|
|
||||||
}
|
|
||||||
|
|
||||||
return _keyPairData!;
|
late final SolanaPrivateKey _solanaPrivateKey;
|
||||||
}
|
|
||||||
|
late final SolanaPublicKey _solanaPublicKey;
|
||||||
|
|
||||||
|
SolanaPublicKey get solanaPublicKey => _solanaPublicKey;
|
||||||
|
|
||||||
|
SolanaPrivateKey get solanaPrivateKey => _solanaPrivateKey;
|
||||||
|
|
||||||
|
String get solanaAddress => _solanaPublicKey.toAddress().address;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String? get seed => _mnemonic;
|
String? get seed => _mnemonic;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get privateKey {
|
String get privateKey => _solanaPrivateKey.seedHex();
|
||||||
final privateKeyBytes = _keyPairData!.bytes;
|
|
||||||
|
|
||||||
final publicKeyBytes = _keyPairData!.publicKey.bytes;
|
|
||||||
|
|
||||||
final encodedBytes = privateKeyBytes + publicKeyBytes;
|
|
||||||
|
|
||||||
final privateKey = base58encode(encodedBytes);
|
|
||||||
|
|
||||||
return privateKey;
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
WalletKeysData get walletKeysData => WalletKeysData(mnemonic: _mnemonic, privateKey: privateKey);
|
WalletKeysData get walletKeysData => WalletKeysData(mnemonic: _mnemonic, privateKey: privateKey);
|
||||||
|
@ -140,35 +126,47 @@ abstract class SolanaWalletBase
|
||||||
|
|
||||||
splTokensBox = await CakeHive.openBox<SPLToken>(boxName);
|
splTokensBox = await CakeHive.openBox<SPLToken>(boxName);
|
||||||
|
|
||||||
// Create WalletPair using either the mnemonic or the privateKey
|
// Create the privatekey using either the mnemonic or the privateKey
|
||||||
_walletKeyPair = await getWalletPair(
|
_solanaPrivateKey = await getPrivateKey(
|
||||||
mnemonic: _mnemonic,
|
mnemonic: _mnemonic,
|
||||||
privateKey: _hexPrivateKey,
|
privateKey: _hexPrivateKey,
|
||||||
|
passphrase: passphrase,
|
||||||
);
|
);
|
||||||
|
|
||||||
// Extract the keyPairData containing both the privateKey bytes and the publicKey hex.
|
// Extract the public key and wallet address
|
||||||
_keyPairData = await _walletKeyPair!.extract();
|
_solanaPublicKey = _solanaPrivateKey.publicKey();
|
||||||
|
|
||||||
walletInfo.address = _walletKeyPair!.address;
|
walletInfo.address = _solanaPublicKey.toAddress().address;
|
||||||
|
|
||||||
await walletAddresses.init();
|
await walletAddresses.init();
|
||||||
await transactionHistory.init();
|
await transactionHistory.init();
|
||||||
await save();
|
await save();
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<Wallet> getWalletPair({String? mnemonic, String? privateKey}) async {
|
Future<SolanaPrivateKey> getPrivateKey({
|
||||||
|
String? mnemonic,
|
||||||
|
String? privateKey,
|
||||||
|
String? passphrase,
|
||||||
|
}) async {
|
||||||
assert(mnemonic != null || privateKey != null);
|
assert(mnemonic != null || privateKey != null);
|
||||||
|
|
||||||
if (mnemonic != null) {
|
if (mnemonic != null) {
|
||||||
return Wallet.fromMnemonic(mnemonic, account: 0, change: 0);
|
final seed = bip39.mnemonicToSeed(mnemonic, passphrase: passphrase ?? '');
|
||||||
|
|
||||||
|
// Derive a Solana private key from the seed
|
||||||
|
final bip44 = Bip44.fromSeed(seed, Bip44Coins.solana);
|
||||||
|
|
||||||
|
final childKey = bip44.deriveDefaultPath.change(Bip44Changes.chainExt);
|
||||||
|
|
||||||
|
return SolanaPrivateKey.fromSeed(childKey.privateKey.raw);
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
final privateKeyBytes = base58decode(privateKey!);
|
final keypairBytes = Base58Decoder.decode(privateKey!);
|
||||||
return await Wallet.fromPrivateKeyBytes(privateKey: privateKeyBytes.take(32).toList());
|
return SolanaPrivateKey.fromSeed(keypairBytes);
|
||||||
} catch (_) {
|
} catch (_) {
|
||||||
final privateKeyBytes = HEX.decode(privateKey!);
|
final privateKeyBytes = HEX.decode(privateKey!);
|
||||||
return await Wallet.fromPrivateKeyBytes(privateKey: privateKeyBytes);
|
return SolanaPrivateKey.fromBytes(privateKeyBytes);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -206,7 +204,8 @@ abstract class SolanaWalletBase
|
||||||
|
|
||||||
Future<void> _getEstimatedFees() async {
|
Future<void> _getEstimatedFees() async {
|
||||||
try {
|
try {
|
||||||
estimatedFee = await _client.getEstimatedFee(_walletKeyPair!);
|
estimatedFee = await _client.getEstimatedFee(_solanaPublicKey, Commitment.confirmed);
|
||||||
|
printV(estimatedFee.toString());
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
estimatedFee = 0.0;
|
estimatedFee = 0.0;
|
||||||
}
|
}
|
||||||
|
@ -274,7 +273,7 @@ abstract class SolanaWalletBase
|
||||||
tokenMint: tokenMint,
|
tokenMint: tokenMint,
|
||||||
tokenTitle: transactionCurrency.title,
|
tokenTitle: transactionCurrency.title,
|
||||||
inputAmount: totalAmount,
|
inputAmount: totalAmount,
|
||||||
ownerKeypair: _walletKeyPair!,
|
ownerPrivateKey: _solanaPrivateKey,
|
||||||
tokenDecimals: transactionCurrency.decimals,
|
tokenDecimals: transactionCurrency.decimals,
|
||||||
destinationAddress: solCredentials.outputs.first.isParsedAddress
|
destinationAddress: solCredentials.outputs.first.isParsedAddress
|
||||||
? solCredentials.outputs.first.extractedAddress!
|
? solCredentials.outputs.first.extractedAddress!
|
||||||
|
@ -291,9 +290,7 @@ abstract class SolanaWalletBase
|
||||||
|
|
||||||
/// Fetches the native SOL transactions linked to the wallet Public Key
|
/// Fetches the native SOL transactions linked to the wallet Public Key
|
||||||
Future<void> _updateNativeSOLTransactions() async {
|
Future<void> _updateNativeSOLTransactions() async {
|
||||||
final address = Ed25519HDPublicKey.fromBase58(_walletKeyPair!.address);
|
final transactions = await _client.fetchTransactions(_solanaPublicKey.toAddress());
|
||||||
|
|
||||||
final transactions = await _client.fetchTransactions(address);
|
|
||||||
|
|
||||||
await _addTransactionsToTransactionHistory(transactions);
|
await _addTransactionsToTransactionHistory(transactions);
|
||||||
}
|
}
|
||||||
|
@ -308,10 +305,10 @@ abstract class SolanaWalletBase
|
||||||
for (var token in tokenKeys) {
|
for (var token in tokenKeys) {
|
||||||
if (token is SPLToken) {
|
if (token is SPLToken) {
|
||||||
final tokenTxs = await _client.getSPLTokenTransfers(
|
final tokenTxs = await _client.getSPLTokenTransfers(
|
||||||
token.mintAddress,
|
mintAddress: token.mintAddress,
|
||||||
token.symbol,
|
splTokenSymbol: token.symbol,
|
||||||
token.decimal,
|
splTokenDecimal: token.decimal,
|
||||||
_walletKeyPair!,
|
privateKey: _solanaPrivateKey,
|
||||||
);
|
);
|
||||||
|
|
||||||
// splTokenTransactions.addAll(tokenTxs);
|
// splTokenTransactions.addAll(tokenTxs);
|
||||||
|
@ -387,6 +384,7 @@ abstract class SolanaWalletBase
|
||||||
'mnemonic': _mnemonic,
|
'mnemonic': _mnemonic,
|
||||||
'private_key': _hexPrivateKey,
|
'private_key': _hexPrivateKey,
|
||||||
'balance': balance[currency]!.toJSON(),
|
'balance': balance[currency]!.toJSON(),
|
||||||
|
'passphrase': passphrase,
|
||||||
});
|
});
|
||||||
|
|
||||||
static Future<SolanaWallet> open({
|
static Future<SolanaWallet> open({
|
||||||
|
@ -414,8 +412,9 @@ abstract class SolanaWalletBase
|
||||||
if (!hasKeysFile) {
|
if (!hasKeysFile) {
|
||||||
final mnemonic = data!['mnemonic'] as String?;
|
final mnemonic = data!['mnemonic'] as String?;
|
||||||
final privateKey = data['private_key'] as String?;
|
final privateKey = data['private_key'] as String?;
|
||||||
|
final passphrase = data['passphrase'] as String?;
|
||||||
|
|
||||||
keysData = WalletKeysData(mnemonic: mnemonic, privateKey: privateKey);
|
keysData = WalletKeysData(mnemonic: mnemonic, privateKey: privateKey, passphrase: passphrase);
|
||||||
} else {
|
} else {
|
||||||
keysData = await WalletKeysFile.readKeysFile(
|
keysData = await WalletKeysFile.readKeysFile(
|
||||||
name,
|
name,
|
||||||
|
@ -428,6 +427,7 @@ abstract class SolanaWalletBase
|
||||||
return SolanaWallet(
|
return SolanaWallet(
|
||||||
walletInfo: walletInfo,
|
walletInfo: walletInfo,
|
||||||
password: password,
|
password: password,
|
||||||
|
passphrase: keysData.passphrase,
|
||||||
mnemonic: keysData.mnemonic,
|
mnemonic: keysData.mnemonic,
|
||||||
privateKey: keysData.privateKey,
|
privateKey: keysData.privateKey,
|
||||||
initialBalance: balance,
|
initialBalance: balance,
|
||||||
|
@ -442,7 +442,7 @@ abstract class SolanaWalletBase
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<SolanaBalance> _fetchSOLBalance() async {
|
Future<SolanaBalance> _fetchSOLBalance() async {
|
||||||
final balance = await _client.getBalance(_walletKeyPair!.address);
|
final balance = await _client.getBalance(solanaAddress);
|
||||||
|
|
||||||
return SolanaBalance(balance);
|
return SolanaBalance(balance);
|
||||||
}
|
}
|
||||||
|
@ -451,8 +451,7 @@ abstract class SolanaWalletBase
|
||||||
for (var token in splTokensBox.values) {
|
for (var token in splTokensBox.values) {
|
||||||
if (token.enabled) {
|
if (token.enabled) {
|
||||||
try {
|
try {
|
||||||
final tokenBalance =
|
final tokenBalance = await _client.getSplTokenBalance(token.mintAddress, solanaAddress) ??
|
||||||
await _client.getSplTokenBalance(token.mintAddress, _walletKeyPair!.address) ??
|
|
||||||
balance[token] ??
|
balance[token] ??
|
||||||
SolanaBalance(0.0);
|
SolanaBalance(0.0);
|
||||||
balance[token] = tokenBalance;
|
balance[token] = tokenBalance;
|
||||||
|
@ -482,8 +481,7 @@ abstract class SolanaWalletBase
|
||||||
await splTokensBox.put(token.mintAddress, token);
|
await splTokensBox.put(token.mintAddress, token);
|
||||||
|
|
||||||
if (token.enabled) {
|
if (token.enabled) {
|
||||||
final tokenBalance =
|
final tokenBalance = await _client.getSplTokenBalance(token.mintAddress, solanaAddress) ??
|
||||||
await _client.getSplTokenBalance(token.mintAddress, _walletKeyPair!.address) ??
|
|
||||||
balance[token] ??
|
balance[token] ??
|
||||||
SolanaBalance(0.0);
|
SolanaBalance(0.0);
|
||||||
|
|
||||||
|
@ -507,37 +505,10 @@ abstract class SolanaWalletBase
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<SPLToken?> getSPLToken(String mintAddress) async {
|
Future<SPLToken?> getSPLToken(String mintAddress) async {
|
||||||
// Convert SPL token mint address to public key
|
|
||||||
final Ed25519HDPublicKey mintPublicKey;
|
|
||||||
try {
|
try {
|
||||||
mintPublicKey = Ed25519HDPublicKey.fromBase58(mintAddress);
|
return await _client.fetchSPLTokenInfo(mintAddress);
|
||||||
} catch (_) {
|
} catch (e, s) {
|
||||||
return null;
|
printV('Error fetching token: ${e.toString()}, ${s.toString()}');
|
||||||
}
|
|
||||||
|
|
||||||
// Fetch token's metadata account
|
|
||||||
try {
|
|
||||||
final token = await solanaClient!.rpcClient.getMetadata(mint: mintPublicKey);
|
|
||||||
|
|
||||||
if (token == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
String? iconPath;
|
|
||||||
try {
|
|
||||||
iconPath = await _client.getIconImageFromTokenUri(token.uri);
|
|
||||||
} catch (_) {}
|
|
||||||
|
|
||||||
String filteredTokenSymbol = token.symbol.replaceFirst(RegExp('^\\\$'), '');
|
|
||||||
|
|
||||||
return SPLToken.fromMetadata(
|
|
||||||
name: token.name,
|
|
||||||
mint: token.mint,
|
|
||||||
symbol: filteredTokenSymbol,
|
|
||||||
mintAddress: mintAddress,
|
|
||||||
iconPath: iconPath,
|
|
||||||
);
|
|
||||||
} catch (e) {
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -582,7 +553,7 @@ abstract class SolanaWalletBase
|
||||||
final messageBytes = utf8.encode(message);
|
final messageBytes = utf8.encode(message);
|
||||||
|
|
||||||
// Sign the message bytes with the wallet's private key
|
// Sign the message bytes with the wallet's private key
|
||||||
final signature = (await _walletKeyPair!.sign(messageBytes)).toString();
|
final signature = (_solanaPrivateKey.sign(messageBytes)).toString();
|
||||||
|
|
||||||
return HEX.encode(utf8.encode(signature)).toUpperCase();
|
return HEX.encode(utf8.encode(signature)).toUpperCase();
|
||||||
}
|
}
|
||||||
|
@ -596,7 +567,7 @@ abstract class SolanaWalletBase
|
||||||
final base58EncodedPublicKeyString = match.group(2)!;
|
final base58EncodedPublicKeyString = match.group(2)!;
|
||||||
final sigBytes = bytesString.split(', ').map(int.parse).toList();
|
final sigBytes = bytesString.split(', ').map(int.parse).toList();
|
||||||
|
|
||||||
List<int> pubKeyBytes = base58decode(base58EncodedPublicKeyString);
|
List<int> pubKeyBytes = SolAddrDecoder().decodeAddr(base58EncodedPublicKeyString);
|
||||||
|
|
||||||
return [sigBytes, pubKeyBytes];
|
return [sigBytes, pubKeyBytes];
|
||||||
} else {
|
} else {
|
||||||
|
@ -619,19 +590,18 @@ abstract class SolanaWalletBase
|
||||||
}
|
}
|
||||||
|
|
||||||
// make sure the address derived from the public key provided matches the one we expect
|
// make sure the address derived from the public key provided matches the one we expect
|
||||||
final pub = Ed25519HDPublicKey(pubKeyBytes);
|
final pub = SolanaPublicKey.fromBytes(pubKeyBytes);
|
||||||
if (address != pub.toBase58()) {
|
if (address != pub.toAddress().address) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return await verifySignature(
|
return pub.verify(
|
||||||
message: messageBytes,
|
message: messageBytes,
|
||||||
signature: sigBytes,
|
signature: sigBytes,
|
||||||
publicKey: Ed25519HDPublicKey(pubKeyBytes),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
SolanaClient? get solanaClient => _client.getSolanaClient;
|
SolanaRPC? get solanaProvider => _client.getSolanaProvider;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get password => _password;
|
String get password => _password;
|
||||||
|
|
|
@ -33,6 +33,7 @@ class SolanaWalletService extends WalletService<SolanaNewWalletCredentials,
|
||||||
walletInfo: credentials.walletInfo!,
|
walletInfo: credentials.walletInfo!,
|
||||||
mnemonic: mnemonic,
|
mnemonic: mnemonic,
|
||||||
password: credentials.password!,
|
password: credentials.password!,
|
||||||
|
passphrase: credentials.passphrase,
|
||||||
encryptionFileUtils: encryptionFileUtilsFor(isDirect),
|
encryptionFileUtils: encryptionFileUtilsFor(isDirect),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -118,6 +119,7 @@ class SolanaWalletService extends WalletService<SolanaNewWalletCredentials,
|
||||||
password: credentials.password!,
|
password: credentials.password!,
|
||||||
mnemonic: credentials.mnemonic,
|
mnemonic: credentials.mnemonic,
|
||||||
walletInfo: credentials.walletInfo!,
|
walletInfo: credentials.walletInfo!,
|
||||||
|
passphrase: credentials.passphrase,
|
||||||
encryptionFileUtils: encryptionFileUtilsFor(isDirect),
|
encryptionFileUtils: encryptionFileUtilsFor(isDirect),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
import 'package:cw_core/crypto_currency.dart';
|
import 'package:cw_core/crypto_currency.dart';
|
||||||
import 'package:cw_core/hive_type_ids.dart';
|
import 'package:cw_core/hive_type_ids.dart';
|
||||||
import 'package:hive/hive.dart';
|
import 'package:hive/hive.dart';
|
||||||
import 'package:solana/metaplex.dart';
|
|
||||||
|
|
||||||
part 'spl_token.g.dart';
|
part 'spl_token.g.dart';
|
||||||
|
|
||||||
|
@ -55,7 +54,7 @@ class SPLToken extends CryptoCurrency with HiveObjectMixin {
|
||||||
required String mint,
|
required String mint,
|
||||||
required String symbol,
|
required String symbol,
|
||||||
required String mintAddress,
|
required String mintAddress,
|
||||||
String? iconPath
|
String? iconPath,
|
||||||
}) {
|
}) {
|
||||||
return SPLToken(
|
return SPLToken(
|
||||||
name: name,
|
name: name,
|
||||||
|
@ -117,31 +116,3 @@ class SPLToken extends CryptoCurrency with HiveObjectMixin {
|
||||||
@override
|
@override
|
||||||
int get hashCode => mintAddress.hashCode;
|
int get hashCode => mintAddress.hashCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
class NFT extends SPLToken {
|
|
||||||
final ImageInfo? imageInfo;
|
|
||||||
|
|
||||||
NFT(
|
|
||||||
String mint,
|
|
||||||
String name,
|
|
||||||
String symbol,
|
|
||||||
String mintAddress,
|
|
||||||
int decimal,
|
|
||||||
String iconPath,
|
|
||||||
this.imageInfo,
|
|
||||||
) : super(
|
|
||||||
name: name,
|
|
||||||
symbol: symbol,
|
|
||||||
mintAddress: mintAddress,
|
|
||||||
decimal: decimal,
|
|
||||||
mint: mint,
|
|
||||||
iconPath: iconPath,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
class ImageInfo {
|
|
||||||
final String uri;
|
|
||||||
final OffChainMetadata? data;
|
|
||||||
|
|
||||||
const ImageInfo(this.uri, this.data);
|
|
||||||
}
|
|
||||||
|
|
|
@ -11,7 +11,6 @@ environment:
|
||||||
dependencies:
|
dependencies:
|
||||||
flutter:
|
flutter:
|
||||||
sdk: flutter
|
sdk: flutter
|
||||||
solana: ^0.31.0+1
|
|
||||||
cw_core:
|
cw_core:
|
||||||
path: ../cw_core
|
path: ../cw_core
|
||||||
http: ^1.1.0
|
http: ^1.1.0
|
||||||
|
@ -21,6 +20,14 @@ dependencies:
|
||||||
shared_preferences: ^2.0.15
|
shared_preferences: ^2.0.15
|
||||||
bip32: ^2.0.0
|
bip32: ^2.0.0
|
||||||
hex: ^0.2.0
|
hex: ^0.2.0
|
||||||
|
on_chain:
|
||||||
|
git:
|
||||||
|
url: https://github.com/cake-tech/on_chain.git
|
||||||
|
ref: cake-update-v2
|
||||||
|
blockchain_utils:
|
||||||
|
git:
|
||||||
|
url: https://github.com/cake-tech/blockchain_utils
|
||||||
|
ref: cake-update-v2
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_test:
|
flutter_test:
|
||||||
|
|
|
@ -17,7 +17,7 @@ dependencies:
|
||||||
path: ../cw_evm
|
path: ../cw_evm
|
||||||
on_chain:
|
on_chain:
|
||||||
git:
|
git:
|
||||||
url: https://github.com/cake-tech/On_chain
|
url: https://github.com/cake-tech/on_chain.git
|
||||||
ref: cake-update-v2
|
ref: cake-update-v2
|
||||||
blockchain_utils:
|
blockchain_utils:
|
||||||
git:
|
git:
|
||||||
|
|
|
@ -3,38 +3,8 @@ PODS:
|
||||||
- Flutter
|
- Flutter
|
||||||
- ReachabilitySwift
|
- ReachabilitySwift
|
||||||
- CryptoSwift (1.8.3)
|
- CryptoSwift (1.8.3)
|
||||||
- cw_haven (0.0.1):
|
|
||||||
- cw_haven/Boost (= 0.0.1)
|
|
||||||
- cw_haven/Haven (= 0.0.1)
|
|
||||||
- cw_haven/OpenSSL (= 0.0.1)
|
|
||||||
- cw_haven/Sodium (= 0.0.1)
|
|
||||||
- cw_shared_external
|
|
||||||
- Flutter
|
|
||||||
- cw_haven/Boost (0.0.1):
|
|
||||||
- cw_shared_external
|
|
||||||
- Flutter
|
|
||||||
- cw_haven/Haven (0.0.1):
|
|
||||||
- cw_shared_external
|
|
||||||
- Flutter
|
|
||||||
- cw_haven/OpenSSL (0.0.1):
|
|
||||||
- cw_shared_external
|
|
||||||
- Flutter
|
|
||||||
- cw_haven/Sodium (0.0.1):
|
|
||||||
- cw_shared_external
|
|
||||||
- Flutter
|
|
||||||
- cw_mweb (0.0.1):
|
- cw_mweb (0.0.1):
|
||||||
- Flutter
|
- Flutter
|
||||||
- cw_shared_external (0.0.1):
|
|
||||||
- cw_shared_external/Boost (= 0.0.1)
|
|
||||||
- cw_shared_external/OpenSSL (= 0.0.1)
|
|
||||||
- cw_shared_external/Sodium (= 0.0.1)
|
|
||||||
- Flutter
|
|
||||||
- cw_shared_external/Boost (0.0.1):
|
|
||||||
- Flutter
|
|
||||||
- cw_shared_external/OpenSSL (0.0.1):
|
|
||||||
- Flutter
|
|
||||||
- cw_shared_external/Sodium (0.0.1):
|
|
||||||
- Flutter
|
|
||||||
- device_display_brightness (0.0.1):
|
- device_display_brightness (0.0.1):
|
||||||
- Flutter
|
- Flutter
|
||||||
- device_info_plus (0.0.1):
|
- device_info_plus (0.0.1):
|
||||||
|
@ -136,9 +106,7 @@ PODS:
|
||||||
DEPENDENCIES:
|
DEPENDENCIES:
|
||||||
- connectivity_plus (from `.symlinks/plugins/connectivity_plus/ios`)
|
- connectivity_plus (from `.symlinks/plugins/connectivity_plus/ios`)
|
||||||
- CryptoSwift
|
- CryptoSwift
|
||||||
- cw_haven (from `.symlinks/plugins/cw_haven/ios`)
|
|
||||||
- cw_mweb (from `.symlinks/plugins/cw_mweb/ios`)
|
- cw_mweb (from `.symlinks/plugins/cw_mweb/ios`)
|
||||||
- cw_shared_external (from `.symlinks/plugins/cw_shared_external/ios`)
|
|
||||||
- device_display_brightness (from `.symlinks/plugins/device_display_brightness/ios`)
|
- device_display_brightness (from `.symlinks/plugins/device_display_brightness/ios`)
|
||||||
- device_info_plus (from `.symlinks/plugins/device_info_plus/ios`)
|
- device_info_plus (from `.symlinks/plugins/device_info_plus/ios`)
|
||||||
- devicelocale (from `.symlinks/plugins/devicelocale/ios`)
|
- devicelocale (from `.symlinks/plugins/devicelocale/ios`)
|
||||||
|
@ -179,12 +147,8 @@ SPEC REPOS:
|
||||||
EXTERNAL SOURCES:
|
EXTERNAL SOURCES:
|
||||||
connectivity_plus:
|
connectivity_plus:
|
||||||
:path: ".symlinks/plugins/connectivity_plus/ios"
|
:path: ".symlinks/plugins/connectivity_plus/ios"
|
||||||
cw_haven:
|
|
||||||
:path: ".symlinks/plugins/cw_haven/ios"
|
|
||||||
cw_mweb:
|
cw_mweb:
|
||||||
:path: ".symlinks/plugins/cw_mweb/ios"
|
:path: ".symlinks/plugins/cw_mweb/ios"
|
||||||
cw_shared_external:
|
|
||||||
:path: ".symlinks/plugins/cw_shared_external/ios"
|
|
||||||
device_display_brightness:
|
device_display_brightness:
|
||||||
:path: ".symlinks/plugins/device_display_brightness/ios"
|
:path: ".symlinks/plugins/device_display_brightness/ios"
|
||||||
device_info_plus:
|
device_info_plus:
|
||||||
|
@ -239,9 +203,7 @@ EXTERNAL SOURCES:
|
||||||
SPEC CHECKSUMS:
|
SPEC CHECKSUMS:
|
||||||
connectivity_plus: bf0076dd84a130856aa636df1c71ccaff908fa1d
|
connectivity_plus: bf0076dd84a130856aa636df1c71ccaff908fa1d
|
||||||
CryptoSwift: 967f37cea5a3294d9cce358f78861652155be483
|
CryptoSwift: 967f37cea5a3294d9cce358f78861652155be483
|
||||||
cw_haven: b3e54e1fbe7b8e6fda57a93206bc38f8e89b898a
|
|
||||||
cw_mweb: 22cd01dfb8ad2d39b15332006f22046aaa8352a3
|
cw_mweb: 22cd01dfb8ad2d39b15332006f22046aaa8352a3
|
||||||
cw_shared_external: 2972d872b8917603478117c9957dfca611845a92
|
|
||||||
device_display_brightness: 1510e72c567a1f6ce6ffe393dcd9afd1426034f7
|
device_display_brightness: 1510e72c567a1f6ce6ffe393dcd9afd1426034f7
|
||||||
device_info_plus: c6fb39579d0f423935b0c9ce7ee2f44b71b9fce6
|
device_info_plus: c6fb39579d0f423935b0c9ce7ee2f44b71b9fce6
|
||||||
devicelocale: 35ba84dc7f45f527c3001535d8c8d104edd5d926
|
devicelocale: 35ba84dc7f45f527c3001535d8c8d104edd5d926
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
|
import 'dart:convert';
|
||||||
import 'dart:developer';
|
import 'dart:developer';
|
||||||
|
|
||||||
|
import 'package:blockchain_utils/blockchain_utils.dart';
|
||||||
import 'package:cake_wallet/core/wallet_connect/chain_service/solana/entities/solana_sign_message.dart';
|
import 'package:cake_wallet/core/wallet_connect/chain_service/solana/entities/solana_sign_message.dart';
|
||||||
import 'package:cake_wallet/core/wallet_connect/chain_service/solana/solana_chain_id.dart';
|
import 'package:cake_wallet/core/wallet_connect/chain_service/solana/solana_chain_id.dart';
|
||||||
import 'package:cake_wallet/core/wallet_connect/wc_bottom_sheet_service.dart';
|
import 'package:cake_wallet/core/wallet_connect/wc_bottom_sheet_service.dart';
|
||||||
|
@ -8,9 +10,9 @@ import 'package:cake_wallet/src/screens/wallet_connect/widgets/message_display_w
|
||||||
import 'package:cake_wallet/core/wallet_connect/models/connection_model.dart';
|
import 'package:cake_wallet/core/wallet_connect/models/connection_model.dart';
|
||||||
import 'package:cake_wallet/src/screens/wallet_connect/widgets/connection_widget.dart';
|
import 'package:cake_wallet/src/screens/wallet_connect/widgets/connection_widget.dart';
|
||||||
import 'package:cake_wallet/src/screens/wallet_connect/widgets/modals/web3_request_modal.dart';
|
import 'package:cake_wallet/src/screens/wallet_connect/widgets/modals/web3_request_modal.dart';
|
||||||
|
import 'package:cw_core/solana_rpc_http_service.dart';
|
||||||
import 'package:cw_core/utils/print_verbose.dart';
|
import 'package:cw_core/utils/print_verbose.dart';
|
||||||
import 'package:solana/base58.dart';
|
import 'package:on_chain/solana/solana.dart';
|
||||||
import 'package:solana/solana.dart';
|
|
||||||
import 'package:walletconnect_flutter_v2/walletconnect_flutter_v2.dart';
|
import 'package:walletconnect_flutter_v2/walletconnect_flutter_v2.dart';
|
||||||
import '../chain_service.dart';
|
import '../chain_service.dart';
|
||||||
import '../../wallet_connect_key_service.dart';
|
import '../../wallet_connect_key_service.dart';
|
||||||
|
@ -27,25 +29,19 @@ class SolanaChainServiceImpl implements ChainService {
|
||||||
|
|
||||||
final SolanaChainId reference;
|
final SolanaChainId reference;
|
||||||
|
|
||||||
final SolanaClient solanaClient;
|
final SolanaRPC solanaProvider;
|
||||||
|
|
||||||
final Ed25519HDKeyPair? ownerKeyPair;
|
final SolanaPrivateKey? ownerPrivateKey;
|
||||||
|
|
||||||
SolanaChainServiceImpl({
|
SolanaChainServiceImpl({
|
||||||
required this.reference,
|
required this.reference,
|
||||||
required this.wcKeyService,
|
required this.wcKeyService,
|
||||||
required this.bottomSheetService,
|
required this.bottomSheetService,
|
||||||
required this.wallet,
|
required this.wallet,
|
||||||
required this.ownerKeyPair,
|
required this.ownerPrivateKey,
|
||||||
required String webSocketUrl,
|
required String formattedRPCUrl,
|
||||||
required Uri rpcUrl,
|
SolanaRPC? solanaProvider,
|
||||||
SolanaClient? solanaClient,
|
}) : solanaProvider = solanaProvider ?? SolanaRPC(SolanaRPCHTTPService(url: formattedRPCUrl)) {
|
||||||
}) : solanaClient = solanaClient ??
|
|
||||||
SolanaClient(
|
|
||||||
rpcUrl: rpcUrl,
|
|
||||||
websocketUrl: Uri.parse(webSocketUrl),
|
|
||||||
timeout: const Duration(minutes: 5),
|
|
||||||
) {
|
|
||||||
for (final String event in getEvents()) {
|
for (final String event in getEvents()) {
|
||||||
wallet.registerEventEmitter(chainId: getChainId(), event: event);
|
wallet.registerEventEmitter(chainId: getChainId(), event: event);
|
||||||
}
|
}
|
||||||
|
@ -110,26 +106,20 @@ class SolanaChainServiceImpl implements ChainService {
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
final message =
|
// Convert transaction string to bytes
|
||||||
await solanaClient.rpcClient.getMessageFromEncodedTx(solanaSignTx.transaction);
|
List<int> transactionBytes = base64Decode(solanaSignTx.transaction);
|
||||||
|
|
||||||
final sign = await ownerKeyPair?.signMessage(
|
final message = SolanaTransactionUtils.deserializeMessageLegacy(transactionBytes);
|
||||||
message: message,
|
|
||||||
recentBlockhash: solanaSignTx.recentBlockhash ?? '',
|
|
||||||
);
|
|
||||||
|
|
||||||
if (sign == null) {
|
final sign = ownerPrivateKey!.sign(message.serialize());
|
||||||
return '';
|
|
||||||
}
|
|
||||||
|
|
||||||
String signature = await solanaClient.sendAndConfirmTransaction(
|
final signature = solanaProvider.request(
|
||||||
message: message,
|
SolanaRPCSendTransaction(
|
||||||
signers: [ownerKeyPair!],
|
encodedTransaction: Base58Encoder.encode(sign),
|
||||||
commitment: Commitment.confirmed,
|
commitment: Commitment.confirmed,
|
||||||
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
printV(signature);
|
|
||||||
|
|
||||||
bottomSheetService.queueBottomSheet(
|
bottomSheetService.queueBottomSheet(
|
||||||
isModalDismissible: true,
|
isModalDismissible: true,
|
||||||
widget: BottomSheetMessageDisplayWidget(
|
widget: BottomSheetMessageDisplayWidget(
|
||||||
|
@ -161,10 +151,10 @@ class SolanaChainServiceImpl implements ChainService {
|
||||||
if (authError != null) {
|
if (authError != null) {
|
||||||
return authError;
|
return authError;
|
||||||
}
|
}
|
||||||
Signature? sign;
|
List<int>? sign;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
sign = await ownerKeyPair?.sign(base58decode(solanaSignMessage.message));
|
sign = ownerPrivateKey!.sign(Base58Decoder.decode(solanaSignMessage.message));
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
printV(e);
|
printV(e);
|
||||||
}
|
}
|
||||||
|
@ -173,7 +163,7 @@ class SolanaChainServiceImpl implements ChainService {
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
String signature = sign.toBase58();
|
final signature = Base58Encoder.encode(sign);
|
||||||
|
|
||||||
return signature;
|
return signature;
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,7 @@ import 'package:cw_core/wallet_type.dart';
|
||||||
import 'package:eth_sig_util/eth_sig_util.dart';
|
import 'package:eth_sig_util/eth_sig_util.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:mobx/mobx.dart';
|
import 'package:mobx/mobx.dart';
|
||||||
|
import 'package:on_chain/solana/solana.dart' hide Store;
|
||||||
import 'package:shared_preferences/shared_preferences.dart';
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
import 'package:walletconnect_flutter_v2/walletconnect_flutter_v2.dart';
|
import 'package:walletconnect_flutter_v2/walletconnect_flutter_v2.dart';
|
||||||
|
|
||||||
|
@ -140,29 +141,28 @@ abstract class Web3WalletServiceBase with Store {
|
||||||
for (final cId in SolanaChainId.values) {
|
for (final cId in SolanaChainId.values) {
|
||||||
final node = appStore.settingsStore.getCurrentNode(appStore.wallet!.type);
|
final node = appStore.settingsStore.getCurrentNode(appStore.wallet!.type);
|
||||||
|
|
||||||
Uri rpcUri = node.uri;
|
String formattedUrl;
|
||||||
String webSocketUrl = 'wss://${node.uriRaw}';
|
String protocolUsed = node.isSSL ? "https" : "http";
|
||||||
|
|
||||||
if (node.uriRaw == 'rpc.ankr.com') {
|
if (node.uriRaw == 'rpc.ankr.com') {
|
||||||
String ankrApiKey = secrets.ankrApiKey;
|
String ankrApiKey = secrets.ankrApiKey;
|
||||||
|
|
||||||
rpcUri = Uri.https(node.uriRaw, '/solana/$ankrApiKey');
|
formattedUrl = '$protocolUsed://${node.uriRaw}/$ankrApiKey';
|
||||||
webSocketUrl = 'wss://${node.uriRaw}/solana/ws/$ankrApiKey';
|
|
||||||
} else if (node.uriRaw == 'solana-mainnet.core.chainstack.com') {
|
} else if (node.uriRaw == 'solana-mainnet.core.chainstack.com') {
|
||||||
String chainStackApiKey = secrets.chainStackApiKey;
|
String chainStackApiKey = secrets.chainStackApiKey;
|
||||||
|
|
||||||
rpcUri = Uri.https(node.uriRaw, '/$chainStackApiKey');
|
formattedUrl = '$protocolUsed://${node.uriRaw}/$chainStackApiKey';
|
||||||
webSocketUrl = 'wss://${node.uriRaw}/$chainStackApiKey';
|
} else {
|
||||||
|
formattedUrl = '$protocolUsed://${node.uriRaw}';
|
||||||
}
|
}
|
||||||
|
|
||||||
SolanaChainServiceImpl(
|
SolanaChainServiceImpl(
|
||||||
reference: cId,
|
reference: cId,
|
||||||
rpcUrl: rpcUri,
|
formattedRPCUrl: formattedUrl,
|
||||||
webSocketUrl: webSocketUrl,
|
|
||||||
wcKeyService: walletKeyService,
|
wcKeyService: walletKeyService,
|
||||||
bottomSheetService: _bottomSheetHandler,
|
bottomSheetService: _bottomSheetHandler,
|
||||||
wallet: _web3Wallet,
|
wallet: _web3Wallet,
|
||||||
ownerKeyPair: solana!.getWalletKeyPair(appStore.wallet!),
|
ownerPrivateKey: SolanaPrivateKey.fromSeedHex(solana!.getPrivateKey(appStore.wallet!)),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,11 +52,8 @@ class CWSolana extends Solana {
|
||||||
String getPrivateKey(WalletBase wallet) => (wallet as SolanaWallet).privateKey;
|
String getPrivateKey(WalletBase wallet) => (wallet as SolanaWallet).privateKey;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String getPublicKey(WalletBase wallet) => (wallet as SolanaWallet).keys.publicKey.toBase58();
|
String getPublicKey(WalletBase wallet) =>
|
||||||
|
(wallet as SolanaWallet).solanaPublicKey.toAddress().address;
|
||||||
@override
|
|
||||||
Ed25519HDKeyPair? getWalletKeyPair(WalletBase wallet) => (wallet as SolanaWallet).walletKeyPair;
|
|
||||||
|
|
||||||
Object createSolanaTransactionCredentials(
|
Object createSolanaTransactionCredentials(
|
||||||
List<Output> outputs, {
|
List<Output> outputs, {
|
||||||
required CryptoCurrency currency,
|
required CryptoCurrency currency,
|
||||||
|
|
|
@ -78,6 +78,7 @@ abstract class AdvancedPrivacySettingsViewModelBase with Store {
|
||||||
WalletType.ethereum,
|
WalletType.ethereum,
|
||||||
WalletType.polygon,
|
WalletType.polygon,
|
||||||
WalletType.tron,
|
WalletType.tron,
|
||||||
|
WalletType.solana,
|
||||||
WalletType.monero,
|
WalletType.monero,
|
||||||
WalletType.wownero,
|
WalletType.wownero,
|
||||||
WalletType.zano,
|
WalletType.zano,
|
||||||
|
|
|
@ -106,12 +106,19 @@ dependencies:
|
||||||
flutter_svg: ^2.0.9
|
flutter_svg: ^2.0.9
|
||||||
polyseed: ^0.0.6
|
polyseed: ^0.0.6
|
||||||
nostr_tools: ^1.0.9
|
nostr_tools: ^1.0.9
|
||||||
solana: ^0.31.0+1
|
|
||||||
ledger_flutter_plus:
|
ledger_flutter_plus:
|
||||||
git:
|
git:
|
||||||
url: https://github.com/vespr-wallet/ledger-flutter-plus
|
url: https://github.com/vespr-wallet/ledger-flutter-plus
|
||||||
ref: c2e341d8038f1108690ad6f80f7b4b7156aacc76
|
ref: c2e341d8038f1108690ad6f80f7b4b7156aacc76
|
||||||
hashlib: ^1.19.2
|
hashlib: ^1.19.2
|
||||||
|
on_chain:
|
||||||
|
git:
|
||||||
|
url: https://github.com/cake-tech/on_chain.git
|
||||||
|
ref: cake-update-v2
|
||||||
|
blockchain_utils:
|
||||||
|
git:
|
||||||
|
url: https://github.com/cake-tech/blockchain_utils
|
||||||
|
ref: cake-update-v2
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_test:
|
flutter_test:
|
||||||
|
|
|
@ -1261,7 +1261,6 @@ import 'package:cw_core/wallet_credentials.dart';
|
||||||
import 'package:cw_core/wallet_info.dart';
|
import 'package:cw_core/wallet_info.dart';
|
||||||
import 'package:cw_core/wallet_service.dart';
|
import 'package:cw_core/wallet_service.dart';
|
||||||
import 'package:hive/hive.dart';
|
import 'package:hive/hive.dart';
|
||||||
import 'package:solana/solana.dart';
|
|
||||||
|
|
||||||
""";
|
""";
|
||||||
const solanaCWHeaders = """
|
const solanaCWHeaders = """
|
||||||
|
@ -1289,7 +1288,6 @@ abstract class Solana {
|
||||||
String getAddress(WalletBase wallet);
|
String getAddress(WalletBase wallet);
|
||||||
String getPrivateKey(WalletBase wallet);
|
String getPrivateKey(WalletBase wallet);
|
||||||
String getPublicKey(WalletBase wallet);
|
String getPublicKey(WalletBase wallet);
|
||||||
Ed25519HDKeyPair? getWalletKeyPair(WalletBase wallet);
|
|
||||||
|
|
||||||
Object createSolanaTransactionCredentials(
|
Object createSolanaTransactionCredentials(
|
||||||
List<Output> outputs, {
|
List<Output> outputs, {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue