diff --git a/packages/common/src/services/audius-backend/AudiusBackend.ts b/packages/common/src/services/audius-backend/AudiusBackend.ts index 0b3ca1b120a..64177a2c7cf 100644 --- a/packages/common/src/services/audius-backend/AudiusBackend.ts +++ b/packages/common/src/services/audius-backend/AudiusBackend.ts @@ -1,4 +1,4 @@ -import { AUDIO, wAUDIO } from '@audius/fixed-decimal' +import { AUDIO, AudioWei, wAUDIO } from '@audius/fixed-decimal' import { AudiusSdk, type StorageNodeSelectorService } from '@audius/sdk' import { type AudiusLibs as AudiusLibsType } from '@audius/sdk-legacy/dist/libs' import type { HedgehogConfig } from '@audius/sdk-legacy/dist/services/hedgehog' @@ -20,6 +20,7 @@ import { VersionedTransaction } from '@solana/web3.js' import BN from 'bn.js' +import { getAddress } from 'viem' import { userMetadataToSdk } from '~/adapters/user' import { Env } from '~/services/env' @@ -1078,33 +1079,25 @@ export const audiusBackend = ({ * Make a request to fetch the eth AUDIO balance of the the user * @params {bool} bustCache * @params {string} ethAddress - Optional ETH wallet address. Defaults to hedgehog wallet - * @returns {Promise} balance or null if failed to fetch balance + * @returns {Promise} balance or null if failed to fetch balance */ async function getBalance({ ethAddress, - bustCache = false + sdk }: { - ethAddress?: string - bustCache?: boolean - } = {}): Promise { + ethAddress: string + sdk: AudiusSdk + }): Promise { await waitForLibsInit() - const wallet = - ethAddress !== undefined - ? ethAddress - : audiusLibs.web3Manager.getWalletAddress() - if (!wallet) return null + if (!ethAddress) return null try { - const ethWeb3 = audiusLibs.ethWeb3Manager.getWeb3() - const checksumWallet = ethWeb3.utils.toChecksumAddress(wallet) - if (bustCache) { - audiusLibs.ethContracts.AudiusTokenClient.bustCache() - } - const balance = await audiusLibs.ethContracts.AudiusTokenClient.balanceOf( - checksumWallet - ) - return balance + const checksumWallet = getAddress(ethAddress) + const balance = await sdk.services.audiusTokenClient.balanceOf({ + account: checksumWallet + }) + return AUDIO(balance).value } catch (e) { console.error(e) reportError({ error: e as Error }) @@ -1175,32 +1168,25 @@ export const audiusBackend = ({ * @params {bool} bustCache * @returns {Promise} balance or null if error */ - async function getAddressTotalStakedBalance( - address: string, - bustCache = false - ) { + async function getAddressTotalStakedBalance(address: string, sdk: AudiusSdk) { await waitForLibsInit() if (!address) return null try { - const ethWeb3 = audiusLibs.ethWeb3Manager.getWeb3() - const checksumWallet = ethWeb3.utils.toChecksumAddress(address) - if (bustCache) { - audiusLibs.ethContracts.AudiusTokenClient.bustCache() - } - const balance = await audiusLibs.ethContracts.AudiusTokenClient.balanceOf( - checksumWallet - ) + const checksumWallet = getAddress(address) + const balance = await sdk.services.audiusTokenClient.balanceOf({ + account: checksumWallet + }) const delegatedBalance = - await audiusLibs.ethContracts.DelegateManagerClient.getTotalDelegatorStake( - checksumWallet + await sdk.services.delegateManagerClient.contract.getTotalDelegatorStake( + { delegatorAddress: checksumWallet } ) const stakedBalance = - await audiusLibs.ethContracts.StakingProxyClient.totalStakedFor( - checksumWallet - ) + await sdk.services.stakingClient.contract.totalStakedFor({ + account: checksumWallet + }) - return balance.add(delegatedBalance).add(stakedBalance) + return AUDIO(balance + delegatedBalance + stakedBalance).value } catch (e) { reportError({ error: e as Error }) console.error(e) diff --git a/packages/common/src/services/wallet-client/WalletClient.ts b/packages/common/src/services/wallet-client/WalletClient.ts index 27fc9f3b87c..3b62466a19a 100644 --- a/packages/common/src/services/wallet-client/WalletClient.ts +++ b/packages/common/src/services/wallet-client/WalletClient.ts @@ -40,15 +40,17 @@ export class WalletClient { /** Get user's current ETH Audio balance. Returns null on failure. */ async getCurrentBalance({ - ethAddress, - bustCache - }: { ethAddress?: string; bustCache?: boolean } = {}): Promise { + ethAddress + }: { + ethAddress: string + }): Promise { try { + const sdk = await this.audiusSdk() const balance = await this.audiusBackendInstance.getBalance({ ethAddress, - bustCache + sdk }) - return balance as BNWei + return new BN(balance?.toString() ?? 0) as BNWei } catch (err) { console.error(err) return null @@ -99,9 +101,14 @@ export class WalletClient { throw new Error('No userbank account.') } - const ercAudioBalance = await this.audiusBackendInstance.getBalance({ - bustCache: true - }) + const ercAudioBalance = new BN( + ( + await this.audiusBackendInstance.getBalance({ + ethAddress, + sdk + }) + )?.toString() ?? 0 + ) if ( !isNullOrUndefined(ercAudioBalance) && ercAudioBalance.gt(new BN('0')) @@ -118,10 +125,7 @@ export class WalletClient { } /** Get total balance of external wallets connected to the user's account. Returns null on failure. */ - async getAssociatedWalletBalance( - userID: ID, - bustCache = false - ): Promise { + async getAssociatedWalletBalance(userID: ID): Promise { try { const sdk = await this.audiusSdk() const { data } = await sdk.users.getConnectedWallets({ @@ -133,12 +137,14 @@ export class WalletClient { } const associatedWallets = userWalletsFromSDK(data) const balances = await Promise.all([ - ...associatedWallets.wallets.map((wallet) => - this.audiusBackendInstance.getAddressTotalStakedBalance( - wallet, - bustCache - ) - ), + ...associatedWallets.wallets.map(async (wallet) => { + const balance = + await this.audiusBackendInstance.getAddressTotalStakedBalance( + wallet, + sdk + ) + return new BN(balance?.toString() ?? 0) as BNWei + }), ...associatedWallets.sol_wallets.map(async (wallet) => { const balance = await this.audiusBackendInstance.getAddressWAudioBalance({ @@ -170,18 +176,21 @@ export class WalletClient { } async getEthWalletBalances( - wallets: string[], - bustCache = false + wallets: string[] ): Promise<{ address: string; balance: BNWei }[]> { try { + const sdk = await this.audiusSdk() const balances: { address: string; balance: BNWei }[] = await Promise.all( wallets.map(async (wallet) => { const balance = await this.audiusBackendInstance.getAddressTotalStakedBalance( wallet, - bustCache + sdk ) - return { address: wallet, balance: balance as BNWei } + return { + address: wallet, + balance: new BN(balance?.toString() ?? 0) as BNWei + } }) ) return balances diff --git a/packages/sdk/src/sdk/services/Ethereum/contracts/AudiusToken/AudiusTokenClient.ts b/packages/sdk/src/sdk/services/Ethereum/contracts/AudiusToken/AudiusTokenClient.ts index f38d4881ca6..adac24782ff 100644 --- a/packages/sdk/src/sdk/services/Ethereum/contracts/AudiusToken/AudiusTokenClient.ts +++ b/packages/sdk/src/sdk/services/Ethereum/contracts/AudiusToken/AudiusTokenClient.ts @@ -11,9 +11,11 @@ import { parseParams } from '../../../../utils/parseParams' import type { AudiusWalletClient } from '../../../AudiusWalletClient' import { + BalanceOfSchema, PermitSchema, type AudiusTokenConfig, - type PermitParams + type PermitParams, + type BalanceOfParams } from './types' const ONE_HOUR_IN_MS = 1000 * 60 * 60 @@ -76,6 +78,17 @@ export class AudiusTokenClient { return await this.walletClient.writeContract(request) } + public async balanceOf(params: BalanceOfParams) { + const { account } = await parseParams('balanceOf', BalanceOfSchema)(params) + const balance = await this.publicClient.readContract({ + address: this.contractAddress, + abi: AudiusToken.abi, + functionName: 'balanceOf', + args: [account] + }) + return BigInt(balance) + } + private async domain(): Promise< TypedDataDefinition['domain'] > { diff --git a/packages/sdk/src/sdk/services/Ethereum/contracts/AudiusToken/types.ts b/packages/sdk/src/sdk/services/Ethereum/contracts/AudiusToken/types.ts index 35ec61e2868..3d7c45f96e9 100644 --- a/packages/sdk/src/sdk/services/Ethereum/contracts/AudiusToken/types.ts +++ b/packages/sdk/src/sdk/services/Ethereum/contracts/AudiusToken/types.ts @@ -10,6 +10,12 @@ export type AudiusTokenConfigInternal = { address: Hex } +export const BalanceOfSchema = z.object({ + account: EthAddressSchema +}) + +export type BalanceOfParams = z.input + export const PermitSchema = GasFeeSchema.and( z.object({ args: z.object({ diff --git a/packages/web/src/common/store/pages/token-dashboard/getWalletInfo.ts b/packages/web/src/common/store/pages/token-dashboard/getWalletInfo.ts index 34df377a557..115b2b1687c 100644 --- a/packages/web/src/common/store/pages/token-dashboard/getWalletInfo.ts +++ b/packages/web/src/common/store/pages/token-dashboard/getWalletInfo.ts @@ -13,7 +13,9 @@ export function* getWalletInfo(walletAddress: string, chain: Chain) { const [{ balance }] = yield* call( [ walletClient, - chain === Chain.Eth ? 'getEthWalletBalances' : 'getSolWalletBalances' + chain === Chain.Eth + ? walletClient.getEthWalletBalances + : walletClient.getSolWalletBalances ], [walletAddress] ) diff --git a/packages/web/src/common/store/pages/token-dashboard/sagas.ts b/packages/web/src/common/store/pages/token-dashboard/sagas.ts index ba2b7a471b3..a1cc7003248 100644 --- a/packages/web/src/common/store/pages/token-dashboard/sagas.ts +++ b/packages/web/src/common/store/pages/token-dashboard/sagas.ts @@ -27,7 +27,7 @@ const { getUserId } = accountSelectors function* fetchEthWalletInfo(wallets: string[]) { const walletClient = yield* getContext('walletClient') const ethWalletBalances = yield* call( - [walletClient, 'getEthWalletBalances'], + [walletClient, walletClient.getEthWalletBalances], wallets ) diff --git a/packages/web/src/common/store/wallet/sagas.ts b/packages/web/src/common/store/wallet/sagas.ts index bea06385228..1da75145ae1 100644 --- a/packages/web/src/common/store/wallet/sagas.ts +++ b/packages/web/src/common/store/wallet/sagas.ts @@ -45,8 +45,7 @@ const { sendFailed, decreaseBalance } = walletActions -const { getAccountBalance, getFreezeUntilTime, getLocalBalanceDidChange } = - walletSelectors +const { getAccountBalance, getFreezeUntilTime } = walletSelectors const { fetchAssociatedWallets, transferEthAudioToSolWAudio, @@ -233,13 +232,9 @@ function* fetchBalanceAsync() { const isBalanceFrozen = yield* call(getIsBalanceFrozen) if (isBalanceFrozen) return - const localBalanceChange: ReturnType = - yield* select(getLocalBalanceDidChange) - const [currentEthAudioWeiBalance, currentSolAudioWeiBalance] = yield* all([ call([walletClient, walletClient.getCurrentBalance], { - ethAddress: account.wallet, - bustCache: localBalanceChange + ethAddress: account.wallet }), call([walletClient, walletClient.getCurrentWAudioBalance], { ethAddress: account.wallet @@ -261,8 +256,7 @@ function* fetchBalanceAsync() { const associatedWalletBalance: BNWei | null = yield* call( [walletClient, walletClient.getAssociatedWalletBalance], - account.user_id, - /* bustCache */ localBalanceChange + account.user_id ) if (isNullOrUndefined(associatedWalletBalance)) { console.warn(