diff --git a/projects/helper/bitcoin-book/fetchers.js b/projects/helper/bitcoin-book/fetchers.js index 220b0b27a..636a21aa7 100644 --- a/projects/helper/bitcoin-book/fetchers.js +++ b/projects/helper/bitcoin-book/fetchers.js @@ -242,38 +242,14 @@ module.exports = { }) return Array.from(new Set(staticAddresses)) }, - zenrock: async (blockHeight = null) => { + zenrock: async () => { const ZRCHAIN_WALLETS_API = 'https://api.diamond.zenrocklabs.io/zrchain/treasury/zenbtc_wallets'; const ZENBTC_PARAMS_API = 'https://api.diamond.zenrocklabs.io/zenbtc/params'; const ZRCHAIN_KEY_BY_ID_API = 'https://api.diamond.zenrocklabs.io/zrchain/treasury/key_by_id'; - // Helper function to make API requests with optional height header - async function apiRequest(url, height = null) { - const options = {}; - if (height) { - options.headers = { - 'x-cosmos-block-height': String(height) - }; - } - - try { - return await get(url, options); - } catch (error) { - // If historical query fails (code 13 - nil pointer), throw descriptive error - // This indicates either: (1) the module was not present on-chain at this block height, - // or (2) historical state has been pruned (varies by module) - const errorStr = error.message || error.toString() || ''; - if (errorStr.includes('code 13') || errorStr.includes('nil pointer')) { - throw new Error(`Historical data unavailable for block height ${height}. The module may not have been present on-chain at this block height, or historical state may have been pruned (varies by module).`); - } - throw error; - } - } - - // Use cache key that includes block height for historical queries - const cacheKey = blockHeight ? `zenrock/addresses/${blockHeight}` : 'zenrock/addresses'; - - return getConfig(cacheKey, undefined, { + // Always use latest addresses since wallets are only added, never removed. + // The balance checker will use the historical timestamp to get correct balances. + return getConfig('zenrock/addresses', undefined, { fetcher: async () => { async function getBitcoinAddresses() { const btcAddresses = []; @@ -284,7 +260,7 @@ module.exports = { if (nextKey) { url += `?pagination.key=${encodeURIComponent(nextKey)}`; } - const data = await apiRequest(url, blockHeight); + const data = await get(url); if (data.zenbtc_wallets && Array.isArray(data.zenbtc_wallets)) { for (const walletGroup of data.zenbtc_wallets) { if (walletGroup.wallets && Array.isArray(walletGroup.wallets)) { @@ -306,12 +282,13 @@ module.exports = { } async function getChangeAddresses() { + const paramsData = await get(ZENBTC_PARAMS_API); + if (!paramsData?.params?.changeAddressKeyIDs) { + return []; + } const changeAddresses = []; - - const paramsData = await apiRequest(ZENBTC_PARAMS_API, blockHeight); - const changeAddressKeyIDs = paramsData.params?.changeAddressKeyIDs || []; - for (const keyID of changeAddressKeyIDs) { - const keyData = await apiRequest(`${ZRCHAIN_KEY_BY_ID_API}/${keyID}/WALLET_TYPE_BTC_MAINNET/`, blockHeight); + for (const keyID of paramsData.params.changeAddressKeyIDs) { + const keyData = await get(`${ZRCHAIN_KEY_BY_ID_API}/${keyID}/WALLET_TYPE_BTC_MAINNET/`); if (keyData.wallets && Array.isArray(keyData.wallets)) { for (const wallet of keyData.wallets) { if (wallet.type === 'WALLET_TYPE_BTC_MAINNET' && wallet.address) { diff --git a/projects/zenrock/index.js b/projects/zenrock/index.js index 6ac1c6e39..fd34bf88a 100644 --- a/projects/zenrock/index.js +++ b/projects/zenrock/index.js @@ -97,19 +97,7 @@ async function apiRequest(url, blockHeight = null) { 'x-cosmos-block-height': String(blockHeight) }; } - - try { - return await get(url, options); - } catch (error) { - // If historical query fails (code 13 - nil pointer), throw descriptive error - // This indicates either: (1) the module was not present on-chain at this block height, - // or (2) historical state has been pruned (varies by module - DCT was launched on 2025-10-31) - const errorStr = error.message || error.toString() || ''; - if (errorStr.includes('code 13') || errorStr.includes('nil pointer')) { - throw new Error(`Historical data unavailable for block height ${blockHeight}. The module may not have been present on-chain at this block height, or historical state may have been pruned (varies by module).`); - } - throw error; - } + return await get(url, options); } async function tvl(api) { @@ -124,8 +112,7 @@ async function tvl(api) { } // Fetch all protocol addresses (treasury + change) from the bitcoin-book fetcher - // Pass blockHeight for historical queries - const allAddresses = await zenrock(blockHeight); + const allAddresses = await zenrock(); if (allAddresses.length === 0) { return { bitcoin: '0' }; @@ -153,21 +140,25 @@ async function zcashTvl(api) { } // Fetch custodied amount from DCT supply endpoint with height header - const supplyData = await apiRequest(`${ZRCHAIN_API}/dct/supply`, blockHeight); - - // Find ASSET_ZENZEC in supplies array + let supplyData; + try { + supplyData = await apiRequest(`${ZRCHAIN_API}/dct/supply`, blockHeight); + } catch (error) { + // If DCT supply API fails, return 0 supply instead of erroring + // This can happen for historical queries before the module was launched (2025-10-31) + return balances; + } const zenZecSupply = supplyData.supplies?.find( item => item.supply?.asset === 'ASSET_ZENZEC' ); - - if (zenZecSupply && zenZecSupply.supply?.custodied_amount) { - // custodied_amount is in Zatoshi (smallest unit, like satoshis for BTC) - // Convert to ZEC by dividing by 1e8 - const custodiedAmount = Number(zenZecSupply.supply.custodied_amount); - const custodiedZEC = custodiedAmount / 1e8; - - sdk.util.sumSingleBalance(balances, 'zcash', custodiedZEC); + if (!zenZecSupply?.supply?.custodied_amount) { + return balances; } + // custodied_amount is in Zatoshi (smallest unit, like satoshis for BTC) + const custodiedAmount = Number(zenZecSupply.supply.custodied_amount); + const custodiedZEC = custodiedAmount / 1e8; + + sdk.util.sumSingleBalance(balances, 'zcash', custodiedZEC); return balances; }