From a62334a692709b0ab8682da255888738d8d0c225 Mon Sep 17 00:00:00 2001 From: Raul Duarte Pereira Date: Thu, 15 Aug 2024 15:41:51 -0300 Subject: [PATCH] CU-86dud53c9 - BSEthereum - Transfer - Change type 1 transaction to type 2 --- .../CU-86dud53c9_2024-08-15-18-41.json | 10 ++ packages/bs-ethereum/src/BSEthereum.ts | 145 ++++++++---------- packages/bs-ethereum/src/BSEthereumHelper.ts | 3 + .../src/__tests__/BSEthereum.spec.ts | 8 +- 4 files changed, 81 insertions(+), 85 deletions(-) create mode 100644 common/changes/@cityofzion/bs-ethereum/CU-86dud53c9_2024-08-15-18-41.json diff --git a/common/changes/@cityofzion/bs-ethereum/CU-86dud53c9_2024-08-15-18-41.json b/common/changes/@cityofzion/bs-ethereum/CU-86dud53c9_2024-08-15-18-41.json new file mode 100644 index 0000000..3c4c9ff --- /dev/null +++ b/common/changes/@cityofzion/bs-ethereum/CU-86dud53c9_2024-08-15-18-41.json @@ -0,0 +1,10 @@ +{ + "changes": [ + { + "packageName": "@cityofzion/bs-ethereum", + "comment": "Change transaction transfer to type 2", + "type": "patch" + } + ], + "packageName": "@cityofzion/bs-ethereum" +} \ No newline at end of file diff --git a/packages/bs-ethereum/src/BSEthereum.ts b/packages/bs-ethereum/src/BSEthereum.ts index bde2a93..c4d3547 100644 --- a/packages/bs-ethereum/src/BSEthereum.ts +++ b/packages/bs-ethereum/src/BSEthereum.ts @@ -59,6 +59,56 @@ export class BSEthereum this.setNetwork(network) } + async #buildTransferParams(param: TransferParam) { + const provider = new ethers.providers.JsonRpcProvider(this.network.url) + + let ledgerTransport: Transport | undefined + + if (param.isLedger) { + if (!this.ledgerService.getLedgerTransport) + throw new Error('You must provide getLedgerTransport function to use Ledger') + ledgerTransport = await this.ledgerService.getLedgerTransport(param.senderAccount) + } + + let signer: ethers.Signer + if (ledgerTransport) { + signer = this.ledgerService.getSigner(ledgerTransport, provider) + } else { + signer = new ethers.Wallet(param.senderAccount.key, provider) + } + + const decimals = param.intent.tokenDecimals ?? 18 + const amount = ethersBigNumber.parseFixed(param.intent.amount, decimals) + + const gasPrice = await provider.getGasPrice() + + let transactionParams: ethers.utils.Deferrable = { + type: 2, + } + + const isNative = + BSEthereumHelper.normalizeHash(this.feeToken.hash) === BSEthereumHelper.normalizeHash(param.intent.tokenHash) + if (isNative) { + transactionParams.to = param.intent.receiverAddress + transactionParams.value = amount + } else { + const contract = new ethers.Contract(param.intent.tokenHash, [ + 'function transfer(address to, uint amount) returns (bool)', + ]) + const populatedTransaction = await contract.populateTransaction.transfer(param.intent.receiverAddress, amount) + transactionParams = { + ...populatedTransaction, + ...transactionParams, + } + } + + return { + transactionParams, + signer, + gasPrice, + } + } + #setTokens(network: Network) { const nativeAsset = BSEthereumHelper.getNativeAsset(network) this.tokens = [nativeAsset] @@ -153,95 +203,28 @@ export class BSEthereum } async transfer(param: TransferParam): Promise { - const provider = new ethers.providers.JsonRpcProvider(this.network.url) - - let ledgerTransport: Transport | undefined - - if (param.isLedger) { - if (!this.ledgerService.getLedgerTransport) - throw new Error('You must provide getLedgerTransport function to use Ledger') - ledgerTransport = await this.ledgerService.getLedgerTransport(param.senderAccount) - } + const { signer, transactionParams, gasPrice } = await this.#buildTransferParams(param) - let signer: ethers.Signer - if (ledgerTransport) { - signer = this.ledgerService.getSigner(ledgerTransport, provider) - } else { - signer = new ethers.Wallet(param.senderAccount.key, provider) - } - - const decimals = param.intent.tokenDecimals ?? 18 - const amount = ethersBigNumber.parseFixed(param.intent.amount, decimals) - - const gasPrice = await provider.getGasPrice() - - let transactionParams: ethers.utils.Deferrable = { - gasPrice, - } - - const isNative = - BSEthereumHelper.normalizeHash(this.feeToken.hash) === BSEthereumHelper.normalizeHash(param.intent.tokenHash) - if (isNative) { - transactionParams.to = param.intent.receiverAddress - transactionParams.value = amount - } else { - const contract = new ethers.Contract(param.intent.tokenHash, [ - 'function transfer(address to, uint amount) returns (bool)', - ]) - const populatedTransaction = await contract.populateTransaction.transfer(param.intent.receiverAddress, amount) - transactionParams = { - ...populatedTransaction, - ...transactionParams, - } + let gasLimit: ethers.BigNumberish + try { + gasLimit = await signer.estimateGas(transactionParams) + } catch { + gasLimit = BSEthereumHelper.DEFAULT_GAS_LIMIT } - const transaction = await signer.sendTransaction(transactionParams) + const transaction = await signer.sendTransaction({ + ...transactionParams, + gasLimit, + maxPriorityFeePerGas: gasPrice, + maxFeePerGas: gasPrice, + }) return transaction.hash } async calculateTransferFee(param: TransferParam): Promise { - const provider = new ethers.providers.JsonRpcProvider(this.network.url) - - let ledgerTransport: Transport | undefined - - if (param.isLedger) { - if (!this.ledgerService.getLedgerTransport) - throw new Error('You must provide getLedgerTransport function to use Ledger') - ledgerTransport = await this.ledgerService.getLedgerTransport(param.senderAccount) - } - - let signer: ethers.Signer - if (ledgerTransport) { - signer = this.ledgerService.getSigner(ledgerTransport, provider) - } else { - signer = new ethers.Wallet(param.senderAccount.key, provider) - } - - const gasPrice = await provider.getGasPrice() - - let estimated: ethers.BigNumber - - const isNative = - BSEthereumHelper.normalizeHash(this.feeToken.hash) === BSEthereumHelper.normalizeHash(param.intent.tokenHash) - const decimals = param.intent.tokenDecimals ?? 18 - const amount = ethersBigNumber.parseFixed(param.intent.amount, decimals) - - if (!isNative) { - const contract = new ethers.Contract( - param.intent.tokenHash, - ['function transfer(address to, uint amount) returns (bool)'], - signer - ) - - estimated = await contract.estimateGas.transfer(param.intent.receiverAddress, amount) - } else { - estimated = await signer.estimateGas({ - to: param.intent.receiverAddress, - value: amount, - }) - } - + const { signer, transactionParams, gasPrice } = await this.#buildTransferParams(param) + const estimated = await signer.estimateGas(transactionParams) return ethers.utils.formatEther(gasPrice.mul(estimated)) } diff --git a/packages/bs-ethereum/src/BSEthereumHelper.ts b/packages/bs-ethereum/src/BSEthereumHelper.ts index 9f9471c..65120c4 100644 --- a/packages/bs-ethereum/src/BSEthereumHelper.ts +++ b/packages/bs-ethereum/src/BSEthereumHelper.ts @@ -21,6 +21,9 @@ export type BSEthereumNetworkId = NetworkId< export class BSEthereumHelper { static DEFAULT_DECIMALS = 18 + + static DEFAULT_GAS_LIMIT = 0x5208 + static #NATIVE_ASSET: Token = { decimals: 18, hash: '-', diff --git a/packages/bs-ethereum/src/__tests__/BSEthereum.spec.ts b/packages/bs-ethereum/src/__tests__/BSEthereum.spec.ts index 5a95b4f..f1cb789 100644 --- a/packages/bs-ethereum/src/__tests__/BSEthereum.spec.ts +++ b/packages/bs-ethereum/src/__tests__/BSEthereum.spec.ts @@ -117,10 +117,10 @@ describe('BSEthereum', () => { const transactionHash = await bsEthereum.transfer({ senderAccount: account, intent: { - amount: '0.00000001', + amount: '0.00001', receiverAddress: '0xFACf5446B71dB33E920aB1769d9427146183aEcd', - tokenDecimals: 18, - tokenHash: '0xba62bcfcaafc6622853cca2be6ac7d845bc0f2dc', + tokenDecimals: 6, + tokenHash: '0x1291070C5f838DCCDddc56312893d3EfE9B372a8', }, }) @@ -197,7 +197,7 @@ describe('BSEthereum', () => { const transactionHash = await service.transfer({ senderAccount: account, intent: { - amount: '0.00000001', + amount: '0.0000000000001', receiverAddress: '0x82B5Cd984880C8A821429cFFf89f36D35BaeBE89', tokenDecimals: 18, tokenHash: '-',