From 7ef4b18bb9e778fe5cee3959574ef0f0a3d3e82f Mon Sep 17 00:00:00 2001 From: Vignesh Date: Fri, 14 Jul 2023 05:28:52 +0530 Subject: [PATCH 1/8] updated the supported networks to include Mantle --- CHANGELOG.md | 4 ++++ package-lock.json | 4 ++-- package.json | 2 +- src/sdk/network/constants.ts | 16 +++++++++++++++- 4 files changed, 22 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8810cab6..5fb72b6e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,8 @@ # Changelog +## [1.0.4] - 2023-07-14 +### New +- Added Mantle Mainnet config as supported networks + ## [1.0.3] - 2023-07-10 ### Fixed - Fuse and ArbitrumGoerli bundler url and native transfer funds example diff --git a/package-lock.json b/package-lock.json index c3bd5493..5812444e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@etherspot/prime-sdk", - "version": "1.0.3", + "version": "1.0.4", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@etherspot/prime-sdk", - "version": "1.0.3", + "version": "1.0.4", "license": "MIT", "dependencies": { "@thehubbleproject/bls": "0.5.1", diff --git a/package.json b/package.json index af5f7115..a7adf054 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@etherspot/prime-sdk", - "version": "1.0.3", + "version": "1.0.4", "description": "Etherspot Prime (Account Abstraction) SDK", "keywords": [ "ether", diff --git a/src/sdk/network/constants.ts b/src/sdk/network/constants.ts index 75201035..4cad95b3 100644 --- a/src/sdk/network/constants.ts +++ b/src/sdk/network/constants.ts @@ -18,9 +18,10 @@ export enum NetworkNames { OptimismGoerli = 'optimismGoerli', RSKTestnet = 'RSKTestnet', VerseTestnet = 'verseTestnet', + Mantle = 'Mantle', } -export const SupportedNetworks = [5, 80001, 84531, 11155111, 10, 137, 42161, 421613, 10200, 122, 123, 100, 2357, 1, 420, 31, 20197 ] +export const SupportedNetworks = [5, 80001, 84531, 11155111, 10, 137, 42161, 421613, 10200, 122, 123, 100, 2357, 1, 420, 31, 20197, 5000] export const NETWORK_NAME_TO_CHAIN_ID: { [key: string]: number; @@ -42,6 +43,7 @@ export const NETWORK_NAME_TO_CHAIN_ID: { [NetworkNames.OptimismGoerli]: 420, [NetworkNames.RSKTestnet]: 31, [NetworkNames.VerseTestnet]: 20197, + [NetworkNames.Mantle]: 5000, }; export const Networks: { @@ -251,6 +253,18 @@ export const Networks: { url: '', }, }, + [5000]: { + chainId: 5000, + bundler: '', + contracts: { + entryPoint: '0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789', + walletFactory: '0x27f11918740060bd9Be146086F6836e18eedBB8C', + }, + paymaster: { + use: false, + url: '', + }, + }, }; export const CHAIN_ID_TO_NETWORK_NAME: { [key: number]: NetworkNames } = Object.entries( From 26a43cc85f4ffaf5acd72fc0fa6c5ae8e00ff475 Mon Sep 17 00:00:00 2001 From: Vignesh Date: Sun, 16 Jul 2023 05:03:51 +0530 Subject: [PATCH 2/8] changed to new wallet factory contract --- src/sdk/network/constants.ts | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/src/sdk/network/constants.ts b/src/sdk/network/constants.ts index 4cad95b3..7bf61ec2 100644 --- a/src/sdk/network/constants.ts +++ b/src/sdk/network/constants.ts @@ -54,7 +54,7 @@ export const Networks: { bundler: 'https://goerli-bundler.etherspot.io', contracts: { entryPoint: '0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789', - walletFactory: '0x2f771DCa6Ffa3879e48355E8A4aF5b81d82A6164', + walletFactory: '0x27f11918740060bd9Be146086F6836e18eedBB8C', }, paymaster: { use: false, @@ -66,7 +66,7 @@ export const Networks: { bundler: 'https://mumbai-bundler.etherspot.io', contracts: { entryPoint: '0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789', - walletFactory: '0x2f771DCa6Ffa3879e48355E8A4aF5b81d82A6164', + walletFactory: '0x27f11918740060bd9Be146086F6836e18eedBB8C', }, paymaster: { use: false, @@ -78,7 +78,7 @@ export const Networks: { bundler: 'https://basegoerli-bundler.etherspot.io', contracts: { entryPoint: '0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789', - walletFactory: '0x2f771DCa6Ffa3879e48355E8A4aF5b81d82A6164', + walletFactory: '0x27f11918740060bd9Be146086F6836e18eedBB8C', }, paymaster: { use: false, @@ -90,7 +90,7 @@ export const Networks: { bundler: 'https://sepolia-bundler.etherspot.io', contracts: { entryPoint: '0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789', - walletFactory: '0x2f771DCa6Ffa3879e48355E8A4aF5b81d82A6164', + walletFactory: '0x27f11918740060bd9Be146086F6836e18eedBB8C', }, paymaster: { use: false, @@ -102,7 +102,7 @@ export const Networks: { bundler: 'https://optimism-bundler.etherspot.io', contracts: { entryPoint: '0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789', - walletFactory: '0x2f771DCa6Ffa3879e48355E8A4aF5b81d82A6164', + walletFactory: '0x27f11918740060bd9Be146086F6836e18eedBB8C', }, paymaster: { use: false, @@ -114,7 +114,7 @@ export const Networks: { bundler: 'https://polygon-bundler.etherspot.io', contracts: { entryPoint: '0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789', - walletFactory: '0x2f771DCa6Ffa3879e48355E8A4aF5b81d82A6164', + walletFactory: '0x27f11918740060bd9Be146086F6836e18eedBB8C', }, paymaster: { use: false, @@ -126,7 +126,7 @@ export const Networks: { bundler: 'https://arbitrum-bundler.etherspot.io', contracts: { entryPoint: '0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789', - walletFactory: '0x2f771DCa6Ffa3879e48355E8A4aF5b81d82A6164', + walletFactory: '0x27f11918740060bd9Be146086F6836e18eedBB8C', }, paymaster: { use: false, @@ -138,7 +138,7 @@ export const Networks: { bundler: 'https://ethereum-bundler.etherspot.io/', contracts: { entryPoint: '0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789', - walletFactory: '0x2f771DCa6Ffa3879e48355E8A4aF5b81d82A6164', + walletFactory: '0x27f11918740060bd9Be146086F6836e18eedBB8C', }, paymaster: { use: false, @@ -150,7 +150,7 @@ export const Networks: { bundler: 'https://arbitrumgoerli-bundler.etherspot.io', contracts: { entryPoint: '0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789', - walletFactory: '0x2f771DCa6Ffa3879e48355E8A4aF5b81d82A6164', + walletFactory: '0x27f11918740060bd9Be146086F6836e18eedBB8C', }, paymaster: { use: false, @@ -162,7 +162,7 @@ export const Networks: { bundler: '', contracts: { entryPoint: '0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789', - walletFactory: '0x2f771DCa6Ffa3879e48355E8A4aF5b81d82A6164', + walletFactory: '0x27f11918740060bd9Be146086F6836e18eedBB8C', }, paymaster: { use: false, @@ -174,7 +174,7 @@ export const Networks: { bundler: 'https://fuse-bundler.etherspot.io', contracts: { entryPoint: '0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789', - walletFactory: '0x2f771DCa6Ffa3879e48355E8A4aF5b81d82A6164', + walletFactory: '0x27f11918740060bd9Be146086F6836e18eedBB8C', }, paymaster: { use: false, @@ -186,7 +186,7 @@ export const Networks: { bundler: '', contracts: { entryPoint: '0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789', - walletFactory: '0x2f771DCa6Ffa3879e48355E8A4aF5b81d82A6164', + walletFactory: '0x27f11918740060bd9Be146086F6836e18eedBB8C', }, paymaster: { use: false, @@ -198,7 +198,7 @@ export const Networks: { bundler: '', contracts: { entryPoint: '0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789', - walletFactory: '0x2f771DCa6Ffa3879e48355E8A4aF5b81d82A6164', + walletFactory: '0x27f11918740060bd9Be146086F6836e18eedBB8C', }, paymaster: { use: false, @@ -210,7 +210,7 @@ export const Networks: { bundler: '', contracts: { entryPoint: '0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789', - walletFactory: '0x2f771DCa6Ffa3879e48355E8A4aF5b81d82A6164', + walletFactory: '0x27f11918740060bd9Be146086F6836e18eedBB8C', }, paymaster: { use: false, @@ -222,7 +222,7 @@ export const Networks: { bundler: '', contracts: { entryPoint: '0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789', - walletFactory: '0x2f771DCa6Ffa3879e48355E8A4aF5b81d82A6164', + walletFactory: '0x27f11918740060bd9Be146086F6836e18eedBB8C', }, paymaster: { use: false, @@ -234,7 +234,7 @@ export const Networks: { bundler: '', contracts: { entryPoint: '0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789', - walletFactory: '0x2f771DCa6Ffa3879e48355E8A4aF5b81d82A6164', + walletFactory: '0x27f11918740060bd9Be146086F6836e18eedBB8C', }, paymaster: { use: false, @@ -246,7 +246,7 @@ export const Networks: { bundler: '', contracts: { entryPoint: '0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789', - walletFactory: '0x2f771DCa6Ffa3879e48355E8A4aF5b81d82A6164', + walletFactory: '0x27f11918740060bd9Be146086F6836e18eedBB8C', }, paymaster: { use: false, @@ -255,7 +255,7 @@ export const Networks: { }, [5000]: { chainId: 5000, - bundler: '', + bundler: 'https://mantle-bundler.etherspot.io/', contracts: { entryPoint: '0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789', walletFactory: '0x27f11918740060bd9Be146086F6836e18eedBB8C', From b5f03500664f7ee434c17d258986a62c14535e5a Mon Sep 17 00:00:00 2001 From: Vignesh Date: Sun, 16 Jul 2023 05:05:24 +0530 Subject: [PATCH 3/8] updated change log file --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5fb72b6e..b9b857c3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,7 @@ # Changelog ## [1.0.4] - 2023-07-14 ### New -- Added Mantle Mainnet config as supported networks +- Added Mantle Mainnet config as supported networks and changed all networks to new wallet factory address ## [1.0.3] - 2023-07-10 ### Fixed From e92f2f373f8a3b204b9f9c10288451b6a7ab1178 Mon Sep 17 00:00:00 2001 From: marie-fourier Date: Mon, 17 Jul 2023 20:06:45 +0500 Subject: [PATCH 4/8] switch to old gas type if eip1559 fails --- src/sdk/base/BaseAccountAPI.ts | 12 +++++++++++- src/sdk/common/getGasFee.ts | 11 ++++++++++- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/src/sdk/base/BaseAccountAPI.ts b/src/sdk/base/BaseAccountAPI.ts index 4b57d95e..e62d2f2e 100644 --- a/src/sdk/base/BaseAccountAPI.ts +++ b/src/sdk/base/BaseAccountAPI.ts @@ -448,7 +448,17 @@ export abstract class BaseAccountAPI { let { maxFeePerGas, maxPriorityFeePerGas } = info; if (maxFeePerGas == null || maxPriorityFeePerGas == null) { const provider = this.services.walletService.getWalletProvider(); - const feeData = await provider.getFeeData(); + let feeData: any = {}; + try { + feeData = await provider.getFeeData(); + } catch (err) { + console.warn( + "getGas: eth_maxPriorityFeePerGas failed, falling back to legacy gas price." + ); + const gas = await provider.getGasPrice(); + + feeData = { maxFeePerGas: gas, maxPriorityFeePerGas: gas }; + } if (maxFeePerGas == null) { maxFeePerGas = feeData.maxFeePerGas ?? undefined; } diff --git a/src/sdk/common/getGasFee.ts b/src/sdk/common/getGasFee.ts index c4077885..9e6a673f 100644 --- a/src/sdk/common/getGasFee.ts +++ b/src/sdk/common/getGasFee.ts @@ -6,7 +6,16 @@ export interface Gas { } export async function getGasFee(provider: ethers.providers.JsonRpcProvider): Promise { - const [fee, block] = await Promise.all([provider.send('eth_maxPriorityFeePerGas', []), provider.getBlock('latest')]); + let fee: any = {}; + try { + fee = await provider.send('eth_maxPriorityFeePerGas', []); + } catch (err) { + console.warn( + "getGas: eth_maxPriorityFeePerGas failed, falling back to legacy gas price." + ); + fee = await provider.getGasPrice(); + } + const block = await provider.getBlock('latest'); const tip = ethers.BigNumber.from(fee); const buffer = tip.div(100).mul(13); const maxPriorityFeePerGas = tip.add(buffer); From 273b53b5beaec4a112a54e0e7a6c5f5108678468 Mon Sep 17 00:00:00 2001 From: marie-fourier Date: Mon, 17 Jul 2023 20:14:09 +0500 Subject: [PATCH 5/8] fix pre-eip1559 gas price --- src/sdk/common/getGasFee.ts | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/src/sdk/common/getGasFee.ts b/src/sdk/common/getGasFee.ts index 9e6a673f..f6d2acc1 100644 --- a/src/sdk/common/getGasFee.ts +++ b/src/sdk/common/getGasFee.ts @@ -6,21 +6,20 @@ export interface Gas { } export async function getGasFee(provider: ethers.providers.JsonRpcProvider): Promise { - let fee: any = {}; try { - fee = await provider.send('eth_maxPriorityFeePerGas', []); + const [fee, block] = await provider.send('eth_maxPriorityFeePerGas', []); + const tip = ethers.BigNumber.from(fee); + const buffer = tip.div(100).mul(13); + const maxPriorityFeePerGas = tip.add(buffer); + const maxFeePerGas = + block.baseFeePerGas != null ? block.baseFeePerGas.mul(2).add(maxPriorityFeePerGas) : maxPriorityFeePerGas; + + return { maxFeePerGas, maxPriorityFeePerGas }; } catch (err) { console.warn( "getGas: eth_maxPriorityFeePerGas failed, falling back to legacy gas price." ); - fee = await provider.getGasPrice(); + const gas = await provider.getGasPrice(); + return { maxFeePerGas: gas, maxPriorityFeePerGas: gas }; } - const block = await provider.getBlock('latest'); - const tip = ethers.BigNumber.from(fee); - const buffer = tip.div(100).mul(13); - const maxPriorityFeePerGas = tip.add(buffer); - const maxFeePerGas = - block.baseFeePerGas != null ? block.baseFeePerGas.mul(2).add(maxPriorityFeePerGas) : maxPriorityFeePerGas; - - return { maxFeePerGas, maxPriorityFeePerGas }; } From 5401e3e4607efd0ebdeb5e7d75784691c382735b Mon Sep 17 00:00:00 2001 From: Vignesh Date: Tue, 18 Jul 2023 15:04:44 +0530 Subject: [PATCH 6/8] changed as per feedback --- CHANGELOG.md | 3 ++- src/sdk/base/BaseAccountAPI.ts | 1 - src/sdk/common/constants.ts | 2 ++ src/sdk/common/getGasFee.ts | 3 ++- src/sdk/network/constants.ts | 2 +- 5 files changed, 7 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b9b857c3..c50fa11a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,8 @@ # Changelog ## [1.0.4] - 2023-07-14 ### New -- Added Mantle Mainnet config as supported networks and changed all networks to new wallet factory address +- Added Mantle Mainnet config as supported networks +- Changed the wallet factory address so the smart wallet address will generate a new address. Whoever wishes to access the old wallet should use version 1.0.3 to connect to the old smart wallet ## [1.0.3] - 2023-07-10 ### Fixed diff --git a/src/sdk/base/BaseAccountAPI.ts b/src/sdk/base/BaseAccountAPI.ts index e62d2f2e..42926723 100644 --- a/src/sdk/base/BaseAccountAPI.ts +++ b/src/sdk/base/BaseAccountAPI.ts @@ -476,7 +476,6 @@ export abstract class BaseAccountAPI { verificationGasLimit, maxFeePerGas, maxPriorityFeePerGas, - chainId: 80001, }; diff --git a/src/sdk/common/constants.ts b/src/sdk/common/constants.ts index c335b241..e0957023 100644 --- a/src/sdk/common/constants.ts +++ b/src/sdk/common/constants.ts @@ -7,3 +7,5 @@ export enum HeaderNames { ProjectKey = 'x-project-key', ProjectMetadata = 'x-project-metadata', } + +export const bufferPercent = 13; // Buffer in percent diff --git a/src/sdk/common/getGasFee.ts b/src/sdk/common/getGasFee.ts index f6d2acc1..83d62a41 100644 --- a/src/sdk/common/getGasFee.ts +++ b/src/sdk/common/getGasFee.ts @@ -1,4 +1,5 @@ import { BigNumberish, ethers } from 'ethers'; +import { bufferPercent } from './constants'; export interface Gas { maxFeePerGas: BigNumberish; @@ -9,7 +10,7 @@ export async function getGasFee(provider: ethers.providers.JsonRpcProvider): Pro try { const [fee, block] = await provider.send('eth_maxPriorityFeePerGas', []); const tip = ethers.BigNumber.from(fee); - const buffer = tip.div(100).mul(13); + const buffer = tip.div(100).mul(bufferPercent); const maxPriorityFeePerGas = tip.add(buffer); const maxFeePerGas = block.baseFeePerGas != null ? block.baseFeePerGas.mul(2).add(maxPriorityFeePerGas) : maxPriorityFeePerGas; diff --git a/src/sdk/network/constants.ts b/src/sdk/network/constants.ts index 7bf61ec2..1aeda71d 100644 --- a/src/sdk/network/constants.ts +++ b/src/sdk/network/constants.ts @@ -21,7 +21,7 @@ export enum NetworkNames { Mantle = 'Mantle', } -export const SupportedNetworks = [5, 80001, 84531, 11155111, 10, 137, 42161, 421613, 10200, 122, 123, 100, 2357, 1, 420, 31, 20197, 5000] +export const SupportedNetworks = [1, 10, 100, 10200, 11155111, 122, 123, 137, 20197, 2357, 31, 420, 42161, 421613, 5, 5000, 80001, 84531] export const NETWORK_NAME_TO_CHAIN_ID: { [key: string]: number; From 7f3b841bc8472b03225758e482a56aeb01a1b4e6 Mon Sep 17 00:00:00 2001 From: Vignesh Date: Thu, 20 Jul 2023 16:49:27 +0530 Subject: [PATCH 7/8] major changes --- CHANGELOG.md | 7 ++++- examples/02-transfer-funds.ts | 18 ++++++++----- examples/03-transfer-erc20.ts | 20 +++++++++----- examples/04-transfer-nft.ts | 16 +++++++---- examples/scripts/commands/NFTTransfer.ts | 16 +++++++---- .../scripts/commands/batchErc20Transfer.ts | 16 +++++++---- examples/scripts/commands/erc20Approve.ts | 16 +++++++---- examples/scripts/commands/erc20Transfer.ts | 16 +++++++---- examples/scripts/commands/transfer.ts | 16 +++++++---- package-lock.json | 4 +-- package.json | 2 +- src/sdk/base/BaseAccountAPI.ts | 7 +---- src/sdk/base/HttpRpcClient.ts | 5 ++++ src/sdk/common/constants.ts | 2 +- src/sdk/common/getGasFee.ts | 3 ++- src/sdk/sdk.ts | 27 ++++++------------- 16 files changed, 117 insertions(+), 74 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c50fa11a..6b599ce7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,8 +1,13 @@ # Changelog -## [1.0.4] - 2023-07-14 +## [1.1.0] - 2023-07-14 ### New - Added Mantle Mainnet config as supported networks +### Breaking Changes - Changed the wallet factory address so the smart wallet address will generate a new address. Whoever wishes to access the old wallet should use version 1.0.3 to connect to the old smart wallet +- Renamed sign method to estimate and get the return object as UserOps without signature +- Now signing the UserOps is moved into send method so provider would be requested to sign only while calling send method +- getUserOpsReceipt returns the whole object with UserOpsReceipt with transaction Receipt as compared to previously returned transaction hash +- getUserOpsReceipt only returns if the transaction is included into the block on-chain and would give results only for 15k blocks from the latest block number ## [1.0.3] - 2023-07-10 ### Fixed diff --git a/examples/02-transfer-funds.ts b/examples/02-transfer-funds.ts index b424e95d..0a8dbbcd 100644 --- a/examples/02-transfer-funds.ts +++ b/examples/02-transfer-funds.ts @@ -2,6 +2,7 @@ import { ethers } from 'ethers'; import { PrimeSdk } from '../src'; import { printOp } from '../src/sdk/common/OperationUtils'; import * as dotenv from 'dotenv'; +import { sleep } from '../src/sdk/common'; dotenv.config(); @@ -30,18 +31,23 @@ async function main() { console.log('balances: ', balance); - // sign transactions added to the batch - const op = await primeSdk.sign(); - console.log(`Signed UserOp: ${await printOp(op)}`); + // estimate transactions added to the batch and get the fee data for the UserOp + const op = await primeSdk.estimate(); + console.log(`Estimate UserOp: ${await printOp(op)}`); - // sending to the bundler... + // sign the UserOp and sending to the bundler... const uoHash = await primeSdk.send(op); console.log(`UserOpHash: ${uoHash}`); // get transaction hash... console.log('Waiting for transaction...'); - const txHash = await primeSdk.getUserOpReceipt(uoHash); - console.log('\x1b[33m%s\x1b[0m', `Transaction hash: ${txHash}`); + let userOpsReceipt = null; + const timeout = Date.now() + 60000; // 1 minute timeout + while((userOpsReceipt == null) && (Date.now() < timeout)) { + await sleep(2); + userOpsReceipt = await primeSdk.getUserOpReceipt(uoHash); + } + console.log('\x1b[33m%s\x1b[0m', `Transaction Receipt: `, userOpsReceipt); } main() diff --git a/examples/03-transfer-erc20.ts b/examples/03-transfer-erc20.ts index 4e2e4104..69ef947d 100644 --- a/examples/03-transfer-erc20.ts +++ b/examples/03-transfer-erc20.ts @@ -3,11 +3,12 @@ import { PrimeSdk } from '../src'; import { printOp } from '../src/sdk/common/OperationUtils'; import { ERC20_ABI } from '../src/sdk/helpers/abi/ERC20_ABI'; import * as dotenv from 'dotenv'; +import { sleep } from '../src/sdk/common'; dotenv.config(); // add/change these values -const recipient: string = '0xD129dB5e418e389c3F7D3ae0B8771B3f76799A52'; // recipient wallet address +const recipient: string = '0x80a1874E1046B1cc5deFdf4D3153838B72fF94Ac'; // recipient wallet address const value: string = '0.1'; // transfer value const tokenAddress: string = '0x326C977E6efc84E512bB9C30f76E30c160eD06FB'; @@ -38,18 +39,23 @@ async function main() { let userOpsBatch = await primeSdk.addUserOpsToBatch({to: tokenAddress, data: transactionData}); console.log('transactions: ', userOpsBatch); - // sign transactions added to the batch - const op = await primeSdk.sign(); - console.log(`Signed UserOp: ${await printOp(op)}`); + // estimate transactions added to the batch and get the fee data for the UserOp + const op = await primeSdk.estimate(); + console.log(`Estimate UserOp: ${await printOp(op)}`); - // sending to the bundler... + // sign the UserOp and sending to the bundler... const uoHash = await primeSdk.send(op); console.log(`UserOpHash: ${uoHash}`); // get transaction hash... console.log('Waiting for transaction...'); - const txHash = await primeSdk.getUserOpReceipt(uoHash); - console.log('\x1b[33m%s\x1b[0m', `Transaction hash: ${txHash}`); + let userOpsReceipt = null; + const timeout = Date.now() + 60000; // 1 minute timeout + while((userOpsReceipt == null) && (Date.now() < timeout)) { + await sleep(2); + userOpsReceipt = await primeSdk.getUserOpReceipt(uoHash); + } + console.log('\x1b[33m%s\x1b[0m', `Transaction Receipt: `, userOpsReceipt); } main() diff --git a/examples/04-transfer-nft.ts b/examples/04-transfer-nft.ts index 1e5a85e7..2de3664d 100644 --- a/examples/04-transfer-nft.ts +++ b/examples/04-transfer-nft.ts @@ -2,6 +2,7 @@ import { ethers } from 'ethers'; import { PrimeSdk } from '../src'; import { printOp } from '../src/sdk/common/OperationUtils'; import * as dotenv from 'dotenv'; +import { sleep } from '../src/sdk/common'; dotenv.config(); @@ -34,17 +35,22 @@ async function main() { console.log('transactions: ', userOpsBatch); // sign transactions added to the batch - const op = await primeSdk.sign(); - console.log(`Signed UserOp: ${await printOp(op)}`); + const op = await primeSdk.estimate(); + console.log(`Estimated UserOp: ${await printOp(op)}`); - // sending to the bundler... + // sign the userOps and sending to the bundler... const uoHash = await primeSdk.send(op); console.log(`UserOpHash: ${uoHash}`); // get transaction hash... console.log('Waiting for transaction...'); - const txHash = await primeSdk.getUserOpReceipt(uoHash); - console.log('\x1b[33m%s\x1b[0m', `Transaction hash: ${txHash}`); + let userOpsReceipt = null; + const timeout = Date.now() + 60000; // 1 minute timeout + while((userOpsReceipt == null) && (Date.now() < timeout)) { + await sleep(2); + userOpsReceipt = await primeSdk.getUserOpReceipt(uoHash); + } + console.log('\x1b[33m%s\x1b[0m', `Transaction Receipt: `, userOpsReceipt); } main() diff --git a/examples/scripts/commands/NFTTransfer.ts b/examples/scripts/commands/NFTTransfer.ts index ee25abd4..750aac25 100644 --- a/examples/scripts/commands/NFTTransfer.ts +++ b/examples/scripts/commands/NFTTransfer.ts @@ -3,6 +3,7 @@ import { ethers } from "ethers"; import config from "../../config.json"; import { PrimeSdk } from "../../../src"; import { printOp } from "../../../src/sdk/common/OperationUtils"; +import { sleep } from "../../../src/sdk/common"; export default async function main( tknid: number, @@ -31,15 +32,20 @@ export default async function main( await primeSdk.addUserOpsToBatch({to: tokenAddress, data: erc721Data}); console.log(`Added transaction to batch`); - const op = await primeSdk.sign(); - console.log(`Signed UserOp: ${await printOp(op)}`); + const op = await primeSdk.estimate(); + console.log(`Estimated UserOp: ${await printOp(op)}`); - // sending to the bundler... + // sign the userOp and sending to the bundler... const uoHash = await primeSdk.send(op); console.log(`UserOpHash: ${uoHash}`); // get transaction hash... console.log('Waiting for transaction...'); - const txHash = await primeSdk.getUserOpReceipt(uoHash); - console.log('\x1b[33m%s\x1b[0m', `Transaction hash: ${txHash}`); + let userOpsReceipt = null; + const timeout = Date.now() + 60000; // 1 minute timeout + while((userOpsReceipt == null) && (Date.now() < timeout)) { + await sleep(2); + userOpsReceipt = await primeSdk.getUserOpReceipt(uoHash); + } + console.log('\x1b[33m%s\x1b[0m', `Transaction Receipt: `, userOpsReceipt); } diff --git a/examples/scripts/commands/batchErc20Transfer.ts b/examples/scripts/commands/batchErc20Transfer.ts index 99268e28..7acc8f7e 100644 --- a/examples/scripts/commands/batchErc20Transfer.ts +++ b/examples/scripts/commands/batchErc20Transfer.ts @@ -4,6 +4,7 @@ import { ERC20_ABI } from '../../../src/sdk/helpers/abi/ERC20_ABI'; import config from "../../config.json"; import { PrimeSdk } from '../../../src'; import { printOp } from "../../../src/sdk/common/OperationUtils"; +import { sleep } from "../../../src/sdk/common"; // This example requires several layers of calls: // EntryPoint @@ -52,15 +53,20 @@ export default async function main( await primeSdk.addUserOpsToBatch({to: dest[i], data: data[i]}) } - const op = await primeSdk.sign(); - console.log(`Signed UserOp: ${await printOp(op)}`); + const op = await primeSdk.estimate(); + console.log(`Estimated UserOp: ${await printOp(op)}`); - // sending to the bundler... + // sign the userop and sending to the bundler... const uoHash = await primeSdk.send(op); console.log(`UserOpHash: ${uoHash}`); // get transaction hash... console.log('Waiting for transaction...'); - const txHash = await primeSdk.getUserOpReceipt(uoHash); - console.log('\x1b[33m%s\x1b[0m', `Transaction hash: ${txHash}`); + let userOpsReceipt = null; + const timeout = Date.now() + 60000; // 1 minute timeout + while((userOpsReceipt == null) && (Date.now() < timeout)) { + await sleep(2); + userOpsReceipt = await primeSdk.getUserOpReceipt(uoHash); + } + console.log('\x1b[33m%s\x1b[0m', `Transaction Receipt: `, userOpsReceipt); } diff --git a/examples/scripts/commands/erc20Approve.ts b/examples/scripts/commands/erc20Approve.ts index a3465407..e51b27af 100644 --- a/examples/scripts/commands/erc20Approve.ts +++ b/examples/scripts/commands/erc20Approve.ts @@ -4,6 +4,7 @@ import { ERC20_ABI } from '../../../src/sdk/helpers/abi/ERC20_ABI'; import config from "../../config.json"; import { PrimeSdk } from "../../../src"; import { printOp } from "../../../src/sdk/common/OperationUtils"; +import { sleep } from "../../../src/sdk/common"; export default async function main( tkn: string, @@ -30,15 +31,20 @@ export default async function main( await primeSdk.addUserOpsToBatch({to: erc20.address, data: approveData}); console.log(`Added transaction to batch`); - const op = await primeSdk.sign(); - console.log(`Signed UserOp: ${await printOp(op)}`); + const op = await primeSdk.estimate(); + console.log(`Estimated UserOp: ${await printOp(op)}`); - // sending to the bundler... + // sign the userOp and sending to the bundler... const uoHash = await primeSdk.send(op); console.log(`UserOpHash: ${uoHash}`); // get transaction hash... console.log('Waiting for transaction...'); - const txHash = await primeSdk.getUserOpReceipt(uoHash); - console.log('\x1b[33m%s\x1b[0m', `Transaction hash: ${txHash}`); + let userOpsReceipt = null; + const timeout = Date.now() + 60000; // 1 minute timeout + while((userOpsReceipt == null) && (Date.now() < timeout)) { + await sleep(2); + userOpsReceipt = await primeSdk.getUserOpReceipt(uoHash); + } + console.log('\x1b[33m%s\x1b[0m', `Transaction Receipt: `, userOpsReceipt); } diff --git a/examples/scripts/commands/erc20Transfer.ts b/examples/scripts/commands/erc20Transfer.ts index 946ff033..909308a9 100644 --- a/examples/scripts/commands/erc20Transfer.ts +++ b/examples/scripts/commands/erc20Transfer.ts @@ -4,6 +4,7 @@ import { ERC20_ABI } from '../../../src/sdk/helpers/abi/ERC20_ABI'; import config from "../../config.json"; import { PrimeSdk } from "../../../src"; import { printOp } from "../../../src/sdk/common/OperationUtils"; +import { sleep } from "../../../src/sdk/common"; export default async function main( tkn: string, @@ -32,15 +33,20 @@ export default async function main( await primeSdk.addUserOpsToBatch({to: erc20.address, data: transferData}); console.log(`Added transaction to batch`); - const op = await primeSdk.sign(); - console.log(`Signed UserOp: ${await printOp(op)}`); + const op = await primeSdk.estimate(); + console.log(`Estimated UserOp: ${await printOp(op)}`); - // sending to the bundler... + // sign the UserOp and sending to the bundler... const uoHash = await primeSdk.send(op); console.log(`UserOpHash: ${uoHash}`); // get transaction hash... console.log('Waiting for transaction...'); - const txHash = await primeSdk.getUserOpReceipt(uoHash); - console.log('\x1b[33m%s\x1b[0m', `Transaction hash: ${txHash}`); + let userOpsReceipt = null; + const timeout = Date.now() + 60000; // 1 minute timeout + while((userOpsReceipt == null) && (Date.now() < timeout)) { + await sleep(2); + userOpsReceipt = await primeSdk.getUserOpReceipt(uoHash); + } + console.log('\x1b[33m%s\x1b[0m', `Transaction Receipt: `, userOpsReceipt); } diff --git a/examples/scripts/commands/transfer.ts b/examples/scripts/commands/transfer.ts index d86ad3c1..77da0269 100644 --- a/examples/scripts/commands/transfer.ts +++ b/examples/scripts/commands/transfer.ts @@ -3,6 +3,7 @@ import { ethers } from "ethers"; import config from "../../config.json"; import { PrimeSdk } from "../../../src"; import { printOp } from "../../../src/sdk/common/OperationUtils"; +import { sleep } from "../../../src/sdk/common"; export default async function main(t: string, amt: string) { @@ -18,15 +19,20 @@ export default async function main(t: string, amt: string) { await primeSdk.addUserOpsToBatch({to: target, value}); console.log(`Added transaction to batch`); - const op = await primeSdk.sign(); - console.log(`Signed UserOp: ${await printOp(op)}`); + const op = await primeSdk.estimate(); + console.log(`Estimated UserOp: ${await printOp(op)}`); - // sending to the bundler... + // sign the userOp and sending to the bundler... const uoHash = await primeSdk.send(op); console.log(`UserOpHash: ${uoHash}`); // get transaction hash... console.log('Waiting for transaction...'); - const txHash = await primeSdk.getUserOpReceipt(uoHash); - console.log('\x1b[33m%s\x1b[0m', `Transaction hash: ${txHash}`); + let userOpsReceipt = null; + const timeout = Date.now() + 60000; // 1 minute timeout + while((userOpsReceipt == null) && (Date.now() < timeout)) { + await sleep(2); + userOpsReceipt = await primeSdk.getUserOpReceipt(uoHash); + } + console.log('\x1b[33m%s\x1b[0m', `Transaction Receipt: `, userOpsReceipt); } diff --git a/package-lock.json b/package-lock.json index 5812444e..9176ee1c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@etherspot/prime-sdk", - "version": "1.0.4", + "version": "1.1.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@etherspot/prime-sdk", - "version": "1.0.4", + "version": "1.1.0", "license": "MIT", "dependencies": { "@thehubbleproject/bls": "0.5.1", diff --git a/package.json b/package.json index a7adf054..1de9583c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@etherspot/prime-sdk", - "version": "1.0.4", + "version": "1.1.0", "description": "Etherspot Prime (Account Abstraction) SDK", "keywords": [ "ether", diff --git a/src/sdk/base/BaseAccountAPI.ts b/src/sdk/base/BaseAccountAPI.ts index 42926723..4c113916 100644 --- a/src/sdk/base/BaseAccountAPI.ts +++ b/src/sdk/base/BaseAccountAPI.ts @@ -384,12 +384,7 @@ export abstract class BaseAccountAPI { } const provider = this.services.walletService.getWalletProvider(); const callGasLimit = - parseNumber(detailsForUserOp.gasLimit) ?? - (await provider.estimateGas({ - from: this.entryPointAddress, - to: this.getAccountAddress(), - data: callData, - })); + parseNumber(detailsForUserOp.gasLimit) ?? BigNumber.from(35000) return { callData, diff --git a/src/sdk/base/HttpRpcClient.ts b/src/sdk/base/HttpRpcClient.ts index d099da57..39dd0b88 100644 --- a/src/sdk/base/HttpRpcClient.ts +++ b/src/sdk/base/HttpRpcClient.ts @@ -58,6 +58,11 @@ export class HttpRpcClient { ]); } + async getUserOpsReceipt(uoHash: string): Promise { + const response = await this.userOpJsonRpcProvider.send('eth_getUserOperationReceipt', [uoHash]); + return response; + } + private async printUserOperation( method: string, [userOp1, entryPointAddress]: [UserOperationStruct, string], diff --git a/src/sdk/common/constants.ts b/src/sdk/common/constants.ts index e0957023..04c9c8f2 100644 --- a/src/sdk/common/constants.ts +++ b/src/sdk/common/constants.ts @@ -8,4 +8,4 @@ export enum HeaderNames { ProjectMetadata = 'x-project-metadata', } -export const bufferPercent = 13; // Buffer in percent +export const bufferPercent:number = 13; // Buffer in percent diff --git a/src/sdk/common/getGasFee.ts b/src/sdk/common/getGasFee.ts index 83d62a41..e1bd0840 100644 --- a/src/sdk/common/getGasFee.ts +++ b/src/sdk/common/getGasFee.ts @@ -1,4 +1,4 @@ -import { BigNumberish, ethers } from 'ethers'; +import { BigNumber, BigNumberish, ethers } from 'ethers'; import { bufferPercent } from './constants'; export interface Gas { @@ -9,6 +9,7 @@ export interface Gas { export async function getGasFee(provider: ethers.providers.JsonRpcProvider): Promise { try { const [fee, block] = await provider.send('eth_maxPriorityFeePerGas', []); + if (BigNumber.from(0).eq(fee)) return { maxFeePerGas: BigNumber.from(1), maxPriorityFeePerGas: BigNumber.from(1) }; const tip = ethers.BigNumber.from(fee); const buffer = tip.div(100).mul(bufferPercent); const maxPriorityFeePerGas = tip.add(buffer); diff --git a/src/sdk/sdk.ts b/src/sdk/sdk.ts index cebc254e..3515268a 100644 --- a/src/sdk/sdk.ts +++ b/src/sdk/sdk.ts @@ -119,7 +119,7 @@ export class PrimeSdk { return this.etherspotWallet.getCounterFactualAddress(); } - async sign(gasDetails?: TransactionGasInfoForUserOp) { + async estimate(gasDetails?: TransactionGasInfoForUserOp) { const gas = await this.getGasFee(); if (this.userOpsBatch.to.length < 1){ @@ -133,7 +133,7 @@ export class PrimeSdk { ...gasDetails, } - let partialtx = await this.etherspotWallet.createSignedUserOp({ + let partialtx = await this.etherspotWallet.createUnsignedUserOp({ ...tx, ...gas, }); @@ -146,7 +146,7 @@ export class PrimeSdk { partialtx.callGasLimit = BigNumber.from(bundlerGasEstimate.callGasLimit); } - return await this.etherspotWallet.signUserOp(partialtx); + return partialtx; } @@ -155,7 +155,8 @@ export class PrimeSdk { } async send(userOp: UserOperationStruct) { - return this.bundler.sendUserOpToBundler(userOp); + const signedUserOp = await this.etherspotWallet.signUserOp(userOp); + return this.bundler.sendUserOpToBundler(signedUserOp); } async getNativeBalance() { @@ -177,21 +178,8 @@ export class PrimeSdk { return ethers.utils.formatUnits(balance[0], dec); } - async getUserOpReceipt(userOpHash: string, timeout = 60000, interval = 5000): Promise { - const block = await this.etherspotWallet.provider.getBlock('latest'); - const endtime = Date.now() + timeout; - while (Date.now() < endtime) { - const events = await this.etherspotWallet.epView.queryFilter( - this.etherspotWallet.epView.filters.UserOperationEvent(userOpHash), - Math.max(100, block.number - 100), - ); - if (events.length > 0) { - console.log(events[0].args.actualGasUsed.toString()); - return events[0].transactionHash; - } - await new Promise((resolve) => setTimeout(resolve, interval)); - } - return null; + async getUserOpReceipt(userOpHash: string) { + return this.bundler.getUserOpsReceipt(userOpHash); } async getUserOpHash(userOp: UserOperationStruct) { @@ -201,6 +189,7 @@ export class PrimeSdk { async addUserOpsToBatch( tx: UserOpsRequest, ): Promise { + if (!tx.data && !tx.value) throw new Error('Data and Value both cannot be empty'); this.userOpsBatch.to.push(tx.to); this.userOpsBatch.value.push(tx.value ?? BigNumber.from(0)); this.userOpsBatch.data.push(tx.data ?? '0x'); From 87ed9eae90a1b77606de82bae18ba82581c63dc2 Mon Sep 17 00:00:00 2001 From: Vignesh Date: Fri, 21 Jul 2023 14:23:00 +0530 Subject: [PATCH 8/8] sorted networks supported --- src/sdk/network/constants.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sdk/network/constants.ts b/src/sdk/network/constants.ts index 1aeda71d..17fa61c3 100644 --- a/src/sdk/network/constants.ts +++ b/src/sdk/network/constants.ts @@ -21,7 +21,7 @@ export enum NetworkNames { Mantle = 'Mantle', } -export const SupportedNetworks = [1, 10, 100, 10200, 11155111, 122, 123, 137, 20197, 2357, 31, 420, 42161, 421613, 5, 5000, 80001, 84531] +export const SupportedNetworks = [1, 5, 10, 31, 100, 122, 123, 137, 420, 2357, 5000, 10200, 20197, 42161, 80001, 84531, 421613, 11155111] export const NETWORK_NAME_TO_CHAIN_ID: { [key: string]: number;