diff --git a/src/utils/bzz-abi.ts b/src/utils/bzz-abi.ts new file mode 100644 index 00000000..4f6c5ce1 --- /dev/null +++ b/src/utils/bzz-abi.ts @@ -0,0 +1,45 @@ +export const BZZ_TOKEN_ADDRESS = '0xdBF3Ea6F5beE45c02255B2c26a16F300502F68da' +export const bzzABI = [ + { + type: 'function', + stateMutability: 'view', + payable: false, + outputs: [ + { + type: 'uint256', + name: '', + }, + ], + name: 'balanceOf', + inputs: [ + { + type: 'address', + name: '_owner', + }, + ], + constant: true, + }, + { + type: 'function', + stateMutability: 'nonpayable', + payable: false, + outputs: [ + { + type: 'bool', + name: '', + }, + ], + name: 'transfer', + inputs: [ + { + type: 'address', + name: '_to', + }, + { + type: 'uint256', + name: '_value', + }, + ], + constant: false, + }, +] diff --git a/src/utils/bzz-contract-interface.ts b/src/utils/bzz-contract-interface.ts deleted file mode 100644 index 2f227072..00000000 --- a/src/utils/bzz-contract-interface.ts +++ /dev/null @@ -1,25 +0,0 @@ -export const bzzContractInterface = [ - { - type: 'function', - stateMutability: 'nonpayable', - payable: false, - outputs: [ - { - type: 'bool', - name: '', - }, - ], - name: 'transfer', - inputs: [ - { - type: 'address', - name: '_to', - }, - { - type: 'uint256', - name: '_value', - }, - ], - constant: false, - }, -] diff --git a/src/utils/rpc.ts b/src/utils/rpc.ts index ce8bbd11..91179314 100644 --- a/src/utils/rpc.ts +++ b/src/utils/rpc.ts @@ -1,6 +1,6 @@ import { debounce } from '@material-ui/core' -import { Contract, providers, Wallet } from 'ethers' -import { bzzContractInterface } from './bzz-contract-interface' +import { Contract, providers, Wallet, BigNumber as BN } from 'ethers' +import { bzzABI, BZZ_TOKEN_ADDRESS } from './bzz-abi' async function eth_getBalance(address: string, provider: providers.JsonRpcProvider): Promise { if (!address.startsWith('0x')) { @@ -17,36 +17,15 @@ async function eth_getBlockByNumber(provider: providers.JsonRpcProvider): Promis return blockNumber.toString() } -const partialERC20tokenABI = [ - { - constant: true, - inputs: [ - { - name: '_owner', - type: 'address', - }, - ], - name: 'balanceOf', - outputs: [ - { - name: 'balance', - type: 'uint256', - }, - ], - payable: false, - type: 'function', - }, -] - async function eth_getBalanceERC20( address: string, provider: providers.JsonRpcProvider, - tokenAddress = '0xdbf3ea6f5bee45c02255b2c26a16f300502f68da', + tokenAddress = BZZ_TOKEN_ADDRESS, ): Promise { if (!address.startsWith('0x')) { address = `0x${address}` } - const contract = new Contract(tokenAddress, partialERC20tokenABI, provider) + const contract = new Contract(tokenAddress, bzzABI, provider) const balance = await contract.balanceOf(address) return balance.toString() @@ -57,14 +36,26 @@ interface TransferResponse { receipt: providers.TransactionReceipt } +export async function estimateNativeTransferTransactionCost( + privateKey: string, + jsonRpcProvider: string, +): Promise<{ gasPrice: BN; totalCost: BN }> { + const signer = await makeReadySigner(privateKey, jsonRpcProvider) + const gasLimit = '21000' + const gasPrice = await signer.getGasPrice() + + return { gasPrice, totalCost: gasPrice.mul(gasLimit) } +} + export async function sendNativeTransaction( privateKey: string, to: string, value: string, jsonRpcProvider: string, + externalGasPrice?: BN, ): Promise { const signer = await makeReadySigner(privateKey, jsonRpcProvider) - const gasPrice = await signer.getGasPrice() + const gasPrice = externalGasPrice ?? (await signer.getGasPrice()) const transaction = await signer.sendTransaction({ to, value, gasPrice }) const receipt = await transaction.wait(1) @@ -79,7 +70,7 @@ export async function sendBzzTransaction( ): Promise { const signer = await makeReadySigner(privateKey, jsonRpcProvider) const gasPrice = await signer.getGasPrice() - const bzz = new Contract('0xdBF3Ea6F5beE45c02255B2c26a16F300502F68da', bzzContractInterface, signer) + const bzz = new Contract(BZZ_TOKEN_ADDRESS, bzzABI, signer) const transaction = await bzz.transfer(to, value, { gasPrice }) const receipt = await transaction.wait(1) diff --git a/src/utils/wallet.ts b/src/utils/wallet.ts index a8ce6333..b84beb17 100644 --- a/src/utils/wallet.ts +++ b/src/utils/wallet.ts @@ -2,7 +2,7 @@ import { providers, Wallet } from 'ethers' import { sleepMs } from '.' import { BzzToken } from '../models/BzzToken' import { DaiToken } from '../models/DaiToken' -import { Rpc } from './rpc' +import { estimateNativeTransferTransactionCost, Rpc } from './rpc' export class WalletAddress { private constructor( @@ -59,19 +59,20 @@ export class ResolvedWallet { } public async transfer(destination: string, jsonRpcProvider: string): Promise { - const DUMMY_GAS_PRICE = '50000000000000' - if (this.bzz.toDecimal.gt(0.05)) { await Rpc.sendBzzTransaction(this.privateKey, destination, this.bzz.toString, jsonRpcProvider) await sleepMs(5_000) } - if (this.dai.toBigNumber.gt(DUMMY_GAS_PRICE)) { + const { gasPrice, totalCost } = await estimateNativeTransferTransactionCost(this.privateKey, jsonRpcProvider) + + if (this.dai.toBigNumber.gt(totalCost.toString())) { await Rpc.sendNativeTransaction( this.privateKey, destination, - this.dai.toBigNumber.minus(DUMMY_GAS_PRICE).toString(), + this.dai.toBigNumber.minus(totalCost.toString()).toString(), jsonRpcProvider, + gasPrice, ) } }