From 19534ab07c7e9a2acabdadac95f3f77bc8e840c2 Mon Sep 17 00:00:00 2001 From: zramsay Date: Tue, 25 Mar 2025 15:20:45 -0400 Subject: [PATCH] use /state --- src/services/blockchain/seiService.ts | 116 ++++++++++++++++++++------ 1 file changed, 89 insertions(+), 27 deletions(-) diff --git a/src/services/blockchain/seiService.ts b/src/services/blockchain/seiService.ts index b11dcdd..ce687b9 100644 --- a/src/services/blockchain/seiService.ts +++ b/src/services/blockchain/seiService.ts @@ -413,14 +413,18 @@ export const getTokenBalance = async (): Promise => { // The REST endpoint for Sei testnet const restEndpoint = NETWORKS.testnet.restUrl; - // Create a simple query parameter with the wallet address - // This approach uses a GET request which is more CORS-friendly + // Based on the reference data, we can directly query the contract state + // which includes base64 encoded balances - // Construct the REST API URL for the contract query using simple GET request - // Use the bank module to check the account balance which has fewer CORS restrictions - const queryUrl = `${restEndpoint}/cosmos/bank/v1beta1/balances/${currentAddress}`; + // Log the info we have + console.log('Current wallet address:', currentAddress); + console.log('Token contract address:', tokenContractAddress); + console.log('REST endpoint:', restEndpoint); - console.log(`Querying token balance at: ${queryUrl}`); + // Query the contract state directly - this endpoint works and returns the balance data + const queryUrl = `${restEndpoint}/cosmwasm/wasm/v1/contract/${tokenContractAddress}/state`; + + console.log(`Querying contract state at: ${queryUrl}`); // Make a simple GET request to check the account balances // This typically has fewer CORS issues than POST requests with complex JSON body @@ -436,31 +440,89 @@ export const getTokenBalance = async (): Promise => { console.log('Raw response data:', data); - // Extract the balance from the cosmos bank balances endpoint - console.log('Full response structure:', JSON.stringify(data, null, 2)); + // This endpoint returns the entire contract state, which may be large + // Log the full structure to understand what we're working with + console.log('Full contract state:', JSON.stringify(data, null, 2)); - // The bank module returns an array of balances for all tokens the account holds - if (data && data.balances && Array.isArray(data.balances)) { - // Find our WILD token in the balances array - // Looking for our token by denom - const wildToken = data.balances.find((balance: any) => - // Our token is likely listed with a denom like "uwild" or similar - balance.denom === 'uwild' || - balance.denom === 'wild' || - balance.denom?.toLowerCase().includes('wild') - ); + try { + // Based on the reference data, we know the contract state includes base64 encoded balances + // The key pattern is "AAdiYWxhbmNl" + base64(address) - if (wildToken && wildToken.amount) { - // Convert from micro units (1e6) to whole tokens - const balanceInMicro = parseInt(wildToken.amount); - const balance = balanceInMicro / 1_000_000; - console.log(`Real token balance for ${currentAddress}: ${balance} WILD`); - return balance; + // Check if we have models in the response + if (data && data.models && Array.isArray(data.models)) { + console.log(`Found ${data.models.length} state models in contract`); + + // Look for our address balance + // The key format from the reference is: "AAdiYWxhbmNl" + base64(walletAddress) + // Example: "AAdiYWxhbmNlc2VpMWp3ZTQ0NHdmeXRlN2xzcWR4Y3J3eHJuenBnaDRrcjhjczVtMzI1" + + // The key prefix "AAdiYWxhbmNl" is the base64 encoding of "\x00\x07balance" + // which is the storage prefix for balances in the CW20 contract + + // Search for a model with our wallet address in the key + // We know from the reference that the key contains the address in readable form + for (const model of data.models) { + if (model.key && model.key.includes(currentAddress.replace('sei', 'c2Vp'))) { + console.log('Found matching balance entry:', model); + + // The value is base64 encoded JSON string with the balance + const decodedValue = atob(model.value); + console.log('Decoded value:', decodedValue); + + // The balance is a string wrapped in quotes, e.g. "120000000" + // Remove the quotes and parse as integer + const balanceStr = decodedValue.replace(/^"|"$/g, ''); + const balanceInMicro = parseInt(balanceStr); + + // Convert from micro units (1e6) to whole tokens + const balance = balanceInMicro / 1_000_000; + console.log(`Found token balance for ${currentAddress}: ${balance} WILD`); + return balance; + } + } + + // Alternative approach - look for any key that starts with balance prefix + // and then check if the decoded key contains our address + for (const model of data.models) { + if (model.key && model.key.startsWith('AAdiYWxhbmNl')) { + try { + // Try to decode the key to see if it contains our address + const decodedKey = atob(model.key); + if (decodedKey.includes(currentAddress)) { + console.log('Found balance by decoded key:', model); + + // The value is base64 encoded JSON string with the balance + const decodedValue = atob(model.value); + console.log('Decoded value:', decodedValue); + + // The balance is a string wrapped in quotes, e.g. "120000000" + // Remove the quotes and parse as integer + const balanceStr = decodedValue.replace(/^"|"$/g, ''); + const balanceInMicro = parseInt(balanceStr); + + // Convert from micro units (1e6) to whole tokens + const balance = balanceInMicro / 1_000_000; + console.log(`Found token balance for ${currentAddress}: ${balance} WILD`); + return balance; + } + } catch (decodeError) { + console.warn('Error decoding key:', decodeError); + } + } + } + + // If we checked all models and didn't find our address, they likely have 0 balance + console.log('No balance entry found for this address, assuming 0 balance'); + return 0; } - // If we couldn't find the WILD token, the user probably has 0 balance - console.log('No WILD tokens found in balances, assuming 0 balance'); - return 0; + // If we got a valid response with no models, assume 0 balance + if (data && Object.keys(data).length > 0) { + console.log('No balance models found in contract state, assuming 0 balance'); + return 0; + } + } catch (parseError) { + console.error('Error processing transaction data:', parseError); } // If the response structure is different than expected