@deserialize/multi-vm-wallet 1.3.0 → 1.3.2
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/.claude/settings.local.json +8 -1
- package/dist/IChainWallet.d.ts +3 -3
- package/dist/evm/aa-service/index.d.ts +1 -1
- package/dist/evm/aa-service/index.js +1 -2
- package/dist/evm/aa-service/index.js.map +1 -1
- package/dist/evm/aa-service/lib/kernel-account.d.ts +1 -43
- package/dist/evm/aa-service/lib/kernel-account.js +21 -88
- package/dist/evm/aa-service/lib/kernel-account.js.map +1 -1
- package/dist/evm/aa-service/lib/type.d.ts +16 -0
- package/dist/evm/aa-service/lib/type.js.map +1 -1
- package/dist/evm/aa-service/services/account-abstraction.d.ts +4 -0
- package/dist/evm/aa-service/services/account-abstraction.js +12 -4
- package/dist/evm/aa-service/services/account-abstraction.js.map +1 -1
- package/dist/evm/aa-service/services/bundler.d.ts +4 -1
- package/dist/evm/aa-service/services/bundler.js +40 -7
- package/dist/evm/aa-service/services/bundler.js.map +1 -1
- package/dist/evm/evm.d.ts +3 -13
- package/dist/evm/evm.js +12 -80
- package/dist/evm/evm.js.map +1 -1
- package/dist/evm/smartWallet.d.ts +2 -19
- package/dist/evm/smartWallet.js +8 -68
- package/dist/evm/smartWallet.js.map +1 -1
- package/dist/evm/utils.js +2 -1
- package/dist/evm/utils.js.map +1 -1
- package/dist/helpers/index.d.ts +6 -1
- package/dist/helpers/index.js +116 -0
- package/dist/helpers/index.js.map +1 -1
- package/dist/svm/svm.d.ts +3 -3
- package/dist/svm/svm.js +6 -17
- package/dist/svm/svm.js.map +1 -1
- package/dist/svm/utils.d.ts +2 -2
- package/dist/svm/utils.js +4 -4
- package/dist/svm/utils.js.map +1 -1
- package/dist/test.d.ts +4 -0
- package/dist/test.js +66 -21
- package/dist/test.js.map +1 -1
- package/dist/types.d.ts +14 -16
- package/dist/types.js.map +1 -1
- package/package.json +7 -1
- package/utils/IChainWallet.ts +3 -3
- package/utils/evm/aa-service/index.ts +1 -2
- package/utils/evm/aa-service/lib/kernel-account.ts +22 -128
- package/utils/evm/aa-service/lib/type.ts +17 -0
- package/utils/evm/aa-service/services/account-abstraction.ts +18 -4
- package/utils/evm/aa-service/services/bundler.ts +53 -11
- package/utils/evm/evm.ts +13 -110
- package/utils/evm/smartWallet.ts +10 -88
- package/utils/evm/utils.ts +2 -1
- package/utils/helpers/index.ts +138 -1
- package/utils/svm/svm.ts +7 -25
- package/utils/svm/utils.ts +4 -10
- package/utils/test.ts +85 -21
- package/utils/types.ts +15 -17
- package/utils/evm/SMART_WALLET_EXAMPLES.ts.bak +0 -591
package/utils/evm/smartWallet.ts
CHANGED
|
@@ -33,8 +33,7 @@ import {
|
|
|
33
33
|
// Import AA service from local aa-service
|
|
34
34
|
import { AccountAbstractionService } from "./aa-service/services/account-abstraction";
|
|
35
35
|
import {
|
|
36
|
-
createKernelAuthorization
|
|
37
|
-
sendSponsoredBatchTransaction
|
|
36
|
+
createKernelAuthorization
|
|
38
37
|
} from "./aa-service/lib/kernel-account";
|
|
39
38
|
import type {
|
|
40
39
|
KernelAccountInstance,
|
|
@@ -62,17 +61,14 @@ export class EVMSmartWallet {
|
|
|
62
61
|
private options: SmartWalletOptions;
|
|
63
62
|
private sessionAccount: any = null;
|
|
64
63
|
private paymasterConfig: PaymasterConfig | null = null;
|
|
65
|
-
private bundlerUrl: string;
|
|
66
64
|
|
|
67
65
|
constructor(
|
|
68
66
|
privateKey: string,
|
|
69
67
|
chain: Chain,
|
|
70
|
-
bundlerUrl: string,
|
|
71
68
|
options: SmartWalletOptions = {}
|
|
72
69
|
) {
|
|
73
70
|
this.ownerAccount = privateKeyToAccount(privateKey as Hex);
|
|
74
71
|
this.chain = chain;
|
|
75
|
-
this.bundlerUrl = bundlerUrl;
|
|
76
72
|
this.options = {
|
|
77
73
|
entryPointVersion: '0.7',
|
|
78
74
|
autoInitialize: true,
|
|
@@ -95,22 +91,26 @@ export class EVMSmartWallet {
|
|
|
95
91
|
* Initialize the smart wallet
|
|
96
92
|
* Creates the Kernel account and sets up delegation if needed
|
|
97
93
|
*/
|
|
98
|
-
async initialize(): Promise<
|
|
94
|
+
async initialize(): Promise<EVMSmartWallet> {
|
|
99
95
|
try {
|
|
100
|
-
// Initialize AA service singleton with
|
|
96
|
+
// Initialize AA service singleton with AA config
|
|
101
97
|
this.aaService = AccountAbstractionService.getInstance({
|
|
102
98
|
bundlerProvider: 'custom',
|
|
103
|
-
customBundlerUrl: this.bundlerUrl
|
|
99
|
+
customBundlerUrl: this.options.bundlerUrl!,
|
|
100
|
+
aaConfig: this.options.aaConfig
|
|
104
101
|
});
|
|
105
102
|
|
|
106
103
|
// Create Kernel account
|
|
107
104
|
this.kernelAccount = await this.aaService.createAccount({
|
|
108
105
|
chain: this.chain,
|
|
109
106
|
owner: this.ownerAccount,
|
|
110
|
-
entryPointVersion: this.options.entryPointVersion
|
|
107
|
+
entryPointVersion: this.options.entryPointVersion,
|
|
108
|
+
aaConfig: this.options.aaConfig
|
|
111
109
|
});
|
|
112
110
|
|
|
113
111
|
console.log(`Smart wallet initialized: ${this.kernelAccount.address}`);
|
|
112
|
+
|
|
113
|
+
return this
|
|
114
114
|
} catch (error) {
|
|
115
115
|
throw new SmartWalletError(
|
|
116
116
|
`Failed to initialize smart wallet: ${error instanceof Error ? error.message : 'Unknown error'}`,
|
|
@@ -700,90 +700,12 @@ export class EVMSmartWallet {
|
|
|
700
700
|
if (!this.aaService) {
|
|
701
701
|
return {
|
|
702
702
|
provider: 'custom',
|
|
703
|
-
url: this.bundlerUrl
|
|
703
|
+
url: this.options.bundlerUrl || ''
|
|
704
704
|
};
|
|
705
705
|
}
|
|
706
706
|
return this.aaService.getBundlerInfo(this.chain);
|
|
707
707
|
}
|
|
708
708
|
|
|
709
|
-
// ============================================
|
|
710
|
-
// Sponsored Transactions (EIP-7702)
|
|
711
|
-
// ============================================
|
|
712
|
-
|
|
713
|
-
/**
|
|
714
|
-
* Send sponsored batch transaction where another wallet pays gas fees
|
|
715
|
-
* Requires smart wallet to be initialized
|
|
716
|
-
*
|
|
717
|
-
* @param calls - Array of calls to execute
|
|
718
|
-
* @param feePayerPrivateKey - Private key of the wallet paying gas fees
|
|
719
|
-
* @returns Transaction result with userOpHash and transactionHash
|
|
720
|
-
*
|
|
721
|
-
* @example
|
|
722
|
-
* // Send ETH transfer with sponsor paying gas
|
|
723
|
-
* const result = await smartWallet.sendSponsoredBatchTransaction(
|
|
724
|
-
* [{ to: recipient, value: parseEther('0.1') }],
|
|
725
|
-
* sponsorPrivateKey
|
|
726
|
-
* );
|
|
727
|
-
*/
|
|
728
|
-
async sendSponsoredBatchTransaction(
|
|
729
|
-
calls: Call[],
|
|
730
|
-
feePayerPrivateKey: Hex
|
|
731
|
-
): Promise<SmartWalletTransactionResult> {
|
|
732
|
-
if (!this.aaService) {
|
|
733
|
-
throw new SmartWalletError(
|
|
734
|
-
'Smart wallet not initialized. Call initialize() first.',
|
|
735
|
-
'NOT_INITIALIZED'
|
|
736
|
-
);
|
|
737
|
-
}
|
|
738
|
-
|
|
739
|
-
if (!this.kernelAccount) {
|
|
740
|
-
throw new SmartWalletError(
|
|
741
|
-
'Kernel account not found. Smart wallet may not be properly initialized.',
|
|
742
|
-
'ACCOUNT_NOT_FOUND'
|
|
743
|
-
);
|
|
744
|
-
}
|
|
745
|
-
|
|
746
|
-
try {
|
|
747
|
-
// Create authorization for owner wallet
|
|
748
|
-
const authorization = await createKernelAuthorization({
|
|
749
|
-
owner: this.ownerAccount,
|
|
750
|
-
chain: this.chain,
|
|
751
|
-
bundlerManager: this.aaService.getBundlerManager(this.chain)
|
|
752
|
-
});
|
|
753
|
-
|
|
754
|
-
if (!authorization) {
|
|
755
|
-
throw new SmartWalletError(
|
|
756
|
-
'Failed to create authorization for sponsored transaction',
|
|
757
|
-
'AUTHORIZATION_FAILED'
|
|
758
|
-
);
|
|
759
|
-
}
|
|
760
|
-
|
|
761
|
-
// Send sponsored transaction with feePayer
|
|
762
|
-
const result = await sendSponsoredBatchTransaction({
|
|
763
|
-
ownerAuthorization: authorization,
|
|
764
|
-
calls,
|
|
765
|
-
feePayerPrivateKey,
|
|
766
|
-
bundlerUrl: this.bundlerUrl,
|
|
767
|
-
paymasterUrl: this.paymasterConfig?.paymasterUrl,
|
|
768
|
-
chain: this.chain,
|
|
769
|
-
entryPointVersion: this.options.entryPointVersion
|
|
770
|
-
});
|
|
771
|
-
|
|
772
|
-
return {
|
|
773
|
-
success: true,
|
|
774
|
-
userOpHash: result.userOpHash,
|
|
775
|
-
transactionHash: result.transactionHash
|
|
776
|
-
};
|
|
777
|
-
} catch (error) {
|
|
778
|
-
console.error('Sponsored batch transaction failed:', error);
|
|
779
|
-
return {
|
|
780
|
-
success: false,
|
|
781
|
-
userOpHash: '0x' as Hex,
|
|
782
|
-
error: error instanceof Error ? error.message : 'Unknown error occurred'
|
|
783
|
-
};
|
|
784
|
-
}
|
|
785
|
-
}
|
|
786
|
-
|
|
787
709
|
/**
|
|
788
710
|
* Clear all caches
|
|
789
711
|
*/
|
package/utils/evm/utils.ts
CHANGED
|
@@ -641,6 +641,7 @@ export const safeApprove = async (
|
|
|
641
641
|
|
|
642
642
|
export const discoverTokens = async (wallet: string, chain: ChainWalletConfig): Promise<UserTokenBalance<string>[]> => {
|
|
643
643
|
const balances = await HelperAPI.getUserToken(wallet, chain.vmType ?? "EVM", chain.chainId)
|
|
644
|
+
console.log('balances: ', JSON.stringify(balances));
|
|
644
645
|
|
|
645
646
|
|
|
646
647
|
const formatBalances: UserTokenBalance<string>[] = balances.data.map((token: any) => {
|
|
@@ -1008,7 +1009,7 @@ export const discoverNFTs = async (wallet: string, chain: ChainWalletConfig): Pr
|
|
|
1008
1009
|
console.log('discoverNFTs: Successfully fetched', response.data.length, 'NFTs');
|
|
1009
1010
|
|
|
1010
1011
|
// Filter out spam NFTs if desired (optional)
|
|
1011
|
-
const evmNfts = response.data.filter(nft => !nft.contract.isSpam);
|
|
1012
|
+
const evmNfts = response.data.filter((nft: any) => !nft.contract.isSpam);
|
|
1012
1013
|
|
|
1013
1014
|
console.log('discoverNFTs: After spam filtering:', evmNfts.length, 'NFTs');
|
|
1014
1015
|
|
package/utils/helpers/index.ts
CHANGED
|
@@ -1,21 +1,158 @@
|
|
|
1
1
|
export * from './routeScan';
|
|
2
2
|
import { vmTypes, EVMNFTResponse } from "../types";
|
|
3
|
+
import { RouteScanAPI } from './routeScan';
|
|
3
4
|
|
|
4
5
|
const BASE_URL = "https://helper.decane.app"
|
|
5
6
|
|
|
6
7
|
export class HelperAPI {
|
|
8
|
+
/**
|
|
9
|
+
* Get network name from chainId for RouteScan API
|
|
10
|
+
* Defaults to 'mainnet' for most chains
|
|
11
|
+
*/
|
|
12
|
+
private static getNetworkFromChainId(chainId: number): string {
|
|
13
|
+
// Map common testnet chain IDs to 'testnet'
|
|
14
|
+
const testnets = [11155111, 80001, 5, 97, 421614, 84532]; // Sepolia, Mumbai, Goerli, BSC Testnet, Arbitrum Sepolia, Base Sepolia
|
|
15
|
+
if (testnets.includes(chainId)) {
|
|
16
|
+
return 'testnet';
|
|
17
|
+
}
|
|
18
|
+
return 'mainnet';
|
|
19
|
+
}
|
|
20
|
+
|
|
7
21
|
static async getUserToken(wallet: string, vm: vmTypes, chainId: number) {
|
|
22
|
+
// Only try RouteScan for EVM chains
|
|
23
|
+
if (vm === 'EVM') {
|
|
24
|
+
try {
|
|
25
|
+
const network = this.getNetworkFromChainId(chainId);
|
|
26
|
+
const routeScanData = await RouteScanAPI.getTokenTransfers(
|
|
27
|
+
network,
|
|
28
|
+
chainId,
|
|
29
|
+
wallet,
|
|
30
|
+
undefined, // contractaddress
|
|
31
|
+
0, // startblock
|
|
32
|
+
99999999, // endblock
|
|
33
|
+
1, // page
|
|
34
|
+
100, // offset - get more results
|
|
35
|
+
'desc' // sort by newest first
|
|
36
|
+
);
|
|
37
|
+
|
|
38
|
+
// If RouteScan succeeds and has valid data, transform to expected format
|
|
39
|
+
if (routeScanData && routeScanData.status === '1' && routeScanData.result) {
|
|
40
|
+
// Group token transfers by contract address to get unique tokens
|
|
41
|
+
const tokenMap = new Map<string, any>();
|
|
42
|
+
|
|
43
|
+
for (const transfer of routeScanData.result) {
|
|
44
|
+
const address = transfer.contractAddress.toLowerCase();
|
|
45
|
+
|
|
46
|
+
if (!tokenMap.has(address)) {
|
|
47
|
+
tokenMap.set(address, {
|
|
48
|
+
contractAddress: transfer.contractAddress,
|
|
49
|
+
name: transfer.tokenName,
|
|
50
|
+
symbol: transfer.tokenSymbol,
|
|
51
|
+
decimals: parseInt(transfer.tokenDecimal) || 0,
|
|
52
|
+
balance: '0', // RouteScan doesn't provide current balance
|
|
53
|
+
logo: undefined
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// Transform to expected format with 'data' field
|
|
59
|
+
return {
|
|
60
|
+
data: Array.from(tokenMap.values())
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
} catch (error) {
|
|
64
|
+
console.warn('RouteScan API failed, falling back to helper.decane.app:', error);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// Fallback to original API
|
|
8
69
|
const res = await fetch("" + BASE_URL + `/${vm}/tokens/discover?wallet=${wallet}&chainId=${chainId}`);
|
|
9
70
|
const data = await res.json();
|
|
10
71
|
return data;
|
|
11
72
|
}
|
|
12
73
|
|
|
13
|
-
static async getUserNFTs(wallet: string, vm: vmTypes, chainId: number): Promise<EVMNFTResponse> {
|
|
74
|
+
static async getUserNFTs(wallet: string, vm: vmTypes, chainId: number): Promise<EVMNFTResponse | any> {
|
|
75
|
+
// Only try RouteScan for EVM chains
|
|
76
|
+
if (vm === 'EVM') {
|
|
77
|
+
try {
|
|
78
|
+
const network = this.getNetworkFromChainId(chainId);
|
|
79
|
+
const routeScanData = await RouteScanAPI.getNftTransfers(
|
|
80
|
+
network,
|
|
81
|
+
chainId,
|
|
82
|
+
wallet,
|
|
83
|
+
undefined, // contractaddress
|
|
84
|
+
0, // startblock
|
|
85
|
+
99999999, // endblock
|
|
86
|
+
1, // page
|
|
87
|
+
100, // offset
|
|
88
|
+
'desc' // sort by newest first
|
|
89
|
+
);
|
|
90
|
+
|
|
91
|
+
// If RouteScan succeeds and has valid data, transform to EVMNFTResponse format
|
|
92
|
+
if (routeScanData && routeScanData.status === '1' && routeScanData.result) {
|
|
93
|
+
// Map RouteScan NFT transfers to EVMNFTResponse format
|
|
94
|
+
const nfts = routeScanData.result.map(nftTx => ({
|
|
95
|
+
contract: {
|
|
96
|
+
address: nftTx.contractAddress,
|
|
97
|
+
name: nftTx.tokenName,
|
|
98
|
+
symbol: nftTx.tokenSymbol,
|
|
99
|
+
totalSupply: '0',
|
|
100
|
+
tokenType: 'ERC721', // Default, RouteScan doesn't specify
|
|
101
|
+
contractDeployer: '',
|
|
102
|
+
deployedBlockNumber: parseInt(nftTx.blockNumber) || 0,
|
|
103
|
+
isSpam: false
|
|
104
|
+
},
|
|
105
|
+
tokenId: nftTx.tokenID,
|
|
106
|
+
tokenType: 'ERC721', // Default
|
|
107
|
+
name: nftTx.tokenName,
|
|
108
|
+
description: '',
|
|
109
|
+
balance: '1', // Default for NFTs
|
|
110
|
+
timeLastUpdated: nftTx.timeStamp,
|
|
111
|
+
acquiredAt: nftTx.timeStamp
|
|
112
|
+
}));
|
|
113
|
+
|
|
114
|
+
return {
|
|
115
|
+
data: nfts
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
} catch (error) {
|
|
119
|
+
console.warn('RouteScan API failed, falling back to helper.decane.app:', error);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// Fallback to original API
|
|
14
124
|
const res = await fetch("" + BASE_URL + `/${vm}/nfts/discover?wallet=${wallet}&chainId=${chainId}`);
|
|
15
125
|
const data = await res.json();
|
|
16
126
|
return data;
|
|
17
127
|
}
|
|
128
|
+
|
|
18
129
|
static async getTransactionHistory(wallet: string, vm: vmTypes, chainId: number, limit: number = 20) {
|
|
130
|
+
// Only try RouteScan for EVM chains
|
|
131
|
+
if (vm === 'EVM') {
|
|
132
|
+
try {
|
|
133
|
+
const network = this.getNetworkFromChainId(chainId);
|
|
134
|
+
const routeScanData = await RouteScanAPI.getTxList(
|
|
135
|
+
network,
|
|
136
|
+
chainId,
|
|
137
|
+
wallet,
|
|
138
|
+
0, // startblock
|
|
139
|
+
99999999, // endblock
|
|
140
|
+
1, // page
|
|
141
|
+
limit, // offset (number of results)
|
|
142
|
+
'desc' // sort by newest first
|
|
143
|
+
);
|
|
144
|
+
|
|
145
|
+
// If RouteScan succeeds and has valid data, transform it to expected format
|
|
146
|
+
// Return RouteScan response as-is - consumer will handle the transformation
|
|
147
|
+
if (routeScanData && routeScanData.status === '1' && routeScanData.result) {
|
|
148
|
+
return routeScanData;
|
|
149
|
+
}
|
|
150
|
+
} catch (error) {
|
|
151
|
+
console.warn('RouteScan API failed, falling back to helper.decane.app:', error);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// Fallback to original API
|
|
19
156
|
const res = await fetch("" + BASE_URL + `/${vm}/transactions/history?wallet=${wallet}&chainId=${chainId}&limit=${limit}`);
|
|
20
157
|
const data = await res.json();
|
|
21
158
|
return data;
|
package/utils/svm/svm.ts
CHANGED
|
@@ -2,7 +2,7 @@ import { Connection, Keypair, PublicKey, Transaction, VersionedTransaction } fro
|
|
|
2
2
|
import { SVMDeriveChildPrivateKey } from "../walletBip32";
|
|
3
3
|
import { VM } from "../vm";
|
|
4
4
|
import { ChainWallet } from "../IChainWallet";
|
|
5
|
-
import { Balance, ChainWalletConfig, UserTokenBalance, TokenInfo, TransactionResult, NFT
|
|
5
|
+
import { Balance, ChainWalletConfig, UserTokenBalance, TokenInfo, TransactionResult, NFT } from "../types";
|
|
6
6
|
import {
|
|
7
7
|
getSvmNativeBalance,
|
|
8
8
|
getTokenBalance,
|
|
@@ -117,56 +117,38 @@ export class SVMChainWallet extends ChainWallet<PublicKey, Keypair, Connection>
|
|
|
117
117
|
return nfts
|
|
118
118
|
}
|
|
119
119
|
|
|
120
|
-
async transferNative(to: PublicKey, amount: number
|
|
120
|
+
async transferNative(to: PublicKey, amount: number): Promise<TransactionResult> {
|
|
121
121
|
// Implement native transfer logic here
|
|
122
|
-
let feePayerKeypair: Keypair | undefined;
|
|
123
|
-
|
|
124
|
-
if (feePayerOptions) {
|
|
125
|
-
// Convert feePayer private key to Keypair
|
|
126
|
-
feePayerKeypair = Keypair.fromSecretKey(base58.decode(feePayerOptions.privateKey));
|
|
127
|
-
}
|
|
128
|
-
|
|
129
122
|
const transaction = await getTransferNativeTransaction(
|
|
130
123
|
this.privateKey,
|
|
131
124
|
to,
|
|
132
125
|
amount,
|
|
133
|
-
this.connection
|
|
134
|
-
feePayerKeypair
|
|
126
|
+
this.connection!
|
|
135
127
|
);
|
|
136
128
|
|
|
137
129
|
const hash = await SVMVM.signAndSendTransaction(
|
|
138
130
|
transaction,
|
|
139
131
|
this.connection!,
|
|
140
|
-
this.privateKey
|
|
141
|
-
feePayerKeypair ? { feePayerSigner: feePayerKeypair } : undefined
|
|
132
|
+
this.privateKey
|
|
142
133
|
);
|
|
143
134
|
|
|
144
135
|
return { success: true, hash };
|
|
145
136
|
}
|
|
146
137
|
|
|
147
|
-
async transferToken(token: TokenInfo, to: PublicKey, amount: number
|
|
138
|
+
async transferToken(token: TokenInfo, to: PublicKey, amount: number): Promise<TransactionResult> {
|
|
148
139
|
// Implement token transfer logic here
|
|
149
|
-
let feePayerKeypair: Keypair | undefined;
|
|
150
|
-
|
|
151
|
-
if (feePayerOptions) {
|
|
152
|
-
// Convert feePayer private key to Keypair
|
|
153
|
-
feePayerKeypair = Keypair.fromSecretKey(base58.decode(feePayerOptions.privateKey));
|
|
154
|
-
}
|
|
155
|
-
|
|
156
140
|
const transaction = await getTransferTokenTransaction(
|
|
157
141
|
this.privateKey,
|
|
158
142
|
new PublicKey(to),
|
|
159
143
|
token,
|
|
160
144
|
amount,
|
|
161
|
-
this.connection
|
|
162
|
-
feePayerKeypair
|
|
145
|
+
this.connection!
|
|
163
146
|
);
|
|
164
147
|
|
|
165
148
|
const hash = await SVMVM.signAndSendTransaction(
|
|
166
149
|
transaction,
|
|
167
150
|
this.connection!,
|
|
168
|
-
this.privateKey
|
|
169
|
-
feePayerKeypair ? { feePayerSigner: feePayerKeypair } : undefined
|
|
151
|
+
this.privateKey
|
|
170
152
|
);
|
|
171
153
|
|
|
172
154
|
return { success: true, hash };
|
package/utils/svm/utils.ts
CHANGED
|
@@ -281,8 +281,7 @@ export const getTransferNativeTransaction = async (
|
|
|
281
281
|
from: Keypair,
|
|
282
282
|
to: PublicKey,
|
|
283
283
|
amount: number,
|
|
284
|
-
connection: Connection
|
|
285
|
-
feePayerKeypair?: Keypair
|
|
284
|
+
connection: Connection
|
|
286
285
|
) => {
|
|
287
286
|
console.log('getTransferNativeTransaction: Starting');
|
|
288
287
|
const instruction = await getTransferNativeInx(from.publicKey, to, amount);
|
|
@@ -290,9 +289,7 @@ export const getTransferNativeTransaction = async (
|
|
|
290
289
|
connection,
|
|
291
290
|
[instruction],
|
|
292
291
|
[from],
|
|
293
|
-
from.publicKey
|
|
294
|
-
undefined,
|
|
295
|
-
feePayerKeypair?.publicKey
|
|
292
|
+
from.publicKey
|
|
296
293
|
);
|
|
297
294
|
console.log('getTransferNativeTransaction: Completed');
|
|
298
295
|
return transaction;
|
|
@@ -475,8 +472,7 @@ export const getTransferTokenTransaction = async (
|
|
|
475
472
|
to: PublicKey,
|
|
476
473
|
token: TokenInfo,
|
|
477
474
|
amount: number,
|
|
478
|
-
connection: Connection
|
|
479
|
-
feePayerKeypair?: Keypair
|
|
475
|
+
connection: Connection
|
|
480
476
|
): Promise<VersionedTransaction> => {
|
|
481
477
|
console.log('getTransferTokenTransaction: Starting');
|
|
482
478
|
const instruction = await getTransferTokenInx(from.publicKey, to, token, amount, connection);
|
|
@@ -484,9 +480,7 @@ export const getTransferTokenTransaction = async (
|
|
|
484
480
|
connection,
|
|
485
481
|
instruction,
|
|
486
482
|
[from],
|
|
487
|
-
from.publicKey
|
|
488
|
-
undefined,
|
|
489
|
-
feePayerKeypair?.publicKey
|
|
483
|
+
from.publicKey
|
|
490
484
|
);
|
|
491
485
|
console.log('getTransferTokenTransaction: Completed');
|
|
492
486
|
return transaction;
|
package/utils/test.ts
CHANGED
|
@@ -11,12 +11,15 @@ import { ChainWalletConfig } from "./types";
|
|
|
11
11
|
import { discoverNFTs, EVMChainWallet } from "./evm";
|
|
12
12
|
import { } from "./svm/transactionParsing";
|
|
13
13
|
import { getEVMTransactionHistory } from "./evm/transactionParsing";
|
|
14
|
-
import { createPublicClient, http, PublicClient } from "viem";
|
|
14
|
+
import { createPublicClient, encodeFunctionData, Hex, http, parseAbi, parseUnits, PublicClient } from "viem";
|
|
15
15
|
import { base, baseGoerli } from "viem/chains";
|
|
16
16
|
import { discoverTokens, fetchWalletNfts, getTokenInfo } from "./svm/utils";
|
|
17
17
|
import { JsonRpcProvider } from "ethers";
|
|
18
18
|
|
|
19
19
|
import { } from "@solana/spl-token-metadata"
|
|
20
|
+
import { entryPoint07Address } from "viem/account-abstraction";
|
|
21
|
+
|
|
22
|
+
import { KERNEL_V3_3, KernelVersionToAddressesMap } from '@zerodev/sdk/constants';
|
|
20
23
|
// const mnemonic = GenerateNewMnemonic()
|
|
21
24
|
|
|
22
25
|
|
|
@@ -31,6 +34,8 @@ const evePrivateKey = "0x4c0883a69102937d6231471b5dbb6204fe5129617082792ae468d01
|
|
|
31
34
|
const evmPrivateKey2 = "0x0123456789012345678901234567890123456789012345678901234567890123"
|
|
32
35
|
const ogPrivKey = "d2d3f7117aa9a4c6e5d4affedd8a5ea624ffd82b2a1de81509e5913709b1ea72"
|
|
33
36
|
|
|
37
|
+
const evmPrivKey = "0xc9ca95aa5f40bae8b0f741ec89acc07b837590b2f9f818d3439df98c6e4f8dbe"
|
|
38
|
+
const evmPrivateKeyExposed = "0x92cccc7792024dcac5992e5d2986dade41770acfd3dab0fe98ee953ed1bf0c3a"
|
|
34
39
|
// const vm = new SVMVM(seed)
|
|
35
40
|
|
|
36
41
|
|
|
@@ -53,13 +58,31 @@ const chainConfig: ChainWalletConfig = {
|
|
|
53
58
|
|
|
54
59
|
const evmChainConfig: ChainWalletConfig = {
|
|
55
60
|
chainId: 8453,
|
|
56
|
-
name: "
|
|
57
|
-
rpcUrl: "https://eth-mainnet.g.alchemy.com/v2/lhoyb3hc9ccT9NA_y2cfA",
|
|
61
|
+
name: "Base",
|
|
62
|
+
// rpcUrl: "https://eth-mainnet.g.alchemy.com/v2/lhoyb3hc9ccT9NA_y2cfA",
|
|
63
|
+
rpcUrl: base.rpcUrls.default.http[0],
|
|
58
64
|
explorerUrl: "https://explorer.ethereum.com",
|
|
59
65
|
nativeToken: { name: "Ethereum", symbol: "ETH", decimals: 18 },
|
|
60
66
|
confirmationNo: 1,
|
|
61
67
|
vmType: "EVM",
|
|
62
|
-
logoUrl: ""
|
|
68
|
+
logoUrl: "",
|
|
69
|
+
aaSupport: {
|
|
70
|
+
enabled: true,
|
|
71
|
+
entryPoints: [
|
|
72
|
+
{
|
|
73
|
+
address: entryPoint07Address,
|
|
74
|
+
version: "0.7"
|
|
75
|
+
}
|
|
76
|
+
],
|
|
77
|
+
bundlerUrl: `https://api.pimlico.io/v2/${8453}/rpc?apikey=pim_3UEhbTpS98H1XFm8p9kRxg`,
|
|
78
|
+
paymasterUrl: "",
|
|
79
|
+
kernelImplementations: [
|
|
80
|
+
{
|
|
81
|
+
address: KernelVersionToAddressesMap[KERNEL_V3_3].accountImplementationAddress,
|
|
82
|
+
version: 3
|
|
83
|
+
}
|
|
84
|
+
]
|
|
85
|
+
}
|
|
63
86
|
}
|
|
64
87
|
|
|
65
88
|
const OgChainConfig: ChainWalletConfig = {
|
|
@@ -76,13 +99,54 @@ const OgChainConfig: ChainWalletConfig = {
|
|
|
76
99
|
|
|
77
100
|
|
|
78
101
|
// const wallet = new SVMChainWallet(chainConfig, testUserKeyPair, 0)
|
|
79
|
-
const wallet = new EVMChainWallet(
|
|
80
|
-
|
|
102
|
+
const wallet = new EVMChainWallet(evmChainConfig, evmPrivateKeyExposed, 0)
|
|
103
|
+
|
|
104
|
+
//IIFE
|
|
105
|
+
const walletA = new EVMChainWallet(evmChainConfig, evmPrivateKeyExposed, 0); //wallet that usdc to send
|
|
106
|
+
const walletB = new EVMChainWallet(evmChainConfig, evmPrivKey, 0); // wallet that has gas
|
|
107
|
+
const SEPOLIA_USDC_ADDRESS = '0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238' as Hex;
|
|
108
|
+
const BASE_USDC_ADDRESS = '0x833589fcd6edb6e08f4c7c32d4f71b54bda02913' as Hex;
|
|
109
|
+
const bundlerUrl = `https://api.pimlico.io/v2/${evmChainConfig.chainId}/rpc?apikey=pim_3UEhbTpS98H1XFm8p9kRxg`;
|
|
110
|
+
|
|
111
|
+
const RECIPIENT = "0x7027F9C9a701adCbfCD55D16aD219501D4b9589A";
|
|
112
|
+
(async () => {
|
|
113
|
+
return
|
|
114
|
+
console.log("walletA address: ", walletA.address);
|
|
115
|
+
console.log("walletB address: ", walletB.address);
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
//GET TOKEN LOGO using @solana/spl-token-metadata
|
|
119
|
+
const walletANativeBalance = await walletA.getNativeBalance();
|
|
120
|
+
console.log('walletA native balance: ', walletANativeBalance);
|
|
121
|
+
|
|
122
|
+
const walletBNativeBalance = await walletB.getNativeBalance();
|
|
123
|
+
console.log('walletB native balance: ', walletBNativeBalance);
|
|
124
|
+
|
|
125
|
+
//wallet B USDC balance
|
|
126
|
+
const walletBUSDCBalance = await walletB.getTokenBalance(BASE_USDC_ADDRESS);
|
|
127
|
+
console.log('walletB USDC balance: ', walletBUSDCBalance);
|
|
128
|
+
|
|
129
|
+
//extend wallet A wallet to a smart wallet with AA support
|
|
130
|
+
const extendedWalletA = await walletA.extend({
|
|
131
|
+
bundlerUrl: bundlerUrl
|
|
132
|
+
})
|
|
133
|
+
|
|
134
|
+
// console.log('extendedWalletA: ', extendedWalletA);
|
|
135
|
+
const initializedExtendedWalletA = await extendedWalletA.initialize()
|
|
136
|
+
|
|
137
|
+
// console.log('initializedExtendedWalletA: ', initializedExtendedWalletA);
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
})();
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
|
|
81
145
|
// console.log('wallet: ', wallet);
|
|
82
146
|
// getTokenInfo(new PublicKey("9BB6NFEcjBCtnNLFko2FqVQBq8HHM13kCyYcdQbgpump"), wallet.connection!).then(e => console.log('token info: ', e))
|
|
83
|
-
|
|
147
|
+
wallet.discoverToken().then(e => console.log('discovered tokens: ', e))
|
|
84
148
|
// wallet.getNativeBalance().then(e => console.log('native balance: ', e))
|
|
85
|
-
|
|
149
|
+
|
|
86
150
|
// const toBuy = new PublicKey("9BB6NFEcjBCtnNLFko2FqVQBq8HHM13kCyYcdQbgpump")
|
|
87
151
|
// wallet.swap({
|
|
88
152
|
// name: NATIVE_MINT.toBase58(),
|
|
@@ -125,19 +189,19 @@ const connection = new Connection(RPC_URL);
|
|
|
125
189
|
// }).catch((error: any) => {
|
|
126
190
|
// console.error("Error fetching transaction history:", error);
|
|
127
191
|
// });
|
|
128
|
-
const client = createPublicClient({
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
})
|
|
132
|
-
|
|
133
|
-
getEVMTransactionHistory(client as PublicClient, "0x9C82CE0e125F61AdE50BC0c19638F6Ba93d71D5e", {
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
}).then((history: any) => {
|
|
137
|
-
|
|
138
|
-
}).catch((error: any) => {
|
|
139
|
-
|
|
140
|
-
});
|
|
192
|
+
// const client = createPublicClient({
|
|
193
|
+
// chain: base,
|
|
194
|
+
// transport: http(base.rpcUrls.default.http[0]),
|
|
195
|
+
// })
|
|
196
|
+
|
|
197
|
+
// getEVMTransactionHistory(client as PublicClient, "0x9C82CE0e125F61AdE50BC0c19638F6Ba93d71D5e", {
|
|
198
|
+
// startBlock: BigInt(37427020)
|
|
199
|
+
// // before: "0xabc..."
|
|
200
|
+
// }).then((history: any) => {
|
|
201
|
+
// console.log("EVM Transaction History:", history);
|
|
202
|
+
// }).catch((error: any) => {
|
|
203
|
+
// console.error("Error fetching EVM transaction history:", error);
|
|
204
|
+
// });
|
|
141
205
|
|
|
142
206
|
// discoverNFTs("0x498581ff718922c3f8e6a244956af099b2652b2b", evmChainConfig).then(nfts => {
|
|
143
207
|
// console.log("Discovered NFTs:", nfts);
|
package/utils/types.ts
CHANGED
|
@@ -21,22 +21,24 @@ export interface ChainWalletConfig {
|
|
|
21
21
|
|
|
22
22
|
// Smart wallet configuration (optional) only for EVM chains and 7702
|
|
23
23
|
|
|
24
|
-
aaSupport?:
|
|
25
|
-
enabled: boolean;
|
|
26
|
-
entryPoints: {
|
|
27
|
-
address: string;
|
|
28
|
-
version: EntryPointVersion;
|
|
29
|
-
}[]
|
|
30
|
-
bundlerUrl: string;
|
|
31
|
-
paymasterUrl: string;
|
|
32
|
-
kernelImplementations: {
|
|
33
|
-
address: string;
|
|
34
|
-
version: number;
|
|
35
|
-
}[];
|
|
36
|
-
};
|
|
24
|
+
aaSupport?: AA_SupportConfig
|
|
37
25
|
|
|
38
26
|
}
|
|
39
27
|
|
|
28
|
+
export interface AA_SupportConfig {
|
|
29
|
+
enabled: boolean;
|
|
30
|
+
entryPoints: {
|
|
31
|
+
address: string;
|
|
32
|
+
version: EntryPointVersion;
|
|
33
|
+
}[]
|
|
34
|
+
bundlerUrl: string;
|
|
35
|
+
paymasterUrl: string;
|
|
36
|
+
kernelImplementations: {
|
|
37
|
+
address: string;
|
|
38
|
+
version: number;
|
|
39
|
+
}[];
|
|
40
|
+
}
|
|
41
|
+
|
|
40
42
|
export interface TokenInfo {
|
|
41
43
|
address: string;
|
|
42
44
|
name: string;
|
|
@@ -262,10 +264,6 @@ export interface TransactionResult {
|
|
|
262
264
|
error?: string;
|
|
263
265
|
}
|
|
264
266
|
|
|
265
|
-
export interface FeePayerOptions {
|
|
266
|
-
privateKey: string; // Private key of the wallet paying fees
|
|
267
|
-
}
|
|
268
|
-
|
|
269
267
|
export interface Balance {
|
|
270
268
|
balance: BN;
|
|
271
269
|
formatted: number;
|