Skip to content

Commit

Permalink
Merge pull request #331 from consensusnetworks/update/calculate-fees
Browse files Browse the repository at this point in the history
Update/calculate fees
  • Loading branch information
ccali11 committed May 11, 2023
2 parents db016d6 + 3b2cd3c commit 3ec2aa4
Show file tree
Hide file tree
Showing 4 changed files with 106 additions and 17 deletions.
107 changes: 95 additions & 12 deletions apps/web/src/composables/ethers.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { ref } from 'vue'
import { ethers } from 'ethers'
import { BrowserProviders, EthersProvider, MessageInit, TransactionInit } from '@/interfaces/index'
import { LoginCredentials, ProviderString } from '@casimir/types'
import { GasEstimate, LoginCredentials, ProviderString } from '@casimir/types'
import useAuth from '@/composables/auth'
import useEnvironment from '@/composables/environment'

Expand Down Expand Up @@ -31,6 +31,75 @@ export default function useEthers() {
}
}

/**
* Estimate gas fee using EIP 1559 methodology
* @returns string in ETH
*/
async function estimateEIP1559GasFee(rpcUrl: string, unsignedTransaction: ethers.utils.Deferrable<ethers.providers.TransactionRequest>) : Promise<GasEstimate> {
try {
const provider = new ethers.providers.JsonRpcProvider(rpcUrl)
const gasPrice = await provider.getFeeData() as ethers.providers.FeeData
const { maxFeePerGas, maxPriorityFeePerGas } = gasPrice
const maxFeePerGasInWei = maxFeePerGas ? ethers.utils.parseEther(maxFeePerGas.toString()) : '0'
const maxPriorityFeePerGasInWei = maxPriorityFeePerGas ? ethers.utils.parseEther(maxPriorityFeePerGas.toString()) : '0'
if (maxFeePerGasInWei === '0') throw new Error('maxFeePerGasInWei is zero')
if (maxPriorityFeePerGasInWei === '0') throw new Error('maxPriorityFeePerGasInWei is zero')

const { to, from, value } = unsignedTransaction
const tx = {
from,
to,
value,
type: 2, // TODO: 2 is for EIP 1559, 0 is for legacy; make this dynamic
maxFeePerGas: maxFeePerGasInWei,
maxPriorityFeePerGas: maxPriorityFeePerGasInWei
}
const gasEstimate = await provider.estimateGas(tx)
// TODO: What is the way to get gas estimate in human readable format?
// const gasEstimateInEth = ethers.utils.formatEther(gasEstimate)
const fee = maxPriorityFeePerGasInWei?.mul(gasEstimate).add(maxFeePerGasInWei)
const feeInWei = ethers.utils.formatEther(fee)
const feeInEth = (parseInt(feeInWei) / 10**18).toFixed(8).toString()
return {
gasEstimate,
fee: feeInEth
}
} catch (err) {
console.error('There was an error in estimateGasFee :>> ', err)
return {
gasEstimate: '0',
fee: '0'
}
}
}

/**
* Estimate gas fee using legacy methodology
* @returns string in ETH
* @deprecated
* @see estimateEIP1559GasFee
*/
async function estimateLegacyGasFee(rpcUrl: string, unsignedTransaction: ethers.utils.Deferrable<ethers.providers.TransactionRequest>) : Promise<GasEstimate> {
try {
const provider = new ethers.providers.JsonRpcProvider(rpcUrl)
const gasPrice = await provider.getGasPrice()
const gasLimit = await provider.estimateGas(unsignedTransaction as ethers.utils.Deferrable<ethers.providers.TransactionRequest>)
const fee = gasPrice.mul(gasLimit)
const feeInWei = ethers.utils.formatEther(fee)
const feeInEth = (parseInt(feeInWei) / 10**18).toFixed(8).toString()
return {
gasLimit,
fee: feeInEth
}
} catch (err) {
console.error('There was an error in estimateGasFee :>> ', err)
return {
gasLimit: '0',
fee: '0'
}
}
}

async function getEthersAddress (providerString: ProviderString) {
const provider = availableProviders.value[providerString as keyof BrowserProviders]
if (provider) {
Expand Down Expand Up @@ -80,6 +149,13 @@ export default function useEthers() {
return currency
}

async function getMaxETHAfterFees(rpcUrl: string, unsignedTx: ethers.utils.Deferrable<ethers.providers.TransactionRequest>, totalAmount: string) {
const { fee } = await estimateEIP1559GasFee(rpcUrl, unsignedTx)
const total = parseInt(totalAmount) - parseInt(fee)
const maxAfterFees = ethers.utils.formatEther(total).toString()
return maxAfterFees
}

async function loginWithEthers(loginCredentials: LoginCredentials) {
const { provider, address, currency } = loginCredentials
const browserProvider = availableProviders.value[provider as keyof BrowserProviders]
Expand Down Expand Up @@ -111,19 +187,23 @@ export default function useEthers() {
}

async function sendEthersTransaction(
{ to, value, providerString }: TransactionInit
{ from, to, value, providerString }: TransactionInit
) {
const browserProvider =
availableProviders.value[providerString as keyof BrowserProviders]
const web3Provider: ethers.providers.Web3Provider =
new ethers.providers.Web3Provider(browserProvider as EthersProvider)
const signer = web3Provider.getSigner()
const etherAmount = ethers.utils.parseEther(value)
const signer = getEthersBrowserSigner(providerString) as ethers.Signer
const weiAmount = ethers.utils.parseEther(value)
const tx = {
from,
to,
value: etherAmount
value: weiAmount
}
const ethFees = await estimateEIP1559GasFee(ethereumURL, tx)
const { fee, gasEstimate } = ethFees
const requiredBalance = parseInt(value) + parseInt(fee)
const balance = await getEthersBalance(from)
if (parseInt(balance) < requiredBalance) {
throw new Error('Insufficient balance')
}
console.log('tx :>> ', tx)
console.log(`Sending ${value} ETH to ${to} with estimated ${fee} ETH in fees using ~${gasEstimate} in gas.`)
return await signer.sendTransaction(tx)
}

Expand Down Expand Up @@ -166,11 +246,14 @@ export default function useEthers() {

return {
addEthersNetwork,
ethersProviderList,
estimateEIP1559GasFee,
estimateLegacyGasFee,
ethersProviderList,
getMaxETHAfterFees,
getEthersAddress,
getEthersAddressWithBalance,
getEthersBalance,
getEthersBrowserSigner,
getEthersBrowserSigner,
getEthersBrowserProviderSelectedCurrency,
getGasPriceAndLimit,
loginWithEthers,
Expand Down
8 changes: 4 additions & 4 deletions apps/web/src/composables/wallet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ import { MessageInit, TransactionInit } from '@/interfaces/index'
import * as Session from 'supertokens-web-js/recipe/session'
import router from './router'

// Test ethereum send from address : 0xd557a5745d4560B24D36A68b52351ffF9c86A212
// Test ethereum send to address : 0xD4e5faa8aD7d499Aa03BDDE2a3116E66bc8F8203
// Test ethereum send to address : 0xd557a5745d4560B24D36A68b52351ffF9c86A212
// Test solana address: 7aVow9eVQjwn7Y4y7tAbPM1pfrE1TzjmJhxcRt8QwX5F
// Test iotex send to address: acc://06da5e904240736b1e21ca6dbbd5f619860803af04ff3d54/acme
// Test bitcoin send to address : 2N3Petr4LMH9tRneZCYME9mu33gR5hExvds
Expand All @@ -24,7 +24,7 @@ const activeWallets = ref([
'Ledger',
'IoPay',
] as ProviderString[])
const amount = ref<string>('0.000001')
const amount = ref<string>('1')
const amountToStake = ref<string>('0.0')
const userAddresses = ref<CryptoAddress[]>([])
const loadingUserWallets = ref(false)
Expand All @@ -33,10 +33,10 @@ const selectedProvider = ref<ProviderString>('')
const selectedAddress = ref<string>('')
const selectedPathIndex = ref<string>('')
const selectedCurrency = ref<Currency>('')
const toAddress = ref<string>('2N3Petr4LMH9tRneZCYME9mu33gR5hExvds')
const toAddress = ref<string>('0x728474D29c2F81eb17a669a7582A2C17f1042b57')

export default function useWallet() {
const { ethersProviderList, getEthersAddress, getEthersAddressWithBalance, getEthersBalance, sendEthersTransaction, signEthersMessage, loginWithEthers, getEthersBrowserProviderSelectedCurrency, switchEthersNetwork } = useEthers()
const { estimateEIP1559GasFee, ethersProviderList, getEthersAddress, getEthersAddressWithBalance, getEthersBalance, sendEthersTransaction, signEthersMessage, loginWithEthers, getEthersBrowserProviderSelectedCurrency, switchEthersNetwork } = useEthers()
const { solanaProviderList, getSolanaAddress, sendSolanaTransaction, signSolanaMessage } = useSolana()
const { getLedgerAddress, loginWithLedger, sendLedgerTransaction, signLedgerMessage } = useLedger()
const { getTrezorAddress, loginWithTrezor, sendTrezorTransaction, signTrezorMessage } = useTrezor()
Expand Down
4 changes: 3 additions & 1 deletion common/types/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@ import { AddAccountOptions } from './interfaces/AddAccountOptions'
import { BalanceSnapshot } from './interfaces/BalanceSnapshot'
import { ContractArgs } from './interfaces/ContractArgs'
import { ContractConfig } from './interfaces/ContractConfig'
import { CryptoAddress } from './interfaces/CryptoAddress'
import { Currency } from './interfaces/Currency'
import { DeploymentConfig } from './interfaces/DeploymentConfig'
import { Event } from './interfaces/Event'
import { CryptoAddress } from './interfaces/CryptoAddress'
import { GasEstimate } from './interfaces/GasEstimate'
import { LoginCredentials } from './interfaces/LoginCredentials'
import { Operator } from './interfaces/Operator'
import { Pool } from './interfaces/Pool'
Expand All @@ -29,6 +30,7 @@ export type {
Currency,
DeploymentConfig,
Event,
GasEstimate,
LoginCredentials,
Operator,
Pool,
Expand Down
4 changes: 4 additions & 0 deletions common/types/src/interfaces/GasEstimate.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export interface GasEstimate {
gasLimit: string
fee: string
}

0 comments on commit 3ec2aa4

Please sign in to comment.