@deserialize/multi-vm-wallet 1.5.22 → 1.5.32
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/IChainWallet.d.ts +11 -7
- package/dist/IChainWallet.js +15 -6
- package/dist/constant.js +40 -48
- package/dist/evm/evm.d.ts +19 -1
- package/dist/evm/evm.js +88 -31
- package/dist/evm/utils.d.ts +1 -0
- package/dist/evm/utils.js +8 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +2 -1
- package/dist/svm/svm.d.ts +17 -1
- package/dist/svm/svm.js +71 -21
- package/dist/test.js +7 -1
- package/dist/types.d.ts +4 -0
- package/dist/walletBip32.js +0 -3
- package/package.json +1 -1
- package/utils/IChainWallet.ts +76 -15
- package/utils/constant.ts +41 -51
- package/utils/evm/evm.ts +369 -290
- package/utils/evm/utils.ts +12 -0
- package/utils/index.ts +2 -2
- package/utils/savings/svm-savings.ts +1 -1
- package/utils/svm/svm.ts +344 -24
- package/utils/test.ts +9 -5
- package/utils/types.ts +6 -2
- package/utils/utils.ts +7 -0
- package/utils/walletBip32.ts +3 -3
package/utils/evm/evm.ts
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
import { EntropyToMnemonic, EVMDeriveChildPrivateKey } from "../walletBip32";
|
|
8
|
-
import { ChainWallet } from "../IChainWallet";
|
|
8
|
+
import { ChainAddress, ChainWallet } from "../IChainWallet";
|
|
9
9
|
import { Balance, ChainWalletConfig, NFTInfo, UserTokenBalance, TokenInfo, TransactionResult, NFT, DiscoveredWallet, WalletDiscoveryOptions, WalletDiscoveryResult, PocketDiscoveryOptions } from "../types";
|
|
10
10
|
import { VM } from "../vm";
|
|
11
11
|
import { VMValidation, sanitizeError, logSafeError } from "../vm-validation";
|
|
@@ -50,6 +50,133 @@ import { Account, generatePrivateKey, privateKeyToAccount } from "viem/accounts"
|
|
|
50
50
|
// import { extendWalletClientWithSavings } from "../savings";
|
|
51
51
|
// import { SavingsManager } from "../savings/saving-actions";
|
|
52
52
|
|
|
53
|
+
/**
|
|
54
|
+
* Create a viem public client for the given EVM chain configuration.
|
|
55
|
+
*
|
|
56
|
+
* @param config - Chain configuration with RPC endpoint and chain metadata.
|
|
57
|
+
* @returns Configured viem `PublicClient`.
|
|
58
|
+
*/
|
|
59
|
+
export const createEvmPublicClient = (config: ChainWalletConfig): PublicClient =>
|
|
60
|
+
createPublicClient({
|
|
61
|
+
chain: fromChainToViemChain(config),
|
|
62
|
+
transport: http(config.rpcUrl),
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Create a viem wallet client bound to a specific account.
|
|
67
|
+
*
|
|
68
|
+
* @param config - Chain configuration with RPC endpoint and chain metadata.
|
|
69
|
+
* @param account - Account used for signing transactions and messages.
|
|
70
|
+
* @returns Configured viem `WalletClient`.
|
|
71
|
+
*/
|
|
72
|
+
export const createEvmWalletClient = (config: ChainWalletConfig, account: Account): WalletClient =>
|
|
73
|
+
createWalletClient({
|
|
74
|
+
account,
|
|
75
|
+
chain: fromChainToViemChain(config),
|
|
76
|
+
transport: http(config.rpcUrl),
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Fetch transaction history and return an empty array on failure.
|
|
81
|
+
*
|
|
82
|
+
* @param connection - viem public client used to query chain data.
|
|
83
|
+
* @param address - Wallet address to inspect.
|
|
84
|
+
* @returns Parsed EVM transaction history items.
|
|
85
|
+
*/
|
|
86
|
+
export const getEvmTransactionHistorySafe = async (
|
|
87
|
+
connection: PublicClient,
|
|
88
|
+
address: string
|
|
89
|
+
): Promise<EVMTransactionHistoryItem[]> => {
|
|
90
|
+
try {
|
|
91
|
+
return await getEVMTransactionHistory(connection, address as Hex);
|
|
92
|
+
} catch {
|
|
93
|
+
return [];
|
|
94
|
+
}
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Fetch token prices for EVM tokens on the configured chain.
|
|
99
|
+
*
|
|
100
|
+
* @param config - Chain configuration used for chain ID resolution.
|
|
101
|
+
* @param tokenAddresses - Token contract addresses to query.
|
|
102
|
+
* @returns Price data keyed by token address.
|
|
103
|
+
* @throws Error when the pricing service returns an error payload.
|
|
104
|
+
*/
|
|
105
|
+
export const getSvmPricesForTokens = async (
|
|
106
|
+
config: ChainWalletConfig,
|
|
107
|
+
tokenAddresses: string[]
|
|
108
|
+
): Promise<PriceResponse> => {
|
|
109
|
+
const result = await fetchPrices({
|
|
110
|
+
vm: 'EVM',
|
|
111
|
+
chainId: config.chainId,
|
|
112
|
+
tokenAddresses,
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
if (result.error) {
|
|
116
|
+
throw new Error(result.error.message);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
return result.data as PriceResponse;
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Get native token balance for an address.
|
|
124
|
+
*
|
|
125
|
+
* @param address - Wallet address to query.
|
|
126
|
+
* @param connection - viem public client.
|
|
127
|
+
* @returns Native balance details.
|
|
128
|
+
*/
|
|
129
|
+
export const getEvmNativeBalance = async (
|
|
130
|
+
address: string,
|
|
131
|
+
connection: PublicClient
|
|
132
|
+
): Promise<Balance> => {
|
|
133
|
+
return await EVMVM.getNativeBalance(address, connection);
|
|
134
|
+
};
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Get ERC-20 token balance for an address.
|
|
138
|
+
*
|
|
139
|
+
* @param address - Wallet address to query.
|
|
140
|
+
* @param tokenAddress - ERC-20 contract address.
|
|
141
|
+
* @param connection - viem public client.
|
|
142
|
+
* @returns Token balance details.
|
|
143
|
+
*/
|
|
144
|
+
export const getEvmTokenBalance = async (
|
|
145
|
+
address: string,
|
|
146
|
+
tokenAddress: string,
|
|
147
|
+
connection: PublicClient
|
|
148
|
+
): Promise<Balance> => {
|
|
149
|
+
return await EVMVM.getTokenBalance(address, tokenAddress, connection);
|
|
150
|
+
};
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Discover token balances held by an address.
|
|
154
|
+
*
|
|
155
|
+
* @param address - Wallet address to scan.
|
|
156
|
+
* @param config - Chain configuration.
|
|
157
|
+
* @returns Discovered token balances.
|
|
158
|
+
*/
|
|
159
|
+
export const discoverEvmTokens = async (
|
|
160
|
+
address: string,
|
|
161
|
+
config: ChainWalletConfig
|
|
162
|
+
): Promise<UserTokenBalance<string>[]> => {
|
|
163
|
+
return await discoverTokens(address, config);
|
|
164
|
+
};
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* Discover NFTs held by an address.
|
|
168
|
+
*
|
|
169
|
+
* @param address - Wallet address to scan.
|
|
170
|
+
* @param config - Chain configuration.
|
|
171
|
+
* @returns Discovered NFT items.
|
|
172
|
+
*/
|
|
173
|
+
export const discoverEvmNFTs = async (
|
|
174
|
+
address: string,
|
|
175
|
+
config: ChainWalletConfig
|
|
176
|
+
): Promise<NFT[]> => {
|
|
177
|
+
return await discoverNFTs(address, config);
|
|
178
|
+
};
|
|
179
|
+
|
|
53
180
|
|
|
54
181
|
interface DebonkQuoteResponse {
|
|
55
182
|
tokenA: string;
|
|
@@ -98,6 +225,15 @@ export class EVMVM extends VM<string, string, PublicClient> {
|
|
|
98
225
|
|
|
99
226
|
getTokenInfo = getTokenInfo
|
|
100
227
|
static getTokenInfo = getTokenInfo
|
|
228
|
+
/**
|
|
229
|
+
* Derive an EVM private key for a wallet index.
|
|
230
|
+
*
|
|
231
|
+
* @param index - Wallet index in the derivation path.
|
|
232
|
+
* @param seed - Optional explicit seed (takes priority over mnemonic).
|
|
233
|
+
* @param mnemonic - Optional mnemonic used when seed is not provided.
|
|
234
|
+
* @param derivationPath - Base derivation path prefix.
|
|
235
|
+
* @returns Derived private key and index.
|
|
236
|
+
*/
|
|
101
237
|
generatePrivateKey(index: number, seed?: string, mnemonic?: string, derivationPath = this.derivationPath) {
|
|
102
238
|
// Validate inputs
|
|
103
239
|
VMValidation.validateIndex(index, 'Wallet index');
|
|
@@ -121,10 +257,22 @@ export class EVMVM extends VM<string, string, PublicClient> {
|
|
|
121
257
|
return { privateKey, index };
|
|
122
258
|
}
|
|
123
259
|
|
|
260
|
+
/**
|
|
261
|
+
* Convert raw private key entropy into a mnemonic phrase.
|
|
262
|
+
*
|
|
263
|
+
* @param privateKey - Private key entropy input.
|
|
264
|
+
* @returns Generated mnemonic phrase.
|
|
265
|
+
*/
|
|
124
266
|
static generateMnemonicFromPrivateKey(privateKey: string): string {
|
|
125
267
|
|
|
126
268
|
return EntropyToMnemonic(privateKey)
|
|
127
269
|
}
|
|
270
|
+
/**
|
|
271
|
+
* Create an `EVMVM` instance from a mnemonic phrase.
|
|
272
|
+
*
|
|
273
|
+
* @param mnemonic - BIP-39 mnemonic phrase.
|
|
274
|
+
* @returns Initialized EVM VM instance.
|
|
275
|
+
*/
|
|
128
276
|
static fromMnemonic(mnemonic: string): VM<string, string, PublicClient> {
|
|
129
277
|
const seed = VM.mnemonicToSeed(mnemonic)
|
|
130
278
|
return new EVMVM(seed)
|
|
@@ -191,16 +339,37 @@ export class EVMVM extends VM<string, string, PublicClient> {
|
|
|
191
339
|
return ethers.getAddress(address);
|
|
192
340
|
}
|
|
193
341
|
|
|
342
|
+
/**
|
|
343
|
+
* Read the native token balance for an address.
|
|
344
|
+
*
|
|
345
|
+
* @param address - Wallet address to query.
|
|
346
|
+
* @param connection - viem public client.
|
|
347
|
+
* @returns Native balance details.
|
|
348
|
+
*/
|
|
194
349
|
static async getNativeBalance(address: string, connection: PublicClient): Promise<Balance> {
|
|
195
350
|
// Implement native balance retrieval logic here
|
|
196
351
|
return await getNativeBalance(address as Hex, connection)
|
|
197
352
|
}
|
|
198
353
|
|
|
354
|
+
/**
|
|
355
|
+
* Read an ERC-20 token balance for an address.
|
|
356
|
+
*
|
|
357
|
+
* @param address - Wallet address that owns the token.
|
|
358
|
+
* @param tokenAddress - ERC-20 contract address.
|
|
359
|
+
* @param connection - viem public client.
|
|
360
|
+
* @returns Token balance details.
|
|
361
|
+
*/
|
|
199
362
|
static async getTokenBalance(address: string, tokenAddress: string, connection: PublicClient): Promise<Balance> {
|
|
200
363
|
// Implement token balance retrieval logic here
|
|
201
364
|
return await getTokenBalance(tokenAddress as Hex, address as Hex, connection)
|
|
202
365
|
}
|
|
203
366
|
|
|
367
|
+
/**
|
|
368
|
+
* Convert arbitrary entropy text into a deterministic private-key-like hash.
|
|
369
|
+
*
|
|
370
|
+
* @param entropy - Input entropy string.
|
|
371
|
+
* @returns `keccak256` hash of the input.
|
|
372
|
+
*/
|
|
204
373
|
static convertFromEntropyToPrivateKey = (entropy: string): string => {
|
|
205
374
|
const p = ethers.id(entropy)
|
|
206
375
|
return p
|
|
@@ -688,29 +857,106 @@ export class EVMVM extends VM<string, string, PublicClient> {
|
|
|
688
857
|
|
|
689
858
|
}
|
|
690
859
|
|
|
860
|
+
export class EVMChainAddress extends ChainAddress<string, PublicClient> {
|
|
861
|
+
/**
|
|
862
|
+
* Create an EVM chain address wrapper with an attached public client.
|
|
863
|
+
*
|
|
864
|
+
* @param config - Chain configuration.
|
|
865
|
+
* @param address - Wallet address.
|
|
866
|
+
* @param index - Optional derivation index.
|
|
867
|
+
*/
|
|
868
|
+
constructor(config: ChainWalletConfig, address: string, index?: number) {
|
|
869
|
+
const connection = createEvmPublicClient(config);
|
|
870
|
+
super(config, address, index);
|
|
871
|
+
this.connection = connection;
|
|
872
|
+
}
|
|
873
|
+
|
|
874
|
+
/**
|
|
875
|
+
* Get native balance for this address.
|
|
876
|
+
*
|
|
877
|
+
* @returns Native balance details.
|
|
878
|
+
*/
|
|
879
|
+
async getNativeBalance(): Promise<Balance> {
|
|
880
|
+
return await getEvmNativeBalance(this.address, this.connection!);
|
|
881
|
+
}
|
|
882
|
+
|
|
883
|
+
/**
|
|
884
|
+
* Get ERC-20 token balance for this address.
|
|
885
|
+
*
|
|
886
|
+
* @param tokenAddress - ERC-20 contract address.
|
|
887
|
+
* @returns Token balance details.
|
|
888
|
+
*/
|
|
889
|
+
async getTokenBalance(tokenAddress: string): Promise<Balance> {
|
|
890
|
+
return await getEvmTokenBalance(this.address, tokenAddress, this.connection!);
|
|
891
|
+
}
|
|
892
|
+
|
|
893
|
+
/**
|
|
894
|
+
* Discover fungible tokens held by this address.
|
|
895
|
+
*
|
|
896
|
+
* @returns Discovered token balances.
|
|
897
|
+
*/
|
|
898
|
+
async discoverToken(): Promise<UserTokenBalance<string>[]> {
|
|
899
|
+
return await discoverEvmTokens(this.address, this.config);
|
|
900
|
+
}
|
|
901
|
+
|
|
902
|
+
/**
|
|
903
|
+
* Discover NFTs held by this address.
|
|
904
|
+
*
|
|
905
|
+
* @returns Discovered NFTs.
|
|
906
|
+
*/
|
|
907
|
+
async discoverNFT(): Promise<NFT[]> {
|
|
908
|
+
return await discoverEvmNFTs(this.address, this.config);
|
|
909
|
+
}
|
|
910
|
+
|
|
911
|
+
/**
|
|
912
|
+
* Retrieve transaction history for this address.
|
|
913
|
+
*
|
|
914
|
+
* @returns Parsed transaction history entries.
|
|
915
|
+
*/
|
|
916
|
+
async getTransactionHistory(): Promise<EVMTransactionHistoryItem[]> {
|
|
917
|
+
return await getEvmTransactionHistorySafe(this.connection!, this.address);
|
|
918
|
+
}
|
|
919
|
+
|
|
920
|
+
/**
|
|
921
|
+
* Fetch price data for the provided token addresses.
|
|
922
|
+
*
|
|
923
|
+
* @param tokenAddresses - Token contract addresses.
|
|
924
|
+
* @returns Price response.
|
|
925
|
+
*/
|
|
926
|
+
async getPrices(tokenAddresses: string[]): Promise<PriceResponse> {
|
|
927
|
+
return await getSvmPricesForTokens(this.config, tokenAddresses);
|
|
928
|
+
}
|
|
929
|
+
|
|
930
|
+
|
|
931
|
+
}
|
|
932
|
+
|
|
933
|
+
|
|
691
934
|
export class EVMChainWallet extends ChainWallet<string, string, PublicClient> {
|
|
692
935
|
wallet: WalletClient
|
|
693
936
|
private smartWallet?: EVMSmartWallet
|
|
694
937
|
// private savingsManager?: SavingsManager
|
|
695
938
|
// private smartSavingsManager?: SmartSavingsManager
|
|
696
939
|
|
|
940
|
+
/**
|
|
941
|
+
* Create an EVM wallet bound to a chain configuration and private key.
|
|
942
|
+
*
|
|
943
|
+
* @param config - Chain configuration.
|
|
944
|
+
* @param privateKey - Hex private key (with or without `0x` prefix).
|
|
945
|
+
* @param index - Wallet index.
|
|
946
|
+
*/
|
|
697
947
|
constructor(config: ChainWalletConfig, privateKey: string, index: number) {
|
|
698
948
|
privateKey = privateKey.startsWith('0x') ? privateKey : `0x${privateKey}`
|
|
699
|
-
|
|
700
|
-
this.connection = createPublicClient(
|
|
701
|
-
{
|
|
702
|
-
chain: fromChainToViemChain(config),
|
|
703
|
-
transport: http(config.rpcUrl)
|
|
704
|
-
},
|
|
705
|
-
)
|
|
949
|
+
const connection = createEvmPublicClient(config);
|
|
706
950
|
const account = privateKeyToAccount(privateKey as Hex)
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
this.address = account.address
|
|
951
|
+
const wallet = createEvmWalletClient(config, account);
|
|
952
|
+
const address = account.address
|
|
953
|
+
super(config, address, privateKey, index);
|
|
954
|
+
|
|
955
|
+
|
|
713
956
|
this.privateKey = privateKey;
|
|
957
|
+
this.wallet = wallet;
|
|
958
|
+
this.connection = connection;
|
|
959
|
+
this.address = address
|
|
714
960
|
}
|
|
715
961
|
|
|
716
962
|
// ============================================
|
|
@@ -725,6 +971,12 @@ export class EVMChainWallet extends ChainWallet<string, string, PublicClient> {
|
|
|
725
971
|
return this.config.aaSupport?.enabled === true;
|
|
726
972
|
}
|
|
727
973
|
|
|
974
|
+
/**
|
|
975
|
+
* Convert entropy text into a hex string.
|
|
976
|
+
*
|
|
977
|
+
* @param entropy - Entropy string.
|
|
978
|
+
* @returns Hex-encoded string.
|
|
979
|
+
*/
|
|
728
980
|
convertFromEntropyToPrivateKey = (entropy: string): string => {
|
|
729
981
|
return toHex(entropy)
|
|
730
982
|
}
|
|
@@ -878,73 +1130,132 @@ export class EVMChainWallet extends ChainWallet<string, string, PublicClient> {
|
|
|
878
1130
|
// Existing Wallet Methods
|
|
879
1131
|
// ============================================
|
|
880
1132
|
|
|
1133
|
+
/**
|
|
1134
|
+
* Get the underlying viem wallet client.
|
|
1135
|
+
*
|
|
1136
|
+
* @returns Wallet client instance.
|
|
1137
|
+
*/
|
|
881
1138
|
getWallet(): WalletClient {
|
|
882
1139
|
return this.wallet
|
|
883
1140
|
}
|
|
884
1141
|
|
|
1142
|
+
/**
|
|
1143
|
+
* Get this wallet's address.
|
|
1144
|
+
*
|
|
1145
|
+
* @returns Wallet address.
|
|
1146
|
+
*/
|
|
885
1147
|
generateAddress(): string {
|
|
886
1148
|
return this.address;
|
|
887
1149
|
}
|
|
888
1150
|
|
|
1151
|
+
/**
|
|
1152
|
+
* Get native token balance for this wallet.
|
|
1153
|
+
*
|
|
1154
|
+
* @returns Native balance details.
|
|
1155
|
+
*/
|
|
889
1156
|
async getNativeBalance(): Promise<Balance> {
|
|
890
1157
|
// Implement native balance retrieval logic here
|
|
891
|
-
return await
|
|
1158
|
+
return await getEvmNativeBalance(this.address, this.connection!);
|
|
892
1159
|
}
|
|
893
1160
|
|
|
1161
|
+
/**
|
|
1162
|
+
* Get ERC-20 token balance for this wallet.
|
|
1163
|
+
*
|
|
1164
|
+
* @param tokenAddress - ERC-20 contract address.
|
|
1165
|
+
* @returns Token balance details.
|
|
1166
|
+
*/
|
|
894
1167
|
async getTokenBalance(tokenAddress: string): Promise<Balance> {
|
|
895
1168
|
// Implement token balance retrieval logic here
|
|
896
|
-
return await
|
|
1169
|
+
return await getEvmTokenBalance(this.address, tokenAddress, this.connection!);
|
|
897
1170
|
}
|
|
898
1171
|
|
|
1172
|
+
/**
|
|
1173
|
+
* Get ERC-20 token metadata.
|
|
1174
|
+
*
|
|
1175
|
+
* @param tokenAddress - ERC-20 contract address.
|
|
1176
|
+
* @returns Token metadata returned by `getTokenInfo`.
|
|
1177
|
+
*/
|
|
899
1178
|
async getTokenInfo(tokenAddress: string) {
|
|
900
1179
|
return await EVMVM.getTokenInfo(tokenAddress as Hex, this.connection!)
|
|
901
1180
|
}
|
|
902
1181
|
|
|
1182
|
+
/**
|
|
1183
|
+
* Discover fungible tokens held by this wallet.
|
|
1184
|
+
*
|
|
1185
|
+
* @returns Discovered token balances.
|
|
1186
|
+
*/
|
|
903
1187
|
async discoverToken(): Promise<UserTokenBalance<string>[]> {
|
|
904
1188
|
// Implement token discovery logic here
|
|
905
|
-
return await
|
|
1189
|
+
return await discoverEvmTokens(this.address, this.config);
|
|
906
1190
|
}
|
|
907
1191
|
|
|
1192
|
+
/**
|
|
1193
|
+
* Discover NFTs held by this wallet.
|
|
1194
|
+
*
|
|
1195
|
+
* @returns Discovered NFTs.
|
|
1196
|
+
*/
|
|
908
1197
|
async discoverNFT(): Promise<NFT[]> {
|
|
909
1198
|
// Implement NFT discovery logic here
|
|
910
|
-
return await
|
|
1199
|
+
return await discoverEvmNFTs(this.address, this.config);
|
|
911
1200
|
}
|
|
912
1201
|
|
|
1202
|
+
/**
|
|
1203
|
+
* Send native tokens to another address.
|
|
1204
|
+
*
|
|
1205
|
+
* @param to - Recipient address.
|
|
1206
|
+
* @param amount - Amount in native token units.
|
|
1207
|
+
* @returns Transaction result.
|
|
1208
|
+
*/
|
|
913
1209
|
async transferNative(to: string, amount: number): Promise<TransactionResult> {
|
|
914
1210
|
const wallet = this.getWallet();
|
|
915
1211
|
return await sendNativeToken(wallet, this.connection!, to as Hex, amount.toString(), this.config.confirmationNo || 5);
|
|
916
1212
|
}
|
|
917
1213
|
|
|
1214
|
+
/**
|
|
1215
|
+
* Send ERC-20 tokens to another address.
|
|
1216
|
+
*
|
|
1217
|
+
* @param tokenAddress - Token info containing contract address.
|
|
1218
|
+
* @param to - Recipient address.
|
|
1219
|
+
* @param amount - Token amount to transfer.
|
|
1220
|
+
* @returns Transaction result.
|
|
1221
|
+
*/
|
|
918
1222
|
async transferToken(tokenAddress: TokenInfo, to: string, amount: number): Promise<TransactionResult> {
|
|
919
1223
|
const wallet = this.getWallet();
|
|
920
1224
|
return await sendERC20Token(wallet, this.connection!, tokenAddress.address as Hex, to as Hex, BigInt(amount.toString()), this.config.confirmationNo || 5);
|
|
921
1225
|
}
|
|
922
1226
|
|
|
1227
|
+
/**
|
|
1228
|
+
* Get transaction history for this wallet address.
|
|
1229
|
+
*
|
|
1230
|
+
* @returns Parsed transaction history entries.
|
|
1231
|
+
*/
|
|
923
1232
|
async getTransactionHistory(): Promise<EVMTransactionHistoryItem[]> {
|
|
924
1233
|
const wallet = this.getWallet();
|
|
925
1234
|
let res: EVMTransactionHistoryItem
|
|
926
|
-
|
|
927
|
-
return await getEVMTransactionHistory(this.connection!, this.address as Hex);
|
|
928
|
-
} catch (error) {
|
|
929
|
-
return []
|
|
930
|
-
}
|
|
1235
|
+
return await getEvmTransactionHistorySafe(this.connection!, this.address);
|
|
931
1236
|
}
|
|
932
1237
|
|
|
1238
|
+
/**
|
|
1239
|
+
* Fetch prices for token contracts on this wallet's chain.
|
|
1240
|
+
*
|
|
1241
|
+
* @param tokenAddresses - Token contract addresses.
|
|
1242
|
+
* @returns Price response.
|
|
1243
|
+
*/
|
|
933
1244
|
async getPrices(tokenAddresses: string[]): Promise<PriceResponse> {
|
|
934
|
-
|
|
935
|
-
vm: 'EVM',
|
|
936
|
-
chainId: this.config.chainId,
|
|
937
|
-
tokenAddresses,
|
|
938
|
-
});
|
|
939
|
-
|
|
940
|
-
if (result.error) {
|
|
941
|
-
throw new Error(result.error.message);
|
|
942
|
-
}
|
|
943
|
-
|
|
944
|
-
return result.data as PriceResponse;
|
|
1245
|
+
return await getSvmPricesForTokens(this.config, tokenAddresses);
|
|
945
1246
|
}
|
|
946
1247
|
|
|
947
1248
|
// Updated swap method signature to match base class so created another method to use it inside swap
|
|
1249
|
+
/**
|
|
1250
|
+
* Swap tokens using the chain's swap integration.
|
|
1251
|
+
*
|
|
1252
|
+
* @param tokenAddress - Source token info.
|
|
1253
|
+
* @param to - Destination token or recipient address, depending on integration.
|
|
1254
|
+
* @param amount - Amount to swap.
|
|
1255
|
+
* @param slippage - Slippage tolerance in basis points.
|
|
1256
|
+
* @returns Transaction result.
|
|
1257
|
+
* @throws Error Always throws because this method is not implemented.
|
|
1258
|
+
*/
|
|
948
1259
|
async swap(
|
|
949
1260
|
tokenAddress: TokenInfo,
|
|
950
1261
|
to: string,
|
|
@@ -959,6 +1270,12 @@ export class EVMChainWallet extends ChainWallet<string, string, PublicClient> {
|
|
|
959
1270
|
|
|
960
1271
|
|
|
961
1272
|
// Helper method for EVMChainWallet class
|
|
1273
|
+
/**
|
|
1274
|
+
* Build a standardized failed swap result.
|
|
1275
|
+
*
|
|
1276
|
+
* @param message - Failure reason.
|
|
1277
|
+
* @returns Failed Debonk swap result.
|
|
1278
|
+
*/
|
|
962
1279
|
private fail(message: string): DebonkSwapResult {
|
|
963
1280
|
return {
|
|
964
1281
|
success: false,
|
|
@@ -971,6 +1288,17 @@ export class EVMChainWallet extends ChainWallet<string, string, PublicClient> {
|
|
|
971
1288
|
|
|
972
1289
|
|
|
973
1290
|
|
|
1291
|
+
/**
|
|
1292
|
+
* Approve ERC-20 token allowance for a spender.
|
|
1293
|
+
*
|
|
1294
|
+
* @param params - Approval parameters.
|
|
1295
|
+
* @param params.tokenAddress - ERC-20 contract address.
|
|
1296
|
+
* @param params.spender - Spender address to approve.
|
|
1297
|
+
* @param params.amountRaw - Raw allowance amount.
|
|
1298
|
+
* @param params.confirmations - Confirmation blocks to wait for.
|
|
1299
|
+
* @param params.gasLimit - Optional gas limit (currently unused in this wrapper).
|
|
1300
|
+
* @returns Transaction result.
|
|
1301
|
+
*/
|
|
974
1302
|
async approveToken(params: {
|
|
975
1303
|
tokenAddress: string
|
|
976
1304
|
spender: string
|
|
@@ -997,6 +1325,13 @@ export class EVMChainWallet extends ChainWallet<string, string, PublicClient> {
|
|
|
997
1325
|
|
|
998
1326
|
|
|
999
1327
|
|
|
1328
|
+
/**
|
|
1329
|
+
* Sign an arbitrary message with this wallet account.
|
|
1330
|
+
*
|
|
1331
|
+
* @param message - Message to sign.
|
|
1332
|
+
* @returns Hex signature string.
|
|
1333
|
+
* @throws Error if wallet account is unavailable.
|
|
1334
|
+
*/
|
|
1000
1335
|
async signMessage(message: string): Promise<string> {
|
|
1001
1336
|
|
|
1002
1337
|
const signer = this.wallet
|
|
@@ -1007,260 +1342,4 @@ export class EVMChainWallet extends ChainWallet<string, string, PublicClient> {
|
|
|
1007
1342
|
return signer.signMessage({ message, account: signer.account?.address })
|
|
1008
1343
|
}
|
|
1009
1344
|
|
|
1010
|
-
// // ============================================
|
|
1011
|
-
// // Savings Pocket Methods
|
|
1012
|
-
// // ============================================
|
|
1013
|
-
|
|
1014
|
-
// /**
|
|
1015
|
-
// * Get or create the SavingsManager instance (lazy initialization)
|
|
1016
|
-
// * @private
|
|
1017
|
-
// */
|
|
1018
|
-
// private getSavingsManager(): SavingsManager {
|
|
1019
|
-
// if (!this.savingsManager) {
|
|
1020
|
-
// // Create a VM instance from the current wallet's seed
|
|
1021
|
-
// // We need to get the seed from the privateKey
|
|
1022
|
-
// // For now, we'll create an EVMVM from the wallet
|
|
1023
|
-
// // Note: This requires access to the seed, which we'll need to handle
|
|
1024
|
-
// throw new Error(
|
|
1025
|
-
// "SavingsManager requires access to the seed phrase. " +
|
|
1026
|
-
// "Please initialize the wallet with a seed phrase or mnemonic to use savings features."
|
|
1027
|
-
// );
|
|
1028
|
-
// }
|
|
1029
|
-
// return this.savingsManager;
|
|
1030
|
-
// }
|
|
1031
|
-
|
|
1032
|
-
// /**
|
|
1033
|
-
// * Initialize savings functionality with a seed phrase
|
|
1034
|
-
// *
|
|
1035
|
-
// * This must be called before using any savings methods.
|
|
1036
|
-
// * The seed is used to derive savings accounts using BIP-44.
|
|
1037
|
-
// *
|
|
1038
|
-
// * @param seed - The wallet seed (hex string)
|
|
1039
|
-
// *
|
|
1040
|
-
// * @example
|
|
1041
|
-
// * const seed = VM.mnemonicToSeed(mnemonic);
|
|
1042
|
-
// * wallet.initializeSavings(seed);
|
|
1043
|
-
// */
|
|
1044
|
-
// initializeSavings(seed: string): void {
|
|
1045
|
-
// const vm = new EVMVM(seed);
|
|
1046
|
-
// this.savingsManager = new SavingsManager(vm);
|
|
1047
|
-
// }
|
|
1048
|
-
|
|
1049
|
-
// /**
|
|
1050
|
-
// * Derive a new savings account from BIP-44 account index
|
|
1051
|
-
// *
|
|
1052
|
-
// * @param accountIndex - The BIP-44 account index (1+ for savings, 0 is main wallet)
|
|
1053
|
-
// * @returns SavingsAccount with derived address and private key
|
|
1054
|
-
// *
|
|
1055
|
-
// * @example
|
|
1056
|
-
// * const savingsAccount1 = wallet.deriveSavingsAccount(1); // m/44'/60'/1'/0/0
|
|
1057
|
-
// * const savingsAccount2 = wallet.deriveSavingsAccount(2); // m/44'/60'/2'/0/0
|
|
1058
|
-
// */
|
|
1059
|
-
// deriveSavingsAccount(accountIndex: number): SavingsAccount {
|
|
1060
|
-
// return this.getSavingsManager().createSavingsAccount(accountIndex);
|
|
1061
|
-
// }
|
|
1062
|
-
|
|
1063
|
-
// /**
|
|
1064
|
-
// * Transfer native tokens to a savings account
|
|
1065
|
-
// *
|
|
1066
|
-
// * Security: Always derives the destination address from accountIndex.
|
|
1067
|
-
// *
|
|
1068
|
-
// * @param accountIndex - Savings account index to deposit to
|
|
1069
|
-
// * @param amount - Amount in ether units (e.g., "1.5" for 1.5 ETH)
|
|
1070
|
-
// * @param options - Optional security and priority settings
|
|
1071
|
-
// * @returns Transaction result
|
|
1072
|
-
// *
|
|
1073
|
-
// * @example
|
|
1074
|
-
// * const result = await wallet.transferToSavings(1, "1.5"); // Send 1.5 ETH to savings account 1
|
|
1075
|
-
// */
|
|
1076
|
-
// async transferToSavings(
|
|
1077
|
-
// accountIndex: number,
|
|
1078
|
-
// amount: string,
|
|
1079
|
-
// options?: TransferToSavingsOptions
|
|
1080
|
-
// ): Promise<TransactionResult> {
|
|
1081
|
-
// const manager = this.getSavingsManager();
|
|
1082
|
-
|
|
1083
|
-
// // Build transaction using derived address
|
|
1084
|
-
// const amountWei = parseEther(amount);
|
|
1085
|
-
// const txParams = manager.buildDepositTransaction(accountIndex, amountWei, options);
|
|
1086
|
-
|
|
1087
|
-
// // Execute using existing transferNative method
|
|
1088
|
-
// return await this.transferNative(txParams.to, Number(amount));
|
|
1089
|
-
// }
|
|
1090
|
-
|
|
1091
|
-
// // /**
|
|
1092
|
-
// // * Withdraw native tokens from a savings account
|
|
1093
|
-
// // *
|
|
1094
|
-
// // * Security: Uses the derived private key for signing.
|
|
1095
|
-
// // *
|
|
1096
|
-
// // * @param accountIndex - Savings account index to withdraw from
|
|
1097
|
-
// // * @param to - Destination address
|
|
1098
|
-
// // * @param amount - Amount in ether units (e.g., "0.5" for 0.5 ETH)
|
|
1099
|
-
// // * @param options - Optional security and priority settings
|
|
1100
|
-
// // * @returns Transaction result
|
|
1101
|
-
// // *
|
|
1102
|
-
// // * @example
|
|
1103
|
-
// // * const result = await wallet.withdrawFromSavings(1, destinationAddress, "0.5");
|
|
1104
|
-
// // */
|
|
1105
|
-
// // async withdrawFromSavings(
|
|
1106
|
-
// // accountIndex: number,
|
|
1107
|
-
// // to: string,
|
|
1108
|
-
// // amount: string,
|
|
1109
|
-
// // options?: WithdrawFromSavingsOptions
|
|
1110
|
-
// // ): Promise<TransactionResult> {
|
|
1111
|
-
// // const manager = this.getSavingsManager();
|
|
1112
|
-
|
|
1113
|
-
// // // Build withdrawal transaction
|
|
1114
|
-
// // const amountWei = parseEther(amount);
|
|
1115
|
-
// // const withdrawalParams = manager.buildWithdrawalTransaction(
|
|
1116
|
-
// // accountIndex,
|
|
1117
|
-
// // to as Hex,
|
|
1118
|
-
// // amountWei,
|
|
1119
|
-
// // options
|
|
1120
|
-
// // );
|
|
1121
|
-
|
|
1122
|
-
// // // Create a temporary wallet with the savings account private key
|
|
1123
|
-
// // const savingsWallet = new Wallet(withdrawalParams.privateKey, this.connection);
|
|
1124
|
-
|
|
1125
|
-
// // // Send transaction using the savings wallet
|
|
1126
|
-
// // const tx = await savingsWallet.sendTransaction({
|
|
1127
|
-
// // to: withdrawalParams.to,
|
|
1128
|
-
// // value: withdrawalParams.value
|
|
1129
|
-
// // });
|
|
1130
|
-
|
|
1131
|
-
// // const receipt = await tx.wait(this.config.confirmationNo || 1);
|
|
1132
|
-
|
|
1133
|
-
// // return {
|
|
1134
|
-
// // success: receipt?.status === 1,
|
|
1135
|
-
// // hash: receipt?.hash || tx.hash
|
|
1136
|
-
// // };
|
|
1137
|
-
// // }
|
|
1138
|
-
|
|
1139
|
-
// /**
|
|
1140
|
-
// * Verify a stored savings address matches the derived address
|
|
1141
|
-
// *
|
|
1142
|
-
// * Security: Prevents database tampering attacks.
|
|
1143
|
-
// *
|
|
1144
|
-
// * @param accountIndex - The account index to verify
|
|
1145
|
-
// * @param storedAddress - The address from storage/database
|
|
1146
|
-
// * @returns Verification result
|
|
1147
|
-
// *
|
|
1148
|
-
// * @example
|
|
1149
|
-
// * const result = wallet.verifySavingsAddress(1, storedAddress);
|
|
1150
|
-
// * if (!result.isValid) {
|
|
1151
|
-
// * console.error("Security alert: Address tampering detected!");
|
|
1152
|
-
// * }
|
|
1153
|
-
// */
|
|
1154
|
-
// verifySavingsAddress(accountIndex: number, storedAddress: Hex): AddressVerificationResult {
|
|
1155
|
-
// return this.getSavingsManager().verifySavingsAddress(accountIndex, storedAddress);
|
|
1156
|
-
// }
|
|
1157
|
-
|
|
1158
|
-
// /**
|
|
1159
|
-
// * Audit multiple savings addresses at once
|
|
1160
|
-
// *
|
|
1161
|
-
// * @param addresses - Map of accountIndex to stored address
|
|
1162
|
-
// * @returns Audit result with summary and details
|
|
1163
|
-
// *
|
|
1164
|
-
// * @example
|
|
1165
|
-
// * const addresses = new Map([[1, "0xabc..."], [2, "0xdef..."]]);
|
|
1166
|
-
// * const audit = wallet.auditSavingsAddresses(addresses);
|
|
1167
|
-
// * console.log(`Valid: ${audit.valid}/${audit.total}`);
|
|
1168
|
-
// */
|
|
1169
|
-
// auditSavingsAddresses(addresses: Map<number, Hex>): SavingsAuditResult {
|
|
1170
|
-
// return this.getSavingsManager().auditSavingsAddresses(addresses);
|
|
1171
|
-
// }
|
|
1172
|
-
|
|
1173
|
-
// /**
|
|
1174
|
-
// * Get savings account information without exposing private key
|
|
1175
|
-
// *
|
|
1176
|
-
// * @param accountIndex - The account index
|
|
1177
|
-
// * @returns Public account information (address and derivation path)
|
|
1178
|
-
// *
|
|
1179
|
-
// * @example
|
|
1180
|
-
// * const info = wallet.getSavingsAccountInfo(1);
|
|
1181
|
-
// * console.log(`Address: ${info.address}`);
|
|
1182
|
-
// * console.log(`Path: ${info.derivationPath}`); // m/44'/60'/1'/0/0
|
|
1183
|
-
// */
|
|
1184
|
-
// getSavingsAccountInfo(accountIndex: number): Omit<SavingsAccount, 'privateKey'> {
|
|
1185
|
-
// return this.getSavingsManager().getSavingsAccountInfo(accountIndex);
|
|
1186
|
-
// }
|
|
1187
|
-
|
|
1188
|
-
// // ============================================
|
|
1189
|
-
// // Smart Savings Methods (EIP-7702)
|
|
1190
|
-
// // ============================================
|
|
1191
|
-
|
|
1192
|
-
// /**
|
|
1193
|
-
// * Get or create the SmartSavingsManager instance (lazy initialization)
|
|
1194
|
-
// * @private
|
|
1195
|
-
// */
|
|
1196
|
-
// private getSmartSavingsManager(): SmartSavingsManager {
|
|
1197
|
-
// if (!this.smartSavingsManager) {
|
|
1198
|
-
// this.smartSavingsManager = new SmartSavingsManager(this.config);
|
|
1199
|
-
// }
|
|
1200
|
-
// return this.smartSavingsManager;
|
|
1201
|
-
// }
|
|
1202
|
-
|
|
1203
|
-
// /**
|
|
1204
|
-
// * Upgrade a savings account to a smart account with EIP-7702 delegation
|
|
1205
|
-
// *
|
|
1206
|
-
// * This enables advanced features:
|
|
1207
|
-
// * - Lock modules for time-locked savings
|
|
1208
|
-
// * - Hooks for spend & save
|
|
1209
|
-
// * - Session keys for periodic savings
|
|
1210
|
-
// * - Sponsored transactions via paymaster
|
|
1211
|
-
// *
|
|
1212
|
-
// * @param accountIndex - The savings account index to upgrade
|
|
1213
|
-
// * @param options - Optional smart wallet configuration
|
|
1214
|
-
// * @param autoInitialize - Whether to initialize the smart wallet (default: false)
|
|
1215
|
-
// * @returns SmartSavingsAccount with EVMSmartWallet instance
|
|
1216
|
-
// *
|
|
1217
|
-
// * @example
|
|
1218
|
-
// * // Upgrade without initialization
|
|
1219
|
-
// * const smartSavings = await wallet.upgradeSavingsToSmartAccount(1);
|
|
1220
|
-
// * await smartSavings.smartWallet.initialize(); // Initialize separately
|
|
1221
|
-
// *
|
|
1222
|
-
// * @example
|
|
1223
|
-
// * // Upgrade and initialize in one step
|
|
1224
|
-
// * const smartSavings = await wallet.upgradeSavingsToSmartAccount(1, {}, true);
|
|
1225
|
-
// * // Ready to use immediately
|
|
1226
|
-
// */
|
|
1227
|
-
// async upgradeSavingsToSmartAccount(
|
|
1228
|
-
// accountIndex: number,
|
|
1229
|
-
// options?: SmartWalletOptions,
|
|
1230
|
-
// autoInitialize: boolean = false
|
|
1231
|
-
// ): Promise<SmartSavingsAccount> {
|
|
1232
|
-
// const manager = this.getSmartSavingsManager();
|
|
1233
|
-
|
|
1234
|
-
// // First derive the basic savings account
|
|
1235
|
-
// const basicSavings = this.deriveSavingsAccount(accountIndex);
|
|
1236
|
-
|
|
1237
|
-
// // Then upgrade to smart account
|
|
1238
|
-
// if (autoInitialize) {
|
|
1239
|
-
// return await manager.upgradeSavingsAndInitialize(basicSavings, options);
|
|
1240
|
-
// } else {
|
|
1241
|
-
// return await manager.upgradeSavingsToSmartAccount(basicSavings, options);
|
|
1242
|
-
// }
|
|
1243
|
-
// }
|
|
1244
|
-
|
|
1245
|
-
// /**
|
|
1246
|
-
// * Check if smart savings is supported on this chain
|
|
1247
|
-
// *
|
|
1248
|
-
// * @returns true if chain supports Account Abstraction
|
|
1249
|
-
// *
|
|
1250
|
-
// * @example
|
|
1251
|
-
// * if (wallet.isSmartSavingsSupported()) {
|
|
1252
|
-
// * const smartSavings = await wallet.upgradeSavingsToSmartAccount(1);
|
|
1253
|
-
// * } else {
|
|
1254
|
-
// * console.log("This chain doesn't support smart savings");
|
|
1255
|
-
// * }
|
|
1256
|
-
// */
|
|
1257
|
-
// isSmartSavingsSupported(): boolean {
|
|
1258
|
-
// try {
|
|
1259
|
-
// const manager = this.getSmartSavingsManager();
|
|
1260
|
-
// return manager.canUpgradeToSmartAccount();
|
|
1261
|
-
// } catch (error) {
|
|
1262
|
-
// return false;
|
|
1263
|
-
// }
|
|
1264
|
-
// }
|
|
1265
1345
|
}
|
|
1266
|
-
|