import { generateKey } from "crypto"; import base58 from "bs58"; import { NATIVE_MINT } from "@solana/spl-token"; import { Connection, PublicKey, Keypair } from "@solana/web3.js"; // import { GenerateNewMnemonic } from "./bip32"; import { SVMChainAddress, SVMChainWallet, SVMVM, } from "./svm"; import { VM } from "./vm"; import { ChainWalletConfig } from "./types"; import { discoverNFTs, EVMChainAddress, EVMChainWallet, EVMVM } from "./evm"; import { } from "./svm/transactionParsing"; import { getEVMTransactionHistory } from "./evm/transactionParsing"; import { createPublicClient, encodeFunctionData, Hex, http, parseAbi, parseUnits, PublicClient, zeroAddress } from "viem"; import { base, baseGoerli, mainnet } from "viem/chains"; import { discoverTokens, fetchWalletNfts, getTokenInfo } from "./svm/utils"; import { JsonRpcProvider, N } from "ethers"; import { } from "@solana/spl-token-metadata" import { entryPoint07Address } from "viem/account-abstraction"; import { KERNEL_V3_3, KernelVersionToAddressesMap } from '@zerodev/sdk/constants'; import { deserializeSessionKey } from "./evm/aa-service"; import { toSpendingLimitHook } from "@zerodev/hooks" import { EVMSavingsManager, SVMSavingsManager, MultiChainSavingsManager } from "./savings"; // const mnemonic = GenerateNewMnemonic() // console.log('mnemonic: ', mnemonic); // const seed = VM.mnemonicToSeed(mnemonic) const pKey = "3Jy2f8KtCvHLAnSHAbznCjdsTM3pDGuDmWvEvhhskBZh8LnWMMLc9RSEYaGNorvSgQRbUuwfg8cGTfMHBgArSSEZ" const testUserKeyPair = Keypair.fromSecretKey(base58.decode(pKey)); // const x = testUserKeyPair instanceof Keypair; const evmPrivKey = "0xcd90354282b35344616d6b53684684bef6e8673ed601d562a5866dc67fafd1ef" const evmPrivateKeyExposed = "0xcd90354282b35344616d6b53684684bef6e8673ed601d562a5866dc67fafd1ef" // const vm = new SVMVM(seed) // const vmFromMnemonic = SVMVM.fromMnemonic(mnemonic) // const keyFromMnemonic = vmFromMnemonic.generatePrivateKey(0) // console.log('keyFromMnemonic: ', keyFromMnemonic.privateKey.publicKey); // const key = vm.generatePrivateKey(0) // console.log('key: ', key.privateKey.publicKey); const chainConfig: ChainWalletConfig = { chainId: 123456789, name: "Solana", rpcUrl: "https://api.mainnet-beta.solana.com", explorerUrl: "https://explorer.solana.com", nativeToken: { name: "Solana", symbol: "SOL", decimals: 9 }, confirmationNo: 1, vmType: "SVM", logoUrl: "" } const evmChainConfig: ChainWalletConfig = { chainId: 8453, name: "Base", // rpcUrl: "https://base-mainnet.g.alchemy.com/v2/TFdA4BilCnKIwaqtypk0d", rpcUrl: base.rpcUrls.default.http[0], explorerUrl: "https://explorer.ethereum.com", nativeToken: { name: "Ethereum", symbol: "ETH", decimals: 18 }, confirmationNo: 1, vmType: "EVM", logoUrl: "", aaSupport: { enabled: true, entryPoints: [ { address: entryPoint07Address , version: "0.7" } ], bundlerUrl: `https://api.pimlico.io/v2/${8453}/rpc?apikey=pim_3UEhbTpS98H1XFm8p9kRxg`, paymasterUrl: "", kernelImplementations: [ { address: KernelVersionToAddressesMap[KERNEL_V3_3].accountImplementationAddress, version: 3 } ] } } const OgChainConfig: ChainWalletConfig = { chainId: 16661, name: "", rpcUrl: "https://evmrpc.0g.ai", explorerUrl: "", nativeToken: { name: "Ethereum", symbol: "ETH", decimals: 18 }, confirmationNo: 1, vmType: "EVM", logoUrl: "" } const ethereumChainConfig: ChainWalletConfig = { chainId: mainnet.id, name: mainnet.name, rpcUrl: mainnet.rpcUrls.default.http[0], explorerUrl: "", nativeToken: mainnet.nativeCurrency, confirmationNo: 1, vmType: "EVM", logoUrl: "" } // const wallet = new SVMChainWallet(chainConfig, testUserKeyPair, 0) const wallet = new EVMChainWallet(evmChainConfig, evmPrivateKeyExposed, 0) //IIFE const walletA = new EVMChainWallet(evmChainConfig, evmPrivateKeyExposed, 0); //wallet that has usdc to send const walletB = new EVMChainWallet(evmChainConfig, evmPrivKey, 0); // wallet that has gas const SEPOLIA_USDC_ADDRESS = '0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238' as Hex; const BASE_USDC_ADDRESS = '0x833589fcd6edb6e08f4c7c32d4f71b54bda02913' as Hex; const bundlerUrl = `https://api.pimlico.io/v2/${evmChainConfig.chainId}/rpc?apikey=pim_3UEhbTpS98H1XFm8p9kRxg`; const RECIPIENT = "0x7027F9C9a701adCbfCD55D16aD219501D4b9589A"; const testWallet = async () => { const wallet = new SVMChainWallet(chainConfig, testUserKeyPair, 0) const res = await wallet.transferNative(wallet.address, 0.0001) console.log('res: ', res); } testWallet() const testSessionKeys = async () => { console.log("walletA address: ", walletA.address); const walletANativeBalance = await walletA.getNativeBalance(); console.log('walletA native balance: ', walletANativeBalance); const walletBNativeBalance = await walletB.getNativeBalance(); console.log('walletB native balance: ', walletBNativeBalance); //wallet B USDC balance const walletBUSDCBalance = await walletB.getTokenBalance(BASE_USDC_ADDRESS); console.log('walletB USDC balance: ', walletBUSDCBalance); console.log("walletB address: ", walletB.address); //extend wallet A wallet to a smart wallet with AA support const extendedWalletA = await walletA.extend({ bundlerUrl: bundlerUrl }) // console.log('extendedWalletA: ', extendedWalletA); const initializedExtendedWalletA = await extendedWalletA.initialize() //now we want to test session keys const sessionKeys = await initializedExtendedWalletA.generateSessionKey() console.log('sessionKeys: ', sessionKeys); // return; const usdcPermission = initializedExtendedWalletA.createUSDCPermission( BASE_USDC_ADDRESS, "1", // approve up to 100 USDC, RECIPIENT ) console.log('usdcPermission: ', usdcPermission); const sessionKeyApproval = await initializedExtendedWalletA.approveSessionKey( { sessionKeyAddress: sessionKeys.address, sessionKeyPrivateKey: sessionKeys.privateKey, permissions: [usdcPermission], // useSudoPolicy: true, } ) const data = encodeFunctionData({ abi: parseAbi([ 'function transfer(address to, uint256 amount) public returns (bool)' ]), functionName: 'transfer', args: [RECIPIENT, parseUnits('0.01', 6)] }) // transfer 10 USDC console.log('sessionKeyApproval: ', sessionKeyApproval); const sessionKeyAccount = await deserializeSessionKey({ approval: sessionKeyApproval, sessionKeySigner: sessionKeys.signer, chain: base }) //send transaction using session key const sessionAccount = { account: sessionKeyAccount, address: sessionKeyAccount.address, }; const hash = await initializedExtendedWalletA.sendTransaction(BASE_USDC_ADDRESS, 0n, data, { sessionAccount: sessionAccount }) console.log('hash: ', hash); //get session key client } const testModule = async () => { const extendedWalletA = await walletA.extend({ bundlerUrl: bundlerUrl }) const initializedExtendedWalletA = await extendedWalletA.initialize() //this is where we will test installation of modules } const testPrice = async () => { walletA.getPrices(['0x98d0baa52b2D063E780DE12F615f963Fe8537553']).then(console.log) } // ============================================ // EVM Savings Pocket Test // ============================================ const testSavingsPocket = async () => { console.log('\n========== EVM Savings Test =========='); const mnemonic = EVMVM.generateMnemonicFromPrivateKey(evmPrivateKeyExposed) console.log('Mnemonic:', mnemonic); // Using new EVMSavingsManager (multi-chain compatible) const savingsManager = new EVMSavingsManager(mnemonic, evmChainConfig, wallet.index) const pocket0 = savingsManager.getPocket(0) console.log('\nPocket 0 Info:'); console.log(' Address:', pocket0.address); console.log(' Derivation path:', pocket0.derivationPath); console.log(' Index:', pocket0.index); // Uncomment to test transfer // const deposited = await savingsManager.transferToPocket(walletA.wallet, 0, "0.00001") // console.log('deposited: ', deposited); // Get balance (updated API: getPocketBalance(pocketIndex, tokens[])) const balance = await savingsManager.getPocketBalance(0, []) console.log('\nPocket 0 Balance:'); console.log(' Native balance:', balance[0].balance.formatted, 'ETH'); // Get multiple pockets const pocket1 = savingsManager.getPocket(1) const pocket2 = savingsManager.getPocket(2) console.log('\nAdditional Pockets:'); console.log(' Pocket 1:', pocket1.address); console.log(' Pocket 2:', pocket2.address); // Cleanup savingsManager.dispose(); console.log('\nāœ… EVM Savings Test Complete\n'); } // ============================================ // SVM (Solana) Savings Pocket Test // ============================================ const testSavingsPocketSVM = async () => { console.log('\n========== SVM (Solana) Savings Test =========='); const mnemonic = EVMVM.generateMnemonicFromPrivateKey(evmPrivateKeyExposed) console.log('Mnemonic:', mnemonic); // Using SVMSavingsManager for Solana const savingsManager = new SVMSavingsManager( mnemonic, chainConfig.rpcUrl, 0 // wallet index ) const pocket0 = savingsManager.getPocket(0) console.log('\nPocket 0 Info:'); console.log(' Address:', pocket0.address.toBase58()); console.log(' Derivation path:', pocket0.derivationPath); console.log(' Index:', pocket0.index); // Get balance const balance = await savingsManager.getPocketBalance(0, []) console.log('\nPocket 0 Balance:'); console.log(' Native balance:', balance[0].balance.formatted, 'SOL'); // Get multiple pockets const pocket1 = savingsManager.getPocket(1) const pocket2 = savingsManager.getPocket(2) console.log('\nAdditional Pockets:'); console.log(' Pocket 1:', pocket1.address.toBase58()); console.log(' Pocket 2:', pocket2.address.toBase58()); // Note: Solana addresses are DIFFERENT from EVM addresses! console.log('\nšŸ’” Note: Solana uses coin type 501, so addresses differ from EVM'); // Cleanup savingsManager.dispose(); console.log('\nāœ… SVM Savings Test Complete\n'); } // ============================================ // Multi-Chain Savings Test // ============================================ const testSavingsPocketMultiChain = async () => { console.log('\n========== Multi-Chain Savings Test =========='); const mnemonic = "exit alert stove save pair brass toss scheme shuffle loan gadget lunch" const vm = new EVMVM(EVMVM.mnemonicToSeed(mnemonic)) const index = 1 const wallet = new EVMChainWallet( ethereumChainConfig , vm.generatePrivateKey(index).privateKey, index) // const result = wallet.transferToken() return // Create multi-chain manager with EVM and Solana const multiChainManager = new MultiChainSavingsManager( mnemonic, [ { id: 'base', type: 'EVM', config: evmChainConfig }, { id: '1', type: 'EVM', config: { chainId: 1, name: 'Ethereum', rpcUrl: 'https://eth-mainnet.g.alchemy.com/v2/demo', explorerUrl: 'https://etherscan.io', nativeToken: { name: 'Ethereum', symbol: 'ETH', decimals: 18 }, confirmationNo: 1, vmType: 'EVM' } }, { id: 'solana', type: 'SVM', config: { rpcUrl: chainConfig.rpcUrl } } ], 0 // wallet index ); console.log('main wallet address', multiChainManager.getMainWalletAddress("1")); return console.log('\nAvailable chains:', multiChainManager.getChains()); console.log('EVM chains:', multiChainManager.getEVMChains()); console.log('SVM chains:', multiChainManager.getSVMChains()); // Get pocket 0 address on different chains console.log('\nPocket 0 Addresses Across Chains:'); const baseAddress = multiChainManager.getPocketAddress('base', 0); const ethAddress = multiChainManager.getPocketAddress('ethereum', 0); const solAddress = multiChainManager.getPocketAddress('solana', 0); console.log(' Base:', baseAddress); console.log(' Ethereum:', ethAddress); console.log(' Solana:', solAddress); // Verify EVM chains share addresses console.log('\nšŸ” EVM Address Check:'); console.log(' Base === Ethereum?', baseAddress === ethAddress, 'āœ…'); console.log(' Base === Solana?', baseAddress === solAddress, 'āŒ (different chain type)'); // Get balances across chains console.log('\nšŸ“Š Getting balances across all chains...'); // try { // const balances = await multiChainManager.getPocketBalanceAcrossChains( // 0, // pocket index // new Map([ // ['base', []], // No tokens, just native // ['ethereum', []], // ['solana', []] // ]) // ); // console.log('\nBalances for Pocket 0:'); // balances.forEach(chainBalance => { // console.log(`\n ${chainBalance.chainId.toUpperCase()} (${chainBalance.chainType}):`); // console.log(` Address: ${chainBalance.address}`); // chainBalance.balances.forEach(bal => { // const tokenName = bal.token === 'native' ? 'Native' : bal.token; // console.log(` ${tokenName}: ${bal.balance.formatted}`); // }); // }); // } catch (error) { // console.log(' āš ļø Balance fetch error (expected for demo RPCs):', (error as Error).message); // } // Get specific chain managers for advanced operations console.log('\nšŸ”§ Advanced: Direct chain manager access'); const baseManager = multiChainManager.getEVMManager('base'); const solanaManager = multiChainManager.getSVMManager('solana'); console.log(' Base manager type:', baseManager.constructor.name); console.log(' Solana manager type:', solanaManager.constructor.name); } const testEntropy = () => { const p = EVMVM.convertFromEntropyToPrivateKey("thishgbmytesentropystringis32bytes!hjkjkhknkjtdyftgkh,jryctdrfygh") console.log('p: ', p); const res = new EVMChainWallet(evmChainConfig, p, 0) console.log('res: ', res); } const testAddressClass = async () => { const evmAddressClass = new EVMChainAddress(evmChainConfig, "0xC9C1D854b82BA9b4FB6f6D58E9EF3d1fAEd601AA", 0) const res = await evmAddressClass.getNativeBalance() console.log('res: ', res); SVMVM.generateMnemonicFromPrivateKey // const svmAddressClass = new SVMChainAddress( ) } // testSavingsPocketMultiChain() // Uncomment to run tests // testSavingsPocket() // testSavingsPocketSVM() // testSavingsPocketMultiChain() // testPrice() // console.log('wallet: ', wallet); // getTokenInfo(new PublicKey("9BB6NFEcjBCtnNLFko2FqVQBq8HHM13kCyYcdQbgpump"), wallet.connection!).then(e => console.log('token info: ', e)) // wallet.getNativeBalance().then(e => console.log('native balance: ', e)) // const toBuy = new PublicKey("9BB6NFEcjBCtnNLFko2FqVQBq8HHM13kCyYcdQbgpump") // wallet.swap({ // name: NATIVE_MINT.toBase58(), // address: NATIVE_MINT.toBase58(), // symbol: NATIVE_MINT.toBase58(), // decimals: 9 // }, toBuy, 0.005,).then(res => console.log(res)) // console.log('wal: ', wal.address); // wal.getNativeBalance().then(e => console.log(e)) const RPC_URL = chainConfig.rpcUrl; const connection = new Connection(RPC_URL); // const evmConnection = new JsonRpcProvider(evmChainConfig.rpcUrl, { // chainId: evmChainConfig.chainId // }); /** * Fetches and logs the token metadata for a given mint address. * @param mintAddress - The mint address of the token. */ // get transaction history // getTransactionHistory( // connection, // wallet.address, // { // limit: 2, // before: "5RKG5zKJdz9PqWSav1J358hm1GtfnV1QnYcrw3sRpY7aCgT7f4HTKnp4c9pXrJRujcHHisu3Z6jdtbzq5aTRbikq" // } // ).then((history: any) => { // console.log("Transaction History:", history); // }).catch((error: any) => { // console.error("Error fetching transaction history:", error); // }); // const client = createPublicClient({ // chain: base, // transport: http(base.rpcUrls.default.http[0]), // }) // getEVMTransactionHistory(client as PublicClient, "0x9C82CE0e125F61AdE50BC0c19638F6Ba93d71D5e", { // startBlock: BigInt(37427020) // // before: "0xabc..." // }).then((history: any) => { // console.log("EVM Transaction History:", history); // }).catch((error: any) => { // console.error("Error fetching EVM transaction history:", error); // }); // discoverNFTs("0x498581ff718922c3f8e6a244956af099b2652b2b", evmChainConfig).then(nfts => { // console.log("Discovered NFTs:", nfts); // }).catch(error => { // console.error("Error discovering NFTs:", error); // }); // fetchWalletNfts(new PublicKey("LebronkTYWjc5J1gtqntdMcbhBXgwRgYcCxMA8JMA17"), connection).then(nfts => { // console.log("Discovered NFTs:", nfts); // }).catch(error => { // console.error("Error discovering NFTs:", error); // }); // discoverTokens(new PublicKey("8AXoqNjEVyhhe43ckDEsYiphWxTBH2oWXkKLZAbCNWLL"), connection).then(tokens => { // console.log("Discovered Tokens:", tokens); // }).catch(error => { // console.error("Error discovering Tokens:", error); // }); // //IIFE // (async () => { // //GET TOKEN LOGO using @solana/spl-token-metadata // })();