diff --git a/src/abis/AaveIncentivesV3.ts b/src/abis/AaveIncentivesV3.ts new file mode 100644 index 00000000000..2e4cd034b2b --- /dev/null +++ b/src/abis/AaveIncentivesV3.ts @@ -0,0 +1,511 @@ +// Incentives ABI from https://docs.aave.com/developers/deployed-contracts/v3-mainnet/arbitrum +const aaveIncentivesV3Abi = [ + { + inputs: [{ internalType: 'address', name: 'emissionManager', type: 'address' }], + stateMutability: 'nonpayable', + type: 'constructor', + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: 'address', + name: 'asset', + type: 'address', + }, + { + indexed: true, + internalType: 'address', + name: 'reward', + type: 'address', + }, + { indexed: true, internalType: 'address', name: 'user', type: 'address' }, + { + indexed: false, + internalType: 'uint256', + name: 'assetIndex', + type: 'uint256', + }, + { + indexed: false, + internalType: 'uint256', + name: 'userIndex', + type: 'uint256', + }, + { + indexed: false, + internalType: 'uint256', + name: 'rewardsAccrued', + type: 'uint256', + }, + ], + name: 'Accrued', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: 'address', + name: 'asset', + type: 'address', + }, + { + indexed: true, + internalType: 'address', + name: 'reward', + type: 'address', + }, + { + indexed: false, + internalType: 'uint256', + name: 'oldEmission', + type: 'uint256', + }, + { + indexed: false, + internalType: 'uint256', + name: 'newEmission', + type: 'uint256', + }, + { + indexed: false, + internalType: 'uint256', + name: 'oldDistributionEnd', + type: 'uint256', + }, + { + indexed: false, + internalType: 'uint256', + name: 'newDistributionEnd', + type: 'uint256', + }, + { + indexed: false, + internalType: 'uint256', + name: 'assetIndex', + type: 'uint256', + }, + ], + name: 'AssetConfigUpdated', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: 'address', name: 'user', type: 'address' }, + { + indexed: true, + internalType: 'address', + name: 'claimer', + type: 'address', + }, + ], + name: 'ClaimerSet', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: 'address', + name: 'reward', + type: 'address', + }, + { + indexed: true, + internalType: 'address', + name: 'rewardOracle', + type: 'address', + }, + ], + name: 'RewardOracleUpdated', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: 'address', name: 'user', type: 'address' }, + { + indexed: true, + internalType: 'address', + name: 'reward', + type: 'address', + }, + { indexed: true, internalType: 'address', name: 'to', type: 'address' }, + { + indexed: false, + internalType: 'address', + name: 'claimer', + type: 'address', + }, + { + indexed: false, + internalType: 'uint256', + name: 'amount', + type: 'uint256', + }, + ], + name: 'RewardsClaimed', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: 'address', + name: 'reward', + type: 'address', + }, + { + indexed: true, + internalType: 'address', + name: 'transferStrategy', + type: 'address', + }, + ], + name: 'TransferStrategyInstalled', + type: 'event', + }, + { + inputs: [], + name: 'EMISSION_MANAGER', + outputs: [{ internalType: 'address', name: '', type: 'address' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'REVISION', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { internalType: 'address[]', name: 'assets', type: 'address[]' }, + { internalType: 'address', name: 'to', type: 'address' }, + ], + name: 'claimAllRewards', + outputs: [ + { internalType: 'address[]', name: 'rewardsList', type: 'address[]' }, + { internalType: 'uint256[]', name: 'claimedAmounts', type: 'uint256[]' }, + ], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { internalType: 'address[]', name: 'assets', type: 'address[]' }, + { internalType: 'address', name: 'user', type: 'address' }, + { internalType: 'address', name: 'to', type: 'address' }, + ], + name: 'claimAllRewardsOnBehalf', + outputs: [ + { internalType: 'address[]', name: 'rewardsList', type: 'address[]' }, + { internalType: 'uint256[]', name: 'claimedAmounts', type: 'uint256[]' }, + ], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [{ internalType: 'address[]', name: 'assets', type: 'address[]' }], + name: 'claimAllRewardsToSelf', + outputs: [ + { internalType: 'address[]', name: 'rewardsList', type: 'address[]' }, + { internalType: 'uint256[]', name: 'claimedAmounts', type: 'uint256[]' }, + ], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { internalType: 'address[]', name: 'assets', type: 'address[]' }, + { internalType: 'uint256', name: 'amount', type: 'uint256' }, + { internalType: 'address', name: 'to', type: 'address' }, + { internalType: 'address', name: 'reward', type: 'address' }, + ], + name: 'claimRewards', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { internalType: 'address[]', name: 'assets', type: 'address[]' }, + { internalType: 'uint256', name: 'amount', type: 'uint256' }, + { internalType: 'address', name: 'user', type: 'address' }, + { internalType: 'address', name: 'to', type: 'address' }, + { internalType: 'address', name: 'reward', type: 'address' }, + ], + name: 'claimRewardsOnBehalf', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { internalType: 'address[]', name: 'assets', type: 'address[]' }, + { internalType: 'uint256', name: 'amount', type: 'uint256' }, + { internalType: 'address', name: 'reward', type: 'address' }, + ], + name: 'claimRewardsToSelf', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { + components: [ + { internalType: 'uint88', name: 'emissionPerSecond', type: 'uint88' }, + { internalType: 'uint256', name: 'totalSupply', type: 'uint256' }, + { internalType: 'uint32', name: 'distributionEnd', type: 'uint32' }, + { internalType: 'address', name: 'asset', type: 'address' }, + { internalType: 'address', name: 'reward', type: 'address' }, + { + internalType: 'contract ITransferStrategyBase', + name: 'transferStrategy', + type: 'address', + }, + { + internalType: 'contract IEACAggregatorProxy', + name: 'rewardOracle', + type: 'address', + }, + ], + internalType: 'struct RewardsDataTypes.RewardsConfigInput[]', + name: 'config', + type: 'tuple[]', + }, + ], + name: 'configureAssets', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { internalType: 'address[]', name: 'assets', type: 'address[]' }, + { internalType: 'address', name: 'user', type: 'address' }, + ], + name: 'getAllUserRewards', + outputs: [ + { internalType: 'address[]', name: 'rewardsList', type: 'address[]' }, + { + internalType: 'uint256[]', + name: 'unclaimedAmounts', + type: 'uint256[]', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [{ internalType: 'address', name: 'asset', type: 'address' }], + name: 'getAssetDecimals', + outputs: [{ internalType: 'uint8', name: '', type: 'uint8' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { internalType: 'address', name: 'asset', type: 'address' }, + { internalType: 'address', name: 'reward', type: 'address' }, + ], + name: 'getAssetIndex', + outputs: [ + { internalType: 'uint256', name: '', type: 'uint256' }, + { internalType: 'uint256', name: '', type: 'uint256' }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [{ internalType: 'address', name: 'user', type: 'address' }], + name: 'getClaimer', + outputs: [{ internalType: 'address', name: '', type: 'address' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { internalType: 'address', name: 'asset', type: 'address' }, + { internalType: 'address', name: 'reward', type: 'address' }, + ], + name: 'getDistributionEnd', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'getEmissionManager', + outputs: [{ internalType: 'address', name: '', type: 'address' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [{ internalType: 'address', name: 'reward', type: 'address' }], + name: 'getRewardOracle', + outputs: [{ internalType: 'address', name: '', type: 'address' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [{ internalType: 'address', name: 'asset', type: 'address' }], + name: 'getRewardsByAsset', + outputs: [{ internalType: 'address[]', name: '', type: 'address[]' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { internalType: 'address', name: 'asset', type: 'address' }, + { internalType: 'address', name: 'reward', type: 'address' }, + ], + name: 'getRewardsData', + outputs: [ + { internalType: 'uint256', name: '', type: 'uint256' }, + { internalType: 'uint256', name: '', type: 'uint256' }, + { internalType: 'uint256', name: '', type: 'uint256' }, + { internalType: 'uint256', name: '', type: 'uint256' }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'getRewardsList', + outputs: [{ internalType: 'address[]', name: '', type: 'address[]' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [{ internalType: 'address', name: 'reward', type: 'address' }], + name: 'getTransferStrategy', + outputs: [{ internalType: 'address', name: '', type: 'address' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { internalType: 'address', name: 'user', type: 'address' }, + { internalType: 'address', name: 'reward', type: 'address' }, + ], + name: 'getUserAccruedRewards', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { internalType: 'address', name: 'user', type: 'address' }, + { internalType: 'address', name: 'asset', type: 'address' }, + { internalType: 'address', name: 'reward', type: 'address' }, + ], + name: 'getUserAssetIndex', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { internalType: 'address[]', name: 'assets', type: 'address[]' }, + { internalType: 'address', name: 'user', type: 'address' }, + { internalType: 'address', name: 'reward', type: 'address' }, + ], + name: 'getUserRewards', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { internalType: 'address', name: 'user', type: 'address' }, + { internalType: 'uint256', name: 'totalSupply', type: 'uint256' }, + { internalType: 'uint256', name: 'userBalance', type: 'uint256' }, + ], + name: 'handleAction', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [{ internalType: 'address', name: '', type: 'address' }], + name: 'initialize', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { internalType: 'address', name: 'user', type: 'address' }, + { internalType: 'address', name: 'caller', type: 'address' }, + ], + name: 'setClaimer', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { internalType: 'address', name: 'asset', type: 'address' }, + { internalType: 'address', name: 'reward', type: 'address' }, + { internalType: 'uint32', name: 'newDistributionEnd', type: 'uint32' }, + ], + name: 'setDistributionEnd', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { internalType: 'address', name: 'asset', type: 'address' }, + { internalType: 'address[]', name: 'rewards', type: 'address[]' }, + { + internalType: 'uint88[]', + name: 'newEmissionsPerSecond', + type: 'uint88[]', + }, + ], + name: 'setEmissionPerSecond', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { internalType: 'address', name: 'reward', type: 'address' }, + { + internalType: 'contract IEACAggregatorProxy', + name: 'rewardOracle', + type: 'address', + }, + ], + name: 'setRewardOracle', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { internalType: 'address', name: 'reward', type: 'address' }, + { + internalType: 'contract ITransferStrategyBase', + name: 'transferStrategy', + type: 'address', + }, + ], + name: 'setTransferStrategy', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, +] as const + +export default aaveIncentivesV3Abi diff --git a/src/earn/EarnDepositBottomSheet.test.tsx b/src/earn/EarnDepositBottomSheet.test.tsx index 5ec09fe2aec..578e246962f 100644 --- a/src/earn/EarnDepositBottomSheet.test.tsx +++ b/src/earn/EarnDepositBottomSheet.test.tsx @@ -12,7 +12,7 @@ import { StatsigDynamicConfigs } from 'src/statsig/types' import { PreparedTransactionsPossible } from 'src/viem/prepareTransactions' import { getSerializablePreparedTransactions } from 'src/viem/preparedTransactionSerialization' import { createMockStore } from 'test/utils' -import { mockARBTokenId, mockTokenBalances } from 'test/values' +import { mockArbEthTokenId, mockTokenBalances } from 'test/values' jest.mock('src/statsig') @@ -39,7 +39,7 @@ const mockPreparedTransaction: PreparedTransactionsPossible = { }, ], feeCurrency: { - ...mockTokenBalances[mockARBTokenId], + ...mockTokenBalances[mockArbEthTokenId], isNative: true, balance: new BigNumber(10), priceUsd: new BigNumber(1), @@ -70,7 +70,7 @@ describe('EarnDepositBottomSheet', () => { @@ -104,7 +104,7 @@ describe('EarnDepositBottomSheet', () => { @@ -117,7 +117,7 @@ describe('EarnDepositBottomSheet', () => { type: depositStart.type, payload: { amount: '100', - tokenId: mockARBTokenId, + tokenId: mockArbEthTokenId, preparedTransactions: getSerializablePreparedTransactions( mockPreparedTransaction.transactions ), @@ -132,7 +132,7 @@ describe('EarnDepositBottomSheet', () => { @@ -148,7 +148,7 @@ describe('EarnDepositBottomSheet', () => { @@ -165,7 +165,7 @@ describe('EarnDepositBottomSheet', () => { @@ -188,7 +188,7 @@ describe('EarnDepositBottomSheet', () => { diff --git a/src/earn/poolInfo.test.ts b/src/earn/poolInfo.test.ts index 8a9942de7f8..bcbbc11e6cc 100644 --- a/src/earn/poolInfo.test.ts +++ b/src/earn/poolInfo.test.ts @@ -1,8 +1,10 @@ import aavePool from 'src/abis/AavePoolV3' -import { fetchAavePoolInfo } from 'src/earn/poolInfo' -import { Network } from 'src/transactions/types' +import { fetchAavePoolInfo, fetchAaveRewards } from 'src/earn/poolInfo' +import { Network, NetworkId } from 'src/transactions/types' +import Logger from 'src/utils/Logger' import { publicClient } from 'src/viem' import networkConfig from 'src/web3/networkConfig' +import { mockArbArbTokenBalance } from 'test/values' describe('poolInfo', () => { it('fetches poolInfo from contract', async () => { @@ -25,3 +27,32 @@ describe('poolInfo', () => { }) }) }) + +describe('fetchAaveRewards', () => { + const mockRewards = [ + ['0x912CE59144191C1204E64559FE8253a0e49E6548', '0xba5ddd1f9d7f570dc94a51479a000e3bce967196'], // ARB and AAVE + [BigInt('2297012079410746'), BigInt('2297012079490746')], + ] + const warnSpy = jest.spyOn(Logger, 'warn') + + it('fetches rewards from contract', async () => { + jest.spyOn(publicClient[Network.Arbitrum], 'readContract').mockResolvedValue(mockRewards) + const result = await fetchAaveRewards({ + walletAddress: '0x1234', + assetAddress: '0x1234', + contractAddress: networkConfig.arbAaveIncentivesV3ContractAddress, + networkId: NetworkId['arbitrum-sepolia'], + allTokens: [mockArbArbTokenBalance], + }) + // should get arb, but not aave because we don't have tokenInfo for it. + expect(result).toEqual([ + { + amount: '0.002297012079410746', + tokenInfo: mockArbArbTokenBalance, + }, + ]) + + // should warn that aave wasn't able to be shown + expect(warnSpy).toHaveBeenCalledTimes(1) + }) +}) diff --git a/src/earn/poolInfo.ts b/src/earn/poolInfo.ts index 0db1002a865..35c36569371 100644 --- a/src/earn/poolInfo.ts +++ b/src/earn/poolInfo.ts @@ -1,10 +1,14 @@ import BigNumber from 'bignumber.js' +import aaveIncentivesV3Abi from 'src/abis/AaveIncentivesV3' import AavePool from 'src/abis/AavePoolV3' -import { Network } from 'src/transactions/types' +import { RewardsInfo } from 'src/earn/types' +import { TokenBalance } from 'src/tokens/slice' +import { Network, NetworkId } from 'src/transactions/types' import Logger from 'src/utils/Logger' import { ensureError } from 'src/utils/ensureError' import { publicClient } from 'src/viem' -import { Address } from 'viem' +import { networkIdToNetwork } from 'src/web3/networkConfig' +import { Address, formatUnits } from 'viem' const TAG = 'earn/poolInfo' @@ -43,3 +47,51 @@ export async function fetchAavePoolInfo({ throw err } } + +export async function fetchAaveRewards({ + walletAddress, + assetAddress, + contractAddress, + networkId, + allTokens, +}: { + walletAddress: Address + assetAddress: Address + contractAddress: Address + networkId: NetworkId + allTokens: TokenBalance[] +}) { + try { + const network = networkIdToNetwork[networkId] + Logger.debug(TAG, 'Fetching Aave reward info', { + assetAddress, + contractAddress, + network, + }) + const [rewardAddresses, rewardAmounts] = await publicClient[network].readContract({ + abi: aaveIncentivesV3Abi, + address: contractAddress, + functionName: 'getAllUserRewards', + args: [[assetAddress], walletAddress], + }) + const rewards: RewardsInfo[] = [] + rewardAddresses.forEach((rewardAddress, index) => { + const tokenInfo = allTokens.find( + (token) => token.address === rewardAddress.toLowerCase() && token.networkId === networkId + ) + if (!tokenInfo) { + Logger.warn(TAG, `Token info not found for rewards address ${rewardAddress}`) + } else { + rewards.push({ + amount: formatUnits(rewardAmounts[index], tokenInfo.decimals), + tokenInfo, + }) + } + }) + return rewards + } catch (error) { + const err = ensureError(error) + Logger.error(TAG, 'Failed to fetch Aave rewards info', err) + throw err + } +} diff --git a/src/earn/types.ts b/src/earn/types.ts index f19bc12271d..7cd3879f494 100644 --- a/src/earn/types.ts +++ b/src/earn/types.ts @@ -1,3 +1,4 @@ +import { TokenBalance } from 'src/tokens/slice' import { SerializableTransactionRequest } from 'src/viem/preparedTransactionSerialization' export interface DepositInfo { @@ -5,3 +6,8 @@ export interface DepositInfo { tokenId: string preparedTransactions: SerializableTransactionRequest[] } + +export interface RewardsInfo { + amount: string + tokenInfo: TokenBalance +} diff --git a/src/web3/networkConfig.ts b/src/web3/networkConfig.ts index d4c2c28b495..3e47891671a 100644 --- a/src/web3/networkConfig.ts +++ b/src/web3/networkConfig.ts @@ -92,6 +92,7 @@ interface NetworkConfig { saveContactsUrl: string getPointsConfigUrl: string arbAavePoolV3ContractAddress: Address + arbAaveIncentivesV3ContractAddress: Address aaveArbUsdcTokenId: string } @@ -154,6 +155,10 @@ const AAVE_ARB_USDC_TOKEN_ID_MAINNET = `${NetworkId['arbitrum-one']}:0x724dc807b const ARB_AAVE_POOL_V3_CONTRACT_ADDRESS_STAGING = '0xBfC91D59fdAA134A4ED45f7B584cAf96D7792Eff' const ARB_AAVE_POOL_V3_CONTRACT_ADDRESS_MAINNET = '0x794a61358D6845594F94dc1DB02A252b5b4814aD' +// also called rewards controller +const ARB_AAVE_INCENTIVES_V3_CONTRACT_ADDRESS_STAGING = '0x3A203B14CF8749a1e3b7314c6c49004B77Ee667A' +const ARB_AAVE_INCENTIVES_V3_CONTRACT_ADDRESS_MAINNET = '0x929EC64c34a17401F460460D4B9390518E5B473e' + const CLOUD_FUNCTIONS_STAGING = 'https://api.alfajores.valora.xyz' const CLOUD_FUNCTIONS_MAINNET = 'https://api.mainnet.valora.xyz' @@ -372,6 +377,7 @@ const networkConfigs: { [testnet: string]: NetworkConfig } = { saveContactsUrl: SAVE_CONTACTS_ALFAJORES, getPointsConfigUrl: GET_POINTS_CONFIG_ALFAJORES, arbAavePoolV3ContractAddress: ARB_AAVE_POOL_V3_CONTRACT_ADDRESS_STAGING, + arbAaveIncentivesV3ContractAddress: ARB_AAVE_INCENTIVES_V3_CONTRACT_ADDRESS_STAGING, aaveArbUsdcTokenId: AAVE_ARB_USDC_TOKEN_ID_STAGING, }, [Testnets.mainnet]: { @@ -468,6 +474,7 @@ const networkConfigs: { [testnet: string]: NetworkConfig } = { saveContactsUrl: SAVE_CONTACTS_MAINNET, getPointsConfigUrl: GET_POINTS_CONFIG_MAINNET, arbAavePoolV3ContractAddress: ARB_AAVE_POOL_V3_CONTRACT_ADDRESS_MAINNET, + arbAaveIncentivesV3ContractAddress: ARB_AAVE_INCENTIVES_V3_CONTRACT_ADDRESS_MAINNET, aaveArbUsdcTokenId: AAVE_ARB_USDC_TOKEN_ID_MAINNET, }, } diff --git a/test/values.ts b/test/values.ts index f9080d828ac..2b266bd5dfd 100644 --- a/test/values.ts +++ b/test/values.ts @@ -127,6 +127,7 @@ export const mockCrealAddress = '0xE4D517785D091D3c54818832dB6094bcc2744545'.toL export const mockWBTCAddress = '0x2260fac5e5542a773aa44fbcfedf7c193bc2c599'.toLowerCase() export const mockUSDCAddress = '0x94a9d9ac8a22534e3faca9f4e7f2e2cf85d5e4c8'.toLowerCase() export const mockAaveArbUsdcAddress = '0x460b97BD498E1157530AEb3086301d5225b91216'.toLowerCase() +export const mockArbArbAddress = '0x912CE59144191C1204E64559FE8253a0e49E6548'.toLowerCase() export const mockCusdTokenId = `celo-alfajores:${mockCusdAddress}` export const mockCeurTokenId = `celo-alfajores:${mockCeurAddress}` @@ -137,9 +138,10 @@ export const mockCrealTokenId = `celo-alfajores:${mockCrealAddress}` export const mockWBTCTokenId = `celo-alfajores:${mockWBTCAddress}` export const mockEthTokenId = 'ethereum-sepolia:native' export const mockUSDCTokenId = `ethereum-sepolia:${mockUSDCAddress}` -export const mockARBTokenId = `arbitrum-sepolia:native` +export const mockArbEthTokenId = `arbitrum-sepolia:native` export const mockOPTokenId = `op-sepolia:native` export const mockArbUsdcTokenId = `arbitrum-sepolia:${mockUSDCAddress}` +export const mockArbArbTokenId = `arbitrum-sepolia:${mockArbArbAddress}` export const mockQrCodeData2 = { address: mockAccount2Invite, @@ -542,10 +544,10 @@ export const mockTokenBalances: Record = { priceUsd: '1', priceFetchedAt: Date.now(), }, - [mockARBTokenId]: { + [mockArbEthTokenId]: { name: 'Ethereum', networkId: NetworkId['arbitrum-sepolia'], - tokenId: mockARBTokenId, + tokenId: mockArbEthTokenId, address: null, symbol: 'ETH', decimals: 18, @@ -583,6 +585,19 @@ export const mockTokenBalances: Record = { priceUsd: '1', priceFetchedAt: Date.now(), }, + [mockArbArbTokenId]: { + name: 'Arbitrum', + networkId: NetworkId['arbitrum-sepolia'], + tokenId: mockArbArbTokenId, + address: mockArbArbAddress, + symbol: 'ARB', + decimals: 18, + imageUrl: + 'https://raw.githubusercontent.com/valora-inc/address-metadata/main/assets/tokens/ARB.png', + balance: '0', + priceUsd: '1.2', + priceFetchedAt: Date.now(), + }, } export const mockCeloTokenBalance: TokenBalance = { @@ -607,6 +622,13 @@ export const mockEthTokenBalance: NativeTokenBalance = { isNative: true, } +export const mockArbArbTokenBalance: TokenBalance = { + ...mockTokenBalances[mockArbArbTokenId], + priceUsd: new BigNumber(1.2), + lastKnownPriceUsd: new BigNumber(1.2), + balance: new BigNumber(0), +} + export const mockTokenBalancesWithHistoricalPrices = { [mockPoofTokenId]: { ...mockTokenBalances[mockPoofTokenId],