From 4e3caa808e262fa62ec72c2050ee6be34ba0f458 Mon Sep 17 00:00:00 2001 From: Andrea Rampin Date: Tue, 19 Dec 2023 14:06:31 +1100 Subject: [PATCH] WT-1971 - allow get balances without connected provider (#1296) Co-authored-by: Deepti Luthra --- .../sdk/src/balances/balances.test.ts | 44 +++++++++++++++++++ .../checkout/sdk/src/balances/balances.ts | 28 +++++++++--- .../checkout/sdk/src/errors/checkoutError.ts | 1 + packages/checkout/sdk/src/sdk.ts | 7 +-- packages/checkout/sdk/src/types/balances.ts | 8 ++-- 5 files changed, 71 insertions(+), 17 deletions(-) diff --git a/packages/checkout/sdk/src/balances/balances.test.ts b/packages/checkout/sdk/src/balances/balances.test.ts index 13bc005ca3..d4ef89f464 100644 --- a/packages/checkout/sdk/src/balances/balances.test.ts +++ b/packages/checkout/sdk/src/balances/balances.test.ts @@ -286,6 +286,50 @@ describe('balances', () => { }); }); + it('should fail if no wallet address or provider are given', async () => { + let message; + try { + await getAllBalances( + { + remote: { + getTokensConfig: () => ({ + blockscout: false, + }), + }, + networkMap: testCheckoutConfig.networkMap, + } as unknown as CheckoutConfiguration, + undefined, + undefined, + ChainId.ETHEREUM, + ); + } catch (e: any) { + message = e.message; + } + expect(message).toContain('both walletAddress and provider are missing'); + }); + + it('should fail if no provider is given and indexer is disabled', async () => { + let message; + try { + await getAllBalances( + { + remote: { + getTokensConfig: () => ({ + blockscout: false, + }), + }, + networkMap: testCheckoutConfig.networkMap, + } as unknown as CheckoutConfiguration, + undefined, + 'wallet-address', + ChainId.ETHEREUM, + ); + } catch (e: any) { + message = e.message; + } + expect(message).toContain('indexer is disabled for this chain, you must provide a provider'); + }); + it('should call getBalance and getERC20Balance functions with native and ERC20 tokens', async () => { const getAllBalancesResult = await getAllBalances( { diff --git a/packages/checkout/sdk/src/balances/balances.ts b/packages/checkout/sdk/src/balances/balances.ts index 2cfbf5091d..bb0b6732d1 100644 --- a/packages/checkout/sdk/src/balances/balances.ts +++ b/packages/checkout/sdk/src/balances/balances.ts @@ -238,12 +238,16 @@ export const getBalances = async ( export const getAllBalances = async ( config: CheckoutConfiguration, - web3Provider: Web3Provider, - walletAddress: string, - chainId?: ChainId, + web3Provider: Web3Provider | undefined, + walletAddress: string | undefined, + chainId: ChainId, ): Promise => { - // eslint-disable-next-line no-param-reassign - chainId ||= await web3Provider.getSigner().getChainId(); + if (!walletAddress && !web3Provider) { + throw new CheckoutError( + 'both walletAddress and provider are missing. At least one must be provided.', + CheckoutErrorType.MISSING_PARAMS, + ); + } const { tokens } = await getTokenAllowList( config, @@ -264,6 +268,7 @@ export const getAllBalances = async ( console.error(err); } + let address = walletAddress; if (flag && Blockscout.isChainSupported(chainId)) { // This is a hack because the widgets are still using the tokens symbol // to drive the conversions. If we remove all the token symbols from e.g. zkevm @@ -271,19 +276,28 @@ export const getAllBalances = async ( // Please remove this hack once https://immutable.atlassian.net/browse/WT-1710 // is done. const isL1Chain = getL1ChainId(config) === chainId; + if (!address) address = await web3Provider?.getSigner().getAddress(); return await measureAsyncExecution( config, `Time to fetch balances using blockscout for ${chainId}`, - getIndexerBalance(walletAddress, chainId, isL1Chain ? tokens : undefined), + getIndexerBalance(address!, chainId, isL1Chain ? tokens : undefined), + ); + } + + if (!web3Provider) { + throw new CheckoutError( + 'indexer is disabled for this chain, you must provide a provider.', + CheckoutErrorType.MISSING_PARAMS, ); } // This fallback to use ERC20s calls which is a best effort solution // Fails in fetching data from the RCP calls might result in some // missing data. + address ||= await web3Provider.getSigner().getAddress(); return await measureAsyncExecution( config, `Time to fetch balances using RPC for ${chainId}`, - getBalances(config, web3Provider, walletAddress, tokens), + getBalances(config, web3Provider, address, tokens), ); }; diff --git a/packages/checkout/sdk/src/errors/checkoutError.ts b/packages/checkout/sdk/src/errors/checkoutError.ts index 12e83b05e7..3eac6d158b 100644 --- a/packages/checkout/sdk/src/errors/checkoutError.ts +++ b/packages/checkout/sdk/src/errors/checkoutError.ts @@ -2,6 +2,7 @@ * Enum representing different types of errors that can occur during the checkout process. */ export enum CheckoutErrorType { + MISSING_PARAMS = 'MISSING_PARAMS', WEB3_PROVIDER_ERROR = 'WEB3_PROVIDER_ERROR', PROVIDER_ERROR = 'PROVIDER_ERROR', DEFAULT_PROVIDER_ERROR = 'DEFAULT_PROVIDER_ERROR', diff --git a/packages/checkout/sdk/src/sdk.ts b/packages/checkout/sdk/src/sdk.ts index 4895352386..6d56ea26c2 100644 --- a/packages/checkout/sdk/src/sdk.ts +++ b/packages/checkout/sdk/src/sdk.ts @@ -251,14 +251,9 @@ export class Checkout { public async getAllBalances( params: GetAllBalancesParams, ): Promise { - const web3Provider = await provider.validateProvider( - this.config, - params.provider, - ); - return balances.getAllBalances( this.config, - web3Provider, + params.provider, params.walletAddress, params.chainId, ); diff --git a/packages/checkout/sdk/src/types/balances.ts b/packages/checkout/sdk/src/types/balances.ts index 32e4c27dfe..70d25c8b1c 100644 --- a/packages/checkout/sdk/src/types/balances.ts +++ b/packages/checkout/sdk/src/types/balances.ts @@ -29,13 +29,13 @@ export interface GetBalanceResult { /** * Interface representing the parameters for {@link Checkout.getAllBalances}. - * @property {Web3Provider} provider - The provider used to get the balances. - * @property {string} walletAddress - The wallet address. + * @property {Web3Provider} provider - The provider used to get the balances, it is a required parameter if no walletAddress is provided. + * @property {string} walletAddress - The wallet address, it is a required parameter if no provider is provided. * @property {ChainId} chainId - The ID of the network. */ export interface GetAllBalancesParams { - provider: Web3Provider; - walletAddress: string; + provider?: Web3Provider; + walletAddress?: string; chainId: ChainId; }