Skip to content

Commit

Permalink
fixup! Use eth-balance-checker contracts for batch token balance queries
Browse files Browse the repository at this point in the history
  • Loading branch information
Jon-edge committed Nov 6, 2023
1 parent 260cb08 commit 625cc1e
Showing 1 changed file with 67 additions and 80 deletions.
147 changes: 67 additions & 80 deletions src/ethereum/EthereumNetwork.ts
Original file line number Diff line number Diff line change
Expand Up @@ -503,20 +503,37 @@ export class EthereumNetwork {
return await resultRaw.json()
}

// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
async fetchPostRPC(
method: string,
params: Object,
networkId: number,
url: string
) {
): Promise<any> {
const body = {
id: networkId,
jsonrpc: '2.0',
method,
params
}
url = this.addRpcApiKey(url)

const response = await this.ethEngine.fetchCors(url, {
headers: {
Accept: 'application/json',
'Content-Type': 'application/json'
},
method: 'POST',
body: JSON.stringify(body)
})

const parsedUrl = parse(url, {}, true)
if (!response.ok) {
this.throwError(response, 'fetchPostRPC', parsedUrl.hostname)
}
return await response.json()
}

addRpcApiKey(url: string): string {
const regex = /{{(.*?)}}/g
const match = regex.exec(url)
if (match != null) {
Expand All @@ -533,21 +550,7 @@ export class EthereumNetwork {
throw new Error('Incorrect apikey type for RPC')
}
}

const response = await this.ethEngine.fetchCors(url, {
headers: {
Accept: 'application/json',
'Content-Type': 'application/json'
},
method: 'POST',
body: JSON.stringify(body)
})

const parsedUrl = parse(url, {}, true)
if (!response.ok) {
this.throwError(response, 'fetchPostRPC', parsedUrl.hostname)
}
return await response.json()
return url
}

// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
Expand Down Expand Up @@ -1515,87 +1518,71 @@ export class EthereumNetwork {
*/
// @ts-expect-error
async checkEthBalChecker(): Promise<EthereumNetworkUpdate> {
const { builtinTokens, networkInfo, walletLocalData, currencyInfo } =
const { allTokensMap, networkInfo, walletLocalData, currencyInfo } =
this.ethEngine
const { chainParams, rpcServers, ethBalCheckerContract } = networkInfo

const tokenBal: { [currencyCode: string]: string } = {}
// TODO: Consider just using a specific rpc server for ethers use
const jsonRpcUrl = rpcServers.find(
rpcServer =>
!rpcServer.includes('alchemyApiKey') &&
!rpcServer.includes('infuraProjectId') &&
!rpcServer.includes('poktPortalApiKey')
)
if (ethBalCheckerContract != null && jsonRpcUrl != null) {
if (ethBalCheckerContract == null) return tokenBal

const mainnetAssetAddr = '0x0000000000000000000000000000000000000000'
const balanceQueryAddrs = [
...Object.values(allTokensMap).map(token =>
token.networkLocation?.contractAddress.toLowerCase()
),
mainnetAssetAddr // to query ETH on ETH network, MATIC on MATIC, etc.
]

const promises: any[] = []
rpcServers.forEach(rpcServer => {
const rpcServerWithApiKey = this.addRpcApiKey(rpcServer)
const ethProvider = new ethers.providers.JsonRpcProvider(
jsonRpcUrl,
rpcServerWithApiKey,
chainParams.chainId
)

const mainnetTokenAddr = '0x0000000000000000000000000000000000000000'
const tokenAddrs = [
...Object.values(builtinTokens)
.map(tokenInfo => tokenInfo.networkLocation)
.filter((location): location is JsonObject => location != null)
.map(location => location.contractAddress),
mainnetTokenAddr
]

const contract = new ethers.Contract(
ethBalCheckerContract,
ETH_BAL_CHECKER_ABI,
ethProvider
)

const balances = await contract
.balances([walletLocalData.publicKey], tokenAddrs)
.catch((e: any) => {
this.logError('checkEthBalChecker', e)
})

for (let i = 0; i < balances.length; i++) {
const tokenAddr = tokenAddrs[i]
const balanceBnHex = balances[i]

let unitName
let multiplier
let balanceCurrencyCode
if (tokenAddr === mainnetTokenAddr) {
unitName = 'ether'
const { currencyCode, denominations } = currencyInfo
balanceCurrencyCode = currencyCode
multiplier = denominations[0].multiplier
} else {
const builtinToken = Object.values(builtinTokens).find(
tokenInfo =>
tokenInfo.networkLocation?.contractAddress === tokenAddr
)
if (builtinToken == null) {
this.logError(
'checkEthBalChecker',
new Error(`checkEthBalChecker missing builtinToken: ${tokenAddr}`)
)
continue
}
const { currencyCode, denominations } = builtinToken
balanceCurrencyCode = currencyCode
multiplier = denominations[0].multiplier
unitName = multiplier.length - 1
}

const nativeAmount = mul(
ethers.utils.formatUnits(balanceBnHex, unitName).toString(),
multiplier
)
promises.push(
contract.balances([walletLocalData.publicKey], balanceQueryAddrs)
)
})

tokenBal[balanceCurrencyCode] = nativeAmount
}
} else {
const balances = await promiseAny(promises).catch(e => {
this.logError(
'checkEthBalChecker',
new Error('checkEthBalChecker missing params')
new Error(`All rpc servers failed eth balance checks: ${e}`)
)
return []
})

for (let i = 0; i < balances.length; i++) {
const tokenAddr = balanceQueryAddrs[i]
const balanceBnHex = balances[i]

let balanceCurrencyCode
if (tokenAddr === mainnetAssetAddr) {
const { currencyCode } = currencyInfo
balanceCurrencyCode = currencyCode
} else {
const token = allTokensMap[tokenAddr.replace('0x', '')]
if (token == null) {
this.logError(
'checkEthBalChecker',
new Error(`checkEthBalChecker missing builtinToken: ${tokenAddr}`)
)
continue
}
const { currencyCode } = token
balanceCurrencyCode = currencyCode
}

tokenBal[balanceCurrencyCode] =
ethers.BigNumber.from(balanceBnHex).toString()
}

return { tokenBal, server: 'ethBalChecker' }
Expand Down

0 comments on commit 625cc1e

Please sign in to comment.