From 86d2a943cf19fef1746ca315cba699df7a5dfb60 Mon Sep 17 00:00:00 2001 From: Abhishek Date: Wed, 12 Nov 2025 11:52:04 +0400 Subject: [PATCH 01/51] feat: add tron + refactor (#55) * initial handling on CA, partial tx handling implementation * feat: completed tron support, fix: chain ids & token address deduplication, added devnet for cerise env * fix: added tron & tron shasta chains to readme * fix: type errors for token contract address * fix: tron shasta rpc urls fix * rebase from develop * feat: refactor (#58) * feat: preliminary refactor * prelim error handling * deduplicate logger, remove unused variables * fix: fixed some regression issues after testing, deduped creating rff from intent fn * feat: added calculateMaxForBridge fn, fix: added caching for balance, feat: added onEvent params to fns and updated docs * feat: added bridge step and swap step, removed catching error in top level fns - let it bubble up, storing SIWE signature to prevent resigning * fix: intial refactor of swap route * fix: update USDT logo URLs and remove unused Ether token entry in swap constants * chore(core): beta release v1.0.0-beta.6 * fix: testing swap usage * fix: fix calculateMax function to include collectionFee, added initial implementation for dynamic permit version, fixed eip2612 not switching chain before signature * feat: add validium chain * fix: deduplicated code in bridgeAndExecute, fixed balance issue when a single chain balance errors out, Removed sending back status in function responses - success is when no error is thrown * fix: incorrect token addresses on folly, fixed using gasPrice and gasUsed in execute * chore: added custom version option in release script * fix: fixed Validium Testnet chain naming * feat: add getCoinbaseRates method to NexusUtils and update local-pack script to remove widget packaging (#60) * fix: readability improvement to exact in and out, fixed switchChain usage in missing bridge * fix: change from chainId to toChainId in bridge & bridgeAndTransfer fn for consistency, removed unused code from tenderly client, removed unused aave contract addresses, replaced partial errors with NexusError, removed unused simulation.ts, added calculateMaxForBridge to have source chains in response * refactor: reorganize balance formatting utilities, remove deprecated functions, and export new formatting options (#61) * chore(core): beta release v1.0.0-beta.24 * fix: standardize few errors, updated intent list to have more data * fix: added gasPrice in execute & bridgeAndExecute simulation response --------- Co-authored-by: decocereus Co-authored-by: Amartya Singh <53113365+decocereus@users.noreply.github.com> * chore(core): beta release v1.0.0-beta.25 * fix: let intent list have chain details also * chore(core): beta release v1.0.0-beta.26 --------- Co-authored-by: decocereus Co-authored-by: Amartya Singh <53113365+decocereus@users.noreply.github.com> --- package.json | 14 +- packages/commons/constants/index.ts | 83 +- packages/commons/index.ts | 3 + packages/commons/package.json | 20 +- packages/commons/types/bridge-steps.ts | 136 ++ packages/commons/types/contract-types.ts | 14 + packages/commons/types/index.ts | 359 ++--- .../steps.ts => commons/types/swap-steps.ts} | 68 +- packages/commons/types/swap-types.ts | 23 +- packages/commons/utils/format.ts | 303 ++++ packages/commons/utils/index.ts | 51 +- packages/commons/utils/logger.ts | 2 +- packages/core/README.md | 1057 ++++-------- .../adapters/chain-abstraction-adapter.ts | 99 -- packages/core/adapters/core/validation.ts | 104 -- .../adapters/services/approval-service.ts | 233 --- .../services/balance-detection-service.ts | 403 ----- .../services/bridge-execute-service.ts | 1317 --------------- .../core/adapters/services/execute-service.ts | 341 ---- .../adapters/services/simulation-engine.ts | 684 -------- .../adapters/services/transaction-service.ts | 534 ------ packages/core/index.ts | 8 +- packages/core/integrations/tenderly.ts | 201 +-- packages/core/package.json | 26 +- packages/core/rollup.config.mjs | 13 +- packages/core/sdk/ca-base/abi/vault.ts | 22 +- packages/core/sdk/ca-base/ca.ts | 606 ++++--- packages/core/sdk/ca-base/chains.ts | 291 +++- packages/core/sdk/ca-base/config.ts | 2 +- packages/core/sdk/ca-base/constants.ts | 109 +- packages/core/sdk/ca-base/errors.ts | 123 +- packages/core/sdk/ca-base/index.ts | 11 +- packages/core/sdk/ca-base/logger.ts | 93 -- packages/core/sdk/ca-base/nexusError.ts | 99 ++ packages/core/sdk/ca-base/query/allowance.ts | 102 -- packages/core/sdk/ca-base/query/bridge.ts | 122 -- .../sdk/ca-base/query/bridgeAndExecute.ts | 598 +++++++ .../sdk/ca-base/query/bridgeAndTransfer.ts | 42 + packages/core/sdk/ca-base/query/index.ts | 4 +- packages/core/sdk/ca-base/query/transfer.ts | 135 -- .../sdk/ca-base/requestHandlers/bridge.ts | 1034 ++++++++++++ .../sdk/ca-base/requestHandlers/bridgeMax.ts | 50 + .../ca-base/requestHandlers/common/base.ts | 1004 ------------ .../ca-base/requestHandlers/common/utils.ts | 121 -- .../sdk/ca-base/requestHandlers/evm/common.ts | 35 - .../sdk/ca-base/requestHandlers/evm/erc20.ts | 246 --- .../sdk/ca-base/requestHandlers/evm/native.ts | 178 -- .../ca-base/requestHandlers/fuel/common.ts | 143 -- .../ca-base/requestHandlers/fuel/native.ts | 91 -- .../ca-base/requestHandlers/fuel/provider.ts | 149 -- .../sdk/ca-base/requestHandlers/fuel/token.ts | 92 -- .../sdk/ca-base/requestHandlers/helpers.ts | 26 + .../sdk/ca-base/requestHandlers/router.ts | 86 - packages/core/sdk/ca-base/simulate.ts | 43 - packages/core/sdk/ca-base/steps.ts | 138 +- packages/core/sdk/ca-base/swap/data.ts | 17 +- packages/core/sdk/ca-base/swap/ob.ts | 308 ++-- packages/core/sdk/ca-base/swap/rff.ts | 122 +- packages/core/sdk/ca-base/swap/route.ts | 551 ++++--- packages/core/sdk/ca-base/swap/sbc.ts | 5 +- packages/core/sdk/ca-base/swap/swap.ts | 146 +- packages/core/sdk/ca-base/swap/utils.ts | 775 +++------ packages/core/sdk/ca-base/utils/api.utils.ts | 143 +- .../core/sdk/ca-base/utils/balance.utils.ts | 227 +++ .../core/sdk/ca-base/utils/common.utils.ts | 331 +++- .../core/sdk/ca-base/utils/contract.utils.ts | 100 +- .../core/sdk/ca-base/utils/cosmos.utils.ts | 20 +- packages/core/sdk/ca-base/utils/index.ts | 12 +- packages/core/sdk/ca-base/utils/rff.utils.ts | 219 ++- packages/core/sdk/ca-base/utils/tron.utils.ts | 15 + packages/core/sdk/index.ts | 195 +-- packages/core/sdk/utils.ts | 47 +- packages/widgets/package.json | 12 +- .../src/components/shared/chain-select.tsx | 4 +- .../components/shared/destination-drawer.tsx | 4 +- .../src/components/shared/token-select.tsx | 4 +- packages/widgets/src/types/index.ts | 8 +- packages/widgets/src/utils/token-utils.ts | 16 +- pnpm-lock.yaml | 1434 ++++++++++------- scripts/local-pack.sh | 23 +- scripts/release-core.sh | 33 +- scripts/release-widgets.sh | 2 +- 82 files changed, 6179 insertions(+), 10485 deletions(-) create mode 100644 packages/commons/types/bridge-steps.ts create mode 100644 packages/commons/types/contract-types.ts rename packages/{core/sdk/ca-base/swap/steps.ts => commons/types/swap-steps.ts} (56%) create mode 100644 packages/commons/utils/format.ts delete mode 100644 packages/core/adapters/chain-abstraction-adapter.ts delete mode 100644 packages/core/adapters/core/validation.ts delete mode 100644 packages/core/adapters/services/approval-service.ts delete mode 100644 packages/core/adapters/services/balance-detection-service.ts delete mode 100644 packages/core/adapters/services/bridge-execute-service.ts delete mode 100644 packages/core/adapters/services/execute-service.ts delete mode 100644 packages/core/adapters/services/simulation-engine.ts delete mode 100644 packages/core/adapters/services/transaction-service.ts delete mode 100644 packages/core/sdk/ca-base/logger.ts create mode 100644 packages/core/sdk/ca-base/nexusError.ts delete mode 100644 packages/core/sdk/ca-base/query/allowance.ts delete mode 100644 packages/core/sdk/ca-base/query/bridge.ts create mode 100644 packages/core/sdk/ca-base/query/bridgeAndExecute.ts create mode 100644 packages/core/sdk/ca-base/query/bridgeAndTransfer.ts delete mode 100644 packages/core/sdk/ca-base/query/transfer.ts create mode 100644 packages/core/sdk/ca-base/requestHandlers/bridge.ts create mode 100644 packages/core/sdk/ca-base/requestHandlers/bridgeMax.ts delete mode 100644 packages/core/sdk/ca-base/requestHandlers/common/base.ts delete mode 100644 packages/core/sdk/ca-base/requestHandlers/common/utils.ts delete mode 100644 packages/core/sdk/ca-base/requestHandlers/evm/common.ts delete mode 100644 packages/core/sdk/ca-base/requestHandlers/evm/erc20.ts delete mode 100644 packages/core/sdk/ca-base/requestHandlers/evm/native.ts delete mode 100644 packages/core/sdk/ca-base/requestHandlers/fuel/common.ts delete mode 100644 packages/core/sdk/ca-base/requestHandlers/fuel/native.ts delete mode 100644 packages/core/sdk/ca-base/requestHandlers/fuel/provider.ts delete mode 100644 packages/core/sdk/ca-base/requestHandlers/fuel/token.ts create mode 100644 packages/core/sdk/ca-base/requestHandlers/helpers.ts delete mode 100644 packages/core/sdk/ca-base/requestHandlers/router.ts delete mode 100644 packages/core/sdk/ca-base/simulate.ts create mode 100644 packages/core/sdk/ca-base/utils/balance.utils.ts create mode 100644 packages/core/sdk/ca-base/utils/tron.utils.ts diff --git a/package.json b/package.json index 05085250..286d7a8a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "nexus-sdk-monorepo", - "version": "0.0.2", + "version": "1.0.0-beta.26", "private": true, "description": "Nexus SDK monorepo - cross-chain transactions with minimal friction", "scripts": { @@ -13,6 +13,8 @@ "dev": "pnpm run dev:core & pnpm run dev:widgets", "format": "prettier --write \"packages/**/*.{ts,tsx}\"", "prepare": "husky install", + "typecheck:core": "pnpm -F @avail-project/nexus-core typecheck", + "typecheck:widgets": "pnpm -F @avail-project/nexus-widgets typecheck", "typecheck": "pnpm -r typecheck", "clean": "rimraf packages/widgets/dist packages/core/dist packages/commons/dist", "clean:modules": "rimraf node_modules packages/widgets/node_modules packages/core/node_modules packages/commons/node_modules", @@ -47,10 +49,10 @@ }, "devDependencies": { "@rollup/plugin-alias": "^5.1.1", - "@types/node": "^20.0.0", - "husky": "^8.0.0", - "prettier": "^3.0.0", - "rimraf": "^5.0.0", - "typescript": "^5.0.0" + "@types/node": "^20.19.22", + "husky": "^8.0.3", + "prettier": "^3.6.2", + "rimraf": "^5.0.10", + "typescript": "^5.9.3" } } diff --git a/packages/commons/constants/index.ts b/packages/commons/constants/index.ts index 274b1504..5e304a37 100644 --- a/packages/commons/constants/index.ts +++ b/packages/commons/constants/index.ts @@ -1,7 +1,6 @@ import { ChainMetadata, TokenMetadata } from '../types'; -export const SUPPORTED_CHAINS = { - // Mainnet chains +export const MAINNET_CHAIN_IDS = { ETHEREUM: 1, BASE: 8453, ARBITRUM: 42161, @@ -13,14 +12,23 @@ export const SUPPORTED_CHAINS = { KAIA: 8217, BNB: 56, HYPEREVM: 999, + TRON: 728126428, +} as const; - // Testnet chains +export const TESTNET_CHAIN_IDS = { SEPOLIA: 11155111, BASE_SEPOLIA: 84532, ARBITRUM_SEPOLIA: 421614, OPTIMISM_SEPOLIA: 11155420, POLYGON_AMOY: 80002, MONAD_TESTNET: 10143, + TRON_SHASTA: 2494104990, + VALIDIUM_TESTNET: 567, +} as const; + +export const SUPPORTED_CHAINS = { + ...MAINNET_CHAIN_IDS, + ...TESTNET_CHAIN_IDS, } as const; const BASE_TOKEN_METADATA = { @@ -28,7 +36,7 @@ const BASE_TOKEN_METADATA = { symbol: 'ETH', name: 'Ethereum', decimals: 18, - icon: 'https://coin-images.coingecko.com/coins/images/279/large/ethereum.png?1696501628', + icon: 'https://coin-images.coingecko.com/coins/images/279/large/ethereum.png', coingeckoId: 'ethereum', isNative: true, }, @@ -43,7 +51,7 @@ const BASE_TOKEN_METADATA = { symbol: 'USDC', name: 'USD Coin', decimals: 6, - icon: 'https://coin-images.coingecko.com/coins/images/6319/large/usdc.png?1696506694', + icon: 'https://coin-images.coingecko.com/coins/images/6319/large/usdc.png', coingeckoId: 'usd-coin', }, } as const; @@ -59,7 +67,7 @@ export const TESTNET_TOKEN_METADATA: Record = { export const CHAIN_METADATA: Record = { // Mainnet chains [SUPPORTED_CHAINS.ETHEREUM]: { - id: 1, + id: SUPPORTED_CHAINS.ETHEREUM, name: 'Ethereum', shortName: 'eth', logo: 'https://assets.coingecko.com/coins/images/279/small/ethereum.png', @@ -68,7 +76,7 @@ export const CHAIN_METADATA: Record = { blockExplorerUrls: ['https://etherscan.io'], }, [SUPPORTED_CHAINS.BASE]: { - id: 8453, + id: SUPPORTED_CHAINS.BASE, name: 'Base', shortName: 'base', logo: 'https://pbs.twimg.com/profile_images/1945608199500910592/rnk6ixxH_400x400.jpg', @@ -77,7 +85,7 @@ export const CHAIN_METADATA: Record = { blockExplorerUrls: ['https://basescan.org'], }, [SUPPORTED_CHAINS.ARBITRUM]: { - id: 42161, + id: SUPPORTED_CHAINS.ARBITRUM, name: 'Arbitrum One', shortName: 'arb1', logo: 'https://assets.coingecko.com/coins/images/16547/small/photo_2023-03-29_21.47.00.jpeg', @@ -89,7 +97,7 @@ export const CHAIN_METADATA: Record = { blockExplorerUrls: ['https://arbiscan.io'], }, [SUPPORTED_CHAINS.OPTIMISM]: { - id: 10, + id: SUPPORTED_CHAINS.OPTIMISM, name: 'Optimism', shortName: 'oeth', logo: 'https://assets.coingecko.com/coins/images/25244/small/Optimism.png', @@ -98,7 +106,7 @@ export const CHAIN_METADATA: Record = { blockExplorerUrls: ['https://optimistic.etherscan.io'], }, [SUPPORTED_CHAINS.POLYGON]: { - id: 137, + id: SUPPORTED_CHAINS.POLYGON, name: 'Polygon', shortName: 'matic', logo: 'https://assets.coingecko.com/coins/images/4713/small/polygon.png', @@ -107,7 +115,7 @@ export const CHAIN_METADATA: Record = { blockExplorerUrls: ['https://polygonscan.com'], }, [SUPPORTED_CHAINS.AVALANCHE]: { - id: 43114, + id: SUPPORTED_CHAINS.AVALANCHE, name: 'Avalanche', shortName: 'avax', logo: 'https://assets.coingecko.com/coins/images/12559/small/Avalanche_Circle_RedWhite_Trans.png', @@ -116,7 +124,7 @@ export const CHAIN_METADATA: Record = { blockExplorerUrls: ['https://snowtrace.io'], }, [SUPPORTED_CHAINS.SCROLL]: { - id: 534352, + id: SUPPORTED_CHAINS.SCROLL, name: 'Scroll', shortName: 'scroll', logo: 'https://assets.coingecko.com/coins/images/50571/standard/scroll.jpg?1728376125', @@ -125,7 +133,7 @@ export const CHAIN_METADATA: Record = { blockExplorerUrls: ['https://scrollscan.com'], }, [SUPPORTED_CHAINS.SOPHON]: { - id: 50104, + id: SUPPORTED_CHAINS.SOPHON, name: 'Sophon', shortName: 'sophon', logo: 'https://assets.coingecko.com/coins/images/38680/large/sophon_logo_200.png', @@ -134,7 +142,7 @@ export const CHAIN_METADATA: Record = { blockExplorerUrls: ['https://explorer.sophon.xyz'], }, [SUPPORTED_CHAINS.KAIA]: { - id: 8217, + id: SUPPORTED_CHAINS.KAIA, name: 'Kaia Mainnet', shortName: 'kaia', logo: 'https://assets.coingecko.com/asset_platforms/images/9672/large/kaia.png', @@ -143,7 +151,7 @@ export const CHAIN_METADATA: Record = { blockExplorerUrls: ['https://kaiascan.io'], }, [SUPPORTED_CHAINS.BNB]: { - id: 56, + id: SUPPORTED_CHAINS.BNB, name: 'BNB Smart Chain', shortName: 'bnb', logo: 'https://assets.coingecko.com/asset_platforms/images/1/large/bnb_smart_chain.png', @@ -163,7 +171,7 @@ export const CHAIN_METADATA: Record = { // Testnet chains [SUPPORTED_CHAINS.SEPOLIA]: { - id: 11155111, + id: SUPPORTED_CHAINS.SEPOLIA, name: 'Sepolia', shortName: 'sepolia', logo: 'https://assets.coingecko.com/asset_platforms/images/279/large/ethereum.png?1706606803', @@ -172,7 +180,7 @@ export const CHAIN_METADATA: Record = { blockExplorerUrls: ['https://sepolia.etherscan.io'], }, [SUPPORTED_CHAINS.BASE_SEPOLIA]: { - id: 84532, + id: SUPPORTED_CHAINS.BASE_SEPOLIA, name: 'Base Sepolia', shortName: 'base-sepolia', logo: 'https://pbs.twimg.com/profile_images/1945608199500910592/rnk6ixxH_400x400.jpg', @@ -181,7 +189,7 @@ export const CHAIN_METADATA: Record = { blockExplorerUrls: ['https://sepolia.basescan.org'], }, [SUPPORTED_CHAINS.MONAD_TESTNET]: { - id: 10143, + id: SUPPORTED_CHAINS.MONAD_TESTNET, name: 'Monad Testnet', shortName: 'monad-testnet', logo: 'https://assets.coingecko.com/coins/images/38927/standard/monad.jpg', @@ -190,7 +198,7 @@ export const CHAIN_METADATA: Record = { blockExplorerUrls: ['https://testnet.monadexplorer.com/'], }, [SUPPORTED_CHAINS.ARBITRUM_SEPOLIA]: { - id: 421614, + id: SUPPORTED_CHAINS.ARBITRUM_SEPOLIA, name: 'Arbitrum Sepolia', shortName: 'arb-sepolia', logo: 'https://assets.coingecko.com/coins/images/16547/small/photo_2023-03-29_21.47.00.jpeg', @@ -199,7 +207,7 @@ export const CHAIN_METADATA: Record = { blockExplorerUrls: ['https://sepolia.arbiscan.io'], }, [SUPPORTED_CHAINS.OPTIMISM_SEPOLIA]: { - id: 11155420, + id: SUPPORTED_CHAINS.OPTIMISM_SEPOLIA, name: 'Optimism Sepolia', shortName: 'op-sepolia', logo: 'https://assets.coingecko.com/coins/images/25244/small/Optimism.png', @@ -208,7 +216,7 @@ export const CHAIN_METADATA: Record = { blockExplorerUrls: ['https://sepolia-optimism.etherscan.io'], }, [SUPPORTED_CHAINS.POLYGON_AMOY]: { - id: 80002, + id: SUPPORTED_CHAINS.POLYGON_AMOY, name: 'Polygon Amoy', shortName: 'amoy', logo: 'https://assets.coingecko.com/coins/images/4713/small/polygon.png', @@ -220,12 +228,9 @@ export const CHAIN_METADATA: Record = { // Event name constants to prevent typos export const NEXUS_EVENTS = { - STEP_COMPLETE: 'step_complete', - EXPECTED_STEPS: 'expected_steps', - SWAP_STEPS: 'swap_step', - // Modular event names - BRIDGE_EXECUTE_EXPECTED_STEPS: 'bridge_execute_expected_steps', - BRIDGE_EXECUTE_COMPLETED_STEPS: 'bridge_execute_completed_steps', + STEP_COMPLETE: 'STEP_COMPLETE', + SWAP_STEP_COMPLETE: 'SWAP_STEP_COMPLETE', + STEPS_LIST: 'STEPS_LIST', } as const; // Helper constants for mainnet and testnet chain categorization @@ -241,6 +246,7 @@ export const MAINNET_CHAINS = [ SUPPORTED_CHAINS.KAIA, SUPPORTED_CHAINS.BNB, SUPPORTED_CHAINS.HYPEREVM, + SUPPORTED_CHAINS.TRON, ] as const; export const TESTNET_CHAINS = [ @@ -250,13 +256,14 @@ export const TESTNET_CHAINS = [ SUPPORTED_CHAINS.OPTIMISM_SEPOLIA, SUPPORTED_CHAINS.POLYGON_AMOY, SUPPORTED_CHAINS.MONAD_TESTNET, + SUPPORTED_CHAINS.TRON_SHASTA, ] as const; /** * Token contract addresses per chain * This registry contains the contract addresses for supported tokens across different chains */ -export const TOKEN_CONTRACT_ADDRESSES: Record> = { +export const TOKEN_CONTRACT_ADDRESSES = { USDC: { [SUPPORTED_CHAINS.ETHEREUM]: '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48', [SUPPORTED_CHAINS.BASE]: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913', @@ -267,14 +274,16 @@ export const TOKEN_CONTRACT_ADDRESSES: Record + ({ + type: 'INTENT_SUBMITTED', + typeID: 'IS', + data: { + explorerURL, + intentID, + }, + }) as const; + +const INTENT_FULFILLED = { + type: 'INTENT_FULFILLED', + typeID: 'IF', +} as const; + +const ALLOWANCE_APPROVAL_REQUEST = (chain: { id: number; name?: string }) => + ({ + type: 'ALLOWANCE_USER_APPROVAL', + typeID: `AUA_${chain.id}`, + data: { + chainID: chain.id, + chainName: chain.name, + }, + }) as const; + +const ALLOWANCE_APPROVAL_MINED = (chain: { id: number; name?: string }) => + ({ + type: 'ALLOWANCE_APPROVAL_MINED', + typeID: `AAM_${chain.id}`, + data: { + chainID: chain.id, + chainName: chain.name, + }, + }) as const; + +const ALLOWANCE_COMPLETE = { + type: 'ALLOWANCE_ALL_DONE', + typeID: 'AAD', +} as const; + +const INTENT_DEPOSIT_REQUEST = ( + id: number, + amount: Decimal, + chain: { id: number; name?: string }, +) => + ({ + type: 'INTENT_DEPOSIT', + typeID: `ID_${id}`, + data: { + amount: amount.toFixed(), + chainID: chain.id, + chainName: chain.name, + }, + }) as const; + +const INTENT_DEPOSITS_CONFIRMED = { + type: 'INTENT_DEPOSITS_CONFIRMED', + typeID: 'UIDC', +} as const; + +const INTENT_COLLECTION_COMPLETE = { + type: 'INTENT_COLLECTION_COMPLETE', + typeID: 'ICC', +} as const; + +const INTENT_COLLECTION = (id: number, total: number) => + ({ + type: 'INTENT_COLLECTION', + typeID: `IC_${id}`, + data: { + confirmed: id, + total, + }, + }) as const; + +const EXECUTE_APPROVAL_STEP = { + type: 'APPROVAL', + typeID: 'AP', +} as const; + +const EXECUTE_TRANSACTION_SENT = { + type: 'TRANSACTION_SENT', + typeID: 'TS', +} as const; + +const EXECUTE_TRANSACTION_CONFIRMED = { + type: 'TRANSACTION_CONFIRMED', + typeID: 'CN', +} as const; + +const BRIDGE_STEPS = { + INTENT_ACCEPTED, + ALLOWANCE_APPROVAL_REQUEST, + ALLOWANCE_APPROVAL_MINED, + ALLOWANCE_COMPLETE, + INTENT_COLLECTION, + INTENT_HASH_SIGNED, + INTENT_COLLECTION_COMPLETE, + INTENT_DEPOSITS_CONFIRMED, + INTENT_DEPOSIT_REQUEST, + INTENT_FULFILLED, + INTENT_SUBMITTED, + EXECUTE_APPROVAL_STEP, + EXECUTE_TRANSACTION_CONFIRMED, + EXECUTE_TRANSACTION_SENT, +}; + +type BridgeStepType = + | ReturnType + | ReturnType + | ReturnType + | ReturnType + | ReturnType + | typeof INTENT_ACCEPTED + | typeof INTENT_HASH_SIGNED + | typeof INTENT_DEPOSITS_CONFIRMED + | typeof INTENT_COLLECTION_COMPLETE + | typeof INTENT_FULFILLED + | typeof ALLOWANCE_COMPLETE + | typeof EXECUTE_APPROVAL_STEP + | typeof EXECUTE_TRANSACTION_CONFIRMED + | typeof EXECUTE_TRANSACTION_SENT; + +export { BridgeStepType, BRIDGE_STEPS }; diff --git a/packages/commons/types/contract-types.ts b/packages/commons/types/contract-types.ts new file mode 100644 index 00000000..bba798ea --- /dev/null +++ b/packages/commons/types/contract-types.ts @@ -0,0 +1,14 @@ +import { Hex } from 'viem'; + +export type GetAllowanceParams = { + contractAddress: Hex; + spender: Hex; + owner: Hex; +}; + +export type SetAllowanceParams = { + contractAddress: Hex; + spender: Hex; + owner: Hex; + amount: bigint; +}; diff --git a/packages/commons/types/index.ts b/packages/commons/types/index.ts index 9bc2c771..bc4ab826 100644 --- a/packages/commons/types/index.ts +++ b/packages/commons/types/index.ts @@ -1,22 +1,25 @@ import { SUPPORTED_CHAINS } from '../constants'; -import { Abi, TransactionReceipt, ByteArray, Hex, WalletClient } from 'viem'; -import { ChainDatum, Environment, PermitVariant, Universe } from '@arcana/ca-common'; +import { TransactionReceipt, ByteArray, Hex, WalletClient } from 'viem'; +import { ChainDatum, Environment, PermitVariant, Universe } from '@avail-project/ca-common'; import * as ServiceTypes from './service-types'; import Decimal from 'decimal.js'; import { SwapIntent } from './swap-types'; -import { FuelConnector, Provider, TransactionRequestLike } from 'fuels'; +import { FuelConnector, Provider } from 'fuels'; import { DirectSecp256k1Wallet } from '@cosmjs/proto-signing'; +import { AdapterProps } from '@tronweb3/tronwallet-abstract-adapter'; +import { SwapStepType } from './swap-steps'; +import { BridgeStepType } from './bridge-steps'; +import { FormatTokenBalanceOptions, FormattedParts } from '../utils/format'; type TokenInfo = { contractAddress: `0x${string}`; decimals: number; - logo?: string; + logo: string; name: string; - platform?: string; symbol: string; }; -type NexusNetwork = 'mainnet' | 'testnet'; +type NexusNetwork = 'mainnet' | 'testnet' | 'devnet'; export interface BlockTransaction { hash?: string; @@ -83,9 +86,9 @@ export type SUPPORTED_CHAINS_IDS = (typeof SUPPORTED_CHAINS)[keyof typeof SUPPOR * This allows for dynamic parameter generation based on actual bridged amounts and user context */ export type DynamicParamBuilder = ( - token: SUPPORTED_TOKENS, + token: string, amount: string, - chainId: SUPPORTED_CHAINS_IDS, + chainId: number, userAddress: `0x${string}`, ) => { functionParams: readonly unknown[]; @@ -97,50 +100,52 @@ export type DynamicParamBuilder = ( * Parameters for bridging tokens between chains. */ export interface BridgeParams { - token: SUPPORTED_TOKENS; - amount: number | string; - chainId: SUPPORTED_CHAINS_IDS; + recipient?: Hex; + token: string; + amount: string; + toChainId: number; gas?: bigint; sourceChains?: number[]; } +export type BridgeMaxResult = { + amountRaw: bigint; + amount: string; + symbol: string; + sourceChainIds: number[]; +}; + /** * Result structure for bridge transactions. */ -export type BridgeResult = - | { success: false; error: string } - | { - success: true; - explorerUrl: string; - transactionHash?: string; - }; +export type BridgeResult = { + explorerUrl: string; +}; /** * Result structure for transfer transactions. */ -export type TransferResult = - | { - success: true; - transactionHash: string; - explorerUrl: string; - } - | { - success: false; - error: string; - }; +export type TransferResult = { + transactionHash: string; + explorerUrl: string; +}; export interface SimulationResult { intent: ReadableIntent; token: TokenInfo; } +export type TronAdapter = AdapterProps & { + isMobile?: boolean; +}; + /** * Parameters for transferring tokens. */ export interface TransferParams { - token: SUPPORTED_TOKENS; - amount: number | string; - chainId: SUPPORTED_CHAINS_IDS; + token: string; + amount: string; + toChainId: number; recipient: `0x${string}`; sourceChains?: number[]; } @@ -160,12 +165,12 @@ export interface TokenBalance { // Enhanced modular parameters for execute functionality with dynamic parameter building export interface ExecuteParams { - toChainId: SUPPORTED_CHAINS_IDS; - contractAddress: string; - contractAbi: Abi; - functionName: string; - buildFunctionParams: DynamicParamBuilder; - value?: string; // Can be overridden by callback + toChainId: number; + to: Hex; + value?: bigint; + data?: Hex; + gas?: bigint; + gasPrice?: bigint; enableTransactionPolling?: boolean; transactionTimeout?: number; // Transaction receipt confirmation options @@ -173,14 +178,10 @@ export interface ExecuteParams { receiptTimeout?: number; requiredConfirmations?: number; tokenApproval?: { - token: SUPPORTED_TOKENS; - amount: string; + token: string; + amount: bigint; + spender: Hex; }; - /** - * Optional approval buffer in basis points (bps). Defaults to 100 (1%). - * Use 0 to disable buffer (e.g., for bridge+execute flows where exact balances are used). - */ - approvalBufferBps?: number; } export interface ExecuteResult { @@ -195,14 +196,14 @@ export interface ExecuteResult { approvalTransactionHash?: string; } -export interface ExecuteSimulation { - contractAddress: string; - functionName: string; - gasUsed: string; - success: boolean; - error?: string; - gasCostEth?: string; -} +export type ExecuteSimulation = { + gasUsed: bigint; + gasPrice: bigint; + /** + * gasFee = gasUsed * gasPrice + */ + gasFee: bigint; +}; // New types for improved approval simulation export interface ApprovalInfo { @@ -231,101 +232,65 @@ export interface SimulationStep { description: string; } -interface SimulationMetadata { - contractAddress: string; - functionName: string; - bridgeReceiveAmount: string; - bridgeFee: string; - inputAmount: string; - optimalBridgeAmount?: string; - targetChain: number; - approvalRequired: boolean; - bridgeSkipped?: boolean; - token?: SUPPORTED_TOKENS; -} +export type EventListenerType = { + onEvent: (eventName: string, ...args: any[]) => void; +}; -export interface BridgeAndExecuteSimulationResult { - steps: SimulationStep[]; +export type BridgeAndExecuteSimulationResult = { bridgeSimulation: SimulationResult | null; - executeSimulation?: ExecuteSimulation; - totalEstimatedCost?: { - total: string; - breakdown: { - bridge: string; - execute: string; - }; - }; - success: boolean; - error?: string; - metadata?: SimulationMetadata; -} + executeSimulation: ExecuteSimulation; +}; export interface BridgeAndExecuteParams { - toChainId: SUPPORTED_CHAINS_IDS; - token: SUPPORTED_TOKENS; - amount: number | string; - recipient?: `0x${string}`; + toChainId: number; + token: string; + amount: bigint; sourceChains?: number[]; - execute?: Omit; + execute: Omit; enableTransactionPolling?: boolean; transactionTimeout?: number; - // Global options for transaction confirmation waitForReceipt?: boolean; receiptTimeout?: number; requiredConfirmations?: number; - // Optional recent approval transaction hash to consider in simulation recentApprovalTxHash?: string; } -export interface BridgeAndExecuteResult { - executeTransactionHash?: string; - executeExplorerUrl?: string; +export type IBridgeOptions = { + cosmos: { + wallet: DirectSecp256k1Wallet; + address: string; + }; + evm: { + address: `0x${string}`; + client: WalletClient; + }; + fuel?: { + address: string; + connector: FuelConnector; + provider: Provider; + }; + tron?: { + address: string; + adapter: TronAdapter; + }; + hooks: { + onAllowance: OnAllowanceHook; + onIntent: OnIntentHook; + }; + emit?: OnEventParam['onEvent']; + networkConfig: NetworkConfig; + chainList: ChainListType; +}; + +export type BridgeAndExecuteResult = { + executeTransactionHash: string; + executeExplorerUrl: string; approvalTransactionHash?: string; - bridgeTransactionHash?: string; // undefined when bridge is skipped bridgeExplorerUrl?: string; // undefined when bridge is skipped toChainId: number; - success: boolean; - error?: string; bridgeSkipped: boolean; // indicates if bridge was skipped due to sufficient funds -} - -/** - * Smart contract call parameters - */ -export interface ContractCallParams { - to: `0x${string}`; - data: `0x${string}`; - value?: bigint; - gas?: bigint; - gasPrice?: bigint; -} - -export type BridgeQueryInput = { - amount: number | string; - chainId: number; - gas?: bigint; - sourceChains?: number[]; - token: string; }; -export interface CA { - createEVMHandler( - tx: EVMTransaction, - options: Partial, - ): Promise; - - createFuelHandler( - tx: TransactionRequestLike, - options: Partial, - ): Promise; - - getChainID(): Promise; - - init(): Promise; - - switchChain(chainID: number): Promise; -} - export type Chain = { blockExplorers?: { default: { @@ -347,6 +312,7 @@ export type Chain = { }; rpcUrls: { default: { + grpc?: string[]; http: string[]; publicHttp?: string[]; webSocket: string[]; @@ -355,11 +321,6 @@ export type Chain = { universe: Universe; }; -export interface CreateHandlerResponse { - handler: IRequestHandler | null; - processTx: () => Promise; -} - interface EthereumProvider { on(eventName: string | symbol, listener: (...args: any[]) => void): this; @@ -420,6 +381,7 @@ export type Intent = { protocol: string; solver: string; }; + recipientAddress: Hex; isAvailableBalanceInsufficient: boolean; sources: IntentSource[]; }; @@ -437,6 +399,7 @@ export type IntentSource = { chainID: number; tokenContract: `0x${string}`; universe: Universe; + holderAddress: Hex; }; export type IntentSourceForAllowance = { @@ -446,17 +409,6 @@ export type IntentSourceForAllowance = { token: TokenInfo; }; -export interface IRequestHandler { - buildIntent(sourceChains: number[]): Promise< - | { - intent: Intent; - token: TokenInfo; - } - | undefined - >; - process(): Promise<{ explorerURL: string } | undefined>; -} - type Network = Extract; export type NetworkConfig = { @@ -556,69 +508,62 @@ type RequestArguments = { readonly params?: object | readonly unknown[]; }; -export type RequestHandler = new (i: RequestHandlerInput) => IRequestHandler; - export type ChainListType = { chains: Chain[]; getVaultContractAddress(chainID: number): `0x${string}`; getTokenInfoBySymbol(chainID: number, symbol: string): TokenInfo | undefined; + getChainAndTokenFromSymbol( + chainID: number, + tokenSymbol: string, + ): { + chain: Chain; + token: (TokenInfo & { isNative: boolean }) | undefined; + }; getTokenByAddress(chainID: number, address: `0x${string}`): TokenInfo | undefined; + getChainAndTokenByAddress( + chainID: number, + address: `0x${string}`, + ): + | { + chain: Chain; + token: TokenInfo | undefined; + } + | undefined; getNativeToken(chainID: number): TokenInfo; getChainByID(id: number): Chain | undefined; getAnkrNameList(): string[]; }; -export type RequestHandlerInput = { - chain: Chain; - chainList: ChainListType; - cosmosWallet: DirectSecp256k1Wallet; - evm: { - address: `0x${string}`; - client: WalletClient; - tx?: EVMTransaction; - }; - fuel?: { - address: string; - connector: FuelConnector; - provider: Provider; - tx?: TransactionRequestLike; - }; - hooks: { - onAllowance: OnAllowanceHook; - onIntent: OnIntentHook; - }; - options: { - emit: (eventName: string, ...args: any[]) => void; - networkConfig: NetworkConfig; - } & TxOptions; -}; +type EventUnion = + | { name: 'STEPS_LIST'; args: BridgeStepType[] } + | { name: 'SWAP_STEP_COMPLETE'; args: SwapStepType } + | { name: 'STEP_COMPLETE'; args: BridgeStepType }; -export type RequestHandlerResponse = { - buildIntent(): Promise< - | { - intent: Intent; - token: TokenInfo; - } - | undefined - >; - input: RequestHandlerInput; - process(): Promise; -} | null; +export type OnEventParam = { + onEvent?: (event: EventUnion) => void; +}; export type RFF = { deposited: boolean; - destinationChainID: number; - destinations: { tokenAddress: Hex; value: bigint }[]; - destinationUniverse: string; + destinationChain: { id: number; name: string; logo: string; universe: string }; + destinations: { + token: { address: Hex; symbol: string; decimals: number }; + value: string; + valueRaw: bigint; + }[]; expiry: number; fulfilled: boolean; id: number; refunded: boolean; sources: { - chainID: number; - tokenAddress: Hex; - universe: string; - value: bigint; + chain: { id: number; name: string; logo: string; universe: string }; + valueRaw: bigint; + value: string; + token: { + address: Hex; + symbol: string; + decimals: number; + }; }[]; }; @@ -673,28 +618,6 @@ export type SponsoredApprovalData = { export type SponsoredApprovalDataArray = SponsoredApprovalData[]; -export type Step = { - data?: - | { - amount: string; - chainName: string; - symbol: string; - } - | { - chainID: number; - chainName: string; - } - | { confirmed: number; total: number } - | { explorerURL: string; intentID: number }; -} & StepInfo; - -export type StepInfo = { - type: string; - typeID: string; -}; - -export type Steps = Step[]; - export type Token = { contractAddress: `0x${string}`; decimals: number; @@ -702,17 +625,6 @@ export type Token = { symbol: string; }; -export type TransferQueryInput = { - to: Hex; -} & Omit; - -export type TxOptions = { - bridge: boolean; - gas: bigint; - skipTx: boolean; - sourceChains: number[]; -}; - export type UnifiedBalanceResponseData = { chain_id: Uint8Array; currencies: { @@ -722,6 +634,7 @@ export type UnifiedBalanceResponseData = { }[]; total_usd: string; universe: Universe; + errored: boolean; }; export type UserAssetDatum = { @@ -754,8 +667,6 @@ export type { OnAllowanceHook, EthereumProvider, RequestArguments, - Step as ProgressStep, - Steps as ProgressSteps, onAllowanceHookSource as AllowanceHookSource, Network, UserAssetDatum as UserAsset, @@ -766,4 +677,6 @@ export type { TransactionReceipt, SwapIntent, SetAllowanceInput, + FormatTokenBalanceOptions, + FormattedParts, }; diff --git a/packages/core/sdk/ca-base/swap/steps.ts b/packages/commons/types/swap-steps.ts similarity index 56% rename from packages/core/sdk/ca-base/swap/steps.ts rename to packages/commons/types/swap-steps.ts index 84b63824..11e1865c 100644 --- a/packages/core/sdk/ca-base/swap/steps.ts +++ b/packages/commons/types/swap-steps.ts @@ -1,33 +1,24 @@ +import { ChainListType } from '.'; import { Hex } from 'viem'; -import { Chain } from '@nexus/commons'; -import { ChainListType } from '@nexus/commons'; -export type SwapStep = - | ReturnType - | ReturnType - | ReturnType - | ReturnType - | ReturnType - | ReturnType - | ReturnType - | ReturnType - | typeof SWAP_COMPLETE - | typeof SWAP_START; - -export const SWAP_START = { +const SWAP_START = { completed: true, type: 'SWAP_START', typeID: 'SWAP_START', } as const; -export const DETERMINING_SWAP = (completed: boolean = false) => +const DETERMINING_SWAP = (completed: boolean = false) => ({ completed, type: 'DETERMINING_SWAP', typeID: DETERMINING_SWAP, }) as const; -export const CREATE_PERMIT_EOA_TO_EPHEMERAL = (completed: boolean, symbol: string, chain: Chain) => +const CREATE_PERMIT_EOA_TO_EPHEMERAL = ( + completed: boolean, + symbol: string, + chain: { id: number; name?: string }, +) => ({ chain: { id: chain.id, @@ -39,7 +30,11 @@ export const CREATE_PERMIT_EOA_TO_EPHEMERAL = (completed: boolean, symbol: strin typeID: `CREATE_PERMIT_EOA_TO_EPHEMERAL_${chain.id}_${symbol}`, }) as const; -export const CREATE_PERMIT_FOR_SOURCE_SWAP = (completed: boolean, symbol: string, chain: Chain) => +const CREATE_PERMIT_FOR_SOURCE_SWAP = ( + completed: boolean, + symbol: string, + chain: { id: number; name?: string }, +) => ({ chain: { id: chain.id, @@ -51,14 +46,14 @@ export const CREATE_PERMIT_FOR_SOURCE_SWAP = (completed: boolean, symbol: string typeID: `CREATE_PERMIT_FOR_SOURCE_SWAP_${chain.id}_${symbol}`, }) as const; -export const SOURCE_SWAP_BATCH_TX = (completed: boolean) => +const SOURCE_SWAP_BATCH_TX = (completed: boolean) => ({ completed, type: 'SOURCE_SWAP_BATCH_TX', typeID: 'SOURCE_SWAP_BATCH_TX', }) as const; -export const SOURCE_SWAP_HASH = (ops: [bigint, Hex], chainList: ChainListType) => { +const SOURCE_SWAP_HASH = (ops: [bigint, Hex], chainList: ChainListType) => { const chainID = ops[0]; const chain = chainList.getChainByID(Number(ops[0])); if (!chain) { @@ -77,7 +72,7 @@ export const SOURCE_SWAP_HASH = (ops: [bigint, Hex], chainList: ChainListType) = } as const; }; -export const RFF_ID = (id: number) => +const RFF_ID = (id: number) => ({ completed: true, data: id, @@ -85,20 +80,20 @@ export const RFF_ID = (id: number) => typeID: 'RFF_ID', }) as const; -export const DESTINATION_SWAP_BATCH_TX = (completed: boolean) => +const DESTINATION_SWAP_BATCH_TX = (completed: boolean) => ({ completed, type: 'DESTINATION_SWAP_BATCH_TX', typeID: 'DESTINATION_SWAP_BATCH_TX', }) as const; -export const SWAP_COMPLETE = { +const SWAP_COMPLETE = { completed: true, type: 'SWAP_COMPLETE', typeID: 'SWAP_COMPLETE', } as const; -export const DESTINATION_SWAP_HASH = (op: [bigint, Hex], chainList: ChainListType) => { +const DESTINATION_SWAP_HASH = (op: [bigint, Hex], chainList: ChainListType) => { const chain = chainList.getChainByID(Number(op[0])); if (!chain) { throw new Error(`Unknown chain: ${op[0]}`); @@ -114,3 +109,28 @@ export const DESTINATION_SWAP_HASH = (op: [bigint, Hex], chainList: ChainListTyp typeID: `DESTINATION_SWAP_HASH_${chain.id}`, } as const; }; + +export const SWAP_STEPS = { + SWAP_START, + CREATE_PERMIT_EOA_TO_EPHEMERAL, + CREATE_PERMIT_FOR_SOURCE_SWAP, + DESTINATION_SWAP_BATCH_TX, + DESTINATION_SWAP_HASH, + DETERMINING_SWAP, + RFF_ID, + SOURCE_SWAP_BATCH_TX, + SOURCE_SWAP_HASH, + SWAP_COMPLETE, +}; + +export type SwapStepType = + | ReturnType + | ReturnType + | ReturnType + | ReturnType + | ReturnType + | ReturnType + | ReturnType + | ReturnType + | typeof SWAP_STEPS.SWAP_COMPLETE + | typeof SWAP_STEPS.SWAP_START; diff --git a/packages/commons/types/swap-types.ts b/packages/commons/types/swap-types.ts index ff74a022..973b7d15 100644 --- a/packages/commons/types/swap-types.ts +++ b/packages/commons/types/swap-types.ts @@ -1,9 +1,9 @@ -import { Universe } from '@arcana/ca-common'; +import { Universe } from '@avail-project/ca-common'; import { DirectSecp256k1Wallet } from '@cosmjs/proto-signing'; import Decimal from 'decimal.js'; import { type Hex, PrivateKeyAccount, WalletClient } from 'viem'; -import { NetworkConfig, TokenInfo, ChainListType } from '../index'; +import { NetworkConfig, ChainListType, OnEventParam } from '../index'; export type AuthorizationList = { address: Uint8Array; @@ -110,15 +110,17 @@ export type SwapIntent = { }[]; }; -export type SwapIntentHook = (data: { +export type OnSwapIntentHookData = { allow: () => void; deny: () => void; intent: SwapIntent; refresh: () => Promise; -}) => unknown; +}; + +export type OnSwapIntentHook = (data: OnSwapIntentHookData) => unknown; export type SwapParams = { - emit: (stepID: string, step: unknown) => void; + onSwapIntent: OnSwapIntentHook; chainList: ChainListType; address: { cosmos: string; @@ -131,14 +133,10 @@ export type SwapParams = { eoa: WalletClient; }; networkConfig: NetworkConfig; -} & SwapInputOptionalParams; - -export type SwapInputOptionalParams = { - swapIntentHook?: SwapIntentHook; -}; +} & OnEventParam; export interface ExactInSwapInput { - from?: { + from: { chainId: number; amount: bigint; tokenAddress: Hex; @@ -269,13 +267,14 @@ export type SupportedChainsResult = { id: number; logo: string; name: string; - tokens: TokenInfo[]; }[]; export type Tx = { data: Hex; to: Hex; value: bigint; + gas?: bigint; + gasPrice?: bigint; }; // export type UserAsset = { diff --git a/packages/commons/utils/format.ts b/packages/commons/utils/format.ts new file mode 100644 index 00000000..8a627854 --- /dev/null +++ b/packages/commons/utils/format.ts @@ -0,0 +1,303 @@ +/** + * Token balance formatter with zero-compression for tiny values. + * + * Examples: + * - 1.234567 -> "1.2346" + * - 0.00008509 -> "~0.0₄8509" (shows 4 leading zeros after decimal) + * - 0.000000000000000123 -> "~0.0₁₅123" + * + * Notes: + * - Uses Unicode subscript digits for the zero count. + * - Returns a single string optimized for UI display. + * - If you need richer rendering (e.g., separate parts to style the subscript), + * use `formatTokenBalanceParts` which returns structured parts. + */ + +import { formatUnits } from 'viem'; +export interface FormatTokenBalanceOptions { + decimals?: number; // when value is base units (bigint) + symbol?: string; // e.g., "ETH" + significantDigits?: number; // digits after the first non-zero in tiny values + maxFractionDigits?: number; // for "normal" values + tinyThresholdPower?: number; // threshold exponent, default -4 => 10^-4 + zeroCompress?: boolean; // show 0.0ₖ for small values + thousandSeparator?: boolean; // e.g., 12,345.67 + trimTrailingZeros?: boolean; // remove trailing 0s + approxTilde?: boolean; // prefix "~" when rounding/truncating +} + +export interface FormattedParts { + text: string; // final string + approx: boolean; + integer: string; // "0" or "12" + zeroCount?: number; // number of zeros after decimal for tiny values + zeroSubscript?: string; // "₆" + significant?: string; // e.g., "8509" + fraction?: string; // normal fraction for non-tiny values + symbol?: string; +} + +const SUBSCRIPT_DIGITS: Record = { + '0': '₀', + '1': '₁', + '2': '₂', + '3': '₃', + '4': '₄', + '5': '₅', + '6': '₆', + '7': '₇', + '8': '₈', + '9': '₉', +}; + +function toSubscript(num: number): string { + return String(num) + .split('') + .map((d) => SUBSCRIPT_DIGITS[d] ?? d) + .join(''); +} + +function expandExponential(n: string): string { + // Handles strings like "1e-7" or "1.23e+5" into normal decimal strings + if (!/e/i.test(n)) return n; + const isNeg = n.startsWith('-'); + const isPos = !isNeg && n.startsWith('+'); + const unsigned = isNeg || isPos ? n.slice(1) : n; + const [mantissa, expStr] = unsigned.toLowerCase().split('e'); + const exp = Number(expStr); + if (!Number.isFinite(exp)) return n; + const [intPart, fracPart = ''] = mantissa.split('.'); + const digits = intPart + fracPart; + if (exp === 0) return (isNeg ? '-' : '') + mantissa; + if (exp > 0) { + // Move decimal right + const pad = Math.max(0, exp - fracPart.length); + const left = digits + '0'.repeat(pad); + const idx = intPart.length + exp; + const whole = left.slice(0, idx); + const frac = left.slice(idx); + const out = frac.length ? `${whole}.${frac}` : whole; + return (isNeg ? '-' : '') + out; + } else { + // Move decimal left + const k = Math.abs(exp); + const pad = Math.max(0, k - intPart.length); + const left = '0'.repeat(pad) + digits; + const idx = left.length - k; + const whole = left.slice(0, idx) || '0'; + const frac = left.slice(idx); + const out = `${whole}.${frac}`; + return (isNeg ? '-' : '') + out; + } +} + +function bigIntToDecimalString(value: bigint, decimals: number): string { + const raw = formatUnits(value, decimals); + if (raw.includes('.')) { + const [i, f] = raw.split('.'); + const f2 = f.replace(/0+$/, ''); + return f2.length ? `${i}.${f2}` : i; + } + return raw; +} + +type InputValue = string | number | bigint; + +function insertThousands(n: string): string { + const neg = n.startsWith('-'); + const s = neg ? n.slice(1) : n; + const [i, f] = s.split('.'); + const withSep = i.replaceAll(/\B(?=(\d{3})+(?!\d))/g, ','); + const suffix = f ? `.${f}` : ''; + if (neg) { + return `-${withSep}${suffix}`; + } + return `${withSep}${suffix}`; +} + +function stripTrailingZeros(s: string): string { + if (s === '') return s; + let end = s.length; + while (end > 0 && s.charAt(end - 1) === '0') end--; + return end === s.length ? s : s.slice(0, end); +} + +function normalizeValue( + value: InputValue, + decimals?: number, +): { negative: boolean; intPart: string; fracRaw: string } { + let decimalStr: string; + if (typeof value === 'bigint') { + if (typeof decimals !== 'number') { + throw new TypeError('decimals is required when formatting bigint amounts'); + } + decimalStr = bigIntToDecimalString(value, decimals); + } else { + decimalStr = expandExponential(String(value)); + } + let negative = false; + if (decimalStr.startsWith('-')) { + negative = true; + decimalStr = decimalStr.slice(1); + } + if (decimalStr === '' || decimalStr === '.') decimalStr = '0'; + const [intRaw, fracRawRaw = ''] = decimalStr.split('.'); + const intPart = intRaw === '' ? '0' : intRaw; + const fracRaw = fracRawRaw; + return { negative, intPart, fracRaw }; +} + +function formatZero(symbol?: string): FormattedParts { + const base = '0'; + const text = symbol ? `${base} ${symbol}` : base; + return { text, approx: false, integer: '0', fraction: '', symbol }; +} + +interface NormalFormatOpts { + maxFractionDigits: number; + trimTrailingZeros: boolean; + thousandSeparator: boolean; + approxTilde: boolean; + symbol?: string; +} + +function formatNormal( + negative: boolean, + intPart: string, + fracRaw: string, + opts: NormalFormatOpts, +): FormattedParts { + let fraction = fracRaw.slice(0, opts.maxFractionDigits); + if (opts.trimTrailingZeros) fraction = stripTrailingZeros(fraction); + let base = fraction ? `${intPart}.${fraction}` : intPart; + if (opts.thousandSeparator) base = insertThousands(base); + const prefix = negative ? '-' : ''; + const withSymbol = opts.symbol ? `${base} ${opts.symbol}` : base; + const text = `${prefix}${withSymbol}`; + const approx = fraction.length < fracRaw.length && opts.approxTilde; + const integer = negative ? `-${intPart}` : intPart; + return { text, approx, integer, fraction, symbol: opts.symbol }; +} + +function countLeadingZeros(fracRaw: string): number { + let count = 0; + for (const ch of fracRaw) { + if (ch === '0') count++; + else break; + } + return count; +} + +interface TinyFormatOpts { + significantDigits: number; + zeroCompress: boolean; + approxTilde: boolean; + symbol?: string; +} + +function formatTiny( + negative: boolean, + fracRaw: string, + zeros: number, + opts: TinyFormatOpts, +): FormattedParts { + const sig = fracRaw.slice(zeros, zeros + opts.significantDigits); + const hasMore = fracRaw.length > zeros + sig.length; + const approx = opts.approxTilde && hasMore; + if (opts.zeroCompress) { + const zeroDisplay = Math.min(zeros, 99); + const zeroSub = toSubscript(zeroDisplay); + const core = `0.0${zeroSub}${sig || '0'}`; + const prefix = approx ? '~' : ''; + const sign = negative ? '-' : ''; + const body = opts.symbol ? `${core} ${opts.symbol}` : core; + const text = `${prefix}${sign}${body}`; + return { + text, + approx, + integer: negative ? '-0' : '0', + zeroCount: zeros, + zeroSubscript: zeroSub, + significant: sig || '0', + symbol: opts.symbol, + }; + } + const shown = `0.${'0'.repeat(zeros)}${sig || '0'}`; + const prefix = approx ? '~' : ''; + const sign = negative ? '-' : ''; + const body = opts.symbol ? `${shown} ${opts.symbol}` : shown; + const text = `${prefix}${sign}${body}`; + return { + text, + approx, + integer: negative ? '-0' : '0', + fraction: shown.slice(2), + symbol: opts.symbol, + }; +} + +export function formatTokenBalanceParts( + value: InputValue, + { + decimals, + symbol, + significantDigits = 4, + maxFractionDigits = 4, + tinyThresholdPower = -4, + zeroCompress = true, + thousandSeparator = false, + trimTrailingZeros = true, + approxTilde = true, + }: FormatTokenBalanceOptions = {}, +): FormattedParts { + const normalized = normalizeValue(value, decimals); + const { negative, intPart, fracRaw } = normalized; + const isZero = intPart === '0' && /^0*$/.test(fracRaw); + + if (isZero) { + return formatZero(symbol); + } + const normalOpts = { + maxFractionDigits, + trimTrailingZeros, + thousandSeparator, + approxTilde, + symbol, + } as const; + + // String-based classification to avoid Number underflow/overflow + const isIntegerNonZero = intPart !== '0'; + if (isIntegerNonZero && tinyThresholdPower < 0) { + return formatNormal(negative, intPart, fracRaw, normalOpts); + } + if (isIntegerNonZero && tinyThresholdPower >= 0) { + const intDigits = intPart.replace(/^0+/, '').length; + if (intDigits - 1 >= tinyThresholdPower) { + return formatNormal(negative, intPart, fracRaw, normalOpts); + } + // else treat as tiny + } + + let zeros = isIntegerNonZero ? 0 : countLeadingZeros(fracRaw); + if (!isIntegerNonZero && tinyThresholdPower < 0) { + const limitZeros = Math.max(0, Math.abs(tinyThresholdPower) - 1); + if (zeros <= limitZeros) { + return formatNormal(negative, intPart, fracRaw, normalOpts); + } + } + + const tinyOpts = { + significantDigits, + zeroCompress, + approxTilde, + symbol, + } as const; + return formatTiny(negative, fracRaw, zeros, tinyOpts); +} + +export function formatTokenBalance( + value: string | number | bigint, + options?: FormatTokenBalanceOptions, +): string { + return formatTokenBalanceParts(value, options).text; +} diff --git a/packages/commons/utils/index.ts b/packages/commons/utils/index.ts index facd33f4..08f0a52a 100644 --- a/packages/commons/utils/index.ts +++ b/packages/commons/utils/index.ts @@ -29,6 +29,8 @@ import { import { mainnet, polygon, arbitrum, optimism, base } from 'viem/chains'; import { logger } from '../utils/logger'; +export * from './format'; + /** * Shared utility for standardized error message extraction */ @@ -69,20 +71,6 @@ export function getViemChain(chainId: number): Chain { } } -/** - * Format a balance string to a human-readable format using Decimal.js - */ -export function formatBalance(balance: string, decimals: number, precision: number = 4): string { - const balanceDecimal = new Decimal(balance); - const divisor = new Decimal(10).pow(decimals); - const formatted = balanceDecimal.div(divisor); - - if (formatted.isZero()) return '0'; - if (formatted.lt(0.0001)) return '< 0.0001'; - - return formatted.toFixed(precision).replace(/\.?0+$/, ''); -} - /** * Parse units from a human-readable string to wei/smallest unit using Decimal.js */ @@ -140,40 +128,6 @@ export function getChainMetadata(chainId: SUPPORTED_CHAINS_IDS): ChainMetadata { return CHAIN_METADATA[chainId]; } -/** - * Format a mainnet token amount with proper decimals and symbol - */ -export function formatTokenAmount( - amount: string | bigint, - tokenSymbol: SUPPORTED_TOKENS, - precision: number = 4, -): string { - const metadata = getMainnetTokenMetadata(tokenSymbol); - if (!metadata) return `${amount} ${tokenSymbol}`; - - const amountStr = typeof amount === 'bigint' ? amount.toString() : amount; - const formatted = formatBalance(amountStr, metadata.decimals, precision); - - return `${formatted} ${metadata.symbol}`; -} - -/** - * Format a testnet token amount with proper decimals and symbol - */ -export function formatTestnetTokenAmount( - amount: string | bigint, - tokenSymbol: SUPPORTED_TOKENS, - precision: number = 4, -): string { - const metadata = getTestnetTokenMetadata(tokenSymbol); - if (!metadata) return `${amount} ${tokenSymbol}`; - - const amountStr = typeof amount === 'bigint' ? amount.toString() : amount; - const formatted = formatBalance(amountStr, metadata.decimals, precision); - - return `${formatted} ${metadata.symbol}`; -} - /** * Truncate an address for display purposes */ @@ -532,6 +486,7 @@ export function getTokenContractAddress( chainId: SUPPORTED_CHAINS_IDS, ): string | undefined { const registry = TOKEN_CONTRACT_ADDRESSES; + // @ts-expect-error const address = registry[token]?.[chainId]; return address || undefined; } diff --git a/packages/commons/utils/logger.ts b/packages/commons/utils/logger.ts index 94d5455e..044a4644 100644 --- a/packages/commons/utils/logger.ts +++ b/packages/commons/utils/logger.ts @@ -66,7 +66,7 @@ class Logger { this.internalLog(LOG_LEVEL.DEBUG, message, params); } - error(message: string, err?: Error | string) { + error(message: string, err?: unknown) { if (err instanceof Error) { this.internalLog(LOG_LEVEL.ERROR, message, err.message); sendException(JSON.stringify({ error: err.message, message })); diff --git a/packages/core/README.md b/packages/core/README.md index ba8cb528..e389e721 100644 --- a/packages/core/README.md +++ b/packages/core/README.md @@ -1,900 +1,421 @@ # @avail-project/nexus/core -A powerful headless TypeScript SDK for cross-chain operations, token bridging, and unified balance management. Perfect for backends, CLIs, and custom UI implementations. +A **headless TypeScript SDK** for **cross-chain operations**, **token bridging**, **swapping**, and **unified balance management** — built for backends, CLIs, and custom UI integrations. -## Installation +> ⚡ Powering next-generation cross-chain apps with a single interface. + +--- + +## 📦 Installation ```bash npm install @avail-project/nexus-core ``` +--- + ## 🚀 Quick Start ```typescript -import { NexusSDK } from '@avail-project/nexus-core'; +import { NexusSDK, NEXUS_EVENTS } from '@avail-project/nexus-core'; // Initialize SDK const sdk = new NexusSDK({ network: 'mainnet' }); -await sdk.initialize(provider); // Your wallet provider - -// Get unified balances -// false by default to get CA applicable token balances -// true to get all the balances including the swappable tokens -const balances = await sdk.getUnifiedBalances(false); -console.log('All balances:', balances); - -// Swap tokens (EXACT_IN - specify input amount) - -const swapWithExactInInput: ExactInSwapInput = { - from: [ - { - chainId: inputData.fromChainID, - amount: parseUnits( - fromAmountStr.toString(), - TOKEN_METADATA[inputData?.fromTokenAddress]?.decimals, - ), - tokenAddress: actualFromTokenAddress as `0x${string}`, +await sdk.initialize(provider); // Your EVM-compatible wallet provider + +// (Optional) Add TRON support +const tronLinkAdapter = new TronLinkAdapter(); +sdk.addTron(tronLinkAdapter); + +// --------------------------- +// 1️⃣ Get unified balances +// --------------------------- +const balances = await sdk.getUnifiedBalances(false); // false = CA balances only +console.log('Balances:', balances); + +// --------------------------- +// 2️⃣ Bridge tokens +// --------------------------- +const bridgeResult = await sdk.bridge( + { + token: 'USDC', + amount: "1.5", + recipient: '0x...' // Optional + chainId: 137, // Polygon + }, + { + onEvent: (event) => { + if (event.name === NEXUS_EVENTS.STEPS_LIST) console.log('Bridge steps:', event.args); + if (event.name === NEXUS_EVENTS.STEP_COMPLETE) console.log('Step completed:', event.args); }, - ], - toChainId: inputData.toChainID, - toTokenAddress: actualToTokenAddress as `0x${string}`, -}; - -const swapWithExactInResult = await sdk.swapWithExactIn(swapWithExactInInput, { - swapIntentHook: async (data: Parameters[0]) => {}, -}); - -// Swap tokens (EXACT_OUT - only specify destination chain, token and amount) - -const swapWithExactOutInput: ExactOutSwapInput = { - toChainId: inputData.toChainID, - toTokenAddress: actualToTokenAddress as `0x${string}`, - toAmount: 0n, // bigint -}; - -const swapWithExactOutResult = await sdk.swapWithExactOut(swapWithExactOutInput, { - swapIntentHook: async (data: Parameters[0]) => {}, -}); - -// Bridge tokens -const bridgeResult = await sdk.bridge({ - token: 'USDC', - amount: 100, - chainId: 137, // to Polygon - sourceChains: [10, 42161], // Only use USDC from `Optimism` and `Arbitrum` as source for bridge -}); + }, +); -// Transfer tokens (automatically optimized) -const transferResult = await sdk.transfer({ - token: 'ETH', - amount: 0.1, - chainId: 1, // Uses direct transfer if ETH + gas available on Ethereum - recipient: '0x742d35Cc6634C0532925a3b8D4C9db96c4b4Db45', - sourceChains: [8453], // Only use ETH from `Base` as source for bridge -}); +// --------------------------- +// 3️⃣ Transfer tokens +// --------------------------- +const transferResult = await sdk.bridgeAndTransfer( + { + token: 'ETH', + amount: "1.5", + chainId: 1, // Ethereum + recipient: '0x742d35Cc6634C0532925a3b8D4C9db96c4b4Db45', + }, + { + onEvent: (event) => { + if (event.name === NEXUS_EVENTS.STEPS_LIST) console.log('Transfer steps:', event.args); + if (event.name === NEXUS_EVENTS.STEP_COMPLETE) console.log('Step completed:', event.args); + }, + }, +); -const executeResult = await sdk.execute({ - contractAddress, - contractAbi: contractAbi, - functionName: functionName, - buildFunctionParams: ( - token: SUPPORTED_TOKENS, - amount: string, - chainId: SUPPORTED_CHAINS_IDS, - user: `0x${string}`, - ) => { - const decimals = TOKEN_METADATA[token].decimals; - const amountWei = parseUnits(amount, decimals); - const tokenAddr = TOKEN_CONTRACT_ADDRESSES[token][chainId]; - return { functionParams: [tokenAddr, amountWei, user, 0] }; +// --------------------------- +// 4️⃣ Execute a contract +// --------------------------- +const executeResult = await sdk.execute( + { + to: '0x...', + value: 0n, + data: '0x...', + tokenApproval: { token: 'USDC', amount: 10000n }, }, - value: ethValue, - tokenApproval: { + { + onEvent: (event) => { + if (event.name === NEXUS_EVENTS.STEPS_LIST) console.log('Execute steps:', event.args); + if (event.name === NEXUS_EVENTS.STEP_COMPLETE) console.log('Step completed:', event.args); + }, + }, +); + +// --------------------------- +// 5️⃣ Bridge and Execute +// --------------------------- +const bridgeAndExecuteResult = await sdk.bridgeAndExecute( + { token: 'USDC', - amount: '100000000', + amount: 100_000_000n, + toChainId: 1, + sourceChains: [8453], + execute: { + to: '0x...', + data: '0x...', + tokenApproval: { token: 'USDC', amount: 100_000_000n }, + }, }, -}); -``` + { + onEvent: (event) => { + if (event.name === NEXUS_EVENTS.STEPS_LIST) console.log('Bridge+Execute steps:', event.args); + if (event.name === NEXUS_EVENTS.STEP_COMPLETE) console.log('Step completed:', event.args); + }, + }, +); -## Core Features +// --------------------------- +// 6️⃣ Swap tokens +// --------------------------- +const swapResult = await sdk.swapWithExactIn( + { + from: [ + { chainId: 10, amount: 1_000_000n, tokenAddress: '0x...' }, + ], + toChainId: 8453, + toTokenAddress: '0x...', + }, + { + onEvent: (event) => console.log('Swap event:', event), + }, +); -- **Cross-chain bridging** - Seamless token bridging between 16 chains -- **Cross-chain swaps** - Token swapping between chains with EXACT_IN and EXACT_OUT modes -- **Unified balances** - Aggregated portfolio view across all chains -- **Allowance management** - Efficient token approval handling -- **Smart direct transfers** - Send tokens to any address with automatic optimization -- **Smart execution** - Direct smart contract interactions with balance checking -- **Full testnet support** - Complete development environment -- **Transaction simulation** - Preview costs before execution -- **Rich utilities** - Address validation, formatting, and metadata -- **Smart optimizations** - Automatic chain abstraction skipping when funds are available locally +``` -## Smart Optimizations +--- -### Bridge Skip Optimization +## ✨ Core Features -When executing bridge-and-execute operations, the SDK checks if sufficient funds already exist on the target chain: +- **Cross-chain bridging** — Move tokens seamlessly across 16+ chains. +- **Cross-chain swaps** — Execute EXACT_IN and EXACT_OUT swaps between any supported networks. +- **Unified balances** — Aggregate user assets and balances across all connected chains. +- **Optimized transfers** — Automatically choose the most efficient transfer route. +- **Contract execution** — Call smart contracts with automatic bridging and funding logic. +- **Transaction simulation** — Estimate gas, fees, and required approvals before sending. +- **Complete testnet coverage** — Full multi-chain test environment. +- **Comprehensive utilities** — Address, token, and chain helpers built in. -- **Smart balance detection** - Validates token balance + gas requirements on destination -- **Automatic bypass** - Skips bridging when funds are available locally or only bridges the required amount -- **Cost reduction** - Eliminates unnecessary bridge fees and delays -- **Seamless fallback** - Uses chain abstraction when local funds are insufficient +--- -### Direct Transfer Optimization +## 🧠 Smart Optimizations -For transfer operations, the SDK intelligently chooses the most efficient path: +### 🔁 Bridge Skip Optimization -- **Local balance checking** - Validates token + gas availability on target chain -- **Direct EVM transfers** - Uses native blockchain calls when possible (faster, cheaper) -- **Chain abstraction fallback** - Automatically uses CA when direct transfer isn't possible -- **Universal compatibility** - Works with both native tokens (ETH, MATIC) and ERC20 (USDC, USDT) +During **bridge-and-execute** operations, the SDK checks whether sufficient funds already exist on the destination chain: -## Initialization +- **Balance detection** — Verifies token and gas availability. +- **Integrated gas supply** — Provides gas alongside bridged tokens. +- **Adaptive bridging** — Skips unnecessary bridging or transfers only the shortfall. +- **Seamless fallback** — Uses chain abstraction if local funds are insufficient. -```typescript -import type { NexusNetwork } from '@avail-project/nexus-core'; +### ⚡ Direct Transfer Optimization -// Mainnet (default) -const sdk = new NexusSDK(); +For transfers, the SDK automatically chooses the most efficient execution path: -// Testnet -const sdk = new NexusSDK({ network: 'testnet' as NexusNetwork }); +- **Local balance checking** — Confirms token and gas availability on the target chain. +- **Direct EVM transfers** — Uses native transfers where possible (faster, cheaper). +- **Chain abstraction fallback** — Uses CA routing only when required. +- **Universal compatibility** — Works with both native tokens (ETH, MATIC) and ERC-20s (USDC, USDT). -// Initialize with provider (required) -await sdk.initialize(window.ethereum); // Returns: Promise -``` +--- -## 📡 Event Handling +## 🏗️ Initialization ```typescript -import type { OnIntentHook, OnAllowanceHook, EventListener } from '@avail-project/nexus-core'; +import { NexusSDK, type NexusNetwork } from '@avail-project/nexus-core'; -// Intent approval flows -sdk.setOnIntentHook(({ intent, allow, deny, refresh }: Parameters[0]) => { - // This is a hook for the dev to show user the intent, the sources and associated fees +// Mainnet +const sdk = new NexusSDK({ network: 'mainnet' }); - // intent: Intent data containing sources and fees for display purpose +// Testnet +const sdkTest = new NexusSDK({ network: 'testnet' }); - // allow(): accept the current intent and continue the flow +// Initialize with wallet provider +await sdk.initialize(window.ethereum); +``` - // deny(): deny the intent and stop the flow +--- - // refresh(): should be on a timer of 5s to refresh the intent - // (old intents might fail due to fee changes if not refreshed) - if (userConfirms) allow(); - else deny(); -}); +## 📡 Event Handling -// Allowance approvals -sdk.setOnAllowanceHook(({ allow, deny, sources }: Parameters[0]) => { - // This is a hook for the dev to show user the allowances that need to be setup - // for the current tx to happen. +**All main SDK functions support the `onEvent` hook**: - // sources: an array of objects with minAllowance, chainID, token symbol, etc. +- `bridge` +- `bridgeAndTransfer` +- `execute` +- `bridgeAndExecute` +- `swapWithExactIn` / `swapWithExactOut` - // allow(allowances): continues the transaction flow with `allowances` array - // allowances.length === sources.length; - // valid values are "max" | "min" | string | bigint +Example usage for **progress steps**: - // deny(): stops the flow - allow(['min']); // or ['max'] or custom amounts +```typescript +sdk.bridge({...}, { + onEvent: (event) => { + if(event.name === NEXUS_EVENTS.STEPS_LIST) { + // Store list of steps + } else if(event.name === NEXUS_EVENTS.STEP_COMPLETE) { + // Mark step as done + } + } }); - -// Account/chain changes -sdk.onAccountChanged((account) => console.log('Account:', account)); -sdk.onChainChanged((chainId) => console.log('Chain:', chainId)); ``` -### Progress Events for All Operations +Additional hooks for user interactions: ```typescript -import { NEXUS_EVENTS, ProgressStep } from '@avail-project/nexus-core'; - -// Bridge & Execute Progress -const unsubscribeBridgeExecuteExpected = sdk.nexusEvents.on( - NEXUS_EVENTS.BRIDGE_EXECUTE_EXPECTED_STEPS, - (steps: ProgressStep[]) => { - console.log( - 'Bridge & Execute steps →', - steps.map((s) => s.typeID), - ); - }, -); - -const unsubscribeBridgeExecuteCompleted = sdk.nexusEvents.on( - NEXUS_EVENTS.BRIDGE_EXECUTE_COMPLETED_STEPS, - (step: ProgressStep) => { - console.log('Bridge & Execute completed →', step.typeID, step.data); - - if (step.typeID === 'IS' && step.data.explorerURL) { - console.log('View transaction:', step.data.explorerURL); - } - }, -); - -// Transfer & Bridge Progress (optimized operations) -const unsubscribeTransferExpected = sdk.nexusEvents.on( - NEXUS_EVENTS.EXPECTED_STEPS, - (steps: ProgressStep[]) => { - console.log( - 'Transfer/Bridge steps →', - steps.map((s) => s.typeID), - ); - // For direct transfers: ['CS', 'TS', 'IS'] (3 steps, ~5-15s) - }, -); - -const unsubscribeTransferCompleted = sdk.nexusEvents.on( - NEXUS_EVENTS.STEP_COMPLETE, - (step: ProgressStep) => { - console.log('Transfer/Bridge completed →', step.typeID, step.data); +sdk.setOnIntentHook(({ intent, allow, deny, refresh }) => { + if (userApproves) allow(); + else deny(); +}); - if (step.typeID === 'IS' && step.data.explorerURL) { - // Transaction submitted with hash - works for both direct and CA - console.log('Transaction hash:', step.data.transactionHash); - console.log('Explorer URL:', step.data.explorerURL); - } - }, -); +sdk.setOnSwapIntentHook(({ intent, allow, deny, refresh }) => { + if (userApproves) allow(); + else deny(); +}); -// Cleanup -return () => { - unsubscribeBridgeExecuteExpected(); - unsubscribeBridgeExecuteCompleted(); - unsubscribeTransferExpected(); - unsubscribeTransferCompleted(); -}; +sdk.setOnAllowanceHook(({ sources, allow, deny }) => { + allow(['min']); // 'max' or custom bigint[] supported +}); ``` -The SDK emits **consistent event patterns** for all operations: +### Consistent Event Pattern -**Bridge & Execute Operations:** +| Operation Type | Event Name | Description | +| ---------------- | -------------------- | --------------------------------------- | +| Bridge / Execute | `STEPS_LIST` | Full ordered list of steps emitted once | +| | `STEP_COMPLETE` | Fired per completed step with data | +| Swap | `SWAP_STEP_COMPLETE` | Fired per completed step with data | -1. `bridge_execute_expected_steps` – _once_ with full ordered array of `ProgressStep`s -2. `bridge_execute_completed_steps` – _many_; one per finished step with runtime data +All events include `typeID`, `transactionHash`, `explorerURL`, and `error` (if any). -**Transfer & Bridge Operations:** +--- -1. `expected_steps` – _once_ with full ordered array of `ProgressStep`s -2. `step_complete` – _many_; one per finished step with runtime data - -All events include the same `typeID` structure and runtime `data` such as `transactionHash`, `explorerURL`, `confirmations`, `error`, etc. This provides consistent progress tracking whether using optimized direct operations or chain abstraction. - -## Balance Operations +## 💰 Balance Operations ```typescript -import type { UserAsset, TokenBalance } from '@avail-project/nexus-core'; - -// Get all balances across chains -// false by default to get CA applicable token balances -// true to get all the balances including the swappable tokens -const balances: UserAsset[] = await sdk.getUnifiedBalances(); - -// Get balance for specific token -// false by default to get CA applicable token balances -// true to get all the balances including the swappable tokens -const usdcBalance: UserAsset | undefined = await sdk.getUnifiedBalance('USDC', false); +const balances = await sdk.getUnifiedBalances(); // CA balances +const allBalances = await sdk.getUnifiedBalances(true); // Includes swappable tokens ``` -## Bridge Operations - -```typescript -import type { BridgeParams, BridgeResult, SimulationResult } from '@avail-project/nexus-core'; +--- -// Bridge tokens between chains -const result: BridgeResult = await sdk.bridge({ - token: 'USDC', - amount: 100, - chainId: 137, -} as BridgeParams); +## 🌉 Bridge Operations -// Simulate bridge to preview costs -const simulation: SimulationResult = await sdk.simulateBridge({ - token: 'USDC', - amount: 100, - chainId: 137, -}); +```typescript +const result = await sdk.bridge({ token: 'USDC', amount: '83.50', chainId: 137 }); +const simulation = await sdk.simulateBridge({ token: 'USDC', amount: '83.50', chainId: 137 }); ``` -## Transfer Operations +--- -```typescript -import type { TransferParams, TransferResult } from '@avail-project/nexus-core'; +## 🔁 Transfer Operations -// Smart transfer with automatic optimization -const result: TransferResult = await sdk.transfer({ +```typescript +const result = await sdk.transfer({ token: 'USDC', - amount: 100, - chainId: 42161, // Arbitrum + amount: '1.53', + chainId: 42161, recipient: '0x...', -} as TransferParams); - -// The SDK automatically: -// 1. Checks if you have USDC + ETH for gas on Arbitrum -// 2. Uses direct EVM transfer if available (faster, cheaper) -// 3. Falls back to chain abstraction if local funds insufficient - -// Simulate transfer to preview costs and optimization path -const simulation: SimulationResult = await sdk.simulateTransfer({ +}); +const simulation = await sdk.simulateTransfer({ token: 'USDC', - amount: 100, + amount: '1.53', chainId: 42161, recipient: '0x...', }); - -// Check if direct transfer will be used -console.log('Fees:', simulation.intent.fees); -// For direct transfers: gasSupplied shows actual native token cost -// For CA transfers: includes additional CA routing fees ``` -## Execute Operations +--- -```typescript -import type { - ExecuteParams, - ExecuteResult, - ExecuteSimulation, - BridgeAndExecuteParams, - BridgeAndExecuteResult, - BridgeAndExecuteSimulationResult, -} from '@avail-project/nexus-core'; +## ⚙️ Execute & Bridge+Execute -// Execute contract functions with dynamic parameter builder - Compound V3 Supply -const result: ExecuteResult = await sdk.execute({ +```typescript +// Direct contract execution +const result = await sdk.execute({ toChainId: 1, - contractAddress: '0xc3d688B66703497DAA19211EEdff47f25384cdc3', // Compound V3 USDC Market - contractAbi: [ - { - inputs: [ - { internalType: 'address', name: 'asset', type: 'address' }, - { internalType: 'uint256', name: 'amount', type: 'uint256' }, - ], - name: 'supply', - outputs: [], - stateMutability: 'nonpayable', - type: 'function', - }, - ], - functionName: 'supply', - buildFunctionParams: ( - token: SUPPORTED_TOKENS, - amount: string, - chainId: SUPPORTED_CHAINS_IDS, - userAddress: `0x${string}`, - ) => { - const decimals = TOKEN_METADATA[token].decimals; - const amountWei = parseUnits(amount, decimals); - const tokenAddress = TOKEN_CONTRACT_ADDRESSES[token][chainId]; - return { - functionParams: [tokenAddress, amountWei], - }; - }, - waitForReceipt: true, - requiredConfirmations: 3, - tokenApproval: { - token: 'USDC', - amount: '1000000', // Amount in token units - }, -} as ExecuteParams); - -// Simulate execute to preview costs and check for approval requirements -const simulation: ExecuteSimulation = await sdk.simulateExecute(executeParams); -if (!simulation.success) { - console.log('Simulation failed:', simulation.error); - // Error might indicate missing token approval -} + to: '0xc3d688B66703497DAA19211EEdff47f25384cdc3', + data: '0x...', + tokenApproval: { token: 'USDC', amount: 1000000n }, +}); -// Bridge tokens and execute contract function - Yearn Vault Deposit -const bridgeAndExecuteResult: BridgeAndExecuteResult = await sdk.bridgeAndExecute({ +// Bridge and execute +const result2 = await sdk.bridgeAndExecute({ token: 'USDC', - amount: '100000000', // 100 USDC (6 decimals) - toChainId: 1, // Ethereum - sourceChains: [8453], // Only use USDC from `Base` as source for bridge + amount: 100_000_000n, + toChainId: 1, + sourceChains: [8453], execute: { - contractAddress: '0xa354F35829Ae975e850e23e9615b11Da1B3dC4DE', // Yearn USDC Vault - contractAbi: [ - { - inputs: [ - { internalType: 'uint256', name: 'assets', type: 'uint256' }, - { internalType: 'address', name: 'receiver', type: 'address' }, - ], - name: 'deposit', - outputs: [{ internalType: 'uint256', name: 'shares', type: 'uint256' }], - stateMutability: 'nonpayable', - type: 'function', - }, - ], - functionName: 'deposit', - buildFunctionParams: ( - token: SUPPORTED_TOKENS, - amount: string, - chainId: SUPPORTED_CHAINS_IDS, - userAddress: `0x${string}`, - ) => { - const decimals = TOKEN_METADATA[token].decimals; - const amountWei = parseUnits(amount, decimals); - return { - functionParams: [amountWei, userAddress], - }; - }, - tokenApproval: { - token: 'USDC', - amount: '100000000', - }, + to: '0xa354F35829Ae975e850e23e9615b11Da1B3dC4DE', + data: '0x...', + tokenApproval: { token: 'USDC', amount: 100_000_000n }, }, - waitForReceipt: true, -} as BridgeAndExecuteParams); - -// Comprehensive simulation with detailed step analysis and approval handling -const simulation: BridgeAndExecuteSimulationResult = await sdk.simulateBridgeAndExecute(params); - -// The simulation provides detailed step analysis: -console.log('Steps:', simulation.steps); - -console.log('Total estimated cost:', simulation.totalEstimatedCost); - -console.log('Approval required:', simulation.metadata?.approvalRequired); -console.log('Bridge receive amount:', simulation.metadata?.bridgeReceiveAmount); -``` - -## Swap Operations - -```typescript -import type { ExactInSwapInput, SwapIntentHook, ExactOutSwapInput SwapResult } from '@avail-project/nexus-core'; - - -// Swap tokens (EXACT_IN - specify input amount) - -const swapWithExactInInput: ExactInSwapInput = { - from: [ - { - chainId: inputData.fromChainID, - amount: parseUnits( - fromAmountStr.toString(), - TOKEN_METADATA[inputData?.fromTokenAddress]?.decimals, - ), - tokenAddress: actualFromTokenAddress as `0x${string}`, - }, - ], - toChainId: inputData.toChainID, - toTokenAddress: actualToTokenAddress as `0x${string}`, -}; - -const swapWithExactInResult = await sdk.swapWithExactIn(swapWithExactInInput, {swapIntentHook : async (data: Parameters[0]) => { - // use this to capture the intent allow, reject and refresh functions - const {intent, allow, reject, refresh} = data; - // Use it to handle user interaction or display transaction details - - // setSwapIntent(intent); - // setAllowCallback(allow); - // setRejectCallback(reject); - // setRefreshCallback(refresh); - - // or directly approve or reject the intent - // calling allow processes the txn - allow() -}}); - -// Swap tokens (EXACT_OUT - only specify destination chain, token and amount) - -const swapWithExactOutInput: ExactOutSwapInput = { - toChainId: inputData.toChainID, - toTokenAddress: actualToTokenAddress as `0x${string}`, - toAmount: 0n // bigint -}; - -const swapWithExactOutResult = await sdk.swapWithExactOut(swapWithExactOutInput, {swapIntentHook : async (data: Parameters[0]) => { - // use this to capture the intent allow, reject and refresh functions - const {intent, allow, reject, refresh} = data; - // Use it to handle user interaction or display transaction details - - // setSwapIntent(intent); - // setAllowCallback(allow); - // setRejectCallback(reject); - // setRefreshCallback(refresh); - - // or directly approve or reject the intent - // calling allow processes the txn - allow() -}}); - - -// Handle swap results -if (swapWithExactInResult.success) { - console.log('✅ Swap successful!'); - console.log('Source transaction:', exactInSwap.result.sourceSwaps); - console.log('Destination transaction:', exactInSwap.result.destinationSwap); - console.log('Explorer URL:', exactInSwap.result.explorerURL); -} else { - console.error('❌ Swap failed:', exactInSwap.error); -} -``` - -### Discovering Available Swap Options - -```typescript -import type { SupportedChainsResult } from '@avail-project/nexus-core'; -import { DESTINATION_SWAP_TOKENS } from '@avail-project/nexus-core'; - -// Get supported source chains and tokens for swaps -const supportedOptions: SupportedChainsResult = sdk.utils.getSwapSupportedChainsAndTokens(); -console.log('Supported source chains and tokens:', supportedOptions); - -// Example: Build a source token selector -supportedOptions.forEach((chain) => { - console.log(`Chain: ${chain.name} (${chain.id})`); - chain.tokens.forEach((token) => { - console.log(` - ${token.symbol}: ${token.tokenAddress}`); - }); }); - -// Get suggested destination tokens (optional - destination can be any token or chain) -const optimismDestinations = DESTINATION_SWAP_TOKENS.get(10); // Optimism -const arbitrumDestinations = DESTINATION_SWAP_TOKENS.get(42161); // Arbitrum -const baseDestinations = DESTINATION_SWAP_TOKENS.get(8453); // Base - -console.log('Popular Optimism destinations:', optimismDestinations); -console.log('Popular Arbitrum destinations:', arbitrumDestinations); -console.log('Popular Base destinations:', baseDestinations); - -// Example: Build destination token options for UI -const buildDestinationOptions = (chainId: number) => { - const popularTokens = DESTINATION_SWAP_TOKENS.get(chainId) || []; - return popularTokens.map((token) => ({ - label: `${token.symbol} - ${token.name}`, - value: token.tokenAddress, - icon: token.logo, - decimals: token.decimals, - })); -}; ``` -**Note:** - -- **Source chains/tokens** are restricted to what `getSwapSupportedChainsAndTokens()` returns -- **Destination chains/tokens** can be any supported chain and token address -- `DESTINATION_SWAP_TOKENS` provides popular destination options but is not exhaustive - -### Swap Types - -**EXACT_IN Swaps:** +--- -- You specify exactly how much you want to spend (`fromAmount`) -- Output amount varies based on market conditions and fees -- Use case: "I want to swap all my 100 USDC" - -**EXACT_OUT Swaps:** - -- You specify exactly how much you want to receive (`toAmount`) -- Input amount varies based on market conditions and fees -- Use case: "I need exactly 1 ETH for a specific purpose" - -### Swap Progress Events +## 🔄 Swap Operations ```typescript -import { NEXUS_EVENTS } from '@avail-project/nexus-core'; - -// Listen for swap progress updates -const unsubscribeSwapSteps = sdk.nexusEvents.on(NEXUS_EVENTS.SWAP_STEPS, (step) => { - console.log('Swap step:', step.type); - - if (step.type === 'SOURCE_SWAP_HASH' && step.explorerURL) { - console.log('Source transaction:', step.explorerURL); - } - - if (step.type === 'DESTINATION_SWAP_HASH' && step.explorerURL) { - console.log('Destination transaction:', step.explorerURL); - } - - if (step.type === 'SWAP_COMPLETE' && step.completed) { - console.log('✅ Swap completed successfully!'); - } -}); - -// Cleanup -unsubscribeSwapSteps(); +const swapResult = await sdk.swapWithExactIn( + { + from: [{ chainId: 10, amount: 1_000_000n, tokenAddress: '0x...' }], + toChainId: 8453, + toTokenAddress: '0x...', + }, + { onEvent: (event) => console.log(event) }, +); ``` -## Allowance Management - -```typescript -import type { AllowanceResponse } from '@avail-project/nexus-core'; - -// Check allowances -const allowances: AllowanceResponse[] = await sdk.getAllowance(137, ['USDC', 'USDT']); +### Swap Types -// Set allowances -await sdk.setAllowance(137, ['USDC'], 1000000n); +| Type | Description | Example | +| ------------- | ------------------------------------------------- | --------------------------- | +| **EXACT_IN** | Specify the amount you’re spending; output varies | “Swap 100 USDC for max ETH” | +| **EXACT_OUT** | Specify the amount you’ll receive; input varies | “Get exactly 1 ETH” | -// Revoke allowances -await sdk.revokeAllowance(137, ['USDC']); -``` +--- -## Intent Management +## 🧩 Intent Management ```typescript -import type { RequestForFunds } from '@avail-project/nexus-core'; - -// Get user's transaction intents -// Bound by web domain and user's wallet address -const intents: RequestForFunds[] = await sdk.getMyIntents(1); +const intents = await sdk.getMyIntents(1); +console.log('Active intents:', intents); ``` -## Utilities - -All utility functions are available under `sdk.utils`: - -```typescript -import type { ChainMetadata, TokenMetadata, SUPPORTED_TOKENS } from '@avail-project/nexus-core'; - -// Address utilities -const isValid: boolean = sdk.utils.isValidAddress('0x...'); -const shortened: string = sdk.utils.truncateAddress('0x...'); - -// Balance formatting -const formatted: string = sdk.utils.formatBalance('1000000', 6); -const units: bigint = sdk.utils.parseUnits('100.5', 6); -const readable: string = sdk.utils.formatUnits(100500000n, 6); - -// Token amount formatting -const formattedAmount: string = sdk.utils.formatTokenAmount('1000000', 'USDC'); // "1.0 USDC" -const testnetFormatted: string = sdk.utils.formatTestnetTokenAmount('1000000', 'USDC'); // "1.0 USDC" - -// Chain & token info -const chainMeta: ChainMetadata | undefined = sdk.utils.getChainMetadata(137); -const tokenMeta: TokenMetadata | undefined = sdk.utils.getTokenMetadata('USDC'); -const mainnetTokenMeta: TokenMetadata | undefined = sdk.utils.getMainnetTokenMetadata('USDC'); -const testnetTokenMeta: TokenMetadata | undefined = sdk.utils.getTestnetTokenMetadata('USDC'); - -// Chain/token validation -const isSupported: boolean = sdk.utils.isSupportedChain(137); -const isSupportedToken: boolean = sdk.utils.isSupportedToken('USDC'); - -// Get supported chains -const chains: Array<{ id: number; name: string; logo: string }> = sdk.utils.getSupportedChains(); - -// Swap discovery utilities -const swapOptions: SupportedChainsResult = sdk.utils.getSwapSupportedChainsAndTokens(); - -// Chain ID conversion -const hexChainId: string = sdk.utils.chainIdToHex(137); -const decimalChainId: number = sdk.utils.hexToChainId('0x89'); -``` +--- -## Provider Methods +## 🛠️ Utilities ```typescript -import type { EthereumProvider, RequestArguments } from '@avail-project/nexus-core'; - -// Get chain abstracted provider -const provider: EthereumProvider = sdk.getEVMProviderWithCA(); - -// Make EIP-1193 requests -const result = await sdk.request({ - method: 'eth_accounts', - params: [], -} as RequestArguments); - -// Cleanup -await sdk.deinit(); +const isValid = sdk.utils.isValidAddress('0x...'); +const chainMeta = sdk.utils.getChainMetadata(137); +const formatted = sdk.utils.formatTokenAmount('1000000', 'USDC'); // "1.0 USDC" ``` -## Usage Examples +--- -### Basic Bridge with Result Handling +## 🧾 Error Handling ```typescript -import { NexusSDK, type BridgeResult } from '@avail-project/nexus-core'; - -const sdk = new NexusSDK(); -await sdk.initialize(window.ethereum); - try { - const result: BridgeResult = await sdk.bridge({ - token: 'USDC', - amount: 100, - chainId: 137, - }); - - if (result.success) { - console.log('✅ Bridge successful!'); - if (result.explorerUrl) { - console.log('View transaction:', result.explorerUrl); - } + await sdk.bridge({ token: 'USDC', amount: 1.53, chainId: 137 }); +} catch (err) { + if (err instanceof NexusError) { + console.error(`[${err.code}] ${err.message}`); } else { - console.error('❌ Bridge failed:', result.error); + console.error('Unexpected error:', err); } -} catch (error) { - console.error('Bridge error:', error); } ``` -### Execute with Receipt Confirmation - -```typescript -import type { ExecuteResult } from '@avail-project/nexus-core'; - -// MakerDAO DSR (Dai Savings Rate) Deposit -const result: ExecuteResult = await sdk.execute({ - toChainId: 1, - contractAddress: '0x373238337Bfe1146fb49989fc222523f83081dDb', // DSR Manager - contractAbi: [ - { - inputs: [ - { internalType: 'address', name: 'usr', type: 'address' }, - { internalType: 'uint256', name: 'wad', type: 'uint256' }, - ], - name: 'join', - outputs: [], - stateMutability: 'nonpayable', - type: 'function', - }, - ], - functionName: 'join', - buildFunctionParams: ( - token: SUPPORTED_TOKENS, - amount: string, - chainId: SUPPORTED_CHAINS_IDS, - userAddress: `0x${string}`, - ) => { - const decimals = TOKEN_METADATA[token].decimals; - const amountWei = parseUnits(amount, decimals); - return { - functionParams: [userAddress, amountWei], - }; - }, - waitForReceipt: true, - requiredConfirmations: 3, - tokenApproval: { - token: 'USDC', // Will be converted to DAI in the bridge - amount: '1000000', - }, -}); - -console.log('Transaction hash:', result.transactionHash); -console.log('Explorer URL:', result.explorerUrl); -console.log('Gas used:', result.gasUsed); -console.log('Confirmations:', result.confirmations); -``` +--- -### Complete Portfolio Management +## 🧠 TypeScript Support ```typescript -import type { UserAsset, ChainMetadata } from '@avail-project/nexus-core'; - -// Get complete balance overview -// false by default to get CA applicable token balances -// true to get all the balances including the swappable tokens -const balances: UserAsset[] = await sdk.getUnifiedBalances(); - -for (const asset of balances) { - console.log(`\n${asset.symbol}: ${asset.balance}`); - console.log(`Fiat value: $${asset.balanceInFiat || 0}`); - - if (asset.breakdown) { - console.log('Chain breakdown:'); - for (const chainBalance of asset.breakdown) { - const chain: ChainMetadata | undefined = sdk.utils.getChainMetadata(chainBalance.chain.id); - console.log(` ${chain?.name}: ${chainBalance.balance}`); - } - } -} +import type { + BridgeParams, + ExecuteParams, + TransferParams, + SwapResult, + NexusNetwork, + TokenMetadata, +} from '@avail-project/nexus-core'; ``` -## Error Handling +--- -```typescript -import type { BridgeResult } from '@avail-project/nexus-core'; +## 🌐 Supported Networks -try { - const result: BridgeResult = await sdk.bridge({ token: 'USDC', amount: 100, chainId: 137 }); - - if (!result.success) { - // Handle bridge failure - console.error('Bridge failed:', result.error); - } -} catch (error) { - if (error.message.includes('User denied')) { - // User cancelled transaction - } else if (error.message.includes('Insufficient')) { - // Insufficient balance - } else if (error.message.includes('Unsupported')) { - // Unsupported chain or token - } else { - // Other errors - console.error('Unexpected error:', error); - } -} -``` - -```typescript -import type { ExecuteSimulation, ExecuteResult } from '@avail-project/nexus-core'; +### Mainnets -// Simulate before executing -const simulation: ExecuteSimulation = await sdk.simulateExecute(params); -if (simulation.success) { - const result: ExecuteResult = await sdk.execute(params); -} +| Network | Chain ID | Native | Status | +| --------- | --------- | ------ | ------ | +| Ethereum | 1 | ETH | ✅ | +| Optimism | 10 | ETH | ✅ | +| Polygon | 137 | MATIC | ✅ | +| Arbitrum | 42161 | ETH | ✅ | +| Avalanche | 43114 | AVAX | ✅ | +| Base | 8453 | ETH | ✅ | +| Scroll | 534352 | ETH | ✅ | +| Sophon | 50104 | SOPH | ✅ | +| Kaia | 8217 | KAIA | ✅ | +| BNB | 56 | BNB | ✅ | +| HyperEVM | 999 | HYPE | ✅ | +| TRON | 728126428 | TRX | ✅ | -// Cleanup when done -sdk.removeAllListeners(); -await sdk.deinit(); -``` +### Testnets -## TypeScript Support +| Network | Chain ID | Native | Status | +| ---------------- | -------- | ------ | ------ | +| Optimism Sepolia | 11155420 | ETH | ✅ | +| Polygon Amoy | 80002 | MATIC | ✅ | +| Arbitrum Sepolia | 421614 | ETH | ✅ | +| Base Sepolia | 84532 | ETH | ✅ | +| Sepolia | 11155111 | ETH | ✅ | +| Monad Testnet | 10143 | MON | ✅ | +| Validium | 567 | VLDM | ✅ | -The SDK is fully typed with comprehensive TypeScript definitions. Import the types you need: +--- -```typescript -import type { - BridgeParams, - BridgeResult, - TransferParams, - TransferResult, - ExecuteParams, - ExecuteResult, - ExecuteSimulation, - BridgeAndExecuteParams, - BridgeAndExecuteResult, - SimulationResult, - SwapInput, - SwapResult, - SwapBalances, - SupportedChainsResult, - DESTINATION_SWAP_TOKENS, - UserAsset, - TokenBalance, - AllowanceResponse, - ChainMetadata, - TokenMetadata, - OnIntentHook, - OnAllowanceHook, - EthereumProvider, - RequestArguments, - EventListener, - NexusNetwork, -} from '@avail-project/nexus-core'; -``` +## 💎 Supported Tokens -## Supported Networks & Tokens - -### Mainnet Chains - -| Network | Chain ID | Native Currency | Status | -| --------- | -------- | --------------- | ------ | -| Ethereum | 1 | ETH | ✅ | -| Optimism | 10 | ETH | ✅ | -| Polygon | 137 | MATIC | ✅ | -| Arbitrum | 42161 | ETH | ✅ | -| Avalanche | 43114 | AVAX | ✅ | -| Base | 8453 | ETH | ✅ | -| Scroll | 534352 | ETH | ✅ | -| Sophon | 50104 | SOPH | ✅ | -| Kaia | 8217 | KAIA | ✅ | -| BNB | 56 | BNB | ✅ | -| HyperEVM | 999 | HYPE | ✅ | - -### Testnet Chains - -| Network | Chain ID | Native Currency | Status | -| ---------------- | -------- | --------------- | ------ | -| Optimism Sepolia | 11155420 | ETH | ✅ | -| Polygon Amoy | 80002 | MATIC | ✅ | -| Arbitrum Sepolia | 421614 | ETH | ✅ | -| Base Sepolia | 84532 | ETH | ✅ | -| Sepolia | 11155111 | ETH | ✅ | -| Monad Testnet | 10143 | MON | ✅ | - -### Supported Tokens - -| Token | Name | Decimals | Networks | +| Token | Name | Decimals | Availability | | ----- | ---------- | -------- | -------------- | | ETH | Ethereum | 18 | All EVM chains | | USDC | USD Coin | 6 | All supported | | USDT | Tether USD | 6 | All supported | -## 🔗 Links +--- + +## 🔗 Resources -- [GitHub Repository](https://github.com/availproject/nexus-sdk) -- [API Documentation](https://docs.availproject.org/api-reference/avail-nexus-sdk) +- **GitHub:** [availproject/nexus-sdk](https://github.com/availproject/nexus-sdk) +- **Docs:** [docs.availproject.org](https://docs.availproject.org/nexus/avail-nexus-sdk) diff --git a/packages/core/adapters/chain-abstraction-adapter.ts b/packages/core/adapters/chain-abstraction-adapter.ts deleted file mode 100644 index d69da568..00000000 --- a/packages/core/adapters/chain-abstraction-adapter.ts +++ /dev/null @@ -1,99 +0,0 @@ -import { Network, SupportedChainsResult } from '@nexus/commons'; -import { isSupportedChain, isSupportedToken } from './core/validation'; -// Services -import { ExecuteService } from './services/execute-service'; -import { BridgeExecuteService } from './services/bridge-execute-service'; -import { - type BridgeAndExecuteParams, - type BridgeAndExecuteResult, - type ExecuteParams, - type ExecuteResult, - type ExecuteSimulation, - type BridgeAndExecuteSimulationResult, - type SUPPORTED_CHAINS_IDS, - logger, -} from '@nexus/commons'; -import { getSupportedChains } from 'sdk/ca-base/utils'; -import { NexusSDK } from 'sdk'; - -/** - * Provides a unified interface for chain abstraction operations. - */ -export class ChainAbstractionAdapter { - private executeService: ExecuteService; - private bridgeExecuteService: BridgeExecuteService; - - constructor(public nexusSDK: NexusSDK) { - logger.debug('ChainAbstractionAdapter', { nexusSDK }); - - // Initialize services - this.executeService = new ExecuteService(this); - this.bridgeExecuteService = new BridgeExecuteService(this); - this.setGasEstimationEnabled(true); - } - - public async getEVMClient() { - return this.nexusSDK.getEVMClient(); - } - - /** - * Execute a contract call using the execute service. - */ - public async execute(params: ExecuteParams): Promise { - return this.executeService.execute(params); - } - - /** - * Simulate contract execution using the execute service. - */ - public async simulateExecute(params: ExecuteParams): Promise { - return this.executeService.simulateExecute(params); - } - - /** - * Get the list of supported chains from the CA SDK. - */ - public getSupportedChains(env?: Network): SupportedChainsResult { - return getSupportedChains(env); - } - - /** - * Check if a chain is supported by the adapter. - */ - public isSupportedChain(chainId: SUPPORTED_CHAINS_IDS): boolean { - return isSupportedChain(chainId); - } - - /** - * Check if a token is supported by the adapter. - */ - public isSupportedToken(token: string): boolean { - return isSupportedToken(token); - } - - /** - * Bridge and execute operation - uses the BridgeExecuteService - */ - public async bridgeAndExecute(params: BridgeAndExecuteParams): Promise { - return this.bridgeExecuteService.bridgeAndExecute(params); - } - - /** - * Simulate bridge and execute operation - */ - public async simulateBridgeAndExecute( - params: BridgeAndExecuteParams, - ): Promise { - return this.bridgeExecuteService.simulateBridgeAndExecute(params); - } - - /** - * Enable or disable gas estimation for transactions - * When enabled, gas estimation will run before each transaction execution - * This helps identify potential failures early and provides cost estimates - */ - private setGasEstimationEnabled(enabled: boolean): void { - this.bridgeExecuteService.setGasEstimationEnabled(enabled); - this.executeService.setGasEstimationEnabled(enabled); - } -} diff --git a/packages/core/adapters/core/validation.ts b/packages/core/adapters/core/validation.ts deleted file mode 100644 index 36b9033d..00000000 --- a/packages/core/adapters/core/validation.ts +++ /dev/null @@ -1,104 +0,0 @@ -import { SUPPORTED_CHAINS, type SUPPORTED_CHAINS_IDS } from '@nexus/commons'; - -/** - * Common validation helpers for adapter services - */ - -/** - * Validate bridge/transfer parameters - */ -export function validateBridgeTransferParams(params: { - chainId: SUPPORTED_CHAINS_IDS; - token: string; -}): void { - if (!isSupportedChain(params.chainId)) { - throw new Error('Unsupported chain'); - } - if (!isSupportedToken(params.token)) { - throw new Error('Unsupported token'); - } -} - -/** - * Validation that returns result objects instead of throwing - */ -export function validateForResultReturn(params: { - chainId: SUPPORTED_CHAINS_IDS; - token: string; - initialized: boolean; -}): { success: boolean; error?: string } { - if (!isSupportedChain(params.chainId)) { - return { success: false, error: 'Unsupported chain' }; - } - if (!isSupportedToken(params.token)) { - return { success: false, error: 'Unsupported token' }; - } - if (!params.initialized) { - return { success: false, error: 'CA SDK not initialized. Call initialize() first.' }; - } - return { success: true }; -} - -/** - * Check if a chain is supported - */ -export function isSupportedChain(chainId: SUPPORTED_CHAINS_IDS): boolean { - return Object.values(SUPPORTED_CHAINS).includes(chainId); -} - -/** - * Check if a token is supported - */ -export function isSupportedToken(token: string): boolean { - const supportedTokens = ['ETH', 'USDC', 'USDT']; - return supportedTokens.includes(token.toUpperCase()); -} - -/** - * Validate ExecuteParams with callback pattern - */ -export function validateExecuteParams(params: { - toChainId: SUPPORTED_CHAINS_IDS; - contractAddress: string; - contractAbi: any; - functionName: string; - buildFunctionParams: Function; - tokenApproval?: { token: string }; -}): { success: boolean; error?: string } { - // Validate chain - if (!isSupportedChain(params.toChainId)) { - return { success: false, error: `Unsupported chain: ${params.toChainId}` }; - } - - // Validate contract address - if (!params.contractAddress || !params.contractAddress.startsWith('0x')) { - return { success: false, error: 'Invalid contract address' }; - } - - // Validate contract ABI - if (!params.contractAbi || !Array.isArray(params.contractAbi)) { - return { success: false, error: 'Invalid contract ABI' }; - } - - // Validate function name - if (!params.functionName || typeof params.functionName !== 'string') { - return { success: false, error: 'Invalid function name' }; - } - - // Validate callback function - if (!params.buildFunctionParams || typeof params.buildFunctionParams !== 'function') { - return { success: false, error: 'buildFunctionParams must be a valid function' }; - } - - // Validate token approval if present - if (params.tokenApproval) { - if (!params.tokenApproval.token || !isSupportedToken(params.tokenApproval.token)) { - return { - success: false, - error: `Unsupported token for approval: ${params.tokenApproval.token}`, - }; - } - } - - return { success: true }; -} diff --git a/packages/core/adapters/services/approval-service.ts b/packages/core/adapters/services/approval-service.ts deleted file mode 100644 index 144e340d..00000000 --- a/packages/core/adapters/services/approval-service.ts +++ /dev/null @@ -1,233 +0,0 @@ -import { - getTokenContractAddress, - extractErrorMessage, - logger, - TOKEN_METADATA, - type ApprovalResult, - type ApprovalInfo, - type SUPPORTED_TOKENS, - type SUPPORTED_CHAINS_IDS, -} from '@nexus/commons'; -import { ChainAbstractionAdapter } from 'adapters/chain-abstraction-adapter'; -import { parseUnits, formatUnits, erc20Abi, Hex } from 'viem'; - -/** - * Internal constants for adapter behavior - */ -const ADAPTER_CONSTANTS = { - // Default 2% buffer (200 bps) to handle precision issues. Can be overridden per-call via ExecuteParams.approvalBufferBps - APPROVAL_BUFFER_BPS_DEFAULT: 200n, - DEFAULT_DECIMALS: 18, - MAX_APPROVAL_AMOUNT: '0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff', -} as const; - -/** - * Service responsible for handling contract approvals - */ -export class ApprovalService { - constructor(private adapter: ChainAbstractionAdapter) {} - - /** - * Check if approval is needed for a token spending operation - */ - async checkApprovalNeeded( - tokenApproval: { token: SUPPORTED_TOKENS; amount: string }, - spenderAddress: string, - chainId: number, - approvalBufferBps?: number, - ): Promise { - const accounts = await this.adapter.nexusSDK.getEVMClient().getAddresses(); - - if (!accounts || accounts.length === 0) { - throw new Error('No accounts available'); - } - - const ownerAddress = accounts[0]; - const tokenContractAddress = getTokenContractAddress( - tokenApproval.token, - chainId as SUPPORTED_CHAINS_IDS, - ); - - if (!tokenContractAddress) { - throw new Error( - `Token contract address not found for ${tokenApproval.token} on chain ${chainId}`, - ); - } - - try { - // Convert amount to proper token units - handle both decimal and integer formats - let amountInWei: bigint; - - // Get token metadata for decimal handling - const tokenMetadata = TOKEN_METADATA[tokenApproval.token.toUpperCase()]; - const decimals = tokenMetadata?.decimals || ADAPTER_CONSTANTS.DEFAULT_DECIMALS; - - try { - // Handle both decimal strings (user-friendly) and integer strings (already converted) - // This matches the logic from the legacy adapter - if (tokenApproval.amount.includes('.')) { - // Decimal amount - user-friendly format like "0.01" - amountInWei = parseUnits(tokenApproval.amount, decimals); - } else { - // Integer amount - likely already in wei/micro format like "10000" - // For USDC and other 6-decimal tokens, check if this is already in micro-units - const amountNum = BigInt(tokenApproval.amount); - const USDC_THRESHOLD = 1_000_000n; // 1 USDC in micro-units - - if (decimals === 6 && amountNum > USDC_THRESHOLD) { - // For USDC, large numbers are likely already in micro-units - amountInWei = amountNum; - } else if (decimals === 18 && amountNum > 1_000_000_000_000_000_000n) { - // For ETH, large numbers are likely already in wei - amountInWei = amountNum; - } else { - // Small numbers are likely user amounts that need conversion - amountInWei = parseUnits(tokenApproval.amount, decimals); - } - } - } catch (error) { - throw new Error( - `Failed to parse amount ${tokenApproval.amount} for ${tokenApproval.token}: ${extractErrorMessage(error, 'amount parsing')}`, - ); - } - - const currentAllowance = await this.adapter.nexusSDK.getEVMClient().readContract({ - address: tokenContractAddress as Hex, - abi: erc20Abi, - functionName: 'allowance', - args: [ownerAddress as Hex, spenderAddress as Hex], - }); - - // Add a small buffer to avoid repeated approvals due to minor amount differences - const bufferBps = - approvalBufferBps !== undefined && approvalBufferBps >= 0 - ? BigInt(approvalBufferBps) - : ADAPTER_CONSTANTS.APPROVAL_BUFFER_BPS_DEFAULT; - const requiredAmountWithBuffer = amountInWei + (amountInWei * bufferBps) / 10000n; - - const needsApproval = currentAllowance < requiredAmountWithBuffer; - - return { - needsApproval, - currentAllowance, - requiredAmount: amountInWei, - tokenAddress: tokenContractAddress, - spenderAddress, - token: tokenApproval.token, - chainId, - hasPendingApproval: !needsApproval, - }; - } catch (error) { - throw new Error( - `Failed to check approval for ${tokenApproval.token}: ${extractErrorMessage(error, 'approval check')}`, - ); - } - } - - /** - * Ensure contract approval is in place for token spending - */ - async ensureContractApproval( - tokenApproval: { token: SUPPORTED_TOKENS; amount: string }, - spenderAddress: string, - chainId: number, - waitForConfirmation: boolean = false, - approvalBufferBps?: number, - ): Promise { - try { - // Check if approval is needed - const approvalInfo = await this.checkApprovalNeeded( - tokenApproval, - spenderAddress, - chainId, - approvalBufferBps, - ); - - // Skip approval if sufficient allowance exists - if (!approvalInfo.needsApproval) { - return { - wasNeeded: false, - confirmed: true, - }; - } - - const accounts = await this.adapter.nexusSDK.getEVMClient().getAddresses(); - - if (!accounts || accounts.length === 0) { - return { - wasNeeded: true, - error: 'No accounts available', - }; - } - - // Calculate buffer amount with proper decimal handling for MetaMask display - const bufferBps = - approvalBufferBps !== undefined && approvalBufferBps >= 0 - ? BigInt(approvalBufferBps) - : ADAPTER_CONSTANTS.APPROVAL_BUFFER_BPS_DEFAULT; - const requiredAmountWithBuffer = - approvalInfo.requiredAmount + (approvalInfo.requiredAmount * bufferBps) / 10000n; - - // Get token decimals for proper formatting - const tokenMetadata = TOKEN_METADATA[tokenApproval.token.toUpperCase()]; - const tokenDecimals = tokenMetadata?.decimals || ADAPTER_CONSTANTS.DEFAULT_DECIMALS; - // Convert to human-readable format first, then back to wei for better MetaMask display - // This ensures MetaMask shows "0.01001" instead of "10100" - const humanReadableAmount = formatUnits(requiredAmountWithBuffer, tokenDecimals); - logger.info('DEBUG approval - Human readable amount for MetaMask:', { - humanReadableAmount, - token: tokenApproval.token, - }); - - // Convert back to wei for the transaction - const finalApprovalAmount = parseUnits(humanReadableAmount, tokenDecimals); - - const chain = this.adapter.nexusSDK.chainList.getChainByID(chainId); - if (!chain) { - throw new Error('chain not supported'); - } - const transactionHash = await this.adapter.nexusSDK.getEVMClient().writeContract({ - functionName: 'approve', - abi: erc20Abi, - address: approvalInfo.tokenAddress as Hex, - args: [spenderAddress as Hex, finalApprovalAmount], - chain, - account: accounts[0], - }); - - if (waitForConfirmation) { - try { - await this.adapter.nexusSDK.getEVMClient().waitForTransactionReceipt({ - hash: transactionHash, - retryCount: 10, - }); - } catch (confirmationError) { - logger.warn('DEBUG approval - Confirmation failed:', confirmationError); - return { - transactionHash, - wasNeeded: true, - confirmed: false, - error: `Approval confirmation failed: ${extractErrorMessage(confirmationError, 'approval confirmation')}`, - }; - } - - return { - transactionHash, - wasNeeded: true, - confirmed: true, - }; - } - return { - transactionHash, - wasNeeded: false, - confirmed: false, - }; - } catch (error) { - logger.error('DEBUG approval - Error:', error as Error); - return { - wasNeeded: true, - error: extractErrorMessage(error, 'contract approval'), - }; - } - } -} diff --git a/packages/core/adapters/services/balance-detection-service.ts b/packages/core/adapters/services/balance-detection-service.ts deleted file mode 100644 index 597f2b68..00000000 --- a/packages/core/adapters/services/balance-detection-service.ts +++ /dev/null @@ -1,403 +0,0 @@ -import { - getTokenContractAddress, - TOKEN_METADATA, - logger, - type SUPPORTED_CHAINS_IDS, - type SUPPORTED_TOKENS, - CHAIN_METADATA, -} from '@nexus/commons'; -import { ChainAbstractionAdapter } from 'adapters/chain-abstraction-adapter'; -import { Hex, erc20Abi } from 'viem'; - -/** - * Detailed balance information for a user - */ -export interface DetailedBalanceInfo { - token: SUPPORTED_TOKENS; - chainId: number; - userAddress: string; - tokenAddress: string; - balance: string; - balanceFormatted: string; - sufficient: boolean; - shortfall: string; - shortfallFormatted: string; - decimals: number; - isNative: boolean; - lastChecked: string; -} - -/** - * Multi-token balance check result - */ -export interface MultiTokenBalanceResult { - userAddress: string; - chainId: number; - balances: DetailedBalanceInfo[]; - totalSufficient: boolean; - insufficientTokens: SUPPORTED_TOKENS[]; - lastChecked: string; -} - -/** - * Balance requirement specification - */ -export interface BalanceRequirement { - token: SUPPORTED_TOKENS; - amount: string; - allowPartial?: boolean; // If true, partial balance is acceptable -} - -/** - * Smart balance detection and analysis service - */ -export class BalanceDetectionService { - private adapter: ChainAbstractionAdapter; - - constructor(adapter: ChainAbstractionAdapter) { - this.adapter = adapter; - } - - private ensureInitialized() { - if (!this.adapter.nexusSDK.isInitialized()) { - throw new Error('Adapter not initialized'); - } - } - - /** - * Check detailed balance for a single token - */ - async getDetailedBalance( - userAddress: string, - token: SUPPORTED_TOKENS, - chainId: number, - requiredAmount?: string, - ): Promise { - this.ensureInitialized(); - - try { - logger.debug('DEBUG BalanceDetectionService - Checking balance:', { - userAddress, - token, - chainId, - requiredAmount, - }); - - const tokenAddress = getTokenContractAddress(token, chainId as SUPPORTED_CHAINS_IDS); - if (!tokenAddress) { - throw new Error(`Token ${token} not supported on chain ${CHAIN_METADATA[chainId]?.name}`); - } - - const isNative = token === 'ETH'; - const tokenMetadata = TOKEN_METADATA[token.toUpperCase()]; - const decimals = tokenMetadata?.decimals || 18; - - let balance: bigint; - - if (isNative) { - // Get ETH balance - balance = await this.adapter.nexusSDK.getEVMClient().getBalance({ - address: userAddress as Hex, - blockTag: 'latest', - }); - } else { - // Get ERC20 token balance using balanceOf - balance = await this.getERC20Balance(userAddress, tokenAddress); - } - - const balanceBigInt = BigInt(balance); - const balanceFormatted = this.formatTokenAmount(balance.toString(), decimals); - - // Calculate sufficiency and shortfall - let sufficient = true; - let shortfall = '0'; - let shortfallFormatted = '0'; - - if (requiredAmount) { - const requiredBigInt = BigInt(requiredAmount); - sufficient = balanceBigInt >= requiredBigInt; - - if (!sufficient) { - shortfall = (requiredBigInt - balanceBigInt).toString(); - shortfallFormatted = this.formatTokenAmount(shortfall, decimals); - } - } - - const result: DetailedBalanceInfo = { - token, - chainId, - userAddress, - tokenAddress, - balance: balance.toString(), - balanceFormatted, - sufficient, - shortfall, - shortfallFormatted, - decimals, - isNative, - lastChecked: new Date().toISOString(), - }; - - logger.info('DEBUG BalanceDetectionService - Balance check result:', { - token, - balance: balanceFormatted, - sufficient, - shortfall: shortfallFormatted, - }); - - return result; - } catch (error) { - logger.error( - `Failed to get detailed balance for ${token}:`, - error instanceof Error ? error : String(error), - ); - - // Return error state - return { - token, - chainId, - userAddress, - tokenAddress: getTokenContractAddress(token, chainId as SUPPORTED_CHAINS_IDS) || '', - balance: '0', - balanceFormatted: '0', - sufficient: false, - shortfall: requiredAmount || '0', - shortfallFormatted: '0', - decimals: TOKEN_METADATA[token.toUpperCase()]?.decimals || 18, - isNative: token === 'ETH', - lastChecked: new Date().toISOString(), - }; - } - } - - /** - * Check balances for multiple tokens - */ - async getMultiTokenBalances( - userAddress: string, - chainId: number, - requirements: BalanceRequirement[], - ): Promise { - this.ensureInitialized(); - - logger.info('DEBUG BalanceDetectionService - Multi-token balance check:', { - userAddress, - chainId, - requirements: requirements.length, - }); - - const balances: DetailedBalanceInfo[] = []; - const insufficientTokens: SUPPORTED_TOKENS[] = []; - - // Check each token balance - for (const requirement of requirements) { - try { - const balanceInfo = await this.getDetailedBalance( - userAddress, - requirement.token, - chainId, - requirement.amount, - ); - - balances.push(balanceInfo); - - // Track insufficient tokens (unless partial is allowed) - if (!balanceInfo.sufficient && !requirement.allowPartial) { - insufficientTokens.push(requirement.token); - } - } catch (error) { - logger.error( - `Failed to check balance for ${requirement.token}:`, - error instanceof Error ? error : String(error), - ); - insufficientTokens.push(requirement.token); - } - } - - const totalSufficient = insufficientTokens.length === 0; - - const result: MultiTokenBalanceResult = { - userAddress, - chainId, - balances, - totalSufficient, - insufficientTokens, - lastChecked: new Date().toISOString(), - }; - - logger.info('DEBUG BalanceDetectionService - Multi-token result:', { - totalSufficient, - insufficientCount: insufficientTokens.length, - insufficientTokens, - }); - - return result; - } - - /** - * Get ERC20 token balance using balanceOf call - */ - private async getERC20Balance(userAddress: string, tokenAddress: string): Promise { - try { - const balance = await this.adapter.nexusSDK.getEVMClient().readContract({ - abi: erc20Abi, - functionName: 'balanceOf', - address: tokenAddress as Hex, - args: [userAddress as Hex], - }); - - return balance; - } catch (error) { - logger.error( - `Failed to get ERC20 balance for ${tokenAddress}:`, - error instanceof Error ? error : String(error), - ); - return 0n; - } - } - - /** - * Format token amount from wei to human readable - */ - private formatTokenAmount(amount: string, decimals: number): string { - try { - const amountBigInt = BigInt(amount); - const divisor = BigInt(10) ** BigInt(decimals); - - // Handle whole number part - const wholePart = amountBigInt / divisor; - const fractionalPart = amountBigInt % divisor; - - if (fractionalPart === 0n) { - return wholePart.toString(); - } - - // Convert fractional part to decimal string - const fractionalStr = fractionalPart.toString().padStart(decimals, '0'); - const trimmedFractional = fractionalStr.replace(/0+$/, ''); - - if (trimmedFractional === '') { - return wholePart.toString(); - } - - return `${wholePart}.${trimmedFractional}`; - } catch (error) { - logger.error( - 'Failed to format token amount:', - error instanceof Error ? error : String(error), - ); - return '0'; - } - } - - /** - * Analyze balance gaps and suggest funding strategies - */ - async analyzeBalanceGaps( - userAddress: string, - chainId: number, - requirements: BalanceRequirement[], - ): Promise<{ - analysis: MultiTokenBalanceResult; - fundingStrategy: { - totalFundingNeeded: boolean; - tokenFunding: Array<{ - token: SUPPORTED_TOKENS; - shortfall: string; - shortfallFormatted: string; - priority: 'high' | 'medium' | 'low'; - suggestionType: 'bridge' | 'swap' | 'acquire'; - }>; - }; - }> { - const analysis = await this.getMultiTokenBalances(userAddress, chainId, requirements); - - const tokenFunding = analysis.balances - .filter((balance) => !balance.sufficient) - .map((balance) => ({ - token: balance.token, - shortfall: balance.shortfall, - shortfallFormatted: balance.shortfallFormatted, - priority: this.calculateFundingPriority(balance), - suggestionType: this.suggestFundingMethod(balance.token), - })); - - return { - analysis, - fundingStrategy: { - totalFundingNeeded: !analysis.totalSufficient, - tokenFunding, - }, - }; - } - - /** - * Calculate funding priority based on shortfall amount and token importance - */ - private calculateFundingPriority(balance: DetailedBalanceInfo): 'high' | 'medium' | 'low' { - const shortfallBigInt = BigInt(balance.shortfall); - const divisor = BigInt(10) ** BigInt(balance.decimals); - const shortfallNormalized = Number(shortfallBigInt) / Number(divisor); - - // High priority for native tokens or large amounts - if (balance.isNative || shortfallNormalized > 1000) { - return 'high'; - } - - // Medium priority for moderate amounts - if (shortfallNormalized > 10) { - return 'medium'; - } - - return 'low'; - } - - /** - * Suggest the best funding method for a token on a specific chain - */ - private suggestFundingMethod(token: SUPPORTED_TOKENS): 'bridge' | 'swap' | 'acquire' { - // For now, simple logic - can be enhanced with actual bridge/swap availability - if (token === 'ETH') { - return 'acquire'; // Need to buy ETH - } - - // For stablecoins, bridging is usually preferred - if (token === 'USDC' || token === 'USDT') { - return 'bridge'; - } - - // Default to swap for other tokens - return 'swap'; - } - - /** - * Check if user can afford a transaction including gas - */ - async canAffordTransaction( - userAddress: string, - chainId: number, - tokenRequirements: BalanceRequirement[], - estimatedGasCost: string, - ): Promise<{ - canAfford: boolean; - tokenDeficits: DetailedBalanceInfo[]; - gasDeficit: string; - totalDeficitValue?: string; - }> { - // Check token requirements - const tokenAnalysis = await this.getMultiTokenBalances(userAddress, chainId, tokenRequirements); - - // Check ETH balance for gas - const ethBalance = await this.getDetailedBalance(userAddress, 'ETH', chainId, estimatedGasCost); - - const canAfford = tokenAnalysis.totalSufficient && ethBalance.sufficient; - const tokenDeficits = tokenAnalysis.balances.filter((b) => !b.sufficient); - const gasDeficit = ethBalance.sufficient ? '0' : ethBalance.shortfall; - - return { - canAfford, - tokenDeficits, - gasDeficit, - }; - } -} diff --git a/packages/core/adapters/services/bridge-execute-service.ts b/packages/core/adapters/services/bridge-execute-service.ts deleted file mode 100644 index 71b394c1..00000000 --- a/packages/core/adapters/services/bridge-execute-service.ts +++ /dev/null @@ -1,1317 +0,0 @@ -import { ExecuteService } from './execute-service'; -import { parseUnits, Hex, toHex, TransactionReceipt } from 'viem'; -import type { ChainAbstractionAdapter } from '../chain-abstraction-adapter'; -import { - type BridgeAndExecuteParams, - type BridgeAndExecuteResult, - type BridgeAndExecuteSimulationResult, - type ExecuteParams, - type ExecuteSimulation, - type SimulationResult, - type SimulationStep, - type SUPPORTED_CHAINS_IDS, - type SUPPORTED_TOKENS, - NEXUS_EVENTS, - TOKEN_METADATA, - CHAIN_METADATA, - extractErrorMessage, - logger, - ProgressStep, - UserAssetDatum as UserAsset, -} from '@nexus/commons'; - -// Local constants for the service -const ADAPTER_CONSTANTS = { - DEFAULT_DECIMALS: 18, -}; - -interface ProviderError extends Error { - data?: { - message?: string; - }; -} - -export class BridgeExecuteService { - private executeService: ExecuteService; - private skipBridge: boolean = false; - private optimalBridgeAmount: string = '0'; - - constructor(private adapter: ChainAbstractionAdapter) { - this.executeService = new ExecuteService(adapter); - } - - /** - * Enable or disable gas estimation for execute transactions - * This provides easy control over whether gas estimation runs before execution - */ - public setGasEstimationEnabled(enabled: boolean): void { - // Access the transaction service through the execute service's public method - this.executeService.setGasEstimationEnabled(enabled); - } - - /** - * Bridge and execute operation - combines bridge and execute with proper sequencing - * Now includes smart balance checking to skip bridging when sufficient funds exist - */ - public async bridgeAndExecute(params: BridgeAndExecuteParams): Promise { - const { - toChainId, - token, - amount, - execute, - enableTransactionPolling = false, - transactionTimeout = 30000, - waitForReceipt = true, - receiptTimeout = 300000, - requiredConfirmations = 1, - } = params; - - // Declare here so accessible in catch/finally - let stepForwarder: (step: ProgressStep) => void = () => {}; - - try { - // Normalize the input amount to ensure consistent processing - const normalizedAmount = this.normalizeAmountToWei(amount, token); - - // Check if simulation was run - if not, calculate optimal bridge amount - if (this.optimalBridgeAmount === '0' && !this.skipBridge) { - logger.info('Simulation was not run, calculating optimal bridge amount...'); - const bridgeOptimization = await this.calculateOptimalBridgeAmount( - toChainId, - token, - normalizedAmount, - ); - this.skipBridge = bridgeOptimization.skipBridge; - this.optimalBridgeAmount = bridgeOptimization.optimalAmount; - } - - // Use the skipBridge flag set during simulation to determine execution path - if (this.skipBridge && execute) { - logger.info( - `Enhanced smart routing: Sufficient ${token} + gas balance on chain ${toChainId}, skipping bridge and executing directly`, - ); - - // Skip bridging - execute directly with existing funds - return await this.executeDirectly( - execute, - toChainId, - token, - normalizedAmount, - enableTransactionPolling, - transactionTimeout, - waitForReceipt, - receiptTimeout, - requiredConfirmations, - ); - } - - // Original bridge-and-execute flow when enhanced balance check fails - logger.info( - `Enhanced smart routing: Insufficient ${token} or gas balance on chain ${toChainId}, proceeding with bridge + execute`, - ); - - // Set up listeners to capture Arcana bridge steps and forward step completions - const bridgeStepsPromise: Promise = new Promise((resolve) => { - const expectedHandler = (steps: ProgressStep[]) => { - this.adapter.nexusSDK.nexusEvents.off(NEXUS_EVENTS.EXPECTED_STEPS, expectedHandler); - resolve(steps); - }; - this.adapter.nexusSDK.nexusEvents.on(NEXUS_EVENTS.EXPECTED_STEPS, expectedHandler); - }); - - stepForwarder = (step: ProgressStep) => { - this.adapter.nexusSDK.nexusEvents.emit(NEXUS_EVENTS.BRIDGE_EXECUTE_COMPLETED_STEPS, step); - }; - this.adapter.nexusSDK.nexusEvents.on(NEXUS_EVENTS.STEP_COMPLETE, stepForwarder); - - // Perform the actual bridge transaction using optimal amount - // Convert optimal bridge amount from wei to user-friendly format for bridge service - const tokenMetadata = TOKEN_METADATA[token.toUpperCase()]; - const decimals = tokenMetadata?.decimals || 18; - const { formatUnits } = await import('viem'); - const userFriendlyBridgeAmount = formatUnits(BigInt(this.optimalBridgeAmount), decimals); - - logger.info('Bridge amount conversion for execution:', { - optimalBridgeAmountWei: this.optimalBridgeAmount, - userFriendlyBridgeAmount, - decimals, - token, - }); - - const bridgeResult = await this.adapter.nexusSDK.bridge({ - token, - amount: userFriendlyBridgeAmount, - chainId: toChainId, - sourceChains: params.sourceChains, - }); - - if (!bridgeResult.success) { - throw new Error(`Bridge failed: ${bridgeResult.error}`); - } - - // Wait for captured bridge steps - const bridgeSteps = await bridgeStepsPromise; - - // Add a small delay to ensure bridge settlement is complete - logger.info('DEBUG bridgeAndExecute - Waiting for bridge settlement...'); - await new Promise((resolve) => setTimeout(resolve, 2000)); // 2 second delay - logger.info('DEBUG bridgeAndExecute - Bridge settlement delay complete'); - - // Prepare extra steps for approval/execute/receipt/confirmation - const extraSteps: ProgressStep[] = []; - - const makeStep = ( - typeID: string, - type: string, - data: Record = {}, - ): ProgressStep => ({ - typeID, - type, - data: { - chainID: toChainId, - chainName: CHAIN_METADATA[toChainId]?.name || toChainId.toString(), - ...data, - }, - }); - - if (execute?.tokenApproval) { - extraSteps.push(makeStep('AP', 'APPROVAL')); - } - - if (execute) { - extraSteps.push(makeStep('TS', 'TRANSACTION_SENT')); - if (waitForReceipt) { - extraSteps.push(makeStep('RR', 'RECEIPT_RECEIVED')); - } - if ((requiredConfirmations ?? 0) > 0) { - extraSteps.push(makeStep('CN', 'TRANSACTION_CONFIRMED')); - } - } - - // Emit consolidated expected steps for the whole operation - this.adapter.nexusSDK.nexusEvents.emit(NEXUS_EVENTS.BRIDGE_EXECUTE_EXPECTED_STEPS, [ - ...bridgeSteps, - ...extraSteps, - ]); - - const { executeTransactionHash, executeExplorerUrl, approvalTransactionHash } = - await this.handleExecutePhase( - execute, - toChainId, - token, - normalizedAmount, - enableTransactionPolling, - transactionTimeout, - waitForReceipt, - receiptTimeout, - requiredConfirmations, - // pass helper to emit steps - (step) => - this.adapter.nexusSDK.nexusEvents.emit( - NEXUS_EVENTS.BRIDGE_EXECUTE_COMPLETED_STEPS, - step, - ), - makeStep, - ); - - const result: BridgeAndExecuteResult = { - executeTransactionHash, - executeExplorerUrl, - approvalTransactionHash, - bridgeTransactionHash: bridgeResult.transactionHash, - bridgeExplorerUrl: bridgeResult.explorerUrl, - toChainId, - success: true, - bridgeSkipped: false, // bridge was performed normally - }; - - // Clean up listener - this.adapter.nexusSDK.nexusEvents.off(NEXUS_EVENTS.STEP_COMPLETE, stepForwarder); - - return result; - } catch (error) { - const errorMessage = extractErrorMessage(error, 'bridge and execute'); - - // Forward error step (generic) for UI consumers - this.adapter.nexusSDK.nexusEvents.emit(NEXUS_EVENTS.BRIDGE_EXECUTE_COMPLETED_STEPS, { - typeID: 'ER', - type: 'operation.failed', - data: { - error: errorMessage, - stage: errorMessage.includes('Execute phase failed') ? 'execute' : 'bridge', - }, - }); - - // Clean listener - this.adapter.nexusSDK.nexusEvents.off(NEXUS_EVENTS.STEP_COMPLETE, stepForwarder); - - return { - toChainId, - success: false, - error: `Bridge and execute operation failed: ${errorMessage}`, - bridgeSkipped: false, // error occurred during normal bridge flow - }; - } - } - - /** - * Simulate bridge and execute operation - * Now includes smart routing simulation - */ - public async simulateBridgeAndExecute( - params: BridgeAndExecuteParams, - ): Promise { - try { - const { execute } = params; - const steps: SimulationStep[] = []; - - // Normalize the input amount to ensure consistent processing - const normalizedAmount = this.normalizeAmountToWei(params.amount, params.token); - - // First, calculate optimal bridge amount based on destination balance - const bridgeOptimization = await this.calculateOptimalBridgeAmount( - params.toChainId, - params.token, - normalizedAmount, - ); - - this.skipBridge = bridgeOptimization.skipBridge; - this.optimalBridgeAmount = bridgeOptimization.optimalAmount; - - // Run simulations with optimal amounts - let bridgeSimulation: SimulationResult | ExecuteSimulation | null = null; - let bridgeReceiveAmount = '0'; - let totalBridgeFee = '0'; - - // Only add bridge step if we're not skipping it - if (!this.skipBridge) { - // Convert optimal bridge amount from wei to user-friendly format for bridge service - const tokenMetadata = TOKEN_METADATA[params.token.toUpperCase()]; - const decimals = tokenMetadata?.decimals || 18; - const { formatUnits } = await import('viem'); - const userFriendlyBridgeAmount = formatUnits(BigInt(this.optimalBridgeAmount), decimals); - - logger.info('Bridge amount conversion for simulation:', { - optimalBridgeAmountWei: this.optimalBridgeAmount, - userFriendlyBridgeAmount, - decimals, - token: params.token, - }); - - bridgeSimulation = await this.adapter.nexusSDK.simulateBridge({ - token: params.token, - amount: userFriendlyBridgeAmount, - chainId: params.toChainId, - sourceChains: params.sourceChains, - }); - steps.push({ - type: 'bridge', - required: true, - simulation: bridgeSimulation!, - description: `Bridge ${userFriendlyBridgeAmount} ${params.token} to chain ${params.toChainId}`, - }); - - // Enhanced bridge analysis - if (bridgeSimulation?.intent) { - const intent = bridgeSimulation.intent; - - // Extract destination amount (received amount after bridging) - if (intent.destination?.amount && intent.destination.amount !== '0') { - bridgeReceiveAmount = intent.destination.amount; - } - - // Format bridge fees properly - if (intent.fees?.total) { - totalBridgeFee = `${intent.fees.total}`; - } - } - } - - let executeSimulation: ExecuteSimulation | undefined; - const approvalRequired = false; - - if (execute) { - try { - // Use the received amount from bridge simulation for execute simulation - let receivedAmountForContract = normalizedAmount; // fallback to normalized original amount - - if (bridgeReceiveAmount !== '0') { - // Get token decimals from bridge simulation - const tokenDecimals = - bridgeSimulation?.intent?.token?.decimals || bridgeSimulation?.token?.decimals; - - if (tokenDecimals) { - const receivedAmountBigInt = parseUnits(bridgeReceiveAmount, tokenDecimals); - receivedAmountForContract = receivedAmountBigInt.toString(); - } - } - - // Create execute parameters for simulation - use wei format for SimulationEngine - // SimulationEngine expects amounts in wei format, not user-friendly format - const modifiedExecuteParams: ExecuteParams = { - ...execute, - toChainId: params.toChainId, - ...(params.token !== 'ETH' && execute.tokenApproval - ? { - tokenApproval: { - token: params.token, - amount: receivedAmountForContract, // Keep in wei format for SimulationEngine - }, - } - : {}), - }; - - executeSimulation = - await this.executeService.simulateExecuteEnhanced(modifiedExecuteParams); - if (executeSimulation) { - steps.push({ - type: 'execute', - required: true, - simulation: executeSimulation, - description: `Execute ${execute.functionName} on contract ${execute.contractAddress}`, - }); - } - - // Execute analysis details are available in the simulation result - } catch (simulationError) { - logger.warn(`Execute simulation error: ${simulationError}`); - executeSimulation = { - contractAddress: execute.contractAddress, - functionName: execute.functionName, - gasUsed: '0', - success: false, - error: `Simulation failed: ${simulationError}`, - }; - - steps.push({ - type: 'execute', - required: true, - simulation: executeSimulation, - description: `Execute ${execute.functionName} on contract ${execute.contractAddress} (failed)`, - }); - } - } - - // Calculate enhanced total cost with approval step - let totalEstimatedCost: - | { total: string; breakdown: { bridge: string; execute: string } } - | undefined; - - if (totalBridgeFee !== '0' || executeSimulation?.gasUsed) { - logger.debug('DEBUG bridge-execute-service - totalBridgeFee (ETH):', totalBridgeFee); - logger.debug( - 'DEBUG bridge-execute-service - executeSimulation?.gasUsed:', - executeSimulation?.gasUsed, - ); - - try { - const executeFee = executeSimulation?.gasCostEth || executeSimulation?.gasUsed || '0'; - logger.debug('DEBUG bridge-execute-service - executeFee source value:', executeFee); - - let executeFeeEth = executeFee; - - // If gasCostEth wasn't available, executeFee will be gas units – convert. - if (executeSimulation?.gasCostEth === undefined) { - logger.debug('DEBUG bridge-execute-service - executeFee (gas units):', executeFee); - - try { - // Get the current gas price from the connected provider (wei, hex string) - const gasPriceHex = (await this.adapter.nexusSDK.request({ - method: 'eth_gasPrice', - })) as string; - const gasPriceWei = parseInt(gasPriceHex, 16); - - // gasUsed (string) * gasPriceWei (number) => wei, then convert to ETH - const gasUsedNum = parseFloat(executeFee); - const costEthNum = (gasUsedNum * gasPriceWei) / 1e18; // 1e18 wei per ETH - executeFeeEth = costEthNum.toFixed(8); // keep reasonable precision - } catch (gpErr) { - logger.warn('Failed to fetch gas price for execute fee conversion:', gpErr); - } - } - logger.debug('DEBUG bridge-execute-service - executeFee (ETH):', executeFeeEth); - - // Add bridge fee (already an ETH figure) with converted execute fee - const totalFeeEth = (parseFloat(totalBridgeFee) + parseFloat(executeFeeEth)).toString(); - logger.debug('DEBUG bridge-execute-service - totalFeeEth:', totalFeeEth); - - totalEstimatedCost = { - total: totalFeeEth, - breakdown: { - bridge: totalBridgeFee, - execute: executeFeeEth, - }, - }; - } catch (error) { - logger.warn('Could not calculate total cost - cost breakdown may be incomplete:', error); - } - } - - // Enhanced balance check after simulations are complete - // Re-validate the skip bridge decision with actual gas estimates - if (!this.skipBridge && executeSimulation?.gasUsed) { - const finalOptimization = await this.calculateOptimalBridgeAmount( - params.toChainId, - params.token, - normalizedAmount, - executeSimulation?.gasUsed, - executeSimulation?.gasCostEth, - ); - - // Update skip bridge decision if gas check reveals we can skip - if (finalOptimization.skipBridge && !this.skipBridge) { - this.skipBridge = true; - this.optimalBridgeAmount = '0'; - logger.info('Updated bridge decision after gas validation: bridge can be skipped'); - } - } - - logger.info( - `Enhanced balance check result: skipBridge = ${this.skipBridge} for chain ${params.toChainId}`, - ); - - // Adjust simulation result based on skip decision - let finalBridgeSimulation: SimulationResult | null = bridgeSimulation; - let finalSteps = steps; - - if (this.skipBridge) { - // When bridge is skipped, set bridgeSimulation to null and filter out bridge steps - finalBridgeSimulation = null; - finalSteps = steps.filter((step) => step.type !== 'bridge'); - - logger.info('Bridge will be skipped - using execute-only simulation result'); - return { - steps: finalSteps, - bridgeSimulation: finalBridgeSimulation, - executeSimulation, - totalEstimatedCost, - success: true, - metadata: { - contractAddress: executeSimulation?.contractAddress ?? '', - functionName: executeSimulation?.functionName ?? '', - bridgeReceiveAmount: this.skipBridge - ? params.amount.toString() - : bridgeReceiveAmount !== '0' - ? bridgeReceiveAmount - : this.optimalBridgeAmount, - bridgeFee: this.skipBridge ? '0' : totalBridgeFee.replace(' ETH', '') || '0', - inputAmount: params.amount.toString(), - optimalBridgeAmount: this.optimalBridgeAmount, - targetChain: params.toChainId, - approvalRequired, - bridgeSkipped: this.skipBridge, - token: params?.token, - }, - }; - } - - return { - steps: finalSteps, - bridgeSimulation: finalBridgeSimulation, - executeSimulation, - totalEstimatedCost, - success: true, - }; - } catch (error) { - return { - steps: [], - bridgeSimulation: null, - executeSimulation: undefined, - success: false, - error: `Simulation failed: ${extractErrorMessage(error, 'simulation')}`, - }; - } - } - - /** - * Handle the execute phase of bridge and execute - * Uses callback-based parameter pattern for dynamic parameter building - */ - private async handleExecutePhase( - execute: Omit | undefined, - toChainId: SUPPORTED_CHAINS_IDS, - bridgeToken: SUPPORTED_TOKENS, - bridgeAmount: string, - enableTransactionPolling: boolean, - transactionTimeout: number, - waitForReceipt?: boolean, - receiptTimeout?: number, - requiredConfirmations?: number, - emitStep?: (step: ProgressStep) => void, - makeStep?: (typeID: string, type: string, data?: Record) => ProgressStep, - approvalBufferBpsOverride?: number, - ): Promise<{ - executeTransactionHash?: string; - executeExplorerUrl?: string; - approvalTransactionHash?: string; - }> { - if (!execute || !emitStep || !makeStep) return {}; - - try { - // Debug logging to understand amount handling - logger.info('DEBUG handleExecutePhase - Bridge amount (micro-units):', bridgeAmount); - logger.info('DEBUG handleExecutePhase - Bridge token:', bridgeToken); - - const { formatUnits } = await import('viem'); - - const decimals = TOKEN_METADATA[bridgeToken]?.decimals || 18; - const userFriendlyAmount = formatUnits(BigInt(bridgeAmount), decimals); - - logger.info('DEBUG handleExecutePhase - Amount conversion:', { - microUnits: bridgeAmount, - decimals, - userFriendly: userFriendlyAmount, - bridgeToken, - }); - - // Create execute parameters with user-friendly amount for the callback - // Only include token approval for ERC-20 tokens. Native ETH should never attempt approval. - const finalExecuteParams: ExecuteParams = { - ...execute, - toChainId, - ...(bridgeToken !== 'ETH' && execute.tokenApproval - ? { - tokenApproval: { - token: bridgeToken, - amount: userFriendlyAmount, - }, - } - : {}), - ...(approvalBufferBpsOverride !== undefined - ? { approvalBufferBps: approvalBufferBpsOverride } - : undefined), - }; - - logger.info('DEBUG handleExecutePhase - Execute params created with user-friendly amount:', { - userFriendlyAmount, - originalBridgeAmount: bridgeAmount, - token: bridgeToken, - decimals, - }); - - // Check user balance on destination chain before executing - try { - const destinationBalance = await this.getDestinationChainBalance(toChainId, bridgeToken); - logger.info('DEBUG handleExecutePhase - User balance on destination chain:', { - chainId: toChainId, - token: bridgeToken, - balance: destinationBalance, - requiredAmount: bridgeAmount, - }); - } catch (balanceError) { - logger.warn( - 'DEBUG handleExecutePhase - Could not check destination balance:', - balanceError, - ); - } - - // Execute the target contract call - let execute service handle approval - logger.info('DEBUG handleExecutePhase - Executing contract call with params:', { - ...finalExecuteParams, - toChainId, - }); - - const executeResult = await this.executeService.execute({ - ...finalExecuteParams, - enableTransactionPolling, - transactionTimeout, - waitForReceipt, - receiptTimeout, - requiredConfirmations, - }); - - // Check if we should verify transaction success - if (executeResult.transactionHash) { - // Transaction sent step - emitStep( - makeStep('TS', 'transaction.sent', { - txHash: executeResult.transactionHash, - }), - ); - } - - if (waitForReceipt && executeResult.transactionHash) { - logger.info( - 'DEBUG handleExecutePhase - Checking transaction success for:', - executeResult.transactionHash, - ); - - const transactionCheck = await this.checkTransactionSuccess( - executeResult.transactionHash, - toChainId, - ); - - if (!transactionCheck.success) { - logger.error('DEBUG handleExecutePhase - Transaction failed:', transactionCheck.error); - emitStep( - makeStep('EX', 'execute', { - error: transactionCheck.error, - }), - ); - throw new Error(`Execute transaction failed: ${transactionCheck.error}`); - } - - logger.info( - 'DEBUG handleExecutePhase - Transaction succeeded with gas used:', - transactionCheck.gasUsed, - ); - - // Emit receipt received step - emitStep( - makeStep('RR', 'receipt.received', { - txHash: executeResult.transactionHash, - }), - ); - - // Emit confirmation step if requiredConfirmations met - if ((requiredConfirmations ?? 0) > 0) { - emitStep( - makeStep('CN', 'transaction.confirmed', { - confirmations: requiredConfirmations, - }), - ); - } - } - - return { - executeTransactionHash: executeResult.transactionHash, - executeExplorerUrl: executeResult.explorerUrl, - approvalTransactionHash: executeResult.approvalTransactionHash, - }; - } catch (executeError) { - logger.error('DEBUG handleExecutePhase - Execute error:', executeError as Error); - emitStep(makeStep('EX', 'execute', { error: (executeError as Error).message })); - throw new Error( - `Execute phase failed: ${extractErrorMessage(executeError, 'execute phase')}`, - ); - } - } - - /** - * Normalize amount input to wei format for consistent processing - * Supports various input formats and automatically handles token decimals - */ - private normalizeAmountToWei(amount: string | number, token: string): string { - try { - // Convert to string if it's a number - const amountStr = amount.toString(); - - logger.info('DEBUG normalizeAmountToWei - Input:', { amount: amountStr, token }); - - // Handle edge cases - if (!amountStr || amountStr === '0') { - return '0'; - } - - // Get token metadata for accurate decimal handling - const tokenUpper = token.toUpperCase(); - const tokenMetadata = TOKEN_METADATA[tokenUpper]; - const decimals = tokenMetadata?.decimals || ADAPTER_CONSTANTS?.DEFAULT_DECIMALS || 18; - - logger.info('DEBUG normalizeAmountToWei - Token info:', { - tokenUpper, - decimals, - tokenMetadata, - }); - - // If it's already in wei format (no decimals, large number), return as-is - // Check length to avoid converting small integers to wei incorrectly - if (!amountStr.includes('.') && amountStr.length > 10) { - logger.info('DEBUG normalizeAmountToWei - Already in wei format'); - return amountStr; - } - - // Handle hex values - if (amountStr.startsWith('0x')) { - const result = BigInt(amountStr).toString(); - logger.info(`DEBUG normalizeAmountToWei - Hex conversion: ${result}`); - return result; - } - - // Handle decimal amounts (need conversion to wei) - if (amountStr.includes('.')) { - const result = parseUnits(amountStr, decimals).toString(); - logger.info(`DEBUG normalizeAmountToWei - Decimal conversion: ${amountStr} -> ${result}`); - return result; - } - - // Handle whole number inputs - const numValue = parseFloat(amountStr); - - // For USDC specifically, be more careful with the conversion - // USDC typically has 6 decimals, so 1 USDC = 1,000,000 micro-USDC - const USDC_MICRO_UNITS_THRESHOLD = 1_000_000; // 1 USDC - - if (tokenUpper === 'USDC') { - // For USDC, small numbers (< 1,000,000) are likely user amounts that need conversion - if (numValue < USDC_MICRO_UNITS_THRESHOLD) { - const result = parseUnits(amountStr, 6).toString(); - logger.info( - `DEBUG normalizeAmountToWei - USDC user amount conversion: ${amountStr} -> ${result}`, - ); - return result; - } else { - // Larger numbers are likely already in micro-USDC - logger.info('DEBUG normalizeAmountToWei - USDC already in micro format'); - return amountStr; - } - } - - // For small whole numbers, likely represent user-friendly amounts (e.g., "1" ETH) - // For larger numbers, likely already in wei format - if (numValue < 1000 || (tokenMetadata?.decimals === 6 && numValue < 1000000)) { - // Convert small numbers as user-friendly amounts - const result = parseUnits(amountStr, decimals).toString(); - logger.info( - `DEBUG normalizeAmountToWei - User amount conversion: ${amountStr} -> ${result}`, - ); - return result; - } else { - // Assume larger numbers are already in the correct format - logger.info('DEBUG normalizeAmountToWei - Already in correct format'); - return amountStr; - } - } catch (error) { - // If conversion fails, return original - logger.warn(`Failed to normalize amount ${amount} for token ${token}:`, error); - return amount.toString(); - } - } - - /** - * Get transaction receipt with retry logic - * Note: Assumes we're already on the correct chain (handled by checkTransactionSuccess) - */ - private async getTransactionReceipt( - txHash: string, - maxRetries: number = 3, - ): Promise { - return this.adapter.nexusSDK.getEVMClient().waitForTransactionReceipt({ - hash: txHash as Hex, - retryCount: maxRetries, - }); - } - - /** - * Simulate a failed transaction to get the revert reason - * Note: Assumes we're already on the correct chain (handled by checkTransactionSuccess) - */ - private async simulateFailedTransaction(txHash: string): Promise { - try { - // Get the original transaction details - const tx = await this.adapter.nexusSDK.getEVMClient().getTransaction({ - hash: txHash as Hex, - }); - - if (!tx || tx === null) { - return null; - } - - // Type guard to ensure transaction has required properties - if (typeof tx !== 'object' || tx === null) { - return 'Invalid transaction data'; - } - - if (!tx.to || !tx.input) { - return 'Invalid transaction data'; - } - - // Get the transaction receipt to find the block number where it failed - const receipt = await this.adapter.nexusSDK.getEVMClient().getTransactionReceipt({ - hash: txHash as Hex, - }); - - // Use the block number where the transaction was mined, or the previous block - // This ensures we simulate the exact state when the transaction failed - let simulationBlock = 0n; - - if (receipt) { - if (receipt.blockNumber) { - simulationBlock = receipt.blockNumber; - } - } else if (tx.blockNumber) { - simulationBlock = tx.blockNumber; - } - - logger.info(`DEBUG simulateFailedTransaction - Simulating at block: ${simulationBlock}`); - - // Simulate the transaction call to get revert reason - await this.adapter.nexusSDK.getEVMClient().call({ - to: tx.to, - data: tx.input, - value: tx.value, - gas: tx.gas, - blockNumber: simulationBlock, - }); - - // If eth_call succeeds when we expected it to fail, this is suspicious - // The original transaction failed but the simulation passes - logger.warn( - 'DEBUG simulateFailedTransaction - eth_call succeeded but original transaction failed. This might indicate a state-dependent failure.', - ); - return 'Transaction failed due to state changes or gas issues'; - } catch (error: unknown) { - logger.info( - 'DEBUG simulateFailedTransaction - eth_call failed as expected, extracting revert reason', - ); - - // This is the expected path - eth_call should fail and give us the revert reason - // Extract revert reason from error - if (error && typeof error === 'object' && 'data' in error) { - const providerError = error as ProviderError; - if (providerError.data?.message) { - return providerError.data.message; - } - } - - if (error && typeof error === 'object' && 'message' in error) { - const errorWithMessage = error as { message: string }; - - // Parse common revert reason patterns - const revertMatch = errorWithMessage.message.match(/revert (.+?)(?:\s|$)/i); - if (revertMatch) { - return revertMatch[1]; - } - - // Check for execution reverted patterns - if (errorWithMessage.message.includes('execution reverted')) { - const cleanMessage = errorWithMessage.message.replace('execution reverted: ', '').trim(); - return cleanMessage || 'Transaction reverted without reason'; - } - - // Handle other common error patterns - if (errorWithMessage.message.includes('insufficient funds')) { - return 'Insufficient funds for gas * price + value'; - } - - if (errorWithMessage.message.includes('gas required exceeds allowance')) { - return 'Out of gas'; - } - - return errorWithMessage.message; - } - - return 'Transaction simulation failed'; - } - } - - /** - * Check transaction success and get detailed error information - */ - private async checkTransactionSuccess( - txHash: string, - chainId: number, - maxRetries: number = 5, - retryDelay: number = 3000, - ): Promise<{ - success: boolean; - error?: string; - gasUsed?: string; - }> { - for (let attempt = 1; attempt <= maxRetries; attempt++) { - try { - logger.info( - `DEBUG checkTransactionSuccess - Attempt ${attempt}/${maxRetries}: Checking transaction: ${txHash} on chain: ${chainId}`, - ); - - // Ensure we're on the correct chain before checking transaction - const currentChainId = await this.adapter.nexusSDK.getEVMClient().getChainId(); - - if (currentChainId !== chainId) { - logger.info( - `DEBUG checkTransactionSuccess - Switching from chain ${currentChainId} to ${chainId}`, - ); - try { - await this.adapter.nexusSDK.getEVMClient().switchChain({ id: chainId }); - // Wait a bit after chain switch - await new Promise((resolve) => setTimeout(resolve, 1000)); - } catch (switchError) { - logger.error( - `DEBUG checkTransactionSuccess - Failed to switch to chain ${chainId}:`, - switchError as Error, - ); - return { - success: false, - error: `Failed to switch to chain ${chainId} for transaction verification`, - }; - } - } - - // 1. Get transaction receipt - basic success/failure - const receipt = await this.getTransactionReceipt(txHash); - - if (!receipt) { - if (attempt < maxRetries) { - logger.info( - `DEBUG checkTransactionSuccess - Receipt not found, retrying in ${retryDelay}ms...`, - ); - await new Promise((resolve) => setTimeout(resolve, retryDelay)); - continue; // Retry - } - - return { - success: false, - error: 'Transaction receipt not found after multiple attempts', - }; - } - - logger.info(`DEBUG checkTransactionSuccess - Receipt status: ${receipt.status}`); - - // Check if transaction succeeded - if (receipt.status === 'success') { - return { - success: true, - gasUsed: toHex(receipt.gasUsed), - }; - } else { - let errorMessage = 'Transaction failed'; - - // 3. Simulate the transaction to get detailed error - try { - const simulationError = await this.simulateFailedTransaction(txHash); - if (simulationError) { - errorMessage = simulationError; - } - } catch (simError) { - logger.warn('DEBUG checkTransactionSuccess - Simulation failed:', simError); - // Keep generic error message if simulation fails - } - - logger.info(`DEBUG checkTransactionSuccess - Final error: ${errorMessage}`); - - return { - success: false, - error: errorMessage, - gasUsed: toHex(receipt.gasUsed), - }; - } - - // Transaction failed - now get the error reason - } catch (error) { - logger.error(`DEBUG checkTransactionSuccess - Attempt ${attempt} failed:`, error as Error); - - if (attempt < maxRetries) { - logger.info(`DEBUG checkTransactionSuccess - Retrying in ${retryDelay}ms...`); - await new Promise((resolve) => setTimeout(resolve, retryDelay)); - continue; // Retry - } - - // Final attempt failed - return { - success: false, - error: `Failed to check transaction status after ${maxRetries} attempts: ${extractErrorMessage(error, 'transaction check')}`, - }; - } - } - - // This should never be reached, but just in case - return { - success: false, - error: `Transaction check failed after ${maxRetries} attempts`, - }; - } - - /** - * Calculate optimal bridge amount based on destination chain balance - * Returns the exact amount needed to bridge, or indicates if bridge can be skipped entirely - */ - private async calculateOptimalBridgeAmount( - chainId: SUPPORTED_CHAINS_IDS, - token: SUPPORTED_TOKENS, - requiredAmount: string, - gasEstimate?: string, - gasCostEth?: string, - ): Promise<{ skipBridge: boolean; optimalAmount: string }> { - try { - // Get destination chain balance - const destinationBalance = await this.getDestinationChainBalance(chainId, token); - - if (destinationBalance === null) { - // If we can't get balance info, bridge the full amount - return { skipBridge: false, optimalAmount: requiredAmount }; - } - - const requiredAmountBigInt = BigInt(requiredAmount); - const destinationBalanceBigInt = BigInt(destinationBalance); - - // Check if we have sufficient balance on destination to skip bridge entirely - if (destinationBalanceBigInt >= requiredAmountBigInt) { - // Check gas balance if we have gas estimate - if (gasEstimate || gasCostEth) { - const hasGasBalance = await this.checkGasBalance(chainId, gasEstimate, gasCostEth); - if (!hasGasBalance) { - logger.info(`Insufficient gas balance on chain ${chainId}, cannot skip bridge`); - return { skipBridge: false, optimalAmount: requiredAmount }; - } - } - - logger.info( - `Sufficient ${token} and gas balance on chain ${chainId}, bridge can be skipped`, - ); - return { skipBridge: true, optimalAmount: '0' }; - } - - // Calculate how much we need to bridge (required - what's already on destination) - const optimalBridgeAmountBigInt = requiredAmountBigInt - destinationBalanceBigInt; - const optimalAmount = ( - optimalBridgeAmountBigInt > 0n ? optimalBridgeAmountBigInt : 0n - ).toString(); - - logger.info(`Optimal bridge calculation:`, { - token, - chainId, - requiredAmount, - destinationBalance, - optimalBridgeAmount: optimalAmount, - }); - - return { skipBridge: false, optimalAmount }; - } catch (error) { - logger.warn(`Failed to calculate optimal bridge amount: ${error}`); - // Default to bridging full amount on error - return { skipBridge: false, optimalAmount: requiredAmount }; - } - } - - /** - * Get destination chain balance for a specific token - * Returns balance in wei as string, or null if not found - */ - private async getDestinationChainBalance( - chainId: SUPPORTED_CHAINS_IDS, - token: SUPPORTED_TOKENS, - ): Promise { - try { - logger.info(`Getting ${token} balance on chain ${chainId}`); - - // Get user's unified balances - const balances = (await this.adapter.nexusSDK.getUnifiedBalances()) as UserAsset[]; - - // Find the balance for the specific token - const tokenBalance = balances.find((asset) => asset.symbol === token); - - if (!tokenBalance || !tokenBalance.breakdown) { - logger.info(`No ${token} balance found`); - return null; - } - - // Find balance on the specific chain - const chainBalance = tokenBalance.breakdown.find((balance) => balance.chain.id === chainId); - - if (!chainBalance) { - logger.info(`No ${token} balance found on chain ${chainId}`); - return '0'; // Return 0 if no balance on this chain - } - - // Get token metadata for decimal conversion - const tokenMetadata = TOKEN_METADATA[token.toUpperCase()]; - const decimals = tokenMetadata?.decimals || 18; - - // Convert the balance to wei for calculation - const balanceInWei = parseUnits(chainBalance.balance, decimals); - - logger.info(`Balance found:`, { - token, - chainId, - balance: chainBalance.balance, - balanceInWei: balanceInWei.toString(), - }); - - return balanceInWei.toString(); - } catch (error) { - logger.warn(`Failed to get destination chain balance: ${error}`); - return null; - } - } - - /** - * Check native token balance for gas requirements - */ - private async checkGasBalance( - chainId: SUPPORTED_CHAINS_IDS, - gasEstimate?: string, - gasCostEth?: string, - ): Promise { - try { - // Get native token symbol for this chain - const chainMetadata = CHAIN_METADATA[chainId]; - if (!chainMetadata) { - logger.warn(`No chain metadata found for chain ${chainId}`); - return false; - } - - const nativeTokenSymbol = chainMetadata.nativeCurrency.symbol; - logger.info(`Checking ${nativeTokenSymbol} balance on chain ${chainId} for gas`); - - // Get user's unified balances - const balances = (await this.adapter.nexusSDK.getUnifiedBalances()) as UserAsset[]; - - // Find the native token balance - const nativeTokenBalance = balances.find((asset) => asset.symbol === nativeTokenSymbol); - - if (!nativeTokenBalance || !nativeTokenBalance.breakdown) { - logger.info(`No ${nativeTokenSymbol} balance found`); - return false; - } - - // Find balance on the specific chain - const chainBalance = nativeTokenBalance.breakdown.find( - (balance) => balance.chain.id === chainId, - ); - - if (!chainBalance) { - logger.info(`No ${nativeTokenSymbol} balance found on chain ${chainId}`); - return false; - } - - // Calculate required gas cost - let requiredGasCost = '0'; - - if (gasCostEth) { - // If we have gas cost in ETH, use it directly - requiredGasCost = gasCostEth; - } else if (gasEstimate) { - // Convert gas estimate to ETH using current gas price - try { - const gasPriceHex = (await this.adapter.nexusSDK.request({ - method: 'eth_gasPrice', - })) as string; - const gasPriceWei = parseInt(gasPriceHex, 16); - - const gasUsedNum = parseFloat(gasEstimate); - const costEthNum = (gasUsedNum * gasPriceWei) / 1e18; // Convert wei to ETH - requiredGasCost = costEthNum.toString(); - } catch (error) { - logger.warn(`Failed to fetch gas price for gas balance check: ${error}`); - return false; - } - } - - // Add 10% buffer to required gas cost - const requiredGasCostWithBuffer = (parseFloat(requiredGasCost) * 1.1).toString(); - - // Compare balances (both in user-friendly format like ETH) - const userBalance = parseFloat(chainBalance.balance); - const requiredGasFloat = parseFloat(requiredGasCostWithBuffer); - - const hasSufficientGasBalance = userBalance >= requiredGasFloat; - - logger.info(`Gas balance check result:`, { - nativeTokenSymbol, - chainId, - userBalance: chainBalance.balance, - requiredGasCost, - requiredGasCostWithBuffer, - hasSufficientGasBalance, - }); - - return hasSufficientGasBalance; - } catch (error) { - logger.warn(`Failed to check gas balance: ${error}`); - return false; - } - } - - /** - * Execute directly without bridging when user has sufficient funds - * Uses callback-based parameters for dynamic execution - */ - private async executeDirectly( - execute: Omit, - toChainId: SUPPORTED_CHAINS_IDS, - token: SUPPORTED_TOKENS, - amount: string, - enableTransactionPolling: boolean, - transactionTimeout: number, - waitForReceipt?: boolean, - receiptTimeout?: number, - requiredConfirmations?: number, - ): Promise { - try { - // Emit expected steps for execute-only flow - const executeSteps: ProgressStep[] = []; - - const makeStep = ( - typeID: string, - type: string, - data: Record = {}, - ): ProgressStep => ({ - typeID, - type, - data: { - chainID: toChainId, - chainName: CHAIN_METADATA[toChainId]?.name || toChainId.toString(), - ...data, - }, - }); - - // Add steps for execute-only flow - if (execute.tokenApproval) { - executeSteps.push(makeStep('AP', 'APPROVAL')); - } - executeSteps.push(makeStep('TS', 'TRANSACTION_SENT')); - if (waitForReceipt) { - executeSteps.push(makeStep('RR', 'RECEIPT_RECEIVED')); - } - if ((requiredConfirmations ?? 0) > 0) { - executeSteps.push(makeStep('CN', 'TRANSACTION_CONFIRMED')); - } - - // Emit expected steps for execute-only flow - this.adapter.nexusSDK.nexusEvents.emit( - NEXUS_EVENTS.BRIDGE_EXECUTE_EXPECTED_STEPS, - executeSteps, - ); - - // Execute directly using existing funds - const { executeTransactionHash, executeExplorerUrl, approvalTransactionHash } = - await this.handleExecutePhase( - execute, - toChainId, - token, - amount, - enableTransactionPolling, - transactionTimeout, - waitForReceipt, - receiptTimeout, - requiredConfirmations, - (step) => - this.adapter.nexusSDK.nexusEvents.emit( - NEXUS_EVENTS.BRIDGE_EXECUTE_COMPLETED_STEPS, - step, - ), - makeStep, - ); - - return { - executeTransactionHash, - executeExplorerUrl, - approvalTransactionHash, - bridgeTransactionHash: undefined, // bridge was skipped - bridgeExplorerUrl: undefined, // bridge was skipped - toChainId, - success: true, - bridgeSkipped: true, // bridge was skipped due to sufficient funds - }; - } catch (error) { - const errorMessage = extractErrorMessage(error, 'execute directly'); - - // Emit error step - this.adapter.nexusSDK.nexusEvents.emit(NEXUS_EVENTS.BRIDGE_EXECUTE_COMPLETED_STEPS, { - typeID: 'ER', - type: 'operation.failed', - data: { - error: errorMessage, - stage: 'execute', - }, - }); - - return { - toChainId, - success: false, - error: `Execute-only operation failed: ${errorMessage}`, - bridgeSkipped: true, // error occurred during execute-only flow - }; - } - } -} diff --git a/packages/core/adapters/services/execute-service.ts b/packages/core/adapters/services/execute-service.ts deleted file mode 100644 index 31e79bdd..00000000 --- a/packages/core/adapters/services/execute-service.ts +++ /dev/null @@ -1,341 +0,0 @@ -import { TransactionService } from './transaction-service'; -import { ApprovalService } from './approval-service'; -import { getSimulationClient } from '../../integrations/tenderly'; -import { - extractErrorMessage, - logger, - type ExecuteParams, - type ExecuteResult, - type ExecuteSimulation, -} from '@nexus/commons'; -import { ChainAbstractionAdapter } from '../chain-abstraction-adapter'; -import { Hex, hexToNumber } from 'viem'; -import { SimulationEngine } from './simulation-engine'; - -/** - * Service responsible for handling execution operations - */ -export class ExecuteService { - private transactionService: TransactionService; - private approvalService: ApprovalService; - - constructor(private adapter: ChainAbstractionAdapter) { - this.transactionService = new TransactionService(adapter); - this.approvalService = new ApprovalService(adapter); - } - - /** - * Enable or disable gas estimation for transactions - */ - public setGasEstimationEnabled(enabled: boolean): void { - this.transactionService.setGasEstimationEnabled(enabled); - } - - /** - * Execute a contract call with approval handling - */ - async execute(params: ExecuteParams): Promise { - try { - // Prepare execution (includes chain switching) - const preparation = await this.transactionService.prepareExecution(params); - - // Handle approval if needed (after chain switching) - let approvalTxHash: string | undefined; - if (params.tokenApproval) { - const approvalResult = await this.approvalService.ensureContractApproval( - params.tokenApproval, - params.contractAddress, - params.toChainId, - false, - params.approvalBufferBps, - ); - - if (approvalResult.error) { - throw new Error(`Approval failed: ${approvalResult.error}`); - } - - approvalTxHash = approvalResult.transactionHash; - } - - // Send transaction - const transactionHash = await this.transactionService.sendTransaction( - preparation.provider, - preparation.fromAddress, - params.contractAddress, - preparation.encodedData, - preparation.value || params.value || '0x0', - { - enableTransactionPolling: params.enableTransactionPolling, - transactionTimeout: params.transactionTimeout, - waitForReceipt: params.waitForReceipt, - receiptTimeout: params.receiptTimeout, - requiredConfirmations: params.requiredConfirmations, - }, - ); - - // Handle transaction confirmation - const receiptInfo = await this.transactionService.handleTransactionConfirmation( - preparation.provider, - transactionHash, - { - waitForReceipt: params.waitForReceipt, - receiptTimeout: params.receiptTimeout, - requiredConfirmations: params.requiredConfirmations, - }, - params.toChainId, - ); - - // Build result - const result = this.transactionService.buildExecuteResult( - transactionHash, - params.toChainId, - receiptInfo, - ); - - // If approval happened, attach approval tx hash if available - if (params.tokenApproval && approvalTxHash) { - // Augment the typed result by casting to the extended type locally before returning - const extendedResult: ExecuteResult = { - ...result, - approvalTransactionHash: approvalTxHash, - }; - return extendedResult; - } - - return result; - } catch (error) { - throw error; - } - } - - /** - * Simulate contract execution - */ - async simulateExecute(params: ExecuteParams): Promise { - try { - // Get simulation client - const simulationClient = getSimulationClient(); - - if (!simulationClient) { - return { - contractAddress: params.contractAddress, - functionName: params.functionName, - gasUsed: '0', - success: false, - error: 'Simulation client not configured', - }; - } - - // Get user address for callback - const fromAddress = await this.adapter.nexusSDK.getEVMClient().getAddresses(); - - if (!fromAddress || fromAddress.length === 0) { - throw new Error('No accounts available'); - } - - // Prepare execution to get encoded data and value (calls buildFunctionParams internally) - const preparation = await this.transactionService.prepareExecution(params); - - // Create simulation parameters - const simulationParams = { - from: preparation.fromAddress, - to: params.contractAddress, - data: preparation.encodedData, - value: preparation.value || params.value || '0x0', - chainId: params.toChainId.toString(), - }; - - // Run simulation - const simulationResult = await simulationClient.simulate(simulationParams); - - if (!simulationResult.success) { - return { - contractAddress: params.contractAddress, - functionName: params.functionName, - gasUsed: '0', - success: false, - error: simulationResult.errorMessage || 'Simulation failed', - } as ExecuteSimulation; - } - - const gasUsedDecimal = hexToNumber(simulationResult.gasUsed as Hex); - let gasCostEth: string | undefined; - try { - const gasPriceHex = (await this.adapter.nexusSDK.request({ - method: 'eth_gasPrice', - })) as string; - const gasPriceWei = parseInt(gasPriceHex, 16); - const costEthNum = (gasUsedDecimal * gasPriceWei) / 1e18; - gasCostEth = costEthNum.toFixed(8); - } catch (gpErr) { - logger.warn('Failed to fetch gas price during simulation cost calc:', gpErr); - } - - return { - gasUsed: gasUsedDecimal.toString(), - success: true, - ...(gasCostEth ? { gasCostEth } : {}), - } as ExecuteSimulation; - } catch (error) { - return { - contractAddress: params.contractAddress, - functionName: params.functionName, - gasUsed: '0', - success: false, - error: extractErrorMessage(error, 'execution simulation'), - }; - } - } - - /** - * Enhanced simulation with automatic state setup - */ - async simulateExecuteEnhanced(params: ExecuteParams): Promise { - try { - // Check if we should use enhanced simulation - logger.debug('DEBUG ExecuteService - Full params received:', { - functionName: params.functionName, - contractAddress: params.contractAddress, - tokenApproval: params.tokenApproval, - buildFunctionParams: typeof params.buildFunctionParams, - toChainId: params.toChainId, - }); - - const shouldUseEnhancedSimulation = this.shouldUseEnhancedSimulation(params); - logger.debug( - 'DEBUG ExecuteService - Final enhanced simulation decision:', - shouldUseEnhancedSimulation, - ); - - if (shouldUseEnhancedSimulation) { - return await this.runEnhancedSimulation(params); - } - - return await this.simulateExecute(params); - } catch (error) { - return { - contractAddress: params.contractAddress, - functionName: params.functionName, - gasUsed: '0', - success: false, - error: extractErrorMessage(error, 'enhanced simulation'), - }; - } - } - - /** - * Determine if enhanced simulation should be used - */ - private shouldUseEnhancedSimulation(params: ExecuteParams): boolean { - // Use enhanced simulation if: - // 1. Token approval is required (indicates ERC20 interaction) - // 2. Function is likely to fail without proper balance setup - const shouldUse = - params.tokenApproval !== undefined && - params.tokenApproval.token !== 'ETH' && - this.isComplexContractCall(params); - logger.debug('DEBUG shouldUseEnhancedSimulation - Decision:', { - hasTokenApproval: !!params.tokenApproval, - isComplex: this.isComplexContractCall(params), - functionName: params.functionName, - finalDecision: shouldUse, - }); - return ( - params.tokenApproval !== undefined && - params.tokenApproval.token !== 'ETH' && - this.isComplexContractCall(params) - ); - } - - /** - * Check if this is a complex contract call that benefits from enhanced simulation - */ - private isComplexContractCall(params: ExecuteParams): boolean { - const complexFunctions = [ - 'deposit', - 'withdraw', - 'swap', - 'trade', - 'stake', - 'unstake', - 'mint', - 'burn', - 'transfer', - 'transferFrom', - 'approve', - 'supply', - 'borrow', - 'repay', - 'redeem', - 'lend', - ]; - - return complexFunctions.some((func) => - params.functionName.toLowerCase().includes(func.toLowerCase()), - ); - } - - /** - * Run enhanced simulation with automatic state setup - */ - private async runEnhancedSimulation(params: ExecuteParams): Promise { - try { - // Check if evmProvider is available - if (!this.adapter.nexusSDK.getEVMProviderWithCA()) { - throw new Error('EVM provider not available for enhanced simulation'); - } - - const simulationEngine = new SimulationEngine(this.adapter); - - // Get user address - const preparation = await this.transactionService.prepareExecution(params); - - // Convert tokenApproval amount to proper format if needed - const tokenAmount = params.tokenApproval?.amount || '0'; - - logger.info('DEBUG ExecuteService - Running enhanced simulation:', { - user: preparation.fromAddress, - token: params.tokenApproval?.token, - amount: tokenAmount, - function: params.functionName, - }); - - // Run enhanced simulation (tokenApproval is guaranteed to exist here due to shouldUseEnhancedSimulation check) - if (!params.tokenApproval) { - throw new Error('Enhanced simulation requires token approval information'); - } - - const enhancedResult = await simulationEngine.simulateWithStateSetup({ - user: preparation.fromAddress, - tokenRequired: params.tokenApproval.token, - amountRequired: tokenAmount, - contractCall: params, - }); - - // Convert enhanced result to ExecuteSimulation format - if (!enhancedResult.success) { - return { - contractAddress: params.contractAddress, - functionName: params.functionName, - gasUsed: '0', - success: false, - error: enhancedResult.error || 'Enhanced simulation failed', - }; - } - - // enhancedResult.totalGasUsed is already an ETH-denominated string (SimulationEngine converts) - return { - contractAddress: params.contractAddress, - functionName: params.functionName, - gasUsed: enhancedResult.totalGasUsed, - success: true, - gasCostEth: enhancedResult.totalGasUsed, - } as ExecuteSimulation; - } catch (error) { - logger.error('Enhanced simulation failed, falling back to standard:', error as Error); - - // Fallback to standard simulation - return await this.simulateExecute(params); - } - } -} diff --git a/packages/core/adapters/services/simulation-engine.ts b/packages/core/adapters/services/simulation-engine.ts deleted file mode 100644 index 65fc2fbf..00000000 --- a/packages/core/adapters/services/simulation-engine.ts +++ /dev/null @@ -1,684 +0,0 @@ -import type { - EnhancedSimulationResult, - EnhancedSimulationStep, - StateOverride, -} from '../../integrations/types'; -import { encodePacked, keccak256, formatUnits, Hex, erc20Abi } from 'viem'; -import { - type SUPPORTED_TOKENS, - type ExecuteParams, - type SUPPORTED_CHAINS_IDS, - extractErrorMessage, - getTokenContractAddress, - logger, - encodeContractCall, - TOKEN_METADATA, - CHAIN_METADATA, -} from '@nexus/commons'; - -import { getSimulationClient } from '../../integrations/tenderly'; -import { ChainAbstractionAdapter } from 'adapters/chain-abstraction-adapter'; - -/** - * Balance check result interface - */ -export interface BalanceCheckResult { - balance: string; - sufficient: boolean; - shortfall: string; - tokenAddress: string; -} - -/** - * Multi-step simulation engine with state override capabilities - */ -export class SimulationEngine { - private adapter: ChainAbstractionAdapter; - - constructor(adapter: ChainAbstractionAdapter) { - this.adapter = adapter; - } - - private ensureInitialized() { - if (!this.adapter.nexusSDK.isInitialized()) { - throw new Error('Adapter not initialized'); - } - } - - /** - * Main entry point for enhanced simulation with automatic state setup - */ - async simulateWithStateSetup(params: { - user: string; - tokenRequired: SUPPORTED_TOKENS; - amountRequired: string; - contractCall: ExecuteParams; - }): Promise { - this.ensureInitialized(); - - try { - const { user, tokenRequired, amountRequired, contractCall } = params; - const chainId = contractCall.toChainId; - - logger.info('DEBUG SimulationEngine - Starting enhanced simulation with full context:', { - user, - tokenRequired, - amountRequired, - chainId, - contract: contractCall.contractAddress, - function: contractCall.functionName, - contractCallParams: { - tokenApproval: contractCall.tokenApproval, - buildFunctionParams: typeof contractCall.buildFunctionParams, - }, - }); - - // Step 1: Check user's current token balance - const balanceCheck = await this.checkUserBalance( - user, - tokenRequired, - chainId, - amountRequired, - ); - logger.info('DEBUG SimulationEngine - Balance check result:', balanceCheck); - - // Step 2: Generate simulation steps - const steps = await this.generateSimulationSteps({ - user, - tokenRequired, - amountRequired, - contractCall, - balanceCheck, - }); - - logger.info('DEBUG SimulationEngine - Generated steps:', steps.length); - - // Step 3: Execute multi-step simulation - const result = await this.executeBatchSimulation(steps, chainId); - - logger.info('DEBUG SimulationEngine - Simulation complete:', { - success: result.success, - totalGas: result.totalGasUsed, - stepsExecuted: result.steps.length, - }); - - return result; - } catch (error) { - logger.error('DEBUG SimulationEngine - Simulation failed:', error as Error); - return this.createFailedResult( - `Enhanced simulation failed: ${extractErrorMessage(error, 'simulation')}`, - ); - } - } - - /** - * Check user's token balance on specific chain - */ - async checkUserBalance( - user: string, - token: SUPPORTED_TOKENS, - chainId: number, - requiredAmount?: string, - ): Promise { - try { - const tokenAddress = getTokenContractAddress(token, chainId as SUPPORTED_CHAINS_IDS); - if (!tokenAddress) { - throw new Error(`Token ${token} not supported on chain ${CHAIN_METADATA[chainId]?.name}`); - } - - // For native ETH, use eth_getBalance - if (token === 'ETH') { - const balance = await this.adapter.nexusSDK.getEVMClient().getBalance({ - address: user as Hex, - blockTag: 'latest', - }); - - const balanceBigInt = BigInt(balance); - const requiredBigInt = requiredAmount ? BigInt(requiredAmount) : BigInt(0); - const sufficient = balanceBigInt >= requiredBigInt; - const shortfall = sufficient ? '0' : (requiredBigInt - balanceBigInt).toString(); - - return { - balance: balance.toString(), - sufficient, - shortfall, - tokenAddress, - }; - } - - const balance = await this.adapter.nexusSDK.getEVMClient().readContract({ - abi: erc20Abi, - functionName: 'balanceOf', - args: [user as Hex], - address: tokenAddress as Hex, - }); - - if (requiredAmount) { - const requiredBigInt = BigInt(requiredAmount); - const sufficient = balance >= requiredBigInt; - const shortfall = sufficient ? '0' : (requiredBigInt - balance).toString(); - - return { - balance: balance.toString(), - sufficient, - shortfall, - tokenAddress, - }; - } - - return { - balance: balance.toString(), - sufficient: false, // Cannot determine without required amount - shortfall: '0', - tokenAddress, - }; - } catch (error) { - logger.warn(`Failed to check balance for ${token} on chain ${chainId}:`, error); - return { - balance: '0', - sufficient: false, - shortfall: requiredAmount || '0', - tokenAddress: getTokenContractAddress(token, chainId as SUPPORTED_CHAINS_IDS) || '', - }; - } - } - - /** - * Get the storage slot for token balances mapping - Production Ready Static Mapping - * Based on actual contract analysis for all supported tokens and chains - */ - private getBalanceStorageSlot(token: SUPPORTED_TOKENS, chainId: number): number { - const storageSlotMapping: Record> = { - // Ethereum Mainnet (1) - 1: { - ETH: 0, - USDC: 9, - USDT: 2, - }, - - // Base Mainnet (8453) - 8453: { - ETH: 0, - USDC: 9, - USDT: 2, - }, - - // Arbitrum One (42161) - 42161: { - ETH: 0, - USDC: 9, - USDT: 2, - }, - - // Optimism (10) - 10: { - ETH: 0, - USDC: 9, - USDT: 2, - }, - - // Polygon (137) - 137: { - ETH: 0, - USDC: 9, - USDT: 2, - }, - - // Avalanche C-Chain (43114) - 43114: { - ETH: 0, - USDC: 9, - USDT: 2, - }, - - // Scroll (534352) - 534352: { - ETH: 0, - USDC: 9, - USDT: 2, - }, - - // Base Sepolia Testnet (84532) - 84532: { - ETH: 0, - USDC: 9, - USDT: 2, - }, - - // Arbitrum Sepolia Testnet (421614) - 421614: { - ETH: 0, - USDC: 9, - USDT: 2, - }, - - // Optimism Sepolia Testnet (11155420) - 11155420: { - ETH: 0, - USDC: 9, - USDT: 2, - }, - - // Polygon Amoy Testnet (80002) - 80002: { - ETH: 0, - USDC: 9, - USDT: 2, - }, - }; - - const chainMapping = storageSlotMapping[chainId]; - if (!chainMapping) { - logger.warn(`Unsupported chain ${chainId}, falling back to defaults`); - // Fallback defaults based on most common patterns - return token === 'USDC' ? 9 : token === 'USDT' ? 2 : 0; - } - - const slot = chainMapping[token]; - if (slot === undefined) { - logger.warn( - `Token ${token} not supported on chain ${CHAIN_METADATA[chainId]?.name}, falling back to defaults`, - ); - return token === 'USDC' ? 9 : token === 'USDT' ? 2 : 0; - } - - logger.info(`Using storage slot ${slot} for ${token} on chain ${chainId}`); - return slot; - } - - /** - * Generate state overrides to fund user with required tokens - */ - async generateStateOverrides( - user: string, - token: SUPPORTED_TOKENS, - requiredAmount: string, - chainId: number, - ): Promise { - try { - const tokenAddress = getTokenContractAddress(token, chainId as SUPPORTED_CHAINS_IDS); - if (!tokenAddress) { - throw new Error(`Token ${token} not supported on chain ${CHAIN_METADATA[chainId]?.name}`); - } - - // For native ETH - if (token === 'ETH') { - return { - [user]: { - balance: `0x${BigInt(requiredAmount).toString(16)}`, - }, - }; - } - - // For ERC20 tokens - override the balance mapping using verified storage slots - const balanceSlot = this.getBalanceStorageSlot(token, chainId); - - // Calculate storage slot for user's balance: keccak256(user_address . balances_slot) - const userBalanceSlot = keccak256( - encodePacked(['address', 'uint256'], [user as `0x${string}`, BigInt(balanceSlot)]), - ); - - // Convert amount to hex with proper padding - const amountHex = `0x${BigInt(requiredAmount).toString(16).padStart(64, '0')}`; - - logger.info( - `Generating state override for ${token} on chain ${chainId}: slot=${balanceSlot}, storageKey=${userBalanceSlot}`, - ); - - return { - [tokenAddress]: { - storage: { - [userBalanceSlot]: amountHex, - }, - }, - }; - } catch (error) { - logger.error('Error generating state overrides:', error as Error); - throw error; - } - } - - /** - * Generate the sequence of simulation steps needed - */ - private async generateSimulationSteps(params: { - user: string; - tokenRequired: SUPPORTED_TOKENS; - amountRequired: string; - contractCall: ExecuteParams; - balanceCheck: BalanceCheckResult; - }): Promise { - const { user, tokenRequired, amountRequired, contractCall, balanceCheck } = params; - const steps: EnhancedSimulationStep[] = []; - - // Check if user has sufficient balance - const requiredAmountBigInt = BigInt(amountRequired); - const currentBalanceBigInt = BigInt(balanceCheck.balance); - const needsFunding = currentBalanceBigInt < requiredAmountBigInt; - - logger.info('DEBUG generateSimulationSteps - Balance analysis:', { - required: requiredAmountBigInt.toString(), - current: currentBalanceBigInt.toString(), - needsFunding, - tokenRequired, - user, - contractCall: { - functionName: contractCall.functionName, - contractAddress: contractCall.contractAddress, - tokenApproval: contractCall.tokenApproval, - buildFunctionParamsType: typeof contractCall.buildFunctionParams, - }, - }); - - // Step 1: Funding step (if needed) - if (needsFunding) { - const stateOverrides = await this.generateStateOverrides( - user, - tokenRequired, - amountRequired, - contractCall.toChainId, - ); - - steps.push({ - type: 'funding', - required: true, - description: `Fund user with ${amountRequired} ${tokenRequired}`, - stepId: 'funding-step', - stateOverride: stateOverrides, - params: { - chainId: contractCall.toChainId.toString(), - from: user, - to: user, - value: '0x0', - }, - }); - } - - // First, convert amountRequired from micro-units to user-friendly format for the callback - // The callback expects amount in user-friendly format (e.g., "0.01" for 0.01 USDC) - // but amountRequired comes in micro-units (e.g., "10000" for 0.01 USDC) - logger.info('Token metadata:', { meta: TOKEN_METADATA, tokenRequired }); - const decimals = TOKEN_METADATA[tokenRequired]?.decimals ?? 6; - const userFriendlyAmount = formatUnits(BigInt(amountRequired), decimals); - - logger.info('DEBUG SimulationEngine - Amount conversion:', { - microUnits: amountRequired, - decimals, - userFriendly: userFriendlyAmount, - }); - - // Call the buildFunctionParams with user-friendly amount - logger.info('DEBUG SimulationEngine - Calling buildFunctionParams with:', { - tokenRequired, - userFriendlyAmount, - chainId: contractCall.toChainId, - user, - }); - - const { functionParams, value } = contractCall.buildFunctionParams( - tokenRequired, - userFriendlyAmount, - contractCall.toChainId, - user as `0x${string}`, - ); - - logger.info('DEBUG SimulationEngine - buildFunctionParams result:', { - functionParams, - value, - functionParamsLength: functionParams?.length, - functionParamsTypes: functionParams?.map((p) => typeof p), - }); - - // Step 2: Approval step (if needed for ERC20) - if (tokenRequired !== 'ETH' && contractCall.tokenApproval) { - const actualAmountToApprove = amountRequired; - - logger.info('DEBUG SimulationEngine - Approval step preparation:', { - tokenRequired, - amountRequired, - actualAmountToApprove, - contractToApprove: contractCall.contractAddress, - tokenAddress: balanceCheck.tokenAddress, - }); - - const approvalCallData = await this.buildApprovalCallData( - contractCall.contractAddress, - actualAmountToApprove, - ); - - steps.push({ - type: 'approval', - required: true, - description: `Approve ${contractCall.contractAddress} to spend ${tokenRequired}`, - stepId: 'approval-step', - dependsOn: needsFunding ? ['funding-step'] : undefined, - params: { - chainId: contractCall.toChainId.toString(), - from: user, - to: balanceCheck.tokenAddress, - data: approvalCallData, - value: '0x0', - }, - }); - } - - // Step 3: Execute step - - // Encode the function call with the built parameters - const encodingResult = encodeContractCall({ - contractAbi: contractCall.contractAbi, - functionName: contractCall.functionName, - functionParams, - }); - - if (!encodingResult.success) { - throw new Error(`Failed to encode contract call: ${encodingResult.error}`); - } - - logger.info('DEBUG SimulationEngine - Execute step preparation:', { - encodedData: encodingResult.data, - contractCallValue: contractCall.value, - callbackValue: value, - finalValue: value || contractCall.value || '0x0', - dependsOn: - tokenRequired !== 'ETH' ? ['approval-step'] : needsFunding ? ['funding-step'] : undefined, - }); - - // Normalize ETH value to 0x-hex if provided - const normalizedValue = (() => { - const v = value || contractCall.value; - if (!v) return '0x0'; - if (typeof v === 'string' && v.startsWith('0x')) return v; - try { - return `0x${BigInt(v).toString(16)}`; - } catch { - return '0x0'; - } - })(); - - steps.push({ - type: 'execute', - required: true, - description: `Execute ${contractCall.functionName} on ${contractCall.contractAddress}`, - stepId: 'execute-step', - dependsOn: - tokenRequired !== 'ETH' ? ['approval-step'] : needsFunding ? ['funding-step'] : undefined, - params: { - chainId: contractCall.toChainId.toString(), - from: user, - to: contractCall.contractAddress, - data: encodingResult.data!, - value: normalizedValue, - }, - }); - - logger.info('DEBUG SimulationEngine - Final steps generated:', { - totalSteps: steps.length, - stepTypes: steps.map((s) => s.type), - stepIds: steps.map((s) => s.stepId), - }); - - return steps; - } - - /** - * Build approval call data for ERC20 token - */ - private async buildApprovalCallData(spender: string, amount: string): Promise { - // ERC20 approve function selector: approve(address,uint256) - const approveSelector = '0x095ea7b3'; - const paddedSpender = spender.slice(2).padStart(64, '0'); - const paddedAmount = BigInt(amount).toString(16).padStart(64, '0'); - - return `${approveSelector}${paddedSpender}${paddedAmount}`; - } - - /** - * Execute batch simulation using bundle endpoint - */ - private async executeBatchSimulation( - steps: EnhancedSimulationStep[], - chainId: number, - ): Promise { - const simulationClient = getSimulationClient(); - if (!simulationClient) { - return this.createFailedResult('Simulation client not configured'); - } - - logger.info( - `DEBUG executeBatchSimulation - Starting bundle simulation with ${steps.length} steps`, - ); - - // Build cumulative state overrides - let cumulativeStateOverrides: StateOverride = {}; - const bundleSimulations: Array<{ - stepId: string; - type: string; - from: string; - to: string; - data: string; - value: string; - stateOverride: StateOverride; - }> = []; - - for (const step of steps) { - // Merge cumulative state overrides with step-specific overrides - cumulativeStateOverrides = this.mergeStateOverrides( - cumulativeStateOverrides, - step.stateOverride || {}, - ); - - // Add to bundle - bundleSimulations.push({ - stepId: step.stepId || '', - type: step.type, - from: step.params.from || '', - to: step.params.to || '', - data: step.params.data || '0x', - value: step.params.value || '0x0', - stateOverride: { ...cumulativeStateOverrides }, // Each step gets cumulative state - }); - - logger.info(`DEBUG executeBatchSimulation - Prepared step: ${step.stepId} (${step.type})`); - } - - try { - // Execute bundle simulation - const bundleRequest = { - chainId: chainId.toString(), - simulations: bundleSimulations, - }; - - logger.info('DEBUG executeBatchSimulation - Sending bundle request'); - const bundleResult = await simulationClient.simulateBundle(bundleRequest); - - if (!bundleResult.success) { - return { - totalGasUsed: '0', - success: false, - error: 'Bundle simulation failed', - steps: bundleResult.results.map((result) => ({ - stepId: result.stepId, - type: bundleSimulations.find((sim) => sim.stepId === result.stepId)?.type || '', - gasUsed: result.gasUsed, - success: result.success, - error: result.error, - })), - stateOverrides: cumulativeStateOverrides, - }; - } - - // Process successful bundle result - const executedSteps = bundleResult.results.map((result) => { - const stepType = bundleSimulations.find((sim) => sim.stepId === result.stepId)?.type || ''; - - logger.info(`DEBUG executeBatchSimulation - Step ${result.stepId} completed:`, { - gasUsed: result.gasUsed, - }); - - return { - stepId: result.stepId, - type: stepType, - gasUsed: result.gasUsed, - success: result.success, - error: result.error, - stateChanges: bundleSimulations.find((sim) => sim.stepId === result.stepId) - ?.stateOverride, - }; - }); - - return { - totalGasUsed: bundleResult.totalGasUsed, - success: true, - steps: executedSteps, - stateOverrides: cumulativeStateOverrides, - simulationMetadata: { - blockNumber: 'latest', - timestamp: new Date().toISOString(), - chainId: chainId.toString(), - }, - }; - } catch (error) { - logger.error('Bundle simulation error:', error as Error); - return this.createFailedResult( - `Bundle simulation failed: ${extractErrorMessage(error, 'bundle simulation')}`, - ); - } - } - - /** - * Merge two state override objects - */ - private mergeStateOverrides(base: StateOverride, additional: StateOverride): StateOverride { - const merged: StateOverride = { ...base }; - - for (const [address, overrides] of Object.entries(additional)) { - if (merged[address]) { - merged[address] = { - ...merged[address], - ...overrides, - storage: { - ...merged[address].storage, - ...overrides.storage, - }, - }; - } else { - merged[address] = overrides; - } - } - - return merged; - } - - /** - * Create a failed simulation result - */ - private createFailedResult(error: string): EnhancedSimulationResult { - return { - totalGasUsed: '0', - success: false, - error, - steps: [], - }; - } -} diff --git a/packages/core/adapters/services/transaction-service.ts b/packages/core/adapters/services/transaction-service.ts deleted file mode 100644 index c15b65f6..00000000 --- a/packages/core/adapters/services/transaction-service.ts +++ /dev/null @@ -1,534 +0,0 @@ -import { ChainAbstractionAdapter } from 'adapters/chain-abstraction-adapter'; - -import { - type EthereumProvider, - type ExecuteParams, - type TransactionOptions, - type TransactionResult, - type ExecutePreparation, - type ChainSwitchResult, - validateContractParams, - encodeContractCall, - getBlockExplorerUrl, - getTransactionHashWithFallback, - waitForTransactionReceipt, - extractErrorMessage, - logger, -} from '@nexus/commons'; - -// Interface for gas estimation result -interface GasEstimationResult { - success: boolean; - gasEstimate?: string; - gasEstimateDecimal?: number; - gasPriceGwei?: string; - estimatedCostEth?: string; - error?: string; - revertReason?: string; -} - -/** - * Service responsible for transaction handling and preparation - */ -export class TransactionService { - constructor(private adapter: ChainAbstractionAdapter) {} - // Flag to enable/disable gas estimation (can be set via constructor or method) - private enableGasEstimation: boolean = true; - - /** - * Enable or disable gas estimation before transaction execution - */ - setGasEstimationEnabled(enabled: boolean): void { - this.enableGasEstimation = enabled; - } - - /** - * Estimate gas for a transaction before execution - */ - async estimateTransactionGas( - provider: EthereumProvider, - transactionParams: { - from: string; - to: string; - data: string; - value: string; - }, - ): Promise { - logger.info('TransactionService - Starting gas estimation...'); - logger.info('TransactionService - Transaction params:', { - from: transactionParams.from, - to: transactionParams.to, - data: transactionParams.data.slice(0, 50) + '...', // Truncate for logging - value: transactionParams.value, - }); - - try { - // Step 1: Estimate gas - const gasEstimate = (await provider.request({ - method: 'eth_estimateGas', - params: [transactionParams], - })) as string; - - const gasEstimateDecimal = parseInt(gasEstimate, 16); - - logger.info('TransactionService - Gas estimation successful:', { - gasEstimateHex: gasEstimate, - gasEstimateDecimal: gasEstimateDecimal, - gasEstimateFormatted: gasEstimateDecimal.toLocaleString(), - }); - - // Step 2: Get current gas price for cost calculation - let gasPriceGwei: string | undefined; - let estimatedCostEth: string | undefined; - - try { - const gasPrice = (await provider.request({ - method: 'eth_gasPrice', - })) as string; - - const gasPriceDecimal = parseInt(gasPrice, 16); - const estimatedCostWei = gasEstimateDecimal * gasPriceDecimal; - const estimatedCostEthNum = estimatedCostWei / 1e18; - - gasPriceGwei = (gasPriceDecimal / 1e9).toFixed(4) + ' gwei'; - estimatedCostEth = estimatedCostEthNum.toFixed(8) + ' ETH'; - - logger.info('TransactionService - Gas cost estimation:', { - gasPriceHex: gasPrice, - gasPriceGwei: gasPriceGwei, - estimatedCostWei: estimatedCostWei.toString(), - estimatedCostEth: estimatedCostEth, - }); - } catch (gasPriceError) { - logger.warn('TransactionService - Failed to get gas price:', gasPriceError); - } - - return { - success: true, - gasEstimate, - gasEstimateDecimal, - gasPriceGwei, - estimatedCostEth, - }; - } catch (gasEstimateError) { - logger.error('TransactionService - Gas estimation failed:', gasEstimateError as Error); - - // Extract revert reason if available - let revertReason: string | undefined; - let errorMessage = 'Gas estimation failed'; - - if (gasEstimateError && typeof gasEstimateError === 'object') { - if ('data' in gasEstimateError && gasEstimateError.data) { - logger.error( - 'TransactionService - Gas estimation revert data:', - gasEstimateError.data as string, - ); - revertReason = JSON.stringify(gasEstimateError.data); - } - if ('message' in gasEstimateError && gasEstimateError.message) { - errorMessage = gasEstimateError.message as string; - logger.error('TransactionService - Gas estimation error message:', errorMessage); - - // Extract common revert patterns - if (errorMessage.includes('execution reverted')) { - const revertMatch = errorMessage.match(/execution reverted:?\s*(.+)/i); - if (revertMatch && revertMatch[1]) { - revertReason = revertMatch[1].trim(); - } else { - revertReason = 'Transaction would revert (no reason provided)'; - } - } else if (errorMessage.includes('insufficient funds')) { - revertReason = 'Insufficient funds for gas * price + value'; - } else if (errorMessage.includes('out of gas')) { - revertReason = 'Transaction would run out of gas'; - } - } - } - - return { - success: false, - error: errorMessage, - revertReason, - }; - } - } - - /** - * Ensure we're on the correct chain, switch if needed - */ - async ensureCorrectChain(targetChainId: number): Promise { - try { - const currentChainId = await this.adapter.nexusSDK.getEVMClient().getChainId(); - - if (currentChainId !== targetChainId) { - try { - await this.adapter.nexusSDK.getEVMClient().switchChain({ id: targetChainId }); - return { success: true }; - } catch (switchError) { - if ( - switchError && - typeof switchError === 'object' && - 'code' in switchError && - switchError.code === 4902 - ) { - throw new Error( - `Chain ${targetChainId} is not configured in wallet. Please add it manually.`, - ); - } - throw switchError; - } - } - return { success: true }; - } catch (error) { - return { - success: false, - error: extractErrorMessage(error, 'chain switching'), - }; - } - } - - /** - * Prepare execution by validating parameters and encoding function call - */ - async prepareExecution(params: ExecuteParams): Promise { - // Get the from address first (needed for callback) - const fromAddress = await this.adapter.nexusSDK.getEVMClient().getAddresses(); - - if (!fromAddress || fromAddress.length === 0) { - throw new Error('No accounts available'); - } - - // Ensure we're on the correct chain - const chainResult = await this.ensureCorrectChain(params.toChainId); - if (!chainResult.success) { - throw new Error(`Failed to switch to chain ${params.toChainId}: ${chainResult.error}`); - } - - // Call buildFunctionParams callback to get the actual function parameters - // For ETH transactions, provide ETH as token and 0 as amount if tokenApproval is undefined - const token = params.tokenApproval?.token || 'ETH'; - const amount = params.tokenApproval?.amount || '0'; - - const { functionParams, value: callbackValue } = params.buildFunctionParams( - token, - amount, - params.toChainId, - fromAddress[0] as `0x${string}`, - ); - - // Validate contract parameters with built function params - const validation = validateContractParams({ - contractAddress: params.contractAddress, - contractAbi: params.contractAbi, - functionName: params.functionName, - functionParams, - chainId: params.toChainId, - }); - - if (!validation.isValid) { - throw new Error(`Invalid contract parameters: ${validation.error}`); - } - - // Encode the function call - const encodingResult = encodeContractCall({ - contractAbi: params.contractAbi, - functionName: params.functionName, - functionParams, - }); - - if (!encodingResult.success) { - throw new Error(`Failed to encode contract call: ${encodingResult.error}`); - } - - return { - provider: this.adapter.nexusSDK.getEVMProviderWithCA(), - fromAddress: fromAddress[0], - encodedData: encodingResult.data!, - value: callbackValue, - }; - } - - /** - * Send transaction with enhanced error handling and polling support - */ - async sendTransaction( - provider: EthereumProvider, - fromAddress: string, - contractAddress: string, - encodedData: `0x${string}`, - value: string, - options: TransactionOptions, - ): Promise<`0x${string}`> { - // Normalize value to 0x-hex string in wei - const normalizedValue = (() => { - if (!value) return '0x0'; - if (typeof value === 'string' && value.startsWith('0x')) return value; - try { - return `0x${BigInt(value).toString(16)}`; - } catch { - // If parsing fails, default to 0x0 to avoid provider rejection; gas estimation will catch issues - return '0x0'; - } - })(); - - const transactionParams = { - from: fromAddress, - to: contractAddress, - data: encodedData, - value: normalizedValue || '0x0', - }; - - try { - // Perform gas estimation if enabled - if (this.enableGasEstimation) { - logger.info('TransactionService - Performing pre-execution gas estimation...'); - const gasEstimation = await this.estimateTransactionGas(provider, transactionParams); - - if (!gasEstimation.success) { - logger.error( - 'TransactionService - Pre-execution gas estimation failed:', - gasEstimation.error, - ); - - if (gasEstimation.revertReason) { - logger.warn( - `TransactionService - Transaction will likely fail: ${gasEstimation.revertReason}`, - ); - throw new Error(`Transaction simulation failed: ${gasEstimation.revertReason}`); - } - } else { - logger.info('TransactionService - Gas estimation completed successfully:', { - gasEstimate: gasEstimation.gasEstimate, - estimatedCost: gasEstimation.estimatedCostEth, - gasPrice: gasEstimation.gasPriceGwei, - }); - } - } else { - logger.info('TransactionService - Gas estimation disabled, proceeding with transaction'); - } - - logger.info('TransactionService - Sending transaction...'); - const response = await provider.request({ - method: 'eth_sendTransaction', - params: [transactionParams], - }); - - // Get transaction hash with fallback polling - const hashResult = await getTransactionHashWithFallback(provider, response, { - enablePolling: options.enableTransactionPolling, - timeout: options.transactionTimeout, - fromAddress, - }); - - if (!hashResult.success || !hashResult.hash) { - throw new Error( - hashResult.error || 'Failed to retrieve transaction hash from provider response', - ); - } - - logger.info('TransactionService - Transaction sent successfully:', { - transactionHash: hashResult.hash, - }); - - return hashResult.hash; - } catch (error) { - // Enhanced error handling for common transaction failures - if (error && typeof error === 'object' && 'code' in error) { - if (error.code === 4001) { - throw new Error('Transaction rejected by user'); - } else if (error.code === -32000) { - throw new Error('Insufficient funds for transaction'); - } else if (error.code === -32603) { - throw new Error('Internal JSON-RPC error during transaction'); - } - } - - throw new Error(`Transaction failed: ${extractErrorMessage(error, 'transaction')}`); - } - } - - /** - * Handle transaction confirmation with receipt and confirmations - */ - async handleTransactionConfirmation( - provider: EthereumProvider, - transactionHash: `0x${string}`, - options: TransactionOptions, - chainId: number, - ): Promise { - if (!options.waitForReceipt) { - return {}; - } - - try { - const receiptResult = await waitForTransactionReceipt( - provider, - transactionHash, - { - timeout: options.receiptTimeout, - requiredConfirmations: options.requiredConfirmations, - }, - chainId, - ); - - if (!receiptResult.success) { - logger.warn(`Failed to get transaction receipt: ${receiptResult.error}`); - return {}; - } - - return { - receipt: receiptResult.receipt, - confirmations: receiptResult.confirmations, - gasUsed: receiptResult.receipt?.gasUsed?.toString(), - effectiveGasPrice: receiptResult.receipt?.effectiveGasPrice?.toString(), - }; - } catch (error) { - logger.warn(`Receipt retrieval failed: ${extractErrorMessage(error, 'receipt retrieval')}`); - return {}; - } - } - - /** - * Build execute result with transaction information - */ - buildExecuteResult(transactionHash: string, chainId: number, receiptInfo: TransactionResult) { - return { - transactionHash, - explorerUrl: getBlockExplorerUrl(chainId, transactionHash), - chainId, - ...receiptInfo, - }; - } - - /** - * Direct native token transfer (ETH, MATIC, AVAX, etc.) - */ - async transferNativeToken( - provider: EthereumProvider, - fromAddress: string, - toAddress: string, - amount: string, // Amount in human-readable format (e.g., "0.1") - decimals: number = 18, - ): Promise<{ - success: boolean; - hash?: `0x${string}`; - error?: string; - }> { - const { parseUnits } = await import('viem'); - - const valueInWei = parseUnits(amount, decimals); - const transactionParams = { - from: fromAddress, - to: toAddress, - data: '0x', - value: `0x${valueInWei.toString(16)}`, - }; - - try { - // Perform gas estimation if enabled - if (this.enableGasEstimation) { - logger.info('TransactionService - Performing gas estimation for native token transfer...'); - const gasEstimation = await this.estimateTransactionGas(provider, transactionParams); - - if (!gasEstimation.success) { - logger.error( - 'TransactionService - Gas estimation failed for native token transfer:', - gasEstimation.error, - ); - throw new Error(`Native token transfer gas estimation failed: ${gasEstimation.error}`); - } - - logger.info('TransactionService - Native token transfer gas estimation successful:', { - gasEstimate: gasEstimation.gasEstimate, - estimatedCost: gasEstimation.estimatedCostEth, - }); - } - - logger.info('TransactionService - Sending native token transfer...'); - const response = await provider.request({ - method: 'eth_sendTransaction', - params: [transactionParams], - }); - - const transactionHash = getTransactionHashWithFallback(provider, response); - logger.info('TransactionService - Native token transfer sent successfully:', transactionHash); - return transactionHash; - } catch (error) { - logger.error('TransactionService - Native token transfer failed:', error as Error); - throw new Error( - `Native token transfer failed: ${extractErrorMessage(error, 'native transfer')}`, - ); - } - } - - /** - * Direct ERC20 token transfer - */ - async transferERC20Token( - provider: EthereumProvider, - fromAddress: string, - tokenAddress: string, - toAddress: string, - amount: string, // Amount in human-readable format (e.g., "100") - decimals: number = 18, - ): Promise<{ - success: boolean; - hash?: `0x${string}`; - error?: string; - }> { - const { parseUnits } = await import('viem'); - - try { - const amountInWei = parseUnits(amount, decimals); - - // ERC20 transfer function selector: transfer(address,uint256) - const transferSelector = '0xa9059cbb'; - const paddedRecipient = toAddress.slice(2).padStart(64, '0'); - const paddedAmount = amountInWei.toString(16).padStart(64, '0'); - const transferData = `${transferSelector}${paddedRecipient}${paddedAmount}`; - - const transactionParams = { - from: fromAddress, - to: tokenAddress, - data: transferData, - value: '0x0', - }; - - // Perform gas estimation if enabled - if (this.enableGasEstimation) { - logger.info('TransactionService - Performing gas estimation for ERC20 transfer...'); - const gasEstimation = await this.estimateTransactionGas(provider, transactionParams); - - if (!gasEstimation.success) { - logger.error( - 'TransactionService - Gas estimation failed for ERC20 transfer:', - gasEstimation.error, - ); - - if (gasEstimation.revertReason) { - throw new Error(`ERC20 transfer will fail: ${gasEstimation.revertReason}`); - } - throw new Error(`ERC20 transfer gas estimation failed: ${gasEstimation.error}`); - } - - logger.info('TransactionService - ERC20 transfer gas estimation successful:', { - gasEstimate: gasEstimation.gasEstimate, - estimatedCost: gasEstimation.estimatedCostEth, - }); - } - - logger.info('TransactionService - Sending ERC20 transfer...'); - const response = await provider.request({ - method: 'eth_sendTransaction', - params: [transactionParams], - }); - - const transactionHash = getTransactionHashWithFallback(provider, response); - logger.info('TransactionService - ERC20 transfer sent successfully:', transactionHash); - return transactionHash; - } catch (error) { - logger.error('TransactionService - ERC20 transfer failed:', error as Error); - throw new Error(`ERC20 transfer failed: ${extractErrorMessage(error, 'ERC20 transfer')}`); - } - } -} diff --git a/packages/core/index.ts b/packages/core/index.ts index c7eeaed4..a54e289d 100644 --- a/packages/core/index.ts +++ b/packages/core/index.ts @@ -1,6 +1,6 @@ // Core SDK entry point - headless, no React dependencies export { NexusSDK } from './sdk/index'; - +export { NexusError, ERROR_CODES } from './sdk/ca-base/nexusError'; // Re-export types from commons for convenience export type { BridgeParams, @@ -31,8 +31,6 @@ export type { SUPPORTED_TOKENS, ChainMetadata, TokenMetadata, - ProgressStep, - ProgressSteps, } from '@nexus/commons'; export { @@ -45,9 +43,9 @@ export { MAINNET_CHAINS, TOKEN_CONTRACT_ADDRESSES, DESTINATION_SWAP_TOKENS, + BRIDGE_STEPS, + SWAP_STEPS, } from '@nexus/commons'; -export type { SwapStep } from './sdk/ca-base'; - // Re-export everything from commons (includes constants, utils, and types) export * from '@nexus/commons'; diff --git a/packages/core/integrations/tenderly.ts b/packages/core/integrations/tenderly.ts index 0c0b90c7..020a5a3c 100644 --- a/packages/core/integrations/tenderly.ts +++ b/packages/core/integrations/tenderly.ts @@ -1,17 +1,15 @@ -import { formatEther, hexToBigInt } from 'viem'; import { type ApiResponse, type BackendConfig, type ChainSupportResponse, - type GasEstimationRequest, - type GasEstimationResponse, type HealthCheckResponse, type ServiceStatusResponse, type BundleSimulationRequest, - type BundleSimulationResponse, type BackendBundleResponse, } from './types'; -import { CHAIN_METADATA, logger } from '@nexus/commons'; +import { logger } from '@nexus/commons'; +import axios from 'axios'; +import { Errors } from 'sdk/ca-base/errors'; /** * Backend simulation result interface @@ -148,190 +146,27 @@ export class BackendSimulationClient { } } - /** - * Simulate transaction using Tenderly's Gateway RPC with state overrides - * This provides more accurate simulation results than basic gas estimation - */ - async simulate(request: GasEstimationRequest): Promise { - try { - const response = await fetch(`${this.baseUrl}/api/gas-estimation/simulate`, { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify(request), - }); - - if (!response.ok) { - const errorText = await response.text(); - throw new Error(`Simulation API error: ${response.status} - ${errorText}`); - } - - const result: ApiResponse = await response.json(); - - if (!result.success || !result.data) { - throw new Error(result.error || result.message || 'Simulation failed'); - } - - const gasData = result.data; - - return { - gasUsed: gasData.gasUsed, - gasPrice: gasData.gasPrice || '0x0', - maxFeePerGas: gasData.maxFeePerGas, - maxPriorityFeePerGas: gasData.maxPriorityFeePerGas, - success: true, - estimatedCost: { - totalFee: gasData?.gasUsed || '0', - }, - }; - } catch (error) { - logger.error('Simulation API error:', error as Error); - return { - gasUsed: '0x0', - gasPrice: '0x0', - success: false, - errorMessage: error instanceof Error ? error.message : 'Unknown error', - estimatedCost: { - totalFee: '0', - }, - }; - } - } - - /** - * Fetch current gas price via RPC - */ - private async getCurrentGasPrice(chainId: string): Promise { - try { - const rpcUrl = this.getRpcUrl(chainId); - - const response = await fetch(rpcUrl, { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify({ - jsonrpc: '2.0', - method: 'eth_gasPrice', - params: [], - id: 1, - }), - }); - - if (!response.ok) { - throw new Error(`RPC request failed: ${response.status}`); - } - - const result = await response.json(); - - if (result.error) { - throw new Error(`RPC error: ${result.error.message}`); - } - - // Convert hex gas price to bigint - return hexToBigInt(result.result); - } catch (error) { - logger.warn('Failed to fetch current gas price, using fallback:', error); - // Fallback to 20 gwei if RPC call fails - return BigInt('20000000000'); // 20 gwei in wei - } - } + async simulateBundleV2(request: BundleSimulationRequest) { + logger.info('DEBUG simulateBundle - request:', JSON.stringify(request, null, 2)); - /** - * Get RPC URL for a given chain ID using CHAIN_METADATA - */ - private getRpcUrl(chainId: string): string { - const chainIdNum = parseInt(chainId, 10); - const chainMetadata = CHAIN_METADATA[chainIdNum]; + const { data } = await axios.post( + new URL(`/api/gas-estimation/bundle`, this.baseUrl).href, + request, + ); - if (!chainMetadata || !chainMetadata.rpcUrls || chainMetadata.rpcUrls.length === 0) { - throw new Error(`No RPC URL available for chain ${chainId}`); + if (!data.success || !data.data) { + throw Errors.simulationError(data.message ?? 'Bundle simulation failed'); } - // Use the first RPC URL from the metadata - return chainMetadata.rpcUrls[0]; - } + const gasUsed = data.data.reduce((acc, d) => { + return acc + BigInt(d.gasUsed); + }, 0n); - async simulateBundle(request: BundleSimulationRequest): Promise { - try { - logger.info('DEBUG simulateBundle - request:', JSON.stringify(request, null, 2)); - - const response = await fetch(`${this.baseUrl}/api/gas-estimation/bundle`, { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify(request), - }); - - if (!response.ok) { - const errorText = await response.text(); - throw new Error(`Bundle simulation API error: ${response.status} - ${errorText}`); - } - - const result: BackendBundleResponse = await response.json(); - - if (!result.success || !result.data) { - throw new Error(result.message || 'Bundle simulation failed'); - } - - logger.info('DEBUG simulateBundle - backend response:', result); - - // Fetch current gas price via RPC - const currentGasPrice = await this.getCurrentGasPrice(request.chainId); - logger.info('DEBUG - Raw gas price from RPC (wei):', currentGasPrice.toString()); - logger.info('DEBUG - Gas price in gwei:', (Number(currentGasPrice) / 1e9).toFixed(2)); - logger.info('DEBUG - Chain ID:', request.chainId); - - // Transform backend response to human-readable format - const transformedResults = result.data.map((item, index) => { - const gasUsed = hexToBigInt(item.gasUsed); - logger.info('DEBUG - Gas used (units):', gasUsed.toString()); - const gasCostWei = gasUsed * currentGasPrice; - logger.info('DEBUG - Gas cost (wei):', gasCostWei.toString()); - const gasCostEther = formatEther(gasCostWei); - - return { - stepId: request.simulations[index]?.stepId || `step-${index}`, - gasUsed: gasCostEther, // Human-readable cost like "0.004205" - success: true, - error: undefined, - }; - }); - - // Calculate total cost - const totalGasCostWei = result.data.reduce((sum, item) => { - const gasUsed = hexToBigInt(item.gasUsed); - return sum + gasUsed * currentGasPrice; - }, BigInt(0)); - - const totalGasCostEther = formatEther(totalGasCostWei); - - logger.info('DEBUG simulateBundle - transformed response:', { - results: transformedResults, - totalGasUsed: totalGasCostEther, - gasPriceUsed: formatEther(currentGasPrice * BigInt(1000000000)) + ' gwei', - }); + const gasLimit = data.data.reduce((acc, d) => { + return acc + BigInt(d.gasLimit); + }, 0n); - return { - success: true, - results: transformedResults, - totalGasUsed: totalGasCostEther, - }; - } catch (error) { - logger.error('Bundle simulation API error:', error as Error); - return { - success: false, - results: request.simulations.map((sim) => ({ - stepId: sim.stepId, - gasUsed: '0.0', - success: false, - error: error instanceof Error ? error.message : 'Unknown error', - })), - totalGasUsed: '0.0', - }; - } + return { gasUsed, gasLimit }; } } diff --git a/packages/core/package.json b/packages/core/package.json index 54ab0af8..c04bdb80 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -1,6 +1,6 @@ { "name": "@avail-project/nexus-core", - "version": "0.0.2", + "version": "1.0.0-beta.26", "description": "Nexus headless SDK for cross-chain transactions", "main": "./dist/index.js", "module": "./dist/index.esm.js", @@ -37,32 +37,34 @@ "author": "decocereus", "license": "MIT", "dependencies": { - "@arcana/ca-common": "1.0.1-alpha.6", + "@avail-project/ca-common": "1.0.0-beta.7", "@cosmjs/proto-signing": "^0.34.0", "@cosmjs/stargate": "^0.34.0", "@metamask/safe-event-emitter": "3.1.2", "@starkware-industries/starkware-crypto-utils": "^0.2.1", - "axios": "^1.7.7", + "@tronweb3/tronwallet-abstract-adapter": "^1.1.9", + "axios": "^1.12.2", "decimal.js": "^10.6.0", - "es-toolkit": "^1.39.8", + "es-toolkit": "^1.40.0", "fuels": "0.101.1", "it-ws": "^6.1.5", "long": "^5.3.2", - "msgpackr": "^1.11.4", + "msgpackr": "^1.11.5", + "tronweb": "^6.0.4", "tslib": "2.8.1" }, "devDependencies": { - "@rollup/plugin-commonjs": "^25.0.0", + "@rollup/plugin-commonjs": "^25.0.8", "@rollup/plugin-json": "6.1.0", - "@rollup/plugin-node-resolve": "^15.0.0", - "@rollup/plugin-typescript": "^11.0.0", - "rollup": "^4.0.0", - "rollup-plugin-dts": "^6.0.0", + "@rollup/plugin-node-resolve": "^15.3.1", + "@rollup/plugin-typescript": "^11.1.6", + "rollup": "^4.52.4", + "rollup-plugin-dts": "^6.2.3", "rollup-plugin-typescript2": "0.36.0", - "typescript": "^5.0.0" + "typescript": "^5.9.3" }, "peerDependencies": { - "viem": "^2.0.0" + "viem": "^2.31.7" }, "publishConfig": { "access": "public" diff --git a/packages/core/rollup.config.mjs b/packages/core/rollup.config.mjs index d1797a64..09894fbf 100644 --- a/packages/core/rollup.config.mjs +++ b/packages/core/rollup.config.mjs @@ -5,8 +5,7 @@ import json from '@rollup/plugin-json'; import alias from '@rollup/plugin-alias'; import dts from 'rollup-plugin-dts'; import { defineConfig } from 'rollup'; -import { createRequire } from 'module'; - +import { createRequire } from 'node:module'; const require = createRequire(import.meta.url); const packageJson = require('./package.json'); @@ -42,7 +41,10 @@ const baseConfig = { ...Object.keys(packageJson.peerDependencies || {}), /^viem/, // External dependencies that consumers should install - '@arcana/ca-common', + '@avail-project/ca-common', + '@tronweb3/tronwallet-abstract-adapter', + // Ensure TronWeb is not bundled to preserve its side-effectful proto setup + 'tronweb', '@cosmjs/proto-signing', '@cosmjs/stargate', '@starkware-industries/starkware-crypto-utils', @@ -58,7 +60,8 @@ const baseConfig = { './commons', ], treeshake: { - moduleSideEffects: false, + // Preserve side effects for external deps like tronweb that rely on global proto init + moduleSideEffects: 'no-external', propertyReadSideEffects: false, unknownGlobalSideEffects: false, }, @@ -116,6 +119,8 @@ export default defineConfig([ /^@cosmjs/, /^@starkware-industries/, '@metamask/safe-event-emitter', + '@tronweb3/tronwallet-abstract-adapter', + 'tronweb', 'decimal.js', 'fuels', 'long', diff --git a/packages/core/sdk/ca-base/abi/vault.ts b/packages/core/sdk/ca-base/abi/vault.ts index 5d18a0fc..5f5b26b5 100644 --- a/packages/core/sdk/ca-base/abi/vault.ts +++ b/packages/core/sdk/ca-base/abi/vault.ts @@ -3,25 +3,25 @@ const FillEvent = { inputs: [ { indexed: true, - internalType: "bytes32", - name: "requestHash", - type: "bytes32", + internalType: 'bytes32', + name: 'requestHash', + type: 'bytes32', }, { indexed: false, - internalType: "address", - name: "from", - type: "address", + internalType: 'address', + name: 'from', + type: 'address', }, { indexed: false, - internalType: "address", - name: "solver", - type: "address", + internalType: 'address', + name: 'solver', + type: 'address', }, ], - name: "Fill", - type: "event", + name: 'Fulfilment', + type: 'event', } as const; export { FillEvent }; diff --git a/packages/core/sdk/ca-base/ca.ts b/packages/core/sdk/ca-base/ca.ts index dc83cee8..09ef8108 100644 --- a/packages/core/sdk/ca-base/ca.ts +++ b/packages/core/sdk/ca-base/ca.ts @@ -1,16 +1,7 @@ -import { createCosmosWallet } from '@arcana/ca-common'; +import { createCosmosWallet, Universe } from '@avail-project/ca-common'; import { DirectSecp256k1Wallet } from '@cosmjs/proto-signing'; -import SafeEventEmitter from '@metamask/safe-event-emitter'; import { keyDerivation } from '@starkware-industries/starkware-crypto-utils'; -import { - Account, - CHAIN_IDS, - FuelConnector, - FuelConnectorSendTxParams, - Provider, - TransactionRequestLike, - TransactionResponse, -} from 'fuels'; +import { Account, FuelConnector, Provider } from 'fuels'; import { createWalletClient, custom, @@ -19,53 +10,65 @@ import { type PublicActions, Client, CustomTransport, + Hex, } from 'viem'; import { privateKeyToAccount, PrivateKeyAccount } from 'viem/accounts'; import { createSiweMessage } from 'viem/siwe'; import { ChainList } from './chains'; import { getNetworkConfig } from './config'; import { FUEL_NETWORK_URL } from './constants'; -import { getLogger, LOG_LEVEL, setLogLevel } from './logger'; -import { AllowanceQuery, BridgeQuery, TransferQuery } from './query'; -import { fixTx } from './requestHandlers/fuel/common'; -import { getFuelProvider } from './requestHandlers/fuel/provider'; -import { createHandler } from './requestHandlers/router'; import { - BridgeQueryInput, + getLogger, + LOG_LEVEL, + setLogLevel, + Chain, + TransferParams, + BridgeParams, +} from '@nexus/commons'; +import { createBridgeParams } from './requestHandlers/helpers'; +import { ChainListType, EthereumProvider, - EVMTransaction, ExactInSwapInput, ExactOutSwapInput, NetworkConfig, NexusNetwork, OnAllowanceHook, OnIntentHook, - RequestArguments, SDKConfig, - SwapInputOptionalParams, SwapMode, SwapParams, - SupportedChainsResult, - TransferQueryInput, - TxOptions, + BridgeAndExecuteParams, + ExecuteParams, + OnEventParam, + OnSwapIntentHook, + TronAdapter, } from '@nexus/commons'; import { cosmosFeeGrant, - equalFold, fetchMyIntents, getSDKConfig, getSupportedChains, - getTxOptions, isArcanaWallet, - isEVMTx, minutesToMs, refundExpiredIntents, + tronHexToEvmAddress, + getBalances, + retrieveSIWESignatureFromLocalStorage, + storeSIWESignatureToLocalStorage, + getBalancesForSwap, switchChain, + intentTransform, } from './utils'; import { swap } from './swap/swap'; -import { getBalances } from './swap/route'; import { getSwapSupportedChains } from './swap/utils'; +import { utils } from 'tronweb'; +import BridgeHandler from './requestHandlers/bridge'; +import { BridgeAndExecuteQuery } from './query/bridgeAndExecute'; +import { BackendSimulationClient, createBackendSimulationClient } from 'integrations/tenderly'; +import { createBridgeAndTransferParams } from './query/bridgeAndTransfer'; +import getMaxValueForBridge from './requestHandlers/bridgeMax'; +import { Errors } from './errors'; setLogLevel(LOG_LEVEL.NOLOGS); const logger = getLogger(); @@ -80,73 +83,93 @@ const SIWE_STATEMENT = 'Sign in to enable Nexus'; export class CA { static getSupportedChains = getSupportedChains; - protected _caEvents = new SafeEventEmitter(); - #cosmosWallet?: DirectSecp256k1Wallet; + #cosmos?: { + wallet: DirectSecp256k1Wallet; + address: string; + }; #ephemeralWallet?: PrivateKeyAccount; public chainList: ChainListType; protected _config: Required; protected _evm?: { client: Client; - modProvider: EthereumProvider; provider: EthereumProvider; + address: Hex; }; protected _fuel?: { account: Account; address: string; connector: FuelConnector; - modConnector: FuelConnector; - modProvider: Provider; provider: Provider; }; + protected _tron?: { + address: string; + adapter: TronAdapter; + }; protected _hooks: { onAllowance: OnAllowanceHook; onIntent: OnIntentHook; + onSwapIntent: OnSwapIntentHook; } = { onAllowance: (data) => data.allow(data.sources.map(() => 'max')), onIntent: (data) => data.allow(), + onSwapIntent: (data) => data.allow(), }; - protected _initPromises: (() => void)[] = []; protected _initStatus = INIT_STATUS.CREATED; protected _isArcanaProvider = false; protected _networkConfig: NetworkConfig; protected _refundInterval: number | undefined; + protected _initPromise: Promise | null = null; + private simulationClient: BackendSimulationClient; + protected constructor( config: { network?: NexusNetwork; debug?: boolean } = { debug: false, network: 'testnet' }, ) { this._config = getSDKConfig(config); this._networkConfig = getNetworkConfig(this._config.network); this.chainList = new ChainList(this._networkConfig.NETWORK_HINT); + this.simulationClient = createBackendSimulationClient({ + baseUrl: 'https://nexus-backend.avail.so', + }); + if (this._config.debug) { setLogLevel(LOG_LEVEL.DEBUG); } } - protected _allowance() { + protected createBridgeHandler = (input: BridgeParams, options?: OnEventParam) => { if (!this._evm) { - throw new Error('EVM provider is not set'); + throw Errors.sdkNotInitialized(); } - return new AllowanceQuery(this._evm.client, this._networkConfig, this.chainList); - } + const params = createBridgeParams(input, this.chainList); + this.universeCheck(params.dstChain); - protected async _bridge(input: BridgeQueryInput) { - const bq = new BridgeQuery( - input, - this._init, - this._changeChain.bind(this), - this._createEVMHandler.bind(this), - this._createFuelHandler.bind(this), - await this._getEVMAddress(), - this.chainList, - this._fuel?.account, - ); + const bridgeHandler = new BridgeHandler(params, { + chainList: this.chainList, + cosmos: this.#cosmos!, + fuel: this._fuel, + evm: this._evm!, + hooks: this._hooks, + tron: this._tron, + networkConfig: this._networkConfig, + emit: options?.onEvent, + }); - await bq.initHandler(); - return { exec: bq.exec, simulate: bq.simulate }; + return bridgeHandler; + }; + + protected async _calculateMaxForBridge(params: Omit) { + return getMaxValueForBridge(params, { + chainList: this.chainList, + fuel: this._fuel, + evm: this._evm!, + tron: this._tron, + networkConfig: this._networkConfig, + }); } protected _deinit = () => { - this.#cosmosWallet = undefined; + this.#cosmos = undefined; if (this._evm) { this._evm.provider.removeListener('accountsChanged', this.onAccountsChanged); } @@ -157,41 +180,18 @@ export class CA { this._initStatus = INIT_STATUS.CREATED; }; - protected _getEVMProviderWithCA = () => { - if (!this._evm) { - throw new Error('EVM provider is not set'); - } - - return this._evm.modProvider; - }; - - protected async _getFuelWithCA() { - if (!this._fuel) { - throw new Error('Fuel connector is not set.'); - } - - return { - connector: this._fuel.modConnector, - provider: this._fuel.modProvider, - }; - } - protected async _getMyIntents(page = 1) { - const wallet = await this._getCosmosWallet(); + const { wallet } = await this._getCosmosWallet(); const address = (await wallet.getAccounts())[0].address; - return fetchMyIntents(address, this._networkConfig.GRPC_URL, page); - } - - protected async _getUnifiedBalance(symbol: string, includeSwappableBalances = false) { - const balances = await this._getUnifiedBalances(includeSwappableBalances); - - return balances.find((s) => equalFold(s.symbol, symbol)); + const rffList = await fetchMyIntents(address, this._networkConfig.GRPC_URL, page); + return intentTransform(rffList, this.chainList); } - protected async _getUnifiedBalances(includeSwappableBalances = false) { - if (!this._evm) { - throw new Error('CA not initialized'); + protected _getUnifiedBalances = async (includeSwappableBalances = false) => { + if (!this._evm || this._initStatus !== INIT_STATUS.DONE) { + throw Errors.sdkNotInitialized(); } + const { assets } = await getBalances({ networkHint: this._networkConfig.NETWORK_HINT, evmAddress: (await this._evm.client.requestAddresses())[0], @@ -200,44 +200,58 @@ export class CA { isCA: includeSwappableBalances === false, vscDomain: this._networkConfig.VSC_DOMAIN, fuelAddress: this._fuel?.address, + tronAddress: this._tron?.address, }); return assets; - } + }; + + protected _getBalancesForSwap = async () => { + if (!this._evm) { + throw Errors.sdkNotInitialized(); + } + + const balances = await getBalancesForSwap({ + evmAddress: (await this._evm.client.requestAddresses())[0], + chainList: this.chainList, + }); + return balances; + }; protected _isInitialized() { return this._initStatus === INIT_STATUS.DONE; } - protected async _swapWithExactIn(input: ExactInSwapInput, options?: SwapInputOptionalParams) { + protected async _swapWithExactIn(input: ExactInSwapInput, options?: OnEventParam) { return swap( { mode: SwapMode.EXACT_IN, data: input, }, - await this.getCommonSwapParams(options), + await this.getSwapOptions(options), ); } - protected async _swapWithExactOut(input: ExactOutSwapInput, options?: SwapInputOptionalParams) { + protected async _swapWithExactOut(input: ExactOutSwapInput, options?: OnEventParam) { return swap( { mode: SwapMode.EXACT_OUT, data: input, }, - await this.getCommonSwapParams(options), + await this.getSwapOptions(options), ); } - private async getCommonSwapParams(options?: SwapInputOptionalParams): Promise { + private async getSwapOptions(options?: OnEventParam): Promise { return { - emit: this._caEvents.emit.bind(this._caEvents), + onSwapIntent: this._hooks.onSwapIntent, + onEvent: options?.onEvent, chainList: this.chainList, address: { - cosmos: (await this.#cosmosWallet!.getAccounts())[0].address, + cosmos: this.#cosmos!.address, eoa: (await this._evm!.client.getAddresses())[0], ephemeral: this.#ephemeralWallet!.address, }, wallet: { - cosmos: this.#cosmosWallet!, + cosmos: this.#cosmos!.wallet, ephemeral: this.#ephemeralWallet!, eoa: this._evm!.client, }, @@ -246,50 +260,44 @@ export class CA { }; } - protected async _handleEVMTx(args: RequestArguments, options: Partial = {}) { - const response = await this._createEVMHandler( - (args.params as EVMTransaction[])[0], - getTxOptions(options), - ); - - if (response) { - await response.handler?.process(); - return response.processTx(); + protected _init = () => { + if (!this._evm) { + throw Errors.sdkNotInitialized(); + } + // Return existing promise if initialization already started or done + if (this._initStatus === INIT_STATUS.RUNNING || this._initStatus === INIT_STATUS.DONE) { + return this._initPromise!; } - return; - } - protected _init = async () => { - if (!this._evm) { - throw new Error('use setEVMProvider before calling init()'); + // Prevent concurrent initializations + if (this._initStatus !== INIT_STATUS.CREATED) { + throw new Error(`Unexpected init state: ${this._initStatus}`); } - if (this._initStatus === INIT_STATUS.CREATED) { - this._initStatus = INIT_STATUS.RUNNING; - try { - const address = await this._getEVMAddress(); - this._setProviderHooks(); - if (!this._isArcanaProvider) { - this.#cosmosWallet = await this._createCosmosWallet(); - this._checkPendingRefunds(); - } + this._initStatus = INIT_STATUS.RUNNING; + this._initPromise = (async () => { + try { + this._setProviderHooks(); + this.#cosmos = await this._createCosmosWallet(); + this._checkPendingRefunds(); this._initStatus = INIT_STATUS.DONE; - this._resolveInitPromises(); - this._caEvents.emit('accountsChanged', [address]); } catch (e) { this._initStatus = INIT_STATUS.CREATED; logger.error('Error initializing CA', e); - throw new Error('Error initializing CA'); + throw e; } - } else if (this._initStatus === INIT_STATUS.RUNNING) { - return await this._waitForInit(); - } + })(); + + return this._initPromise; }; protected onAccountsChanged = (accounts: Array<`0x${string}`>) => { this._deinit(); if (accounts.length !== 0) { + if (this._evm) { + this._evm.address = accounts[0]; + } this._init(); } }; @@ -298,27 +306,45 @@ export class CA { if (this._evm?.provider === provider) { return; } + const client = createWalletClient({ + transport: custom(provider), + }).extend(publicActions); + + const address = (await client.getAddresses())[0]; this._evm = { - client: createWalletClient({ - transport: custom(provider), - }).extend(publicActions), - modProvider: Object.assign({}, provider, { - request: async (args: RequestArguments): Promise => { - if (args.method === 'eth_sendTransaction') { - if (!this._isArcanaProvider) { - return this._handleEVMTx(args); - } - } - return provider.request(args); - }, - }), + client, provider, + address, }; this._isArcanaProvider = isArcanaWallet(provider); } + public async _setTronAdapter(adapter: TronAdapter) { + if (this._tron) { + logger.debug('Already has tron adapter, so skip', { + adapter, + classVal: this._tron, + }); + return; + } + + if (!adapter.connected) { + await adapter.connect(); + } + + logger.debug('setTronAdapter', { + address: adapter.address, + classVal: this._tron, + }); + + this._tron = { + adapter, + address: tronHexToEvmAddress(utils.address.toHex(adapter.address as string)), + }; + } + protected async _setFuelConnector(connector: FuelConnector) { if (this._fuel?.connector === connector) { return; @@ -338,56 +364,14 @@ export class CA { throw new Error('could not get current account from connector'); } - const modProvider = getFuelProvider( - this._getUnifiedBalances.bind(this), - address, - this.chainList.getChainByID(CHAIN_IDS.fuel.mainnet)!, - ); - const provider = new Provider(FUEL_NETWORK_URL, { resourceCacheTTL: -1, }); - const clone: FuelConnector = Object.create(connector); - clone.sendTransaction = async ( - _address: string, - _transaction: TransactionRequestLike, - _params?: FuelConnectorSendTxParams, - ): Promise => { - logger.debug('fuelClone:sendTransaction:1', { - _address, - _params, - _transaction, - }); - const handlerResponse = await this._createFuelHandler(_transaction, { - bridge: false, - gas: 0n, - }); - - if (handlerResponse) { - await handlerResponse.handler?.process(); - } - - logger.debug('fuelClone:sendTransaction:2', { - request: Object.assign( - { - inputs: [], - }, - _transaction, - ), - }); - - const tx = await fixTx(_address, _transaction, provider); - - return connector.sendTransaction(_address, tx, _params); - }; - this._fuel = { - account: new Account(address, modProvider, connector), + account: new Account(address, provider, connector), address, - connector: connector, - modConnector: clone, - modProvider, + connector, provider, }; } @@ -400,28 +384,27 @@ export class CA { this._hooks.onIntent = hook; } - protected async _transfer(input: TransferQueryInput) { - const tq = new TransferQuery( - input, - this._init, - this._changeChain.bind(this), - this._createEVMHandler.bind(this), - this._createFuelHandler.bind(this), - await this._getEVMAddress(), - this.chainList, - this._fuel?.account, - ); - await tq.initHandler(); - return { exec: tq.exec, simulate: tq.simulate }; + protected _setOnSwapIntentHook(hook: OnSwapIntentHook) { + this._hooks.onSwapIntent = hook; + } + + protected async _bridgeAndTransfer(input: TransferParams, options?: OnEventParam) { + const params = createBridgeAndTransferParams(input, this.chainList); + return this._bridgeAndExecute(params, options); + } + + protected async _simulateBridgeAndTransfer(input: TransferParams) { + const params = createBridgeAndTransferParams(input, this.chainList); + return this._simulateBridgeAndExecute(params); } protected _changeChain(chainID: number) { if (!this._evm) { - throw new Error('EVM provider is not set'); + throw Errors.sdkNotInitialized(); } const chain = this.chainList.getChainByID(chainID); if (!chain) { - throw new Error('chain not supported'); + throw Errors.chainNotFound(chainID); } return switchChain(this._evm.client, chain); @@ -431,10 +414,10 @@ export class CA { await this._init(); const account = await this._getEVMAddress(); try { - await refundExpiredIntents(account, this._networkConfig.COSMOS_URL, this.#cosmosWallet!); + await refundExpiredIntents(account, this._networkConfig.COSMOS_URL, this.#cosmos!.wallet); this._refundInterval = window.setInterval(async () => { - await refundExpiredIntents(account, this._networkConfig.COSMOS_URL, this.#cosmosWallet!); + await refundExpiredIntents(account, this._networkConfig.COSMOS_URL, this.#cosmos!.wallet); }, minutesToMs(10)); } catch (e) { logger.error('Error checking pending refunds', e); @@ -442,140 +425,37 @@ export class CA { } protected async _createCosmosWallet() { - const sig = await this._signatureForLogin(); - const pvtKey = keyDerivation.getPrivateKeyFromEthSignature(sig); + let sig = this._getStoredSIWESignature(this._evm!.address); + if (!sig) { + sig = await this._signatureForLogin(); + this._storeSIWESignature(this._evm!.address, sig); + } - const cosmosWallet = await createCosmosWallet(`0x${pvtKey.padStart(64, '0')}`); + const pvtKey = keyDerivation.getPrivateKeyFromEthSignature(sig); + const wallet = await createCosmosWallet(`0x${pvtKey.padStart(64, '0')}`); this.#ephemeralWallet = privateKeyToAccount(`0x${pvtKey.padStart(64, '0')}`); - const address = (await cosmosWallet.getAccounts())[0].address; + const address = (await wallet.getAccounts())[0].address; await cosmosFeeGrant(this._networkConfig.COSMOS_URL, this._networkConfig.VSC_DOMAIN, address); - return cosmosWallet; - } - - protected async _createEVMHandler(tx: EVMTransaction, options: Partial = {}) { - if (!this._evm) { - throw new Error('EVM provider is not set'); - } - - if (!isEVMTx(tx)) { - logger.debug('invalid evm tx, returning', { tx }); - return null; - } - - const opt = getTxOptions(options); - - const chainId = await this._getChainID(); - const chain = this.chainList.getChainByID(chainId); - if (!chain) { - logger.info('chain not supported, returning', { - chainId, - }); - return null; - } - - return createHandler({ - chain, - chainList: this.chainList, - cosmosWallet: await this._getCosmosWallet(), - evm: { - address: await this._getEVMAddress(), - client: this._evm.client, - tx, - }, - fuel: this._fuel, - hooks: this._hooks, - options: { - emit: this._caEvents.emit.bind(this._caEvents), - networkConfig: this._networkConfig, - ...opt, - }, - }); - } - - public getEVMClient() { - if (!this._evm) { - throw new Error('EVM provider is not set'); - } - return this._evm.client; - } - - protected async _createFuelHandler(tx: TransactionRequestLike, options: Partial = {}) { - const chain = this.chainList.getChainByID(CHAIN_IDS.fuel.mainnet); - if (!chain) { - throw new Error(`chain not found: ${CHAIN_IDS.fuel.mainnet}`); - } - - if (!this._fuel) { - throw new Error('Fuel provider is not connected'); - } - - const address = await this._fuel.connector.currentAccount(); - if (!address) { - throw new Error('could not get current account from connector'); - } - - const opt = getTxOptions(options); - - return createHandler({ - chain, - chainList: this.chainList, - cosmosWallet: await this._getCosmosWallet(), - evm: { - address: await this._getEVMAddress(), - client: this._evm!.client, - }, - fuel: { - address, - connector: this._fuel.connector, - provider: this._fuel.provider, - tx, - }, - hooks: { - onAllowance: this._hooks.onAllowance, - onIntent: this._hooks.onIntent, - }, - options: { - emit: this._caEvents.emit.bind(this._caEvents), - networkConfig: this._networkConfig, - ...opt, - }, - }); - } - - protected _getChainID() { - if (!this._evm) { - throw new Error('EVM provider is not set'); - } - - return this._evm.client.getChainId(); + return { wallet, address }; } protected async _getCosmosWallet() { - if (!this.#cosmosWallet) { - this.#cosmosWallet = await this._createCosmosWallet(); + if (!this.#cosmos) { + this.#cosmos = await this._createCosmosWallet(); } - return this.#cosmosWallet; + return this.#cosmos; } protected async _getEVMAddress() { if (!this._evm) { - throw new Error('EVM provider is not set'); + throw Errors.sdkNotInitialized(); } return (await this._evm.client.requestAddresses())[0]; } - protected _resolveInitPromises() { - const list = this._initPromises; - this._initPromises = []; - - for (const r of list) { - r(); - } - } - protected async _setProviderHooks() { if (!this._evm) { - throw new Error('EVM provider is not set'); + throw Errors.sdkNotInitialized(); } if (this._evm.provider) { this._evm.provider.on('accountsChanged', this.onAccountsChanged); @@ -584,7 +464,7 @@ export class CA { protected async _signatureForLogin() { if (!this._evm) { - throw new Error('EVM provider is not set'); + throw Errors.sdkNotInitialized(); } const scheme = window.location.protocol.slice(0, -1); const domain = window.location.host; @@ -601,27 +481,107 @@ export class CA { uri: origin, version: '1', }); - const currentChain = await this._getChainID(); + const currentChain = await this._evm.client.getChainId(); try { await this._evm.client.switchChain({ id: 1 }); - const res = await this._evm.client.signMessage({ - account: address, - message, - }); + const res = await this._evm.client + .signMessage({ + account: address, + message, + }) + .catch((e) => { + e.walk(); + throw e; + }); return res; } finally { await this._evm.client.switchChain({ id: currentChain }); } } - protected async _waitForInit(): Promise { - const promise = new Promise((resolve) => { - this._initPromises.push(resolve); - }); - return await promise; + protected _getSwapSupportedChains() { + return getSwapSupportedChains(this.chainList); } - protected _getSwapSupportedChainsAndTokens(): SupportedChainsResult { - return getSwapSupportedChains(this.chainList); + protected _simulateBridgeAndExecute(params: BridgeAndExecuteParams) { + if (!this._evm) { + throw Errors.sdkNotInitialized(); + } + + const handler = new BridgeAndExecuteQuery( + this.chainList, + this._evm.client, + this.createBridgeHandler, + this._getUnifiedBalances, + this.simulationClient, + ); + + return handler.simulateBridgeAndExecute(params); + } + + protected _bridgeAndExecute(params: BridgeAndExecuteParams, options?: OnEventParam) { + if (!this._evm) { + throw Errors.sdkNotInitialized(); + } + + const handler = new BridgeAndExecuteQuery( + this.chainList, + this._evm.client, + this.createBridgeHandler, + this._getUnifiedBalances, + this.simulationClient, + ); + + return handler.bridgeAndExecute(params, options); + } + + protected async _execute(params: ExecuteParams, options?: OnEventParam) { + if (!this._evm) { + throw Errors.sdkNotInitialized(); + } + + const handler = new BridgeAndExecuteQuery( + this.chainList, + this._evm.client, + this.createBridgeHandler, + this._getUnifiedBalances, + this.simulationClient, + ); + + return handler.execute(params, options); + } + + protected async _simulateExecute(params: ExecuteParams) { + if (!this._evm) { + throw Errors.sdkNotInitialized(); + } + + const handler = new BridgeAndExecuteQuery( + this.chainList, + this._evm.client, + this.createBridgeHandler, + this._getUnifiedBalances, + this.simulationClient, + ); + + return handler.simulateExecute(params, this._evm.address); + } + + private universeCheck = (dstChain: Chain) => { + if (dstChain.universe === Universe.FUEL && !this._fuel) { + throw Errors.walletNotConnected('Fuel'); + } + + if (dstChain.universe === Universe.TRON && !this._tron) { + throw Errors.walletNotConnected('Tron'); + } + }; + + private _getStoredSIWESignature(address: Hex) { + return retrieveSIWESignatureFromLocalStorage(address); + } + + private _storeSIWESignature(address: Hex, signature: string) { + return storeSIWESignatureToLocalStorage(address, signature); } } diff --git a/packages/core/sdk/ca-base/chains.ts b/packages/core/sdk/ca-base/chains.ts index aca9c520..5670ec78 100644 --- a/packages/core/sdk/ca-base/chains.ts +++ b/packages/core/sdk/ca-base/chains.ts @@ -4,21 +4,12 @@ import { getVaultContractMap, OmniversalChainID, Universe, -} from '@arcana/ca-common'; -// import { CHAIN_IDS } from 'fuels'; - -import { - // FUEL_BASE_ASSET_ID, - // FUEL_NETWORK_URL, - getLogoFromSymbol, - HYPEREVM_CHAIN_ID, - KAIA_CHAIN_ID, - MONAD_TESTNET_CHAIN_ID, - SOPHON_CHAIN_ID, - ZERO_ADDRESS, -} from './constants'; -import { Chain, TokenInfo } from '@nexus/commons'; +} from '@avail-project/ca-common'; +import { getLogoFromSymbol, ZERO_ADDRESS } from './constants'; +import { Chain, SUPPORTED_CHAINS, TOKEN_CONTRACT_ADDRESSES, TokenInfo } from '@nexus/commons'; import { convertToHexAddressByUniverse, equalFold } from './utils'; +import { Errors } from './errors'; +import { Hex } from 'viem'; class ChainList { public chains: Chain[]; @@ -48,7 +39,7 @@ class ChainList { public getNativeToken(chainID: number): TokenInfo { const chain = this.getChainByID(chainID); if (!chain) { - throw new Error('chain not found'); + throw Errors.chainNotFound(chainID); } return { @@ -61,6 +52,14 @@ class ChainList { } public getTokenByAddress(chainID: number, address: `0x${string}`) { + const result = this.getChainAndTokenByAddress(chainID, address); + if (result) { + return result.token; + } + return undefined; + } + + public getChainAndTokenByAddress(chainID: number, address: Hex) { const chain = this.getChainByID(chainID); if (!chain) { return undefined; @@ -69,10 +68,10 @@ class ChainList { if (!token) { if (equalFold(address, ZERO_ADDRESS)) { - return this.getNativeToken(chainID); + return { chain, token: this.getNativeToken(chainID) }; } } - return token; + return { chain, token }; } public getTokenInfoBySymbol(chainID: number, symbol: string) { @@ -96,17 +95,45 @@ class ChainList { return token; } + public getChainAndTokenFromSymbol( + chainID: number, + tokenSymbol: string, + ): { chain: Chain; token: (TokenInfo & { isNative: boolean }) | undefined } { + const chain = this.getChainByID(chainID); + if (!chain) { + throw Errors.chainNotFound(chainID); + } + + const token = chain.custom.knownTokens.find((t) => equalFold(t.symbol, tokenSymbol)); + if (!token) { + if (equalFold(chain.nativeCurrency.symbol, tokenSymbol)) { + return { + token: { + contractAddress: ZERO_ADDRESS, + decimals: chain.nativeCurrency.decimals, + logo: chain.custom.icon, + name: chain.nativeCurrency.name, + symbol: chain.nativeCurrency.symbol, + isNative: true, + }, + chain, + }; + } + } + return { chain, token: token ? { ...token, isNative: false } : undefined }; + } + public getVaultContractAddress(chainID: number) { const chain = this.getChainByID(chainID); if (!chain) { - throw new Error('chain not supported'); + throw Errors.chainNotFound(chainID); } const omniversalChainID = new OmniversalChainID(chain.universe, chainID); const vc = this.vcm.get(omniversalChainID); if (!vc) { - throw new Error('vault contract not found'); + throw new Error(`vault contract not found for chain: ${chainID}`); } return convertToHexAddressByUniverse(vc, chain.universe); @@ -118,6 +145,43 @@ class ChainList { } const TESTNET_CHAINS: Chain[] = [ + // { + // blockExplorers: { + // default: { + // name: 'TronScan', + // url: 'https://shasta.tronscan.org', + // }, + // }, + // custom: { + // icon: 'https://assets.coingecko.com/asset_platforms/images/1094/large/TRON_LOGO.png', + // knownTokens: [ + // { + // contractAddress: TOKEN_CONTRACT_ADDRESSES['USDT'][SUPPORTED_CHAINS.TRON_SHASTA], + // decimals: 6, + // logo: getLogoFromSymbol('USDT'), + // name: 'Tether USD', + // symbol: 'USDT', + // }, + // ], + // }, + // id: SUPPORTED_CHAINS.TRON_SHASTA, + // ankrName: '', + // name: 'Tron Shasta', + // nativeCurrency: { + // decimals: 6, + // name: 'TRX', + // symbol: 'TRX', + // }, + // rpcUrls: { + // default: { + // http: ['https://api.shasta.trongrid.io/jsonrpc'], + // grpc: ['https://api.shasta.trongrid.io'], + // publicHttp: ['https://api.shasta.trongrid.io/jsonrpc'], + // webSocket: [], + // }, + // }, + // universe: Universe.TRON, + // }, { blockExplorers: { default: { @@ -126,17 +190,17 @@ const TESTNET_CHAINS: Chain[] = [ }, }, custom: { - icon: 'https://assets.coingecko.com/coins/images/16547/large/arb.jpg?1721358242', + icon: 'https://assets.coingecko.com/coins/images/16547/large/arb.jpg', knownTokens: [ { - contractAddress: '0x75faf114eafb1BDbe2F0316DF893fd58CE46AA4d', + contractAddress: TOKEN_CONTRACT_ADDRESSES['USDC'][SUPPORTED_CHAINS.ARBITRUM_SEPOLIA], decimals: 6, logo: getLogoFromSymbol('USDC'), name: 'USD Coin', symbol: 'USDC', }, { - contractAddress: '0xF954d4A5859b37De88a91bdbb8Ad309056FB04B1', + contractAddress: TOKEN_CONTRACT_ADDRESSES['USDT'][SUPPORTED_CHAINS.ARBITRUM_SEPOLIA], decimals: 18, logo: getLogoFromSymbol('USDT'), name: 'Testing USD', @@ -144,7 +208,7 @@ const TESTNET_CHAINS: Chain[] = [ }, ], }, - id: 421614, + id: SUPPORTED_CHAINS.ARBITRUM_SEPOLIA, name: 'Arbitrum Sepolia', ankrName: '', nativeCurrency: { @@ -172,17 +236,17 @@ const TESTNET_CHAINS: Chain[] = [ }, }, custom: { - icon: 'https://assets.coingecko.com/coins/images/25244/large/Optimism.png?1696524385', + icon: 'https://assets.coingecko.com/coins/images/25244/large/Optimism.png', knownTokens: [ { - contractAddress: '0x5fd84259d66Cd46123540766Be93DFE6D43130D7', + contractAddress: TOKEN_CONTRACT_ADDRESSES['USDC'][SUPPORTED_CHAINS.OPTIMISM_SEPOLIA], decimals: 6, logo: getLogoFromSymbol('USDC'), name: 'USD Coin', symbol: 'USDC', }, { - contractAddress: '0x6462693c2F21AC0E517f12641D404895030F7426', + contractAddress: TOKEN_CONTRACT_ADDRESSES['USDT'][SUPPORTED_CHAINS.OPTIMISM_SEPOLIA], decimals: 18, logo: getLogoFromSymbol('USDT'), name: 'Testing USD', @@ -190,7 +254,7 @@ const TESTNET_CHAINS: Chain[] = [ }, ], }, - id: 11155420, + id: SUPPORTED_CHAINS.OPTIMISM_SEPOLIA, name: 'OP Sepolia', ankrName: '', nativeCurrency: { @@ -218,10 +282,10 @@ const TESTNET_CHAINS: Chain[] = [ }, }, custom: { - icon: 'https://assets.coingecko.com/asset_platforms/images/15/large/polygon_pos.png?1706606645', + icon: 'https://assets.coingecko.com/asset_platforms/images/15/large/polygon_pos.png', knownTokens: [ { - contractAddress: '0x41E94Eb019C0762f9Bfcf9Fb1E58725BfB0e7582', + contractAddress: TOKEN_CONTRACT_ADDRESSES['USDC'][SUPPORTED_CHAINS.POLYGON_AMOY], decimals: 6, logo: getLogoFromSymbol('USDC'), name: 'USD Coin', @@ -229,7 +293,7 @@ const TESTNET_CHAINS: Chain[] = [ }, ], }, - id: 80002, + id: SUPPORTED_CHAINS.POLYGON_AMOY, name: 'Amoy', ankrName: '', nativeCurrency: { @@ -257,10 +321,10 @@ const TESTNET_CHAINS: Chain[] = [ }, }, custom: { - icon: 'https://assets.coingecko.com/asset_platforms/images/131/large/base-network.png?1720533039', + icon: 'https://assets.coingecko.com/asset_platforms/images/131/large/base-network.png', knownTokens: [ { - contractAddress: '0x036CbD53842c5426634e7929541eC2318f3dCF7e', + contractAddress: TOKEN_CONTRACT_ADDRESSES['USDC'][SUPPORTED_CHAINS.BASE_SEPOLIA], decimals: 6, logo: getLogoFromSymbol('USDC'), name: 'USD Coin', @@ -268,7 +332,7 @@ const TESTNET_CHAINS: Chain[] = [ }, ], }, - id: 84532, + id: SUPPORTED_CHAINS.BASE_SEPOLIA, name: 'Base Sepolia', ankrName: '', nativeCurrency: { @@ -299,14 +363,14 @@ const TESTNET_CHAINS: Chain[] = [ icon: 'https://assets.coingecko.com/coins/images/38927/standard/monad.jpg', knownTokens: [ { - contractAddress: '0xf817257fed379853cDe0fa4F97AB987181B1E5Ea', + contractAddress: TOKEN_CONTRACT_ADDRESSES['USDC'][SUPPORTED_CHAINS.MONAD_TESTNET], decimals: 6, logo: getLogoFromSymbol('USDC'), name: 'USD Coin', symbol: 'USDC', }, { - contractAddress: '0x1c56F176D6735888fbB6f8bD9ADAd8Ad7a023a0b', + contractAddress: TOKEN_CONTRACT_ADDRESSES['USDT'][SUPPORTED_CHAINS.MONAD_TESTNET], decimals: 18, logo: getLogoFromSymbol('USDT'), name: 'Testing USDT', @@ -314,7 +378,7 @@ const TESTNET_CHAINS: Chain[] = [ }, ], }, - id: MONAD_TESTNET_CHAIN_ID, + id: SUPPORTED_CHAINS.MONAD_TESTNET, name: 'Monad Testnet', ankrName: '', nativeCurrency: { @@ -339,10 +403,10 @@ const TESTNET_CHAINS: Chain[] = [ }, }, custom: { - icon: 'https://assets.coingecko.com/asset_platforms/images/279/large/ethereum.png?1706606803', + icon: 'https://assets.coingecko.com/asset_platforms/images/279/large/ethereum.png', knownTokens: [ { - contractAddress: '0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238', + contractAddress: TOKEN_CONTRACT_ADDRESSES['USDC'][SUPPORTED_CHAINS.SEPOLIA], decimals: 6, logo: getLogoFromSymbol('USDC'), name: 'USD Coin', @@ -350,7 +414,7 @@ const TESTNET_CHAINS: Chain[] = [ }, ], }, - id: 11155111, + id: SUPPORTED_CHAINS.SEPOLIA, name: 'Ethereum Sepolia', ankrName: '', nativeCurrency: { @@ -370,6 +434,42 @@ const TESTNET_CHAINS: Chain[] = [ }, universe: Universe.ETHEREUM, }, + { + blockExplorers: { + default: { + name: 'Validium Testnet Explorer', + url: 'https://testnet.explorer.validium.network', + }, + }, + custom: { + icon: 'https://assets.coingecko.com/asset_platforms/images/279/large/ethereum.png', + knownTokens: [ + { + contractAddress: TOKEN_CONTRACT_ADDRESSES['USDC'][SUPPORTED_CHAINS.VALIDIUM_TESTNET], + decimals: 6, + logo: getLogoFromSymbol('USDC'), + name: 'USD Coin', + symbol: 'USDC', + }, + ], + }, + id: SUPPORTED_CHAINS.VALIDIUM_TESTNET, + name: 'Validium Testnet', + ankrName: '', + nativeCurrency: { + decimals: 18, + name: 'VLDM', + symbol: 'VLDM', + }, + rpcUrls: { + default: { + http: ['https://testnet.l2.rpc.validium.network'], + publicHttp: ['https://testnet.l2.rpc.validium.network'], + webSocket: ['wss://testnet.l2.rpc.validium.network/ws'], + }, + }, + universe: Universe.ETHEREUM, + }, ]; const MAINNET_CHAINS: Chain[] = [ @@ -433,14 +533,14 @@ const MAINNET_CHAINS: Chain[] = [ icon: 'https://assets.coingecko.com/coins/images/38680/large/sophon_logo_200.png', knownTokens: [ { - contractAddress: '0x6386da73545ae4e2b2e0393688fa8b65bb9a7169', + contractAddress: TOKEN_CONTRACT_ADDRESSES['USDT'][SUPPORTED_CHAINS.SOPHON], decimals: 6, logo: getLogoFromSymbol('USDT'), name: 'Tether USD', symbol: 'USDT', }, { - contractAddress: '0x9aa0f72392b5784ad86c6f3e899bcc053d00db4f', + contractAddress: TOKEN_CONTRACT_ADDRESSES['USDC'][SUPPORTED_CHAINS.SOPHON], decimals: 6, logo: getLogoFromSymbol('USDC'), name: 'USD Coin', @@ -455,7 +555,7 @@ const MAINNET_CHAINS: Chain[] = [ }, ], }, - id: SOPHON_CHAIN_ID, + id: SUPPORTED_CHAINS.SOPHON, name: 'Sophon', ankrName: '', nativeCurrency: { @@ -483,7 +583,7 @@ const MAINNET_CHAINS: Chain[] = [ icon: 'https://assets.coingecko.com/asset_platforms/images/9672/large/kaia.png', knownTokens: [ { - contractAddress: '0xd077a400968890eacc75cdc901f0356c943e4fdb', + contractAddress: TOKEN_CONTRACT_ADDRESSES['USDT'][SUPPORTED_CHAINS.KAIA], decimals: 6, logo: getLogoFromSymbol('USDT'), name: 'Tether USD', @@ -491,7 +591,7 @@ const MAINNET_CHAINS: Chain[] = [ }, ], }, - id: KAIA_CHAIN_ID, + id: SUPPORTED_CHAINS.KAIA, name: 'Kaia Mainnet', ankrName: '', nativeCurrency: { @@ -516,17 +616,17 @@ const MAINNET_CHAINS: Chain[] = [ }, }, custom: { - icon: 'https://assets.coingecko.com/asset_platforms/images/279/large/ethereum.png?1706606803', + icon: 'https://assets.coingecko.com/asset_platforms/images/279/large/ethereum.png', knownTokens: [ { - contractAddress: '0xdac17f958d2ee523a2206206994597c13d831ec7', + contractAddress: TOKEN_CONTRACT_ADDRESSES['USDT'][SUPPORTED_CHAINS.ETHEREUM], decimals: 6, logo: getLogoFromSymbol('USDT'), name: 'Tether USD', symbol: 'USDT', }, { - contractAddress: '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48', + contractAddress: TOKEN_CONTRACT_ADDRESSES['USDC'][SUPPORTED_CHAINS.ETHEREUM], decimals: 6, logo: getLogoFromSymbol('USDC'), name: 'USD Coin', @@ -534,7 +634,7 @@ const MAINNET_CHAINS: Chain[] = [ }, ], }, - id: 1, + id: SUPPORTED_CHAINS.ETHEREUM, name: 'Ethereum Mainnet', ankrName: 'eth', nativeCurrency: { @@ -559,17 +659,17 @@ const MAINNET_CHAINS: Chain[] = [ }, }, custom: { - icon: 'https://assets.coingecko.com/coins/images/25244/large/Optimism.png?1696524385', + icon: 'https://assets.coingecko.com/coins/images/25244/large/Optimism.png', knownTokens: [ { - contractAddress: '0x94b008aa00579c1307b0ef2c499ad98a8ce58e58', + contractAddress: TOKEN_CONTRACT_ADDRESSES['USDT'][SUPPORTED_CHAINS.OPTIMISM], decimals: 6, logo: getLogoFromSymbol('USDT'), name: 'Tether USD', symbol: 'USDT', }, { - contractAddress: '0x0b2c639c533813f4aa9d7837caf62653d097ff85', + contractAddress: TOKEN_CONTRACT_ADDRESSES['USDC'][SUPPORTED_CHAINS.OPTIMISM], decimals: 6, logo: getLogoFromSymbol('USDC'), name: 'USD Coin', @@ -577,7 +677,7 @@ const MAINNET_CHAINS: Chain[] = [ }, ], }, - id: 10, + id: SUPPORTED_CHAINS.OPTIMISM, name: 'OP Mainnet', ankrName: 'optimism', nativeCurrency: { @@ -602,17 +702,17 @@ const MAINNET_CHAINS: Chain[] = [ }, }, custom: { - icon: 'https://assets.coingecko.com/asset_platforms/images/15/large/polygon_pos.png?1706606645', + icon: 'https://assets.coingecko.com/asset_platforms/images/15/large/polygon_pos.png', knownTokens: [ { - contractAddress: '0xc2132d05d31c914a87c6611c10748aeb04b58e8f', + contractAddress: TOKEN_CONTRACT_ADDRESSES['USDT'][SUPPORTED_CHAINS.POLYGON], decimals: 6, logo: getLogoFromSymbol('USDT'), name: 'Tether USD', symbol: 'USDT', }, { - contractAddress: '0x3c499c542cef5e3811e1192ce70d8cc03d5c3359', + contractAddress: TOKEN_CONTRACT_ADDRESSES['USDC'][SUPPORTED_CHAINS.POLYGON], decimals: 6, logo: getLogoFromSymbol('USDC'), name: 'USD Coin', @@ -620,7 +720,7 @@ const MAINNET_CHAINS: Chain[] = [ }, ], }, - id: 137, + id: SUPPORTED_CHAINS.POLYGON, name: 'Polygon PoS', ankrName: 'polygon', nativeCurrency: { @@ -645,10 +745,10 @@ const MAINNET_CHAINS: Chain[] = [ }, }, custom: { - icon: 'https://assets.coingecko.com/asset_platforms/images/131/large/base-network.png?1720533039', + icon: 'https://assets.coingecko.com/asset_platforms/images/131/large/base-network.png', knownTokens: [ { - contractAddress: '0x833589fcd6edb6e08f4c7c32d4f71b54bda02913', + contractAddress: TOKEN_CONTRACT_ADDRESSES['USDC'][SUPPORTED_CHAINS.BASE], decimals: 6, logo: getLogoFromSymbol('USDC'), name: 'USD Coin', @@ -656,7 +756,7 @@ const MAINNET_CHAINS: Chain[] = [ }, ], }, - id: 8453, + id: SUPPORTED_CHAINS.BASE, name: 'Base', ankrName: 'base', nativeCurrency: { @@ -681,17 +781,17 @@ const MAINNET_CHAINS: Chain[] = [ }, }, custom: { - icon: 'https://assets.coingecko.com/coins/images/16547/large/arb.jpg?1721358242', + icon: 'https://assets.coingecko.com/coins/images/16547/large/arb.jpg', knownTokens: [ { - contractAddress: '0xfd086bc7cd5c481dcc9c85ebe478a1c0b69fcbb9', + contractAddress: TOKEN_CONTRACT_ADDRESSES['USDT'][SUPPORTED_CHAINS.ARBITRUM], decimals: 6, logo: getLogoFromSymbol('USDT'), name: 'Tether USD', symbol: 'USDT', }, { - contractAddress: '0xaf88d065e77c8cc2239327c5edb3a432268e5831', + contractAddress: TOKEN_CONTRACT_ADDRESSES['USDC'][SUPPORTED_CHAINS.ARBITRUM], decimals: 6, logo: getLogoFromSymbol('USDC'), name: 'USD Coin', @@ -699,7 +799,7 @@ const MAINNET_CHAINS: Chain[] = [ }, ], }, - id: 42161, + id: SUPPORTED_CHAINS.ARBITRUM, name: 'Arbitrum One', ankrName: 'arbitrum', nativeCurrency: { @@ -724,17 +824,17 @@ const MAINNET_CHAINS: Chain[] = [ }, }, custom: { - icon: 'https://assets.coingecko.com/asset_platforms/images/153/large/scroll.jpeg?1706606782', + icon: 'https://assets.coingecko.com/asset_platforms/images/153/large/scroll.jpeg', knownTokens: [ { - contractAddress: '0xf55bec9cafdbe8730f096aa55dad6d22d44099df', + contractAddress: TOKEN_CONTRACT_ADDRESSES['USDT'][SUPPORTED_CHAINS.SCROLL], decimals: 6, logo: getLogoFromSymbol('USDT'), name: 'Tether USD', symbol: 'USDT', }, { - contractAddress: '0x06efdbff2a14a7c8e15944d1f4a48f9f95f663a4', + contractAddress: TOKEN_CONTRACT_ADDRESSES['USDC'][SUPPORTED_CHAINS.SCROLL], decimals: 6, logo: getLogoFromSymbol('USDC'), name: 'USD Coin', @@ -742,7 +842,7 @@ const MAINNET_CHAINS: Chain[] = [ }, ], }, - id: 534352, + id: SUPPORTED_CHAINS.SCROLL, name: 'Scroll', ankrName: 'scroll', nativeCurrency: { @@ -770,14 +870,14 @@ const MAINNET_CHAINS: Chain[] = [ icon: 'https://assets.coingecko.com/asset_platforms/images/12/large/avalanche.png', knownTokens: [ { - contractAddress: '0xb97ef9ef8734c71904d8002f8b6bc66dd9c48a6e', + contractAddress: TOKEN_CONTRACT_ADDRESSES['USDC'][SUPPORTED_CHAINS.AVALANCHE], decimals: 6, logo: getLogoFromSymbol('USDC'), name: 'USD Coin', symbol: 'USDC', }, { - contractAddress: '0x9702230a8ea53601f5cd2dc00fdbc13d4df4a8c7', + contractAddress: TOKEN_CONTRACT_ADDRESSES['USDT'][SUPPORTED_CHAINS.AVALANCHE], decimals: 6, logo: getLogoFromSymbol('USDT'), name: 'Tether USD', @@ -785,7 +885,7 @@ const MAINNET_CHAINS: Chain[] = [ }, ], }, - id: 43114, + id: SUPPORTED_CHAINS.AVALANCHE, ankrName: 'avalanche', name: 'Avalanche C-Chain', nativeCurrency: { @@ -813,14 +913,14 @@ const MAINNET_CHAINS: Chain[] = [ icon: 'https://assets.coingecko.com/asset_platforms/images/1/large/bnb_smart_chain.png', knownTokens: [ { - contractAddress: '0x8AC76a51cc950d9822D68b83fE1Ad97B32Cd580d', + contractAddress: TOKEN_CONTRACT_ADDRESSES['USDC'][SUPPORTED_CHAINS.BNB], decimals: 18, logo: getLogoFromSymbol('USDC'), name: 'USD Coin', symbol: 'USDC', }, { - contractAddress: '0x55d398326f99059fF775485246999027B3197955', + contractAddress: TOKEN_CONTRACT_ADDRESSES['USDT'][SUPPORTED_CHAINS.BNB], decimals: 18, logo: getLogoFromSymbol('USDT'), name: 'Tether USD', @@ -835,7 +935,7 @@ const MAINNET_CHAINS: Chain[] = [ }, ], }, - id: 0x38, + id: SUPPORTED_CHAINS.BNB, name: 'BNB Smart Chain', ankrName: 'bsc', nativeCurrency: { @@ -863,14 +963,14 @@ const MAINNET_CHAINS: Chain[] = [ icon: 'https://assets.coingecko.com/asset_platforms/images/243/large/hyperliquid.png', knownTokens: [ { - contractAddress: '0xB8CE59FC3717ada4C02eaDF9682A9e934F625ebb', + contractAddress: TOKEN_CONTRACT_ADDRESSES['USDT'][SUPPORTED_CHAINS.HYPEREVM], decimals: 6, logo: getLogoFromSymbol('USDT'), name: 'Tether USD', symbol: 'USDT', }, { - contractAddress: '0xb88339CB7199b77E23DB6E890353E22632Ba630f', + contractAddress: TOKEN_CONTRACT_ADDRESSES['USDC'][SUPPORTED_CHAINS.HYPEREVM], decimals: 6, logo: getLogoFromSymbol('USDC'), name: 'USD Coin', @@ -878,7 +978,7 @@ const MAINNET_CHAINS: Chain[] = [ }, ], }, - id: HYPEREVM_CHAIN_ID, + id: SUPPORTED_CHAINS.HYPEREVM, ankrName: '', name: 'HyperEVM', nativeCurrency: { @@ -895,6 +995,43 @@ const MAINNET_CHAINS: Chain[] = [ }, universe: Universe.ETHEREUM, }, + { + blockExplorers: { + default: { + name: 'TronScan', + url: 'https://tronscan.org', + }, + }, + custom: { + icon: 'https://assets.coingecko.com/asset_platforms/images/1094/large/TRON_LOGO.png', + knownTokens: [ + { + contractAddress: TOKEN_CONTRACT_ADDRESSES['USDT'][SUPPORTED_CHAINS.TRON], + decimals: 6, + logo: getLogoFromSymbol('USDT'), + name: 'Tether USD', + symbol: 'USDT', + }, + ], + }, + id: SUPPORTED_CHAINS.TRON, + ankrName: '', + name: 'Tron mainnet', + nativeCurrency: { + decimals: 6, + name: 'TRX', + symbol: 'TRX', + }, + rpcUrls: { + default: { + http: ['https://api.trongrid.io/jsonrpc'], + grpc: ['https://api.trongrid.io'], + publicHttp: ['https://api.trongrid.io/jsonrpc', 'https://tron.therpc.io/jsonrpc'], + webSocket: ['wss://tron.drpc.org'], + }, + }, + universe: Universe.TRON, + }, ]; -export { ChainList, KAIA_CHAIN_ID, SOPHON_CHAIN_ID }; +export { ChainList }; diff --git a/packages/core/sdk/ca-base/config.ts b/packages/core/sdk/ca-base/config.ts index ec66079f..b5960070 100644 --- a/packages/core/sdk/ca-base/config.ts +++ b/packages/core/sdk/ca-base/config.ts @@ -1,4 +1,4 @@ -import { Environment } from '@arcana/ca-common'; +import { Environment } from '@avail-project/ca-common'; import { NetworkConfig } from '@nexus/commons'; diff --git a/packages/core/sdk/ca-base/constants.ts b/packages/core/sdk/ca-base/constants.ts index 8cc8fb18..371583ec 100644 --- a/packages/core/sdk/ca-base/constants.ts +++ b/packages/core/sdk/ca-base/constants.ts @@ -1,11 +1,4 @@ -import { Universe } from '@arcana/ca-common'; - -import { convertTo32BytesHex } from './utils'; - -const KAIA_CHAIN_ID = 8217; -const SOPHON_CHAIN_ID = 50104; -const HYPEREVM_CHAIN_ID = 0x3e7; -const MONAD_TESTNET_CHAIN_ID = 10143; +import { Universe } from '@avail-project/ca-common'; const FUEL_NETWORK_URL = 'https://mainnet.fuel.network/v1/graphql'; @@ -36,7 +29,7 @@ const getLogoFromSymbol = (symbol: string) => { }; const isNativeAddress = (universe: Universe, address: `0x${string}`) => { - if (universe === Universe.ETHEREUM) { + if (universe === Universe.ETHEREUM || universe === Universe.TRON) { return address === ZERO_ADDRESS || address === ZERO_ADDRESS_FUEL; } @@ -50,111 +43,15 @@ const isNativeAddress = (universe: Universe, address: `0x${string}`) => { const INTENT_EXPIRY = 15 * 60 * 1000; -const AaveTokenContracts: { - [key: number]: { - [symbol: string]: `0x${string}`; - }; -} = { - 1: { - USDC: '0x98C23E9d8f34FEFb1B7BD6a91B7FF122F4e16F5c', - USDT: '0x23878914EFE38d27C4D67Ab83ed1b93A74D4086a', - WETH: '0x4d5F47FA6A74757f35C14fD3a6Ef8E3C9BC514E8', - }, - 10: { - USDC: '0x38d693cE1dF5AaDF7bC62595A37D667aD57922e5', - USDT: '0x6ab707Aca953eDAeFBc4fD23bA73294241490620', - WETH: '0xe50fA9b3c56FfB159cB0FCA61F5c9D750e8128c8', - }, - 11155420: { - USDC: '0xa818F1B57c201E092C4A2017A91815034326Efd1', - }, - 137: { - USDC: '0xA4D94019934D8333Ef880ABFFbF2FDd611C762BD', - USDT: '0x6ab707Aca953eDAeFBc4fD23bA73294241490620', - WETH: '0xe50fA9b3c56FfB159cB0FCA61F5c9D750e8128c8', - }, - 42161: { - USDC: '0x724dc807b04555b71ed48a6896b6F41593b8C637', - USDT: '0x6ab707Aca953eDAeFBc4fD23bA73294241490620', - WETH: '0xe50fA9b3c56FfB159cB0FCA61F5c9D750e8128c8', - }, - // Testnet chains - 421614: { - USDC: '0x460b97BD498E1157530AEb3086301d5225b91216', - }, - 43114: { - USDC: '0x625E7708f30cA75bfd92586e17077590C60eb4cD', - USDT: '0x6ab707Aca953eDAeFBc4fD23bA73294241490620', - WETH: '0xe50fA9b3c56FfB159cB0FCA61F5c9D750e8128c8', - }, - 534352: { - USDC: '0x1D738a3436A8C49CefFbaB7fbF04B660fb528CbD', - WETH: '0xf301805bE1Df81102C957f6d4Ce29d2B8c056B2a', - }, - 56: { - USDC: '0x00901a076785e0906d1028c7d6372d247bec7d61', - USDT: '0xa9251ca9DE909CB71783723713B21E4233fbf1B1', - }, - 59144: { - USDC: '0x374D7860c4f2f604De0191298dD393703Cce84f3', - USDT: '0x88231dfEC71D4FF5c1e466D08C321944A7adC673', - WETH: '0x787897dF92703BB3Fc4d9Ee98e15C0b8130Bf163', - }, - 8453: { - USDC: '0x4e65fE4DbA92790696d040ac24Aa414708F5c0AB', - WETH: '0x7C307e128efA31F540F2E2d976C995E0B65F51F6', - }, - 84532: { - USDC: '0x10F1A9D11CDf50041f3f8cB7191CBE2f31750ACC', - USDT: '0xcE3CAae5Ed17A7AafCEEbc897DE843fA6CC0c018', - }, -}; - -const TOKEN_MINTER_CONTRACTS: { - [key: number]: { - [symbol: string]: `0x${string}`; - }; -} = { - 534352: { - USDT: '0xe2b4795039517653c5ae8c2a9bfdd783b48f447a', - }, - 59144: { - USDC: '0xA2Ee6Fce4ACB62D95448729cDb781e3BEb62504A', - USDT: '0x353012dc4a9A6cF55c941bADC267f82004A8ceB9', - }, - 8453: { - USDT: '0x4200000000000000000000000000000000000010', - }, -}; - -const TOP_OWNER: { - [key: number]: { - [symbol: string]: `0x${string}`; - }; -} = { - [SOPHON_CHAIN_ID]: { - ETH: '0x353B35a3362Dff8174cd9679BC4a46365CcD4dA7', - USDC: '0x61a87fa6Dd89a23c78F0754EF3372d35ccde5935', - USDT: '0x61a87fa6Dd89a23c78F0754EF3372d35ccde5935', - }, -}; - const ZERO_ADDRESS: `0x${string}` = '0x0000000000000000000000000000000000000000'; -const ZERO_ADDRESS_FUEL = convertTo32BytesHex(ZERO_ADDRESS); +const ZERO_ADDRESS_FUEL = '0x0000000000000000000000000000000000000000000000000000000000000000'; export { - AaveTokenContracts, FUEL_BASE_ASSET_ID, FUEL_NETWORK_URL, getLogoFromSymbol, - HYPEREVM_CHAIN_ID, INTENT_EXPIRY, isNativeAddress, - KAIA_CHAIN_ID, - MONAD_TESTNET_CHAIN_ID, - SOPHON_CHAIN_ID, - TOKEN_MINTER_CONTRACTS, - TOP_OWNER, ZERO_ADDRESS, }; diff --git a/packages/core/sdk/ca-base/errors.ts b/packages/core/sdk/ca-base/errors.ts index 079c7e87..da1af450 100644 --- a/packages/core/sdk/ca-base/errors.ts +++ b/packages/core/sdk/ca-base/errors.ts @@ -1,29 +1,96 @@ -import { InternalRpcError, UserRejectedRequestError } from "viem"; - -const ErrorUserDeniedIntent = new UserRejectedRequestError( - new Error("User denied intent."), -); - -const ErrorUserDeniedAllowance = new UserRejectedRequestError( - new Error("User denied allowance."), -); - -const ErrorInsufficientBalance = new InternalRpcError( - new Error("Insufficient balance."), -); - -const ErrorBuildingIntent = new InternalRpcError( - new Error("Error while building intent."), -); - -const ErrorLiquidityTimeout = new InternalRpcError( - new Error("Timed out waiting for liquidity."), -); - -export { - ErrorBuildingIntent, - ErrorInsufficientBalance, - ErrorLiquidityTimeout, - ErrorUserDeniedAllowance, - ErrorUserDeniedIntent, +import { ERROR_CODES, createError } from './nexusError'; + +export const Errors = { + sdkNotInitialized: () => createError(ERROR_CODES.SDK_NOT_INITIALIZED, 'SDK is not initialized()'), + invalidAllowance: (expected: number, got: number) => + createError( + ERROR_CODES.INVALID_VALUES_ALLOWANCE_HOOK, + 'Invalid allowance values passed. The length of allowances should equal input lengths.', + { + context: 'onAllowance:allow()', + details: { expectedLength: expected, receivedLength: got }, + }, + ), + + chainNotFound: (chainId: number | bigint) => + createError(ERROR_CODES.CHAIN_NOT_FOUND, `Chain not found: ${chainId}`, { + details: { chainId }, + }), + + internal: (msg: string, details?: Record) => + createError(ERROR_CODES.INTERNAL_ERROR, `Internal error: ${msg}`, { + details, + }), + + tokenNotSupported: (address: string, chainId: number) => + createError( + ERROR_CODES.TOKEN_NOT_SUPPORTED, + `Token with address ${address} is not supported on chain ${chainId}`, + { + details: { address, chainId }, + }, + ), + + tokenNotFound: (symbol: string, chainId: number) => + createError( + ERROR_CODES.TOKEN_NOT_SUPPORTED, + `Token with symbol ${symbol} not found on chain ${chainId}`, + { + details: { symbol, chainId }, + }, + ), + + tronDepositFailed: (result: unknown) => + createError(ERROR_CODES.TRON_DEPOSIT_FAIL, 'Tron deposit transaction failed.', { + details: { result }, + }), + + tronApprovalFailed: (result: unknown) => + createError(ERROR_CODES.TRON_APPROVAL_FAIL, 'Tron approval transaction failed.', { + details: { result }, + }), + + fuelDepositFailed: (result: unknown) => + createError(ERROR_CODES.FUEL_DEPOSIT_FAIL, 'Fuel deposit transaction failed.', { + details: { result }, + }), + + liquidityTimeout: () => + createError(ERROR_CODES.LIQUIDITY_TIMEOUT, 'Timed out waiting for fulfilment.'), + + userDeniedIntent: () => createError(ERROR_CODES.USER_DENIED_INTENT, 'User rejected the intent.'), + + userRejectedAllowance: () => + createError(ERROR_CODES.USER_DENIED_ALLOWANCE, 'User rejected the allowance.'), + + userRejectedIntentSignature: () => + createError(ERROR_CODES.USER_DENIED_ALLOWANCE, 'User rejected signing the intent hash.'), + + insufficientBalance: () => + createError(ERROR_CODES.INSUFFICIENT_BALANCE, 'Insufficient balance to proceed.'), + + walletNotConnected: (walletType: string) => + createError(ERROR_CODES.WALLET_NOT_CONNECTED, `Wallet is not connected for ${walletType}`), + + userRejectedSIWESignature: () => + createError(ERROR_CODES.USER_DENIED_SIWE_SIGNATURE, `User rejected SIWE signature.`), + + vscError: (msg: string) => createError(ERROR_CODES.INTERNAL_ERROR, `VSC: ${msg}`), + + cosmosError: (msg: string) => createError(ERROR_CODES.INTERNAL_ERROR, `COSMOS: ${msg}`), + gasPriceError: (result: unknown) => + createError(ERROR_CODES.FETCH_GAS_PRICE_FAILED, `rpc: estimateMaxFeePerGas failed`, { + details: { + result, + }, + }), + slippageError: (msg: string) => + createError(ERROR_CODES.SLIPPAGE_EXCEEDED_ALLOWANCE, `rpc: slippage exceeded - ${msg}`), + vaultContractNotFound: (chainId: number | bigint) => + createError( + ERROR_CODES.VAULT_CONTRACT_NOT_FOUND, + `vault contract not found for chain ${chainId.toString()}`, + ), + simulationError: (msg: string) => + createError(ERROR_CODES.SIMULATION_FAILED, `tenderly simulation failed: ${msg}`), }; diff --git a/packages/core/sdk/ca-base/index.ts b/packages/core/sdk/ca-base/index.ts index eeaf895b..ecf0a6c3 100644 --- a/packages/core/sdk/ca-base/index.ts +++ b/packages/core/sdk/ca-base/index.ts @@ -1,24 +1,19 @@ export { CA } from './ca'; -export { simulateTransaction, type SimulationRequest, type SimulationResponse } from './simulate'; -export { SwapStep } from './swap/steps'; export type { AllowanceHookSources, - BridgeQueryInput, EthereumProvider, ReadableIntent as Intent, NetworkConfig, OnAllowanceHook, onAllowanceHookSource, OnIntentHook, - Step as ProgressStep, - Steps as ProgressSteps, RequestArguments, RFF, SDKConfig, - StepInfo, - TransferQueryInput, UserAssetDatum as UserAsset, + BridgeStepType, + SwapStepType, } from '@nexus/commons'; -export { Environment as Network, RequestForFunds } from '@arcana/ca-common'; +export { Environment as Network, RequestForFunds } from '@avail-project/ca-common'; diff --git a/packages/core/sdk/ca-base/logger.ts b/packages/core/sdk/ca-base/logger.ts deleted file mode 100644 index f0146063..00000000 --- a/packages/core/sdk/ca-base/logger.ts +++ /dev/null @@ -1,93 +0,0 @@ -export const LOG_LEVEL = { - DEBUG: 1, - ERROR: 4, - INFO: 2, - NOLOGS: 5, - WARNING: 3, -}; - -type ExceptionReporter = ((msg: string) => void) | null; -export const setExceptionReporter = (reporter: (msg: string) => void): void => { - state.exceptionReporter = reporter; -}; - -const sendException = (msg: string) => { - if (state.exceptionReporter) { - state.exceptionReporter(msg); - } -}; - -export const setLogLevel = (level: number): void => { - state.logLevel = level; -}; - -export const getLogger = (): Logger => { - return state.logger; -}; - -class Logger { - private prefix = "XAR_CA_SDK"; - - consoleLog(level: number, message: string, params: unknown): void { - if (level < state.logLevel) { - return; - } - - switch (level) { - case LOG_LEVEL.DEBUG: - console.debug(`[DEBUG]`, message, params); - break; - case LOG_LEVEL.ERROR: - console.error(`[ERROR]`, message, params); - break; - case LOG_LEVEL.INFO: - console.info(`[INFO]`, message, params); - break; - case LOG_LEVEL.WARNING: - console.warn(`[WARN]`, message, params); - break; - default: - console.log(`[LOG]`, message, params); - } - } - - debug(message: string, params: unknown = {}): void { - this.internalLog(LOG_LEVEL.DEBUG, message, params); - } - - error(message: string, err: unknown): void { - if (err instanceof Error) { - this.internalLog(LOG_LEVEL.ERROR, message, err.message); - sendException(JSON.stringify({ error: err.message, message })); - return; - } - if (typeof err == "string") { - this.internalLog(LOG_LEVEL.ERROR, message, err); - sendException(JSON.stringify({ error: err, message })); - } - } - - info(message: string, params: unknown = {}): void { - this.internalLog(LOG_LEVEL.INFO, message, params); - } - - internalLog(level: number, message: string, params: unknown): void { - const logMessage = `[${this.prefix}] Msg: ${message}\n`; - - this.consoleLog(level, logMessage, params); - } - - warn(message: string, params: unknown = {}): void { - this.internalLog(LOG_LEVEL.WARNING, message, params); - } -} - -const state: { - exceptionReporter: ExceptionReporter | null; - logger: Logger; - logLevel: number; -} = { - exceptionReporter: null, - logger: new Logger(), - logLevel: LOG_LEVEL.NOLOGS, -}; diff --git a/packages/core/sdk/ca-base/nexusError.ts b/packages/core/sdk/ca-base/nexusError.ts new file mode 100644 index 00000000..51d55411 --- /dev/null +++ b/packages/core/sdk/ca-base/nexusError.ts @@ -0,0 +1,99 @@ +export interface NexusErrorData { + context?: string; // Where or why it happened + cause?: unknown; // Optional nested error + details?: Record; // Specific structured info +} + +export class NexusError extends Error { + readonly code: ErrorCode; + readonly data?: NexusErrorData; + + constructor(code: ErrorCode, message: string, data?: NexusErrorData) { + super(message); + this.name = 'NexusError'; + this.code = code; + this.data = data; + } + + toJSON() { + return { + name: this.name, + code: this.code, + message: this.message, + data: this.data, + }; + } +} + +export const ERROR_CODES = { + INVALID_VALUES_ALLOWANCE_HOOK: 'INVALID_VALUES_ALLOWANCE_HOOK', + SDK_NOT_INITIALIZED: 'SDK_NOT_INITIALIZED', + CHAIN_NOT_FOUND: 'CHAIN_NOT_FOUND', + INTERNAL_ERROR: 'INTERNAL_ERROR', + TOKEN_NOT_SUPPORTED: 'TOKEN_NOT_SUPPORTED', + TRON_DEPOSIT_FAIL: 'TRON_DEPOSIT_FAIL', + TRON_APPROVAL_FAIL: 'TRON_APPROVAL_FAIL', + FUEL_DEPOSIT_FAIL: 'FUEL_DEPOSIT_FAIL', + LIQUIDITY_TIMEOUT: 'LIQUIDITY_TIMEOUT', + USER_DENIED_INTENT: 'USER_DENIED_INTENT', + USER_DENIED_ALLOWANCE: 'USER_DENIED_ALLOWANCE', + USER_DENIED_INTENT_SIGNATURE: 'USER_DENIED_INTENT_SIGNATURE', + INSUFFICIENT_BALANCE: 'INSUFFICIENT_BALANCE', + WALLET_NOT_CONNECTED: 'WALLET_NOT_CONNECTED', + USER_DENIED_SIWE_SIGNATURE: 'USER_DENIED_SIWE_SIGNATURE', + FETCH_GAS_PRICE_FAILED: 'FETCH_GAS_PRICE_FAILED', + SIMULATION_FAILED: 'SIMULATION_FAILED', + CONNECT_ACCOUNT_FAILED: 'CONNECT_ACCOUNT_FAILED', + VAULT_CONTRACT_NOT_FOUND: 'VAULT_CONTRACT_NOT_FOUND', + SLIPPAGE_EXCEEDED_ALLOWANCE: 'SLIPPAGE_EXCEEDED_ALLOWANCE', +} as const; + +export type ErrorCode = (typeof ERROR_CODES)[keyof typeof ERROR_CODES]; + +export function createError(code: ErrorCode, message: string, data?: NexusErrorData): NexusError { + return new NexusError(code, message, data); +} + +/* --- Expected handling --- + +function handleNexusError(err: unknown) { + if (err instanceof NexusError) { + console.error(`[${err.code}] ${err.message}`); + + if (err.data?.context) { + console.error(`Context: ${err.data.context}`); + } + + if (err.data?.details) { + console.error('Details:', err.data.details); + } + + switch (err.code) { + case ERROR_CODES.USER_DENIED_INTENT: + case ERROR_CODES.USER_DENIED_ALLOWANCE: + alert('You rejected the transaction. Please try again.'); + break; + + case ERROR_CODES.INSUFFICIENT_BALANCE: + alert('Your wallet does not have enough funds.'); + break; + + case ERROR_CODES.TRON_DEPOSIT_FAIL: + case ERROR_CODES.FUEL_DEPOSIT_FAIL: + console.warn('Deposit failed'); + // Possibly ask user to retry + break; + + default: + // Unknown but typed error + console.error('Unexpected NexusError:', err.toJSON()); + } + + // Optional: + logErrorToService(err.toJSON()); + } else { + // Non-Nexus errors (network, library, etc.) + console.error('Unexpected error:', err); + } +} +*/ diff --git a/packages/core/sdk/ca-base/query/allowance.ts b/packages/core/sdk/ca-base/query/allowance.ts deleted file mode 100644 index c17d752d..00000000 --- a/packages/core/sdk/ca-base/query/allowance.ts +++ /dev/null @@ -1,102 +0,0 @@ -import { WalletClient } from 'viem'; - -import { equalFold, getAllowance, setAllowances, switchChain } from '../utils'; -import { NetworkConfig, ChainListType } from '@nexus/commons'; - -class AllowanceQuery { - constructor( - private walletClient: WalletClient, - private networkConfig: NetworkConfig, - private chainList: ChainListType, - ) {} - - async get(input: { chainID?: number; tokens?: string[] }) { - const addresses = await this.walletClient.getAddresses(); - if (!addresses.length) { - throw new Error('No account connected with wallet client'); - } - const address = addresses[0]; - const tokens = input.tokens ?? ['USDT', 'USDC']; - const chainID = input.chainID ? [input.chainID] : this.chainList.chains.map((c) => c.id); - - const inp = []; - const out: Array<{ - allowance: bigint; - chainID: number; - token: string; - }> = []; - for (const c of chainID) { - for (const t of tokens) { - const token = this.chainList.getTokenInfoBySymbol(c, t); - if (token) { - const chain = this.chainList.getChainByID(c); - if (!chain) { - throw new Error('chain not supported'); - } - inp.push( - getAllowance(chain, address, token.contractAddress, this.chainList).then((val) => { - out.push({ - allowance: val, - chainID: c, - token: t, - }); - }), - ); - } - } - } - return Promise.all(inp).then(() => out); - } - - async revoke(input: { chainID: number; tokens: string[] }) { - await this.set({ ...input, amount: 0n }); - } - - async set(input: { amount: bigint; chainID: number; tokens: string[] }) { - if (input.tokens == null) { - throw new Error('missing token param'); - } - - if (input.amount == null) { - throw new Error('missing amount param'); - } - - if (input.chainID == null) { - throw new Error('missing chainID param'); - } - - const chain = this.chainList.getChainByID(input.chainID); - if (!chain) { - throw new Error('chain not supported'); - } - - let chainID = await this.walletClient.getChainId(); - if (input.chainID && input.chainID !== chainID) { - await switchChain(this.walletClient, chain); - chainID = input.chainID; - } - - const tokenAddresses: Array<`0x${string}`> = []; - for (const t of input.tokens) { - const token = chain.custom.knownTokens.find((kt) => equalFold(kt.symbol, t)); - if (token) { - tokenAddresses.push(token.contractAddress); - } - } - - if (!tokenAddresses.length) { - throw new Error('None of the supplied token symbols are recognised on this chain'); - } - - await setAllowances( - tokenAddresses, - this.walletClient, - this.networkConfig, - this.chainList, - chain, - input.amount, - ); - } -} - -export { AllowanceQuery }; diff --git a/packages/core/sdk/ca-base/query/bridge.ts b/packages/core/sdk/ca-base/query/bridge.ts deleted file mode 100644 index 505e876f..00000000 --- a/packages/core/sdk/ca-base/query/bridge.ts +++ /dev/null @@ -1,122 +0,0 @@ -import { Account, bn, CHAIN_IDS } from 'fuels'; -import { encodeFunctionData, toHex } from 'viem'; - -import ERC20ABI from '../abi/erc20'; -import { ZERO_ADDRESS } from '../constants'; -import { convertIntent, equalFold, mulDecimals } from '../utils'; -import { - BridgeQueryInput, - CA, - EVMTransaction, - IRequestHandler, - ChainListType, -} from '@nexus/commons'; - -class BridgeQuery { - private handler?: IRequestHandler | null = null; - constructor( - private input: BridgeQueryInput, - private init: CA['init'], - private switchChain: CA['switchChain'], - private createEVMHandler: CA['createEVMHandler'], - private createFuelHandler: CA['createFuelHandler'], - private address: `0x${string}`, - private chainList: ChainListType, - private fuelAccount?: Account, - ) {} - - exec = () => { - if (!this.handler) { - throw new Error('ca not applicable'); - } - - return this.handler.process(); - }; - - public async initHandler() { - if (!this.handler) { - const input = this.input; - await this.init(); - - if (input.token && input.amount && input.chainId) { - const token = this.chainList.getTokenInfoBySymbol(input.chainId, input.token); - if (!token) { - throw new Error('Token not supported on this chain.'); - } - - const bridgeAmount = mulDecimals(input.amount, token.decimals); - - if (input.chainId === CHAIN_IDS.fuel.mainnet) { - if (this.fuelAccount) { - const tx = await this.fuelAccount.createTransfer( - // Random address, since bridge won't call the final tx - '0xE78655DfAd552fc3658c01bfb427b9EAb0c628F54e60b54fDA16c95aaAdE797A', - bn(bridgeAmount.toString()), - token.contractAddress, - ); - - const handlerResponse = await this.createFuelHandler(tx, { - bridge: true, - gas: input.gas ?? 0n, - skipTx: true, - }); - - this.handler = handlerResponse?.handler; - } else { - throw new Error('Fuel connector is not set'); - } - } else { - await this.switchChain(input.chainId); - const p: EVMTransaction = { - from: this.address, - to: this.address, - }; - - const isNative = equalFold(token.contractAddress, ZERO_ADDRESS); - - if (isNative) { - p.value = toHex(bridgeAmount); - input.gas = 0n; - } else { - p.to = token.contractAddress; - p.data = encodeFunctionData({ - abi: ERC20ABI, - args: [this.address, BigInt(bridgeAmount.toString())], - functionName: 'transfer', - }); - } - - const handlerResponse = await this.createEVMHandler(p, { - bridge: true, - gas: input.gas ?? 0n, - skipTx: true, - sourceChains: input.sourceChains, - }); - - this.handler = handlerResponse?.handler; - } - - return; - } - throw new Error('bridge: missing params'); - } - } - - simulate = async () => { - if (!this.handler) { - throw new Error('ca not applicable'); - } - - const response = await this.handler.buildIntent(this.input.sourceChains ?? []); - if (!response) { - throw new Error('ca not applicable'); - } - - return { - intent: convertIntent(response.intent, response.token, this.chainList), - token: response.token, - }; - }; -} - -export { BridgeQuery }; diff --git a/packages/core/sdk/ca-base/query/bridgeAndExecute.ts b/packages/core/sdk/ca-base/query/bridgeAndExecute.ts new file mode 100644 index 00000000..90339133 --- /dev/null +++ b/packages/core/sdk/ca-base/query/bridgeAndExecute.ts @@ -0,0 +1,598 @@ +import { + BridgeAndExecuteParams, + BridgeAndExecuteResult, + BridgeResult, + logger, + Tx, + Chain, + ChainListType, + BridgeParams, + UserAssetDatum, + ExecuteParams, + ExecuteResult, + ExecuteSimulation, + OnEventParam, + BridgeAndExecuteSimulationResult, + NEXUS_EVENTS, + BRIDGE_STEPS, + BridgeStepType, +} from '@nexus/commons'; +import { createPublicClient, Hex, http, PublicClient, toHex, WalletClient } from 'viem'; +import { + createExplorerTxURL, + divDecimals, + mulDecimals, + UserAssets, + waitForTxReceipt, + generateStateOverride, + switchChain, + erc20GetAllowance, +} from '../utils'; +import { packERC20Approve } from '../swap/utils'; +import { BackendSimulationClient } from 'integrations/tenderly'; +import BridgeHandler from '../requestHandlers/bridge'; +import { Errors } from '../errors'; + +class BridgeAndExecuteQuery { + constructor( + private chainList: ChainListType, + private evmClient: WalletClient, + private bridge: (input: BridgeParams, options?: OnEventParam) => BridgeHandler, + private getUnifiedBalances: () => Promise, + private simulationClient: BackendSimulationClient, + ) {} + + private async estimateBridgeAndExecute(params: BridgeAndExecuteParams) { + const { toChainId, token: tokenSymbol, amount, execute } = params; + + const { token, chain: dstChain } = this.chainList.getChainAndTokenFromSymbol( + params.toChainId, + tokenSymbol, + ); + if (!token) { + throw Errors.tokenNotFound(tokenSymbol, toChainId); + } + + await switchChain(this.evmClient, dstChain); + + const address = (await this.evmClient.getAddresses())[0]; + let txs: Tx[] = []; + + const { tx, approvalTx, dstPublicClient } = await this.createTxsForExecute( + { ...execute, toChainId: params.toChainId }, + address, + ); + + logger.debug('BridgeAndExecute:2', { + tx, + approvalTx, + }); + + if (approvalTx) { + txs.push(approvalTx); + } + + txs.push(tx); + + const determineGasUsed = params.execute.gas + ? Promise.resolve({ gasUsed: params.execute.gas + (approvalTx ? 85_000n : 0n) }) + : this.simulateBundle({ + txs, + amount: BigInt(execute.tokenApproval?.amount ?? '0'), + userAddress: address, + chainId: dstChain.id, + tokenAddress: token.contractAddress, + tokenSymbol: execute.tokenApproval?.token ?? 'ETH', + }); + + const determineGasFee = params.execute.gasPrice + ? Promise.resolve({ + maxFeePerGas: params.execute.gasPrice, + gasPrice: params.execute.gasPrice, + }) + : dstPublicClient.estimateFeesPerGas(); + + // 5. simulate approval(?) and execution + fetch gasPrice + fetch unified balance + const [{ gasUsed }, gasFeeEstimate, balances] = await Promise.all([ + determineGasUsed, + determineGasFee, + this.getUnifiedBalances(), + ]); + + const gasPrice = gasFeeEstimate.maxFeePerGas ?? gasFeeEstimate.gasPrice ?? 0n; + if (gasPrice === 0n) { + throw Errors.gasPriceError({ + chainId: dstChain.id, + }); + } + + const gasFee = gasUsed * gasPrice; + + logger.debug('BridgeAndExecute:3', { + gasUsed, + gasFeeEstimate, + gasPrice, + balances, + }); + + // 6. Determine gas or token needed via bridge + const { skipBridge, tokenAmount, gasAmount } = await this.calculateOptimalBridgeAmount( + dstChain, + token.contractAddress, + token.decimals, + amount, + gasFee, + balances, + ); + + return { + skipBridge, + tokenAmount, + gasAmount, + tx, + approvalTx, + token, + dstChain, + address, + dstPublicClient, + gasFee, + gasUsed, + gasPrice, + }; + } + + public async simulateBridgeAndExecute( + params: BridgeAndExecuteParams, + ): Promise { + const { gasFee, token, skipBridge, tokenAmount, gasAmount, gasUsed, gasPrice } = + await this.estimateBridgeAndExecute(params); + + logger.debug('BridgeAndExecute:4:CalculateOptimalBridgeAmount', { + skipBridge, + tokenAmount, + gasAmount, + }); + + let bridgeResult = null; + + // 7. If bridge is required then simulate bridge + if (!skipBridge) { + bridgeResult = await this.simulateBridgeWrapper({ + token: token.symbol, + amount: divDecimals(BigInt(tokenAmount), token.decimals).toFixed(), + toChainId: params.toChainId, + sourceChains: params.sourceChains, + gas: gasAmount, + }); + } + + // 8. Return result + const result: BridgeAndExecuteSimulationResult = { + bridgeSimulation: bridgeResult, + executeSimulation: { + gasUsed, + gasPrice, + gasFee, + }, + }; + + return result; + } + + /** + * Bridge and execute operation - combines bridge and execute with proper sequencing + * Checks balance and gas present on destination chain & bridges (required - available) token + gas. + * Simulates using tenderly for gas and gasPrice if gas and gasPrice not provided. + */ + public async bridgeAndExecute( + params: BridgeAndExecuteParams, + options?: OnEventParam, + ): Promise { + const { + dstPublicClient, + address, + dstChain, + token, + skipBridge, + tokenAmount, + gasAmount, + tx, + approvalTx, + gasUsed, + gasPrice, + } = await this.estimateBridgeAndExecute(params); + + logger.debug('BridgeAndExecute:4:CalculateOptimalBridgeAmount', { + skipBridge, + tokenAmount, + gasAmount, + }); + + const executeSteps: BridgeStepType[] = [ + BRIDGE_STEPS.EXECUTE_TRANSACTION_SENT, + BRIDGE_STEPS.EXECUTE_TRANSACTION_CONFIRMED, + ]; + + // Approval and execute + if (approvalTx) { + executeSteps.unshift(BRIDGE_STEPS.EXECUTE_APPROVAL_STEP); + } + + let bridgeResult: BridgeResult = { + explorerUrl: '', + }; + + // 7. If bridge is required then bridge + if (!skipBridge) { + bridgeResult = await this.bridgeWrapper( + { + token: token.symbol, + amount: divDecimals(BigInt(tokenAmount), token.decimals).toFixed(), + toChainId: params.toChainId, + sourceChains: params.sourceChains, + gas: gasAmount, + }, + { + onEvent: (event) => { + if (options && options.onEvent) { + if (event.name === NEXUS_EVENTS.STEPS_LIST) { + options.onEvent({ + name: NEXUS_EVENTS.STEPS_LIST, + args: event.args.concat(executeSteps), + }); + } else { + options.onEvent(event); + } + } + }, + }, + ); + } else { + if (options && options.onEvent) { + options.onEvent({ name: NEXUS_EVENTS.STEPS_LIST, args: executeSteps }); + } + } + + // 8. Execute the transaction + const executeResponse = await this.sendTx( + { + approvalTx, + tx, + gas: gasUsed, + gasPrice, + }, + { + emit: options?.onEvent, + chain: dstChain, + dstPublicClient, + address, + receiptTimeout: params.receiptTimeout, + requiredConfirmations: params.requiredConfirmations, + waitForReceipt: params.waitForReceipt, + client: this.evmClient, + }, + ); + + logger.debug('BridgeAndExecute:5', { + executeResponse, + }); + + // 9. Return result + const result: BridgeAndExecuteResult = { + executeTransactionHash: executeResponse.txHash, + executeExplorerUrl: createExplorerTxURL( + executeResponse.txHash, + dstChain.blockExplorers!.default.url, + ), + approvalTransactionHash: executeResponse.approvalHash, + bridgeExplorerUrl: bridgeResult.explorerUrl, + toChainId: params.toChainId, + bridgeSkipped: skipBridge, + }; + + return result; + } + + private async createTxsForExecute(params: ExecuteParams, address: Hex) { + // 1. Check if dst chain data is available + const dstChain = this.chainList.getChainByID(params.toChainId); + if (!dstChain) { + throw Errors.chainNotFound(params.toChainId); + } + + const dstPublicClient = createPublicClient({ + transport: http(dstChain.rpcUrls.default.http[0]), + }); + + // 2. Check if token is supported + let approvalTx: Tx | null = null; + if (params.tokenApproval) { + const token = this.chainList.getTokenInfoBySymbol( + params.toChainId, + params.tokenApproval.token, + ); + if (!token) { + throw Errors.tokenNotFound(params.tokenApproval.token, params.toChainId); + } + const spender = params.tokenApproval.spender; + const currentAllowance = await erc20GetAllowance( + { + contractAddress: token.contractAddress, + spender: params.tokenApproval.spender, + owner: address, + }, + dstPublicClient, + ); + + const requiredAllowance = BigInt(params.tokenApproval.amount); + if (currentAllowance < requiredAllowance) { + approvalTx = { + to: token.contractAddress, + data: packERC20Approve(spender, requiredAllowance), + value: 0n, + }; + } + } + + // 4. Encode execute tx + const tx = { + to: params.to, + value: params.value ?? 0n, + data: params.data ?? '0x', + }; + + return { tx, approvalTx, dstChain, dstPublicClient }; + } + + public async execute(params: ExecuteParams, options?: OnEventParam) { + const address = (await this.evmClient.getAddresses())[0]; + const { dstPublicClient, dstChain, approvalTx, tx } = await this.createTxsForExecute( + params, + address, + ); + + // 1. Execute the transaction + const executeResponse = await this.sendTx( + { + approvalTx, + tx, + }, + { + emit: options?.onEvent, + chain: dstChain, + dstPublicClient, + address, + receiptTimeout: params.receiptTimeout, + requiredConfirmations: params.requiredConfirmations, + waitForReceipt: params.waitForReceipt, + client: this.evmClient, + }, + ); + + const result: ExecuteResult = { + chainId: params.toChainId, + explorerUrl: createExplorerTxURL( + executeResponse.txHash, + dstChain.blockExplorers!.default.url, + ), + transactionHash: executeResponse.txHash, + approvalTransactionHash: executeResponse.approvalHash, + receipt: executeResponse.receipt, + confirmations: params.requiredConfirmations, + effectiveGasPrice: String(0), + gasUsed: String(executeResponse.receipt?.gasUsed ?? 0n), + }; + + return result; + } + + public async simulateExecute(params: ExecuteParams, address: Hex): Promise { + const { dstPublicClient, tx } = await this.createTxsForExecute(params, address); + + const [gasUsed, feeEstimate] = await Promise.all([ + dstPublicClient.estimateGas({ + to: tx.to, + data: tx.data, + value: tx.value, + account: address, + }), + dstPublicClient.estimateFeesPerGas(), + ]); + + const gasPrice = feeEstimate.maxFeePerGas ?? feeEstimate.gasPrice ?? 0n; + if (gasPrice === 0n) { + throw Errors.gasPriceError({}); + } + + return { + gasUsed: gasUsed, + gasPrice: gasPrice, + gasFee: gasUsed * gasPrice, + }; + } + + /** + * Calculate optimal bridge amount based on destination chain balance + * Returns the exact amount needed to bridge, or indicates if bridge can be skipped entirely + */ + private async calculateOptimalBridgeAmount( + chain: Chain, + tokenAddress: Hex, + tokenDecimals: number, + requiredTokenAmount: bigint, + requiredGasAmount: bigint, + assets: UserAssetDatum[], + ): Promise<{ skipBridge: boolean; tokenAmount: bigint; gasAmount: bigint }> { + try { + let skipBridge = true; + let tokenAmount = requiredTokenAmount; + let gasAmount = requiredGasAmount; + const assetList = new UserAssets(assets); + const { destinationAssetBalance, destinationGasBalance } = assetList.getAssetDetails( + chain, + tokenAddress, + ); + + const destinationTokenAmount = mulDecimals(destinationAssetBalance, tokenDecimals); + const destinationGasAmount = mulDecimals( + destinationGasBalance, + chain.nativeCurrency.decimals, + ); + + logger.debug('calculateOptimalBridgeAmount', { + destinationTokenAmount, + requiredTokenAmount, + destinationGasAmount, + requiredGasAmount, + }); + + const isGasBridgeRequired = destinationGasAmount < requiredGasAmount; + const isTokenBridgeRequired = destinationTokenAmount < requiredTokenAmount; + + if (isGasBridgeRequired || isTokenBridgeRequired) { + skipBridge = false; + + tokenAmount = + destinationTokenAmount < requiredTokenAmount + ? requiredTokenAmount - destinationTokenAmount + : 0n; + + gasAmount = + destinationGasAmount < requiredGasAmount ? requiredGasAmount - destinationGasAmount : 0n; + } + + return { + skipBridge, + tokenAmount, + gasAmount, + }; + } catch (error) { + logger.warn(`Failed to calculate optimal bridge amount: ${error}`); + // Default to bridging full amount on error + return { skipBridge: false, tokenAmount: requiredTokenAmount, gasAmount: requiredGasAmount }; + } + } + + private async simulateBundle(input: { + tokenSymbol: string; + tokenAddress: Hex; + amount: bigint; + txs: Tx[]; + chainId: number; + userAddress: Hex; + }) { + const overrides = generateStateOverride(input); + return this.simulationClient.simulateBundleV2({ + chainId: String(input.chainId), + simulations: input.txs.map((tx, i) => ({ + type: 'something', + from: input.userAddress, + to: tx.to, + data: tx.data, + value: toHex(tx.value), + stepId: `sim_${i}`, + stateOverride: overrides, + })), + }); + } + + private async sendTx( + params: { + tx: Tx; + approvalTx: Tx | null; + gas?: bigint; + gasPrice?: bigint; + }, + options: { + emit?: OnEventParam['onEvent']; + chain: Chain; + dstPublicClient: PublicClient; + address: Hex; + client: WalletClient; + waitForReceipt?: boolean; + receiptTimeout?: number; + requiredConfirmations?: number; + }, + ) { + const { waitForReceipt = true, receiptTimeout = 300000, requiredConfirmations = 1 } = options; + + let approvalHash; + if (params.approvalTx) { + approvalHash = await options.client.sendTransaction({ + ...params.approvalTx, + account: options.address, + chain: options.chain, + }); + + await waitForTxReceipt(approvalHash, options.dstPublicClient, 1); + if (options.emit) { + options.emit({ + name: NEXUS_EVENTS.STEP_COMPLETE, + args: BRIDGE_STEPS.EXECUTE_APPROVAL_STEP, + }); + } + } + + const txHash = await options.client.sendTransaction({ + ...params.tx, + account: options.address, + chain: options.chain, + gas: params.gas, + gasPrice: params.gasPrice, + }); + + if (options.emit) { + options.emit({ + name: NEXUS_EVENTS.STEP_COMPLETE, + args: BRIDGE_STEPS.EXECUTE_TRANSACTION_SENT, + }); + } + + let receipt; + if (waitForReceipt) { + receipt = await waitForTxReceipt( + txHash, + options.dstPublicClient, + requiredConfirmations, + receiptTimeout, + ); + + if (options.emit) { + options.emit({ + name: NEXUS_EVENTS.STEP_COMPLETE, + args: BRIDGE_STEPS.EXECUTE_TRANSACTION_CONFIRMED, + }); + } + } + + return { + txHash, + receipt, + approvalHash, + }; + } + + private bridgeWrapper = async ( + params: BridgeParams, + options?: OnEventParam, + ): Promise => { + const handler = this.bridge(params, options); + const result = await handler.execute(); + return { + explorerUrl: result?.explorerURL ?? '', + }; + }; + + private simulateBridgeWrapper = async (params: BridgeParams) => { + try { + const handler = this.bridge(params); + const result = await handler.simulate(); + return result; + } catch (e) { + logger.debug('simulateBridgeError', { e }); + return null; + } + }; +} + +export { BridgeAndExecuteQuery }; diff --git a/packages/core/sdk/ca-base/query/bridgeAndTransfer.ts b/packages/core/sdk/ca-base/query/bridgeAndTransfer.ts new file mode 100644 index 00000000..cb5d4a65 --- /dev/null +++ b/packages/core/sdk/ca-base/query/bridgeAndTransfer.ts @@ -0,0 +1,42 @@ +import { mulDecimals } from '../utils'; +import { ChainListType, BridgeAndExecuteParams, Tx, TransferParams } from '@nexus/commons'; +import { encodeFunctionData } from 'viem'; +import { ERC20ABI } from '@avail-project/ca-common'; +import { Errors } from '../errors'; + +const createBridgeAndTransferParams = ( + input: TransferParams, + chainList: ChainListType, +): BridgeAndExecuteParams => { + const { token } = chainList.getChainAndTokenFromSymbol(input.toChainId, input.token); + if (!token) { + throw Errors.tokenNotFound(input.token, input.toChainId); + } + + const tokenAmountInBigint = mulDecimals(input.amount, token.decimals); + + const tx: Tx = token.isNative + ? { + to: input.recipient, + value: tokenAmountInBigint, + data: '0x', + } + : { + to: token.contractAddress, + value: 0n, + data: encodeFunctionData({ + abi: ERC20ABI, + functionName: 'transfer', + args: [input.recipient, tokenAmountInBigint], + }), + }; + + return { + toChainId: input.toChainId, + amount: tokenAmountInBigint, + token: input.token, + execute: tx, + }; +}; + +export { createBridgeAndTransferParams }; diff --git a/packages/core/sdk/ca-base/query/index.ts b/packages/core/sdk/ca-base/query/index.ts index 49611871..4d3eacf5 100644 --- a/packages/core/sdk/ca-base/query/index.ts +++ b/packages/core/sdk/ca-base/query/index.ts @@ -1,3 +1 @@ -export * from "./allowance"; -export * from "./bridge"; -export * from "./transfer"; +export * from "./bridgeAndTransfer"; diff --git a/packages/core/sdk/ca-base/query/transfer.ts b/packages/core/sdk/ca-base/query/transfer.ts deleted file mode 100644 index d8264489..00000000 --- a/packages/core/sdk/ca-base/query/transfer.ts +++ /dev/null @@ -1,135 +0,0 @@ -import { Account, bn, CHAIN_IDS } from 'fuels'; -import { encodeFunctionData, Hex } from 'viem'; - -import ERC20ABI from '../abi/erc20'; -import { ZERO_ADDRESS } from '../constants'; -import { getLogger } from '../logger'; -import { convertIntent, equalFold, mulDecimals } from '../utils'; -import { - CA, - CreateHandlerResponse, - EVMTransaction, - TransferQueryInput, - ChainListType, -} from '@nexus/commons'; - -const logger = getLogger(); - -class TransferQuery { - private handlerResponse: CreateHandlerResponse | null = null; - constructor( - private input: TransferQueryInput, - private init: CA['init'], - private switchChain: CA['switchChain'], - private createEVMHandler: CA['createEVMHandler'], - private createFuelHandler: CA['createFuelHandler'], - private evmAddress: Hex, - private chainList: ChainListType, - private fuelAccount?: Account, - ) {} - - exec = async () => { - if (!this.handlerResponse?.handler) { - throw new Error('ca not applicable'); - } - - let explorerURL = ''; - const result = await this.handlerResponse.handler.process(); - if (result) { - explorerURL = result.explorerURL; - } - logger.debug('TransferQuery:Exec', { - state: 'processing completed, going to processTx()', - }); - const hash = (await this.handlerResponse.processTx()) as Hex; - return { - hash, - explorerURL, - }; - }; - - public async initHandler() { - if (!this.handlerResponse) { - const input = this.input; - await this.init(); - - logger.debug('SendQueryBuilder.exec', { - c: input.chainId, - p: input, - }); - if (input.to && input.amount !== undefined && input.token && input.chainId) { - const tokenInfo = this.chainList.getTokenInfoBySymbol(input.chainId, input.token); - if (!tokenInfo) { - throw new Error('Token not supported on this chain.'); - } - - const amount = mulDecimals(input.amount, tokenInfo.decimals); - - logger.debug('transfer:2', { amount, tokenInfo }); - - if (input.chainId === CHAIN_IDS.fuel.mainnet) { - if (this.fuelAccount) { - const tx = await this.fuelAccount.createTransfer( - input.to, - bn(amount.toString()), - tokenInfo.contractAddress, - ); - this.handlerResponse = await this.createFuelHandler(tx, { - bridge: false, - gas: 0n, - skipTx: false, - }); - } else { - throw new Error('Fuel connector is not set'); - } - } else { - await this.switchChain(input.chainId); - const isNative = equalFold(tokenInfo.contractAddress, ZERO_ADDRESS); - - const p: EVMTransaction = { - from: this.evmAddress, - to: input.to, - }; - if (isNative) { - p.value = `0x${amount.toString(16)}`; - } else { - p.to = tokenInfo.contractAddress; - p.data = encodeFunctionData({ - abi: ERC20ABI, - args: [input.to, amount], - functionName: 'transfer', - }); - } - - this.handlerResponse = await this.createEVMHandler(p, { - bridge: false, - gas: 0n, - skipTx: false, - sourceChains: input.sourceChains, - }); - } - - return; - } - throw new Error('transfer: missing params'); - } - } - - simulate = async () => { - if (!this.handlerResponse?.handler) { - throw new Error('ca not applicable'); - } - - const response = await this.handlerResponse.handler.buildIntent(this.input.sourceChains ?? []); - if (!response) { - throw new Error('ca not applicable'); - } - - return { - intent: convertIntent(response.intent, response.token, this.chainList), - token: response.token, - }; - }; -} - -export { TransferQuery }; diff --git a/packages/core/sdk/ca-base/requestHandlers/bridge.ts b/packages/core/sdk/ca-base/requestHandlers/bridge.ts new file mode 100644 index 00000000..420f8089 --- /dev/null +++ b/packages/core/sdk/ca-base/requestHandlers/bridge.ts @@ -0,0 +1,1034 @@ +import { + ArcanaVault, + ChaindataMap, + ERC20ABI, + EVMVaultABI, + OmniversalChainID, + PermitVariant, + Universe, +} from '@avail-project/ca-common'; +import Decimal from 'decimal.js'; +import { Account, BN, CHAIN_IDS, hexlify } from 'fuels'; +import Long from 'long'; +import { + ContractFunctionExecutionError, + createPublicClient, + encodeFunctionData, + Hex, + hexToBytes, + JsonRpcAccount, + maxUint256, + parseSignature, + toHex, + UserRejectedRequestError, + webSocket, +} from 'viem'; +import { isNativeAddress } from '../constants'; +import { createSteps } from '../steps'; +import { + Intent, + onAllowanceHookSource, + SetAllowanceInput, + SponsoredApprovalDataArray, + Chain, + TokenInfo, + getLogger, + IBridgeOptions, + NEXUS_EVENTS, + BridgeStepType, + BRIDGE_STEPS, +} from '@nexus/commons'; +import { + convertGasToToken, + convertIntent, + convertTo32Bytes, + cosmosCreateRFF, + createDepositDoubleCheckTx, + createPublicClientWithFallback, + equalFold, + FeeStore, + fetchPriceOracle, + getAllowances, + getExplorerURL, + getFeeStore, + mulDecimals, + removeIntentHashFromStore, + signPermitForAddressAndValue, + storeIntentHashToStore, + switchChain, + vscCreateRFF, + vscCreateSponsoredApprovals, + vscPublishRFF, + waitForTxReceipt, + UserAssets, + waitForTronDepositTxConfirmation, + waitForTronApprovalTxConfirmation, + divDecimals, + requestTimeout, + cosmosFillCheck, + waitForIntentFulfilment, + createRFFromIntent, + retrieveAddress, + getBalances, +} from '../utils'; +import { TronWeb } from 'tronweb'; +import { Errors } from '../errors'; + +type Params = { + recipient?: Hex; + dstChain: Chain; + dstToken: TokenInfo; + tokenAmount: bigint; + nativeAmount: bigint; + sourceChains: number[]; +}; + +const logger = getLogger(); + +class BridgeHandler { + protected steps: BridgeStepType[] = []; + protected params: Required; + constructor( + params: Params, + readonly options: IBridgeOptions, + ) { + this.params = { + ...params, + recipient: retrieveAddress(params.dstChain.universe, options), + }; + console.log({ params: this.params, options }); + } + + public async simulate() { + const intent = await this.buildIntent(this.params.sourceChains); + return { + intent: convertIntent(intent, this.params.dstToken, this.options.chainList), + token: this.params.dstToken, + }; + } + + private buildIntent = async (sourceChains: number[] = []) => { + console.time('process:preIntentSteps'); + + console.time('preIntentSteps:API'); + const [balances, oraclePrices, feeStore] = await Promise.all([ + getBalances({ + networkHint: this.options.networkConfig.NETWORK_HINT, + vscDomain: this.options.networkConfig.VSC_DOMAIN, + evmAddress: this.options.evm.address, + chainList: this.options.chainList, + fuelAddress: this.options.fuel?.address, + tronAddress: this.options.tron?.address, + isCA: true, + }), + fetchPriceOracle(this.options.networkConfig.GRPC_URL), + getFeeStore(this.options.networkConfig.GRPC_URL), + ]); + + logger.debug('Step 0: BuildIntent', { + balances, + oraclePrices, + feeStore, + }); + + console.timeEnd('preIntentSteps:API'); + logger.debug('Step 1:', { + balances, + feeStore, + oraclePrices, + }); + + console.time('preIntentSteps: Parse'); + + const { assets } = balances; + // Step 2: parse simulation results + + const userAssets = new UserAssets(assets); + + console.time('preIntentSteps: CalculateGas'); + + const nativeAmountInDecimal = divDecimals( + this.params.nativeAmount, + this.params.dstChain.nativeCurrency.decimals, + ); + + const tokenAmountInDecimal = divDecimals( + this.params.tokenAmount, + this.params.dstToken.decimals, + ); + + const gasInToken = convertGasToToken( + this.params.dstToken, + oraclePrices, + this.params.dstChain.id, + this.params.dstChain.universe, + nativeAmountInDecimal, + ); + + console.timeEnd('preIntentSteps: CalculateGas'); + + logger.debug('preIntent:1', { + gasInNative: nativeAmountInDecimal.toFixed(), + gasInToken: gasInToken.toFixed(), + }); + + // Step 4: create intent + console.time('preIntentSteps: CreateIntent'); + const intent = this.createIntent({ + amount: tokenAmountInDecimal, + assets: userAssets, + feeStore, + gas: nativeAmountInDecimal, + gasInToken, + sourceChains, + token: this.params.dstToken, + }); + console.timeEnd('preIntentSteps: CreateIntent'); + console.timeEnd('process:preIntentSteps'); + + if (intent.isAvailableBalanceInsufficient) { + throw Errors.insufficientBalance(); + } + + return intent; + }; + + private filterInsufficientAllowanceSources( + intent: Intent, + allowances: Awaited>, + ) { + const sources: onAllowanceHookSource[] = []; + for (const s of intent.sources) { + if ( + s.chainID === intent.destination.chainID || + isNativeAddress(s.universe, s.tokenContract) + ) { + continue; + } + + const chain = this.options.chainList.getChainByID(s.chainID); + if (!chain) { + throw Errors.chainNotFound(s.chainID); + } + + const token = this.options.chainList.getTokenByAddress(s.chainID, s.tokenContract); + if (!token) { + throw Errors.tokenNotSupported(s.tokenContract, s.chainID); + } + + const requiredAllowance = mulDecimals(s.amount, token.decimals); + const currentAllowance = allowances[s.chainID] ?? 0n; + + logger.debug('getUnallowedSources:1', { + currentAllowance: currentAllowance.toString(), + requiredAllowance: requiredAllowance.toString(), + token, + }); + + if (requiredAllowance > currentAllowance) { + const d = { + allowance: { + current: currentAllowance.toString(), + minimum: requiredAllowance.toString(), + }, + chain: { + id: chain.id, + logo: chain.custom.icon, + name: chain.name, + }, + token: { + contractAddress: token.contractAddress, + decimals: token.decimals, + logo: token.logo || '', + name: token.name, + symbol: token.symbol, + }, + }; + sources.push(d); + } + } + return sources; + } + + public execute = async () => { + let intent = await this.buildIntent(this.params.sourceChains); + + const allowances = await getAllowances(intent.allSources, this.options.chainList); + + let insufficientAllowanceSources = this.filterInsufficientAllowanceSources(intent, allowances); + this.createExpectedSteps(intent, insufficientAllowanceSources); + + let accepted = false; + const refresh = async (sourceChains?: number[]) => { + if (accepted) { + logger.warn('Intent refresh called after acceptance'); + return convertIntent(intent, this.params.dstToken, this.options.chainList); + } + + intent = await this.buildIntent(sourceChains); + if (intent.isAvailableBalanceInsufficient) { + throw Errors.insufficientBalance(); + } + insufficientAllowanceSources = this.filterInsufficientAllowanceSources(intent, allowances); + this.createExpectedSteps(intent, insufficientAllowanceSources); + + return convertIntent(intent, this.params.dstToken, this.options.chainList); + }; + + // wait for intent acceptance hook + await new Promise((resolve, reject) => { + const allow = () => { + accepted = true; + return resolve('User allowed intent'); + }; + + const deny = () => { + return reject(Errors.userDeniedIntent()); + }; + + this.options.hooks.onIntent({ + allow, + deny, + intent: convertIntent(intent, this.params.dstToken, this.options.chainList), + refresh, + }); + }); + + this.markStepDone(BRIDGE_STEPS.INTENT_ACCEPTED); + + console.time('process:AllowanceHook'); + + // Step 5: set allowance if not set + await this.waitForOnAllowanceHook(insufficientAllowanceSources); + console.timeEnd('process:AllowanceHook'); + + // Step 6: process intent + return this.executeIntent(intent); + }; + + private async waitForFill( + requestHash: `0x${string}`, + intentID: Long, + waitForDoubleCheckTx: () => Promise, + ) { + waitForDoubleCheckTx(); + + const ac = new AbortController(); + let promisesToRace = [ + requestTimeout(3, ac), + cosmosFillCheck( + intentID, + this.options.networkConfig.GRPC_URL, + this.options.networkConfig.COSMOS_URL, + ac, + ), + ]; + + // Use eth_subscribe to read fill events if destination is EVM - usually the fastest + if (this.params.dstChain.universe === Universe.ETHEREUM) { + promisesToRace.push( + waitForIntentFulfilment( + createPublicClient({ + transport: webSocket(this.params.dstChain.rpcUrls.default.webSocket[0]), + }), + this.options.chainList.getVaultContractAddress(this.params.dstChain.id), + requestHash, + ac, + ), + ); + } + await Promise.race(promisesToRace); + } + + private async executeIntent(intent: Intent) { + logger.debug('intent', { intent }); + + const { explorerURL, intentID, requestHash, waitForDoubleCheckTx } = + await this.processRFF(intent); + + storeIntentHashToStore(this.options.evm.address, intentID.toNumber()); + await this.waitForFill(requestHash, intentID, waitForDoubleCheckTx); + removeIntentHashFromStore(this.options.evm.address, intentID); + + this.markStepDone(BRIDGE_STEPS.INTENT_FULFILLED); + + if (this.params.dstChain.universe === Universe.ETHEREUM) { + await switchChain(this.options.evm.client, this.params.dstChain); + } + + return { explorerURL, intentID }; + } + + private async processRFF(intent: Intent) { + const { msgBasicCosmos, omniversalRFF, signatureData, sources, universes } = + await createRFFromIntent(intent, this.options, this.params.dstChain.universe); + + this.markStepDone(BRIDGE_STEPS.INTENT_HASH_SIGNED); + + logger.debug('processRFF:3', { msgBasicCosmos }); + + const intentID = await cosmosCreateRFF({ + address: this.options.cosmos.address, + cosmosURL: this.options.networkConfig.COSMOS_URL, + msg: msgBasicCosmos, + wallet: this.options.cosmos.wallet, + }); + + const explorerURL = getExplorerURL(this.options.networkConfig.EXPLORER_URL, intentID); + this.markStepDone(BRIDGE_STEPS.INTENT_SUBMITTED(explorerURL, intentID.toNumber())); + + const tokenCollections: number[] = []; + for (const [i, s] of sources.entries()) { + if (!isDeposit(s.universe, s.tokenAddress)) { + tokenCollections.push(i); + } + } + + const evmDeposits: Promise[] = []; + const fuelDeposits: Promise[] = []; + const tronDeposits: Promise[] = []; + + const evmSignatureData = signatureData.find((d) => d.universe === Universe.ETHEREUM); + + if (!evmSignatureData && universes.has(Universe.ETHEREUM)) { + throw Errors.internal('ethereum in universe list but no signature data present'); + } + + const fuelSignatureData = signatureData.find((d) => d.universe === Universe.FUEL); + + if (!fuelSignatureData && universes.has(Universe.FUEL)) { + throw Errors.internal('fuel in universe list but no signature data present'); + } + + const tronSignatureData = signatureData.find((d) => d.universe === Universe.TRON); + + if (!tronSignatureData && universes.has(Universe.TRON)) { + throw Errors.internal('tron in universe list but no signature data present'); + } + + const doubleCheckTxs = []; + + for (const [i, s] of sources.entries()) { + const chain = this.options.chainList.getChainByID(Number(s.chainID)); + if (!chain) { + throw Errors.chainNotFound(s.chainID); + } + + if (s.universe === Universe.FUEL) { + if (!this.options.fuel) { + throw Errors.internal('fuel is involved but no associated data'); + } + + const account = new Account( + this.options.fuel.address, + this.options.fuel.provider, + this.options.fuel.connector, + ); + + const vault = new ArcanaVault( + this.options.chainList.getVaultContractAddress(CHAIN_IDS.fuel.mainnet), + account, + ); + + const tx = await vault.functions + .deposit(omniversalRFF.asFuelRFF(), hexlify(fuelSignatureData!.signature), i) + .callParams({ + forward: { + amount: new BN(s.valueRaw.toString()), + assetId: s.tokenAddress, + }, + }) + .call(); + + this.markStepDone(BRIDGE_STEPS.INTENT_DEPOSIT_REQUEST(i + 1, s.value, chain)); + + fuelDeposits.push( + (async function () { + const result = await tx.waitForResult(); + logger.debug('PostIntentSubmission: Fuel deposit result', { + result, + }); + + if (result.transactionResult.isStatusFailure) { + throw Errors.fuelDepositFailed(result.transactionResult); + } + })(), + ); + } else if (s.universe === Universe.ETHEREUM && isNativeAddress(s.universe, s.tokenAddress)) { + await switchChain(this.options.evm.client, chain); + + const publicClient = createPublicClientWithFallback(chain); + + const { request } = await publicClient.simulateContract({ + abi: EVMVaultABI, + account: this.options.evm.address, + address: this.options.chainList.getVaultContractAddress(chain.id), + args: [omniversalRFF.asEVMRFF(), toHex(evmSignatureData!.signature), BigInt(i)], + chain: chain, + functionName: 'deposit', + value: s.valueRaw, + }); + const hash = await this.options.evm.client.writeContract(request); + this.markStepDone(BRIDGE_STEPS.INTENT_DEPOSIT_REQUEST(i + 1, s.value, chain)); + + evmDeposits.push(waitForTxReceipt(hash, publicClient)); + } else if (s.universe === Universe.TRON) { + const provider = new TronWeb({ + fullHost: chain.rpcUrls.default.grpc![0], + }); + const vaultContractAddress = this.options.chainList.getVaultContractAddress( + Number(s.chainID), + ); + const txWrap = await provider.transactionBuilder.triggerSmartContract( + TronWeb.address.fromHex(vaultContractAddress), + '', + { + txLocal: true, + input: encodeFunctionData({ + abi: EVMVaultABI, + functionName: 'deposit', + args: [omniversalRFF.asEVMRFF(), toHex(tronSignatureData!.signature), BigInt(i)], + }), + }, + [], + TronWeb.address.fromHex(this.options.tron!.address), + ); + + const signedTx = await this.options.tron!.adapter.signTransaction(txWrap.transaction); + + logger.debug('tron deposit signTransaction result', { + signedTx, + }); + + if (!this.options.tron!.adapter.isMobile) { + const txResult = await provider.trx.sendRawTransaction(signedTx); + + logger.debug('tron deposit tx result', { + txResult, + }); + if (!txResult.result) { + throw Errors.tronDepositFailed(txResult); + } + } + + tronDeposits.push( + (async () => { + await waitForTronDepositTxConfirmation( + tronSignatureData!.requestHash, + vaultContractAddress, + provider, + this.options.tron!.address as Hex, + ); + })(), + ); + } + doubleCheckTxs.push( + createDepositDoubleCheckTx( + convertTo32Bytes(chain.id), + this.options.cosmos, + intentID, + this.options.networkConfig, + ), + ); + } + + if (evmDeposits.length || fuelDeposits.length || tronDeposits.length) { + await Promise.all([ + Promise.all(evmDeposits), + Promise.all(tronDeposits), + Promise.all(fuelDeposits), + ]); + this.markStepDone(BRIDGE_STEPS.INTENT_DEPOSITS_CONFIRMED); + } + + logger.debug('PostIntentSubmission: Intent ID', { + id: intentID.toNumber(), + }); + + if (tokenCollections.length > 0) { + logger.debug('processRFF', { + intentID: intentID.toString(), + message: 'going to create RFF', + tokenCollections, + }); + await vscCreateRFF( + this.options.networkConfig.VSC_DOMAIN, + intentID, + this.markStepDone, + tokenCollections, + ); + } else { + logger.debug('processRFF', { + message: 'going to publish RFF', + }); + await vscPublishRFF(this.options.networkConfig.VSC_DOMAIN, intentID); + } + + const destinationSigData = signatureData.find( + (s) => s.universe === intent.destination.universe, + ); + + if (!destinationSigData) { + throw new Error('requestHash not found for destination'); + } + + return { + explorerURL, + intentID, + requestHash: destinationSigData.requestHash, + waitForDoubleCheckTx: waitForDoubleCheckTx(doubleCheckTxs), + }; + } + + private async setAllowances(input: Array) { + const originalChain = this.params.dstChain.id; + logger.debug('setAllowances', { originalChain, input }); + + const sponsoredApprovalParams: SponsoredApprovalDataArray = []; + try { + for (const source of input) { + const chain = this.options.chainList.getChainByID(source.chainID); + if (!chain) { + throw Errors.chainNotFound(source.chainID); + } + + const publicClient = createPublicClientWithFallback(chain); + + const vc = this.options.chainList.getVaultContractAddress(chain.id); + + const chainId = new OmniversalChainID(chain.universe, source.chainID); + const chainDatum = ChaindataMap.get(chainId); + if (!chainDatum) { + throw Errors.internal('Chain data not found', { + chainId: source.chainID, + universe: chain.universe, + }); + } + + const currency = chainDatum.CurrencyMap.get(convertTo32Bytes(source.tokenContract)); + if (!currency) { + throw Errors.internal('currency not found', { + chainId: source.chainID, + tokenContractAddress: source.tokenContract, + }); + } + + if (currency.permitVariant === PermitVariant.Unsupported || chain.id === 1) { + if (chain.universe === Universe.ETHEREUM) { + await switchChain(this.options.evm.client, chain); + + const h = await this.options.evm.client + .writeContract({ + abi: ERC20ABI, + account: this.options.evm.address, + address: source.tokenContract, + args: [vc, BigInt(source.amount)], + chain, + functionName: 'approve', + }) + .catch((e) => { + if (e instanceof ContractFunctionExecutionError) { + const isUserRejectedRequestError = + e.walk((e) => e instanceof UserRejectedRequestError) instanceof + UserRejectedRequestError; + if (isUserRejectedRequestError) { + throw Errors.userRejectedAllowance(); + } + } + throw e; + }); + + this.markStepDone(BRIDGE_STEPS.ALLOWANCE_APPROVAL_REQUEST(chain)); + + await waitForTxReceipt(h, publicClient); + } else if (chain.universe === Universe.TRON) { + if (!this.options.tron) { + throw Errors.internal('Tron is available in sources but has no adapter/provider'); + } + + const provider = new TronWeb({ + fullHost: chain.rpcUrls.default.grpc![0], + }); + const tx = await provider.transactionBuilder.triggerSmartContract( + TronWeb.address.fromHex(source.tokenContract), + 'approve(address,uint256)', + { + txLocal: true, + }, + [ + { type: 'address', value: TronWeb.address.fromHex(vc) }, + { type: 'uint256', value: source.amount.toString() }, + ], + TronWeb.address.fromHex(this.options.tron?.address), + ); + const signedTx = await this.options.tron.adapter.signTransaction(tx.transaction); + logger.debug('tron approval signTransaction result', { + signedTx, + }); + + if (!this.options.tron!.adapter.isMobile) { + const txResult = await provider.trx.sendRawTransaction(signedTx); + + logger.debug('tron tx result', { + txResult, + }); + if (!txResult.result) { + throw Errors.tronApprovalFailed(txResult); + } + } + + await waitForTronApprovalTxConfirmation( + source.amount, + this.options.tron.address as Hex, + vc, + source.tokenContract, + provider, + ); + } + + this.markStepDone(BRIDGE_STEPS.ALLOWANCE_APPROVAL_MINED(chain)); + } else { + const account: JsonRpcAccount = { + address: this.options.evm.address, + type: 'json-rpc', + }; + + await switchChain(this.options.evm.client, chain); + + const signed = parseSignature( + await signPermitForAddressAndValue( + currency, + this.options.evm.client, + publicClient, + account, + vc, + source.amount, + ).catch((e) => { + if (e instanceof ContractFunctionExecutionError) { + const isUserRejectedRequestError = + e.walk((e) => e instanceof UserRejectedRequestError) instanceof + UserRejectedRequestError; + if (isUserRejectedRequestError) { + throw Errors.userRejectedAllowance(); + } + } + throw e; + }), + ); + + this.markStepDone(BRIDGE_STEPS.ALLOWANCE_APPROVAL_REQUEST(chain)); + + sponsoredApprovalParams.push({ + address: convertTo32Bytes(account.address), + chain_id: chainDatum.ChainID32, + operations: [ + { + sig_r: hexToBytes(signed.r), + sig_s: hexToBytes(signed.s), + sig_v: signed.yParity < 27 ? signed.yParity + 27 : signed.yParity, + token_address: currency.tokenAddress, + value: convertTo32Bytes(source.amount), + variant: currency.permitVariant === PermitVariant.PolygonEMT ? 2 : 1, + }, + ], + universe: chainDatum.Universe, + }); + } + } + + if (sponsoredApprovalParams.length) { + logger.debug('setAllowances:sponsoredApprovals', { + sponsoredApprovalParams, + }); + await vscCreateSponsoredApprovals( + this.options.networkConfig.VSC_DOMAIN, + sponsoredApprovalParams, + this.markStepDone, + ); + } + } catch (e) { + logger.error('Error setting allowances', e); + throw e; + } finally { + if (this.params.dstChain.universe === Universe.ETHEREUM) { + await switchChain(this.options.evm.client, this.params.dstChain); + } + this.markStepDone(BRIDGE_STEPS.ALLOWANCE_COMPLETE); + } + } + + private async waitForOnAllowanceHook(sources: onAllowanceHookSource[]): Promise { + if (sources.length === 0) { + return false; + } + + await new Promise((resolve, reject) => { + const allow = (allowances: Array<'max' | 'min' | bigint | string>) => { + if (sources.length !== allowances.length) { + return reject(Errors.invalidAllowance(sources.length, allowances.length)); + } + + logger.debug('CA:BaseRequest:Allowances', { + allowances, + sources, + }); + const val: Array = []; + for (let i = 0; i < sources.length; i++) { + const source = sources[i]; + const allowance = allowances[i]; + let amount = 0n; + if (typeof allowance === 'string' && equalFold(allowance, 'max')) { + amount = maxUint256; + } else if (typeof allowance === 'string' && equalFold(allowance, 'min')) { + amount = BigInt(source.allowance.minimum); + } else if (typeof allowance === 'string') { + amount = mulDecimals(allowance, source.token.decimals); + } else { + amount = allowance; + } + val.push({ + amount, + chainID: source.chain.id, + tokenContract: source.token.contractAddress, + }); + } + this.setAllowances(val).then(resolve).catch(reject); + }; + + const deny = () => { + return reject(Errors.userRejectedAllowance); + }; + + this.options.hooks.onAllowance({ + allow, + deny, + sources, + }); + }); + + return true; + } + + private createExpectedSteps( + intent: Intent, + insufficientAllowanceSources?: onAllowanceHookSource[], + ) { + this.steps = createSteps(intent, this.options.chainList, insufficientAllowanceSources); + if (this.options.emit) { + this.options.emit({ name: NEXUS_EVENTS.STEPS_LIST, args: this.steps }); + } + logger.debug('BridgeSteps', this.steps); + } + + private createIntent(input: { + amount: Decimal; + assets: UserAssets; + feeStore: FeeStore; + gas: Decimal; + gasInToken: Decimal; + sourceChains: number[]; + token: TokenInfo; + }) { + const { amount, assets, feeStore, gas, gasInToken, token } = input; + const intent: Intent = { + allSources: [], + destination: { + amount: new Decimal('0'), + chainID: this.params.dstChain.id, + decimals: token.decimals, + gas: 0n, + tokenContract: token.contractAddress, + universe: this.params.dstChain.universe, + }, + fees: { + caGas: '0', + collection: '0', + fulfilment: '0', + gasSupplied: input.gasInToken.toFixed(), + protocol: '0', + solver: '0', + }, + isAvailableBalanceInsufficient: false, + sources: [], + recipientAddress: this.params.recipient, + }; + + const asset = assets.find(token.symbol); + if (!asset) { + throw new Error(`Asset ${token.symbol} not found in UserAssets`); + } + + const allSources = asset.iterate(feeStore).map((v) => { + const chain = this.options.chainList.getChainByID(v.chainID); + if (!chain) { + throw Errors.chainNotFound(v.chainID); + } + + return { ...v, amount: v.balance, holderAddress: retrieveAddress(v.universe, this.options) }; + }); + + intent.allSources = allSources; + + const destinationBalance = asset.getBalanceOnChain( + this.params.dstChain.id, + token.contractAddress, + ); + + const borrow = amount; + + const protocolFee = feeStore.calculateProtocolFee(borrow); + intent.fees.protocol = protocolFee.toFixed(); + + let borrowWithFee = borrow.add(gasInToken).add(protocolFee); + + logger.debug('createIntent:0', { + borrow: borrow.toFixed(), + borrowWithFee: borrowWithFee.toFixed(), + destinationBalance, + gasInToken: gasInToken.toFixed(), + protocolFee: protocolFee.toFixed(), + }); + + const fulfilmentFee = feeStore.calculateFulfilmentFee({ + decimals: token.decimals, + destinationChainID: this.params.dstChain.id, + destinationTokenAddress: token.contractAddress, + }); + logger.debug('createIntent:1', { fulfilmentFee }); + + intent.fees.fulfilment = fulfilmentFee.toFixed(); + + borrowWithFee = borrowWithFee.add(fulfilmentFee); + + let accountedAmount = new Decimal(0); + + const allowedSources = allSources.filter((b) => { + if (input.sourceChains.length === 0) { + return true; + } + return input.sourceChains.includes(b.chainID); + }); + + logger.debug('createIntent:1.1', { allowedSources }); + + for (const assetC of allowedSources) { + if (accountedAmount.greaterThanOrEqualTo(borrowWithFee)) { + break; + } + + if (assetC.chainID === this.params.dstChain.id) { + continue; + } + + // if (assetC.chainID === CHAIN_IDS.fuel.mainnet) { + // const fuelChain = this.options.chainList.getChainByID(CHAIN_IDS.fuel.mainnet); + // const baseAssetBalanceOnFuel = assets.getNativeBalance(fuelChain!); + // if (new Decimal(baseAssetBalanceOnFuel).lessThan('0.000_003')) { + // logger.debug('fuel base asset balance is lesser than min expected deposit fee, so skip', { + // current: baseAssetBalanceOnFuel, + // minimum: '0.000_003', + // }); + // continue; + // } + // } + + // Now collectionFee is a fixed amount - applicable to all + const collectionFee = feeStore.calculateCollectionFee({ + decimals: assetC.decimals, + sourceChainID: assetC.chainID, + sourceTokenAddress: assetC.tokenContract, + }); + + intent.fees.collection = collectionFee.add(intent.fees.collection).toFixed(); + borrowWithFee = borrowWithFee.add(collectionFee); + + logger.debug('createIntent:2', { collectionFee }); + + const unaccountedAmount = borrowWithFee.minus(accountedAmount); + + let borrowFromThisChain = new Decimal(assetC.balance).lessThanOrEqualTo(unaccountedAmount) + ? new Decimal(assetC.balance) + : unaccountedAmount; + + logger.debug('createIntent:2.1', { + accountedAmount: accountedAmount.toFixed(), + asset: assetC, + balance: assetC.balance.toFixed(), + borrowFromThisChain: borrowFromThisChain.toFixed(), + unaccountedAmount: unaccountedAmount.toFixed(), + }); + + const solverFee = feeStore.calculateSolverFee({ + borrowAmount: borrowFromThisChain, + decimals: assetC.decimals, + destinationChainID: this.params.dstChain.id, + destinationTokenAddress: token.contractAddress, + sourceChainID: assetC.chainID, + sourceTokenAddress: assetC.tokenContract, + }); + intent.fees.solver = solverFee.add(intent.fees.solver).toFixed(); + + logger.debug('createIntent:3', { solverFee }); + + borrowWithFee = borrowWithFee.add(solverFee); + + const unaccountedBalance = borrowWithFee.minus(accountedAmount); + + borrowFromThisChain = new Decimal(assetC.balance).lessThanOrEqualTo(unaccountedBalance) + ? new Decimal(assetC.balance) + : unaccountedBalance; + + intent.sources.push({ + amount: borrowFromThisChain, + chainID: assetC.chainID, + tokenContract: assetC.tokenContract, + universe: assetC.universe, + holderAddress: assetC.holderAddress, + }); + + accountedAmount = accountedAmount.add(borrowFromThisChain); + } + + intent.destination.amount = borrow; + + if (accountedAmount.lt(borrowWithFee)) { + intent.isAvailableBalanceInsufficient = true; + } + + if (!gas.equals(0)) { + intent.destination.gas = mulDecimals(gas, this.params.dstChain.nativeCurrency.decimals); + } + + logger.debug('createIntent:4', { intent }); + + return intent; + } + + private markStepDone = (step: BridgeStepType) => { + if (this.options.emit) { + const s = this.steps.find((s) => s.typeID === step.typeID); + if (s) { + this.options.emit({ + name: NEXUS_EVENTS.STEP_COMPLETE, + args: step, + }); + } + } + }; +} + +const isDeposit = (universe: Universe, tokenAddress: Hex) => { + if (universe === Universe.ETHEREUM) { + return isNativeAddress(universe, tokenAddress); + } + + return true; +}; + +const waitForDoubleCheckTx = (input: Array<() => Promise>) => { + return async () => { + await Promise.allSettled(input.map((i) => i())); + }; +}; + +export default BridgeHandler; diff --git a/packages/core/sdk/ca-base/requestHandlers/bridgeMax.ts b/packages/core/sdk/ca-base/requestHandlers/bridgeMax.ts new file mode 100644 index 00000000..17fca6a4 --- /dev/null +++ b/packages/core/sdk/ca-base/requestHandlers/bridgeMax.ts @@ -0,0 +1,50 @@ +import { BridgeParams, IBridgeOptions } from '@nexus/commons'; +import { getBalances, calculateMaxBridgeFee, getFeeStore, mulDecimals, UserAssets } from '../utils'; +import { Errors } from '../errors'; + +const getMaxValueForBridge = async ( + params: Omit, + options: Omit, +) => { + const token = options.chainList.getTokenInfoBySymbol(params.toChainId, params.token); + if (!token) { + throw Errors.tokenNotFound(params.token, params.toChainId); + } + + const [balances, feeStore] = await Promise.all([ + getBalances({ + networkHint: options.networkConfig.NETWORK_HINT, + vscDomain: options.networkConfig.VSC_DOMAIN, + evmAddress: options.evm.address, + chainList: options.chainList, + fuelAddress: options.fuel?.address, + tronAddress: options.tron?.address, + isCA: true, + }), + getFeeStore(options.networkConfig.GRPC_URL), + ]); + + const assets = new UserAssets(balances.assets); + + // FIXME: error in asset.find use NexusError and better messaging. + const tokenAsset = assets.find(params.token); + + const { maxAmount, sourceChainIds } = calculateMaxBridgeFee({ + assets: tokenAsset.getBridgeAssets(params.toChainId), + feeStore: feeStore, + dst: { + chainId: params.toChainId, + tokenAddress: token.contractAddress, + decimals: token.decimals, + }, + }); + + return { + sourceChainIds, + amountRaw: mulDecimals(maxAmount, token.decimals), + amount: maxAmount, + symbol: token.symbol, + }; +}; + +export default getMaxValueForBridge; diff --git a/packages/core/sdk/ca-base/requestHandlers/common/base.ts b/packages/core/sdk/ca-base/requestHandlers/common/base.ts deleted file mode 100644 index 3f4700f0..00000000 --- a/packages/core/sdk/ca-base/requestHandlers/common/base.ts +++ /dev/null @@ -1,1004 +0,0 @@ -import { - ArcanaVault, - ChaindataMap, - ERC20ABI, - EVMVaultABI, - MsgCreateRequestForFunds, - OmniversalChainID, - OmniversalRFF, - PermitVariant, - Universe, -} from '@arcana/ca-common'; -import Decimal from 'decimal.js'; -import { Account, BN, CHAIN_IDS, hexlify } from 'fuels'; -import Long from 'long'; -import { Hex, hexToBytes, JsonRpcAccount, maxUint256, parseSignature, toBytes, toHex } from 'viem'; -import { INTENT_EXPIRY, isNativeAddress } from '../../constants'; -import { - ErrorInsufficientBalance, - ErrorUserDeniedAllowance, - ErrorUserDeniedIntent, -} from '../../errors'; -import { getLogger } from '../../logger'; -import { - ALLOWANCE_APPROVAL_MINED, - ALLOWANCE_APPROVAL_REQ, - ALLOWANCE_COMPLETE, - createSteps, - INTENT_ACCEPTED, - INTENT_DEPOSIT_REQ, - INTENT_DEPOSITS_CONFIRMED, - INTENT_FULFILLED, - INTENT_HASH_SIGNED, - INTENT_SUBMITTED, -} from '../../steps'; -import { - ChainListType, - Intent, - IRequestHandler, - onAllowanceHookSource, - RequestHandlerInput, - SetAllowanceInput, - SimulateReturnType, - SponsoredApprovalDataArray, - Step, - StepInfo, - TokenInfo, -} from '@nexus/commons'; -import { - convertGasToToken, - convertIntent, - convertTo32Bytes, - convertTo32BytesHex, - cosmosCreateRFF, - createDepositDoubleCheckTx, - createPublicClientWithFallback, - createRequestEVMSignature, - createRequestFuelSignature, - equalFold, - FeeStore, - fetchPriceOracle, - getAllowances, - getExplorerURL, - getFeeStore, - getSourcesAndDestinationsForRFF, - mulDecimals, - removeIntentHashFromStore, - signPermitForAddressAndValue, - storeIntentHashToStore, - switchChain, - vscCreateRFF, - vscCreateSponsoredApprovals, - vscPublishRFF, - waitForTxReceipt, - UserAssets, -} from '../../utils'; -import { getBalances } from 'sdk/ca-base/swap/route'; - -const logger = getLogger(); - -abstract class BaseRequest implements IRequestHandler { - abstract destinationUniverse: Universe; - protected chainList: ChainListType; - protected steps: Step[] = []; - - constructor(readonly input: RequestHandlerInput) { - this.chainList = this.input.chainList; - } - - buildIntent = async (sourceChains: number[] = []) => { - console.time('process:preIntentSteps'); - - console.time('preIntentSteps:API'); - const [simulation, [balances, oraclePrices, feeStore]] = await Promise.all([ - this.simulateTx(), - Promise.all([ - getBalances({ - networkHint: this.input.options.networkConfig.NETWORK_HINT, - vscDomain: this.input.options.networkConfig.VSC_DOMAIN, - evmAddress: this.input.evm.address, - chainList: this.chainList, - fuelAddress: this.input.fuel?.address, - isCA: true, - }), - fetchPriceOracle(this.input.options.networkConfig.GRPC_URL), - getFeeStore(this.input.options.networkConfig.GRPC_URL), - ]), - ]); - - // if simulation is null, then the transaction is not a supported token transfer, so skip - if (!simulation) { - return; - } - - console.timeEnd('preIntentSteps:API'); - logger.debug('Step 1:', { - balances, - feeStore, - oraclePrices, - simulation, - }); - - console.time('preIntentSteps: Parse'); - - const { assets } = balances; - // Step 2: parse simulation results - - const userAssets = new UserAssets(assets); - const { amount, gas, isIntentRequired } = this.parseSimulation({ - assets: userAssets, - simulation, - }); - - console.timeEnd('preIntentSteps: Parse'); - if (!isIntentRequired) { - return; - } - console.time('preIntentSteps: CalculateGas'); - - const gasInToken = convertGasToToken( - simulation.token, - oraclePrices, - this.input.chain.id, - this.input.chain.universe, - gas, - ); - console.timeEnd('preIntentSteps: CalculateGas'); - - logger.debug('preIntent:1', { - gasInNative: gas.toFixed(), - gasInToken: gasInToken.toFixed(), - }); - - // Step 4: create intent - console.time('preIntentSteps: CreateIntent'); - const intent = this.createIntent({ - amount, - assets: userAssets, - feeStore, - gas, - gasInToken, - sourceChains, - token: simulation.token, - }); - console.timeEnd('preIntentSteps: CreateIntent'); - console.timeEnd('process:preIntentSteps'); - - if (intent.isAvailableBalanceInsufficient) { - throw ErrorInsufficientBalance; - } - - return { intent, token: simulation.token }; - }; - - getUnallowedSources(intent: Intent, allowances: Awaited>) { - const sources: onAllowanceHookSource[] = []; - for (const s of intent.sources) { - if ( - s.chainID === intent.destination.chainID || - isNativeAddress(s.universe, s.tokenContract) - ) { - continue; - } - - const chain = this.chainList.getChainByID(s.chainID); - if (!chain) { - throw new Error('chain is not supported'); - } - - const token = this.chainList.getTokenByAddress(s.chainID, s.tokenContract); - if (!token) { - throw new Error('token is not supported'); - } - - const requiredAllowance = mulDecimals(s.amount, token.decimals); - const currentAllowance = allowances[s.chainID] ?? 0n; - - logger.debug('getUnallowedSources:1', { - currentAllowance: currentAllowance.toString(), - requiredAllowance: requiredAllowance.toString(), - token, - }); - - if (requiredAllowance > currentAllowance) { - const d = { - allowance: { - current: currentAllowance.toString(), - minimum: requiredAllowance.toString(), - }, - chain: { - id: chain.id, - logo: chain.custom.icon, - name: chain.name, - }, - token: { - contractAddress: token.contractAddress, - decimals: token.decimals, - logo: token.logo || '', - name: token.name, - symbol: token.symbol, - }, - }; - sources.push(d); - } - } - return sources; - } - - abstract parseSimulation(input: { assets: UserAssets; simulation: SimulateReturnType }): { - amount: Decimal; - gas: Decimal; - isIntentRequired: boolean; - }; - - process = async () => { - const i = await this.buildIntent(this.input.options.sourceChains); - if (!i) { - return; - } - let intent = i.intent; - const token = i.token; - - if (intent.isAvailableBalanceInsufficient) { - throw ErrorInsufficientBalance; - } - - // Create steps like a crazy person to create another one again - const allowances = await getAllowances( - intent.allSources, - this.input.evm.address, - this.input.chainList, - ); - - let unallowedSources = this.getUnallowedSources(intent, allowances); - this.createExpectedSteps(intent, unallowedSources); - - let accepted = false; - const refresh = async (sourceChains?: number[]) => { - if (accepted) { - logger.warn('Intent refresh called after acceptance'); - return convertIntent(intent, token, this.chainList); - } - const i = await this.buildIntent(sourceChains); - intent = i!.intent; - logger.debug('in refresh', { - i, - intent, - }); - if (intent.isAvailableBalanceInsufficient) { - throw ErrorInsufficientBalance; - } - unallowedSources = this.getUnallowedSources(intent, allowances); - this.createExpectedSteps(intent, unallowedSources); - - return convertIntent(intent, token, this.chainList); - }; - - // wait for intent acceptance hook - await new Promise((resolve, reject) => { - const allow = () => { - accepted = true; - return resolve('User allowed intent'); - }; - - const deny = () => { - return reject(ErrorUserDeniedIntent); - }; - - this.input.hooks.onIntent({ - allow, - deny, - intent: convertIntent(intent, token, this.chainList), - refresh, - }); - }); - - this.markStepDone(INTENT_ACCEPTED); - - console.time('process:AllowanceHook'); - - // Step 5: set allowance if not set - await this.waitForOnAllowanceHook(unallowedSources); - console.timeEnd('process:AllowanceHook'); - - // FIXME: Add showing intent again if prices change? - // Step 6: process intent - return await this.processIntent(intent); - }; - - async processIntent(intent: Intent) { - logger.debug('intent', { intent }); - - const { explorerURL, id, requestHash, waitForDoubleCheckTx } = await this.processRFF(intent); - - storeIntentHashToStore(this.input.evm.address, id.toNumber()); - await this.waitForFill(requestHash, id, waitForDoubleCheckTx); - removeIntentHashFromStore(this.input.evm.address, id); - - this.markStepDone(INTENT_FULFILLED); - - if (this.input.chain.universe === Universe.ETHEREUM) { - await this.input.evm.client.switchChain({ id: this.input.chain.id }); - } - - return { explorerURL }; - } - - async processRFF(intent: Intent) { - const { destinations, sources, universes } = getSourcesAndDestinationsForRFF( - intent, - this.input.chainList, - this.destinationUniverse, - ); - - const parties: Array<{ address: string; universe: Universe }> = []; - for (const universe of universes) { - if (universe === Universe.ETHEREUM) { - parties.push({ - address: convertTo32BytesHex(this.input.evm.address), - universe: universe, - }); - } - - if (universe === Universe.FUEL) { - parties.push({ - address: convertTo32BytesHex(this.input.fuel!.address as Hex), - universe, - }); - } - } - - logger.debug('processRFF:1', { - destinations, - parties, - sources, - universes, - }); - - const omniversalRff = new OmniversalRFF({ - destinationChainID: convertTo32Bytes(intent.destination.chainID), - destinations: destinations.map((dest) => ({ - tokenAddress: toBytes(dest.tokenAddress), - value: toBytes(dest.value), - })), - destinationUniverse: intent.destination.universe, - expiry: Long.fromString((BigInt(Date.now() + INTENT_EXPIRY) / 1000n).toString()), - nonce: window.crypto.getRandomValues(new Uint8Array(32)), - // @ts-ignore - signatureData: parties.map((p) => ({ - address: toBytes(p.address), - universe: p.universe, - })), - // @ts-ignore - sources: sources.map((source) => ({ - chainID: convertTo32Bytes(source.chainID), - tokenAddress: convertTo32Bytes(source.tokenAddress), - universe: source.universe, - value: toBytes(source.value), - })), - }); - - const signatureData: { - address: Uint8Array; - requestHash: `0x${string}`; - signature: Uint8Array; - universe: Universe; - }[] = []; - - for (const universe of universes) { - if (universe === Universe.ETHEREUM) { - const { requestHash, signature } = await createRequestEVMSignature( - omniversalRff.asEVMRFF(), - this.input.evm.address, - this.input.evm.client, - ); - - signatureData.push({ - address: convertTo32Bytes(this.input.evm.address), - requestHash, - signature, - universe: Universe.ETHEREUM, - }); - } - - if (universe === Universe.FUEL) { - if ( - !this.input.fuel?.address || - !this.input.fuel?.provider || - !this.input.fuel?.connector - ) { - logger.error('universe has fuel but not expected input', { - fuelInput: this.input.fuel, - }); - throw new Error('universe has fuel but not expected input'); - } - - const { requestHash, signature } = await createRequestFuelSignature( - this.input.chainList.getVaultContractAddress(CHAIN_IDS.fuel.mainnet), - this.input.fuel.provider, - this.input.fuel.connector, - omniversalRff.asFuelRFF(), - ); - signatureData.push({ - address: toBytes(this.input.fuel.address), - requestHash, - signature, - universe: Universe.FUEL, - }); - } - } - - logger.debug('processRFF:2', { omniversalRff, signatureData }); - - this.markStepDone(INTENT_HASH_SIGNED); - - const cosmosWalletAddress = (await this.input.cosmosWallet.getAccounts())[0].address; - - const msgBasicCosmos = MsgCreateRequestForFunds.create({ - destinationChainID: omniversalRff.protobufRFF.destinationChainID, - destinations: omniversalRff.protobufRFF.destinations, - destinationUniverse: omniversalRff.protobufRFF.destinationUniverse, - expiry: omniversalRff.protobufRFF.expiry, - nonce: omniversalRff.protobufRFF.nonce, - signatureData: signatureData.map((s) => ({ - address: s.address, - signature: s.signature, - universe: s.universe, - })), - sources: omniversalRff.protobufRFF.sources, - user: cosmosWalletAddress, - }); - - logger.debug('processRFF:3', { msgBasicCosmos }); - - const intentID = await cosmosCreateRFF({ - address: cosmosWalletAddress, - cosmosURL: this.input.options.networkConfig.COSMOS_URL, - msg: msgBasicCosmos, - wallet: this.input.cosmosWallet, - }); - - const explorerURL = getExplorerURL(this.input.options.networkConfig.EXPLORER_URL, intentID); - this.markStepDone(INTENT_SUBMITTED, { - explorerURL, - intentID: intentID.toNumber(), - }); - - const tokenCollections = []; - for (const [i, s] of sources.entries()) { - if (!isNativeAddress(s.universe, s.tokenAddress)) { - tokenCollections.push(i); - } - } - - const evmDeposits: Promise[] = []; - const fuelDeposits: Promise[] = []; - - const evmSignatureData = signatureData.find((d) => d.universe === Universe.ETHEREUM); - - if (!evmSignatureData && universes.has(Universe.ETHEREUM)) { - throw new Error('ethereum in universe list but no signature data present'); - } - - const fuelSignatureData = signatureData.find((d) => d.universe === Universe.FUEL); - - if (!fuelSignatureData && universes.has(Universe.FUEL)) { - throw new Error('fuel in universe list but no signature data present'); - } - - const doubleCheckTxs = []; - - for (const [i, s] of sources.entries()) { - const chain = this.input.chainList.getChainByID(Number(s.chainID)); - if (!chain) { - throw new Error('chain not found'); - } - - if (s.universe === Universe.FUEL) { - if (!this.input.fuel) { - throw new Error('fuel is involved but no associated data'); - } - - const account = new Account( - this.input.fuel.address, - this.input.fuel.provider, - this.input.fuel.connector, - ); - - const vault = new ArcanaVault( - this.chainList.getVaultContractAddress(CHAIN_IDS.fuel.mainnet), - account, - ); - - const tx = await vault.functions - .deposit(omniversalRff.asFuelRFF(), hexlify(fuelSignatureData!.signature), i) - .callParams({ - forward: { - amount: new BN(s.value.toString()), - assetId: s.tokenAddress, - }, - }) - .call(); - - this.markStepDone(INTENT_DEPOSIT_REQ(i + 1)); - - fuelDeposits.push( - (async function () { - const txResult = await tx.waitForResult(); - logger.debug('PostIntentSubmission: Fuel deposit result', { - txResult, - }); - - if (txResult.transactionResult.isStatusFailure) { - throw new Error('fuel deposit failed'); - } - })(), - ); - } else if (s.universe === Universe.ETHEREUM && isNativeAddress(s.universe, s.tokenAddress)) { - const chain = this.input.chainList.getChainByID(Number(s.chainID)); - if (!chain) { - throw new Error('chain not found'); - } - - await switchChain(this.input.evm.client, chain); - - const publicClient = createPublicClientWithFallback(chain); - - const { request } = await publicClient.simulateContract({ - abi: EVMVaultABI, - account: this.input.evm.address, - address: this.input.chainList.getVaultContractAddress(chain.id), - args: [omniversalRff.asEVMRFF(), toHex(evmSignatureData!.signature), BigInt(i)], - chain: chain, - functionName: 'deposit', - value: s.value, - }); - const hash = await this.input.evm.client.writeContract(request); - this.markStepDone(INTENT_DEPOSIT_REQ(i + 1)); - - evmDeposits.push(waitForTxReceipt(hash, publicClient)); - } - doubleCheckTxs.push( - createDepositDoubleCheckTx( - convertTo32Bytes(chain.id), - { - address: cosmosWalletAddress, - wallet: this.input.cosmosWallet, - }, - intentID, - this.input.options.networkConfig, - ), - ); - } - - if (evmDeposits.length || fuelDeposits.length) { - await Promise.all([Promise.all(evmDeposits), Promise.all(fuelDeposits)]); - this.markStepDone(INTENT_DEPOSITS_CONFIRMED); - } - - logger.debug('PostIntentSubmission: Intent ID', { - id: intentID.toNumber(), - }); - - if (tokenCollections.length > 0) { - logger.debug('processRFF', { - intentID: intentID.toString(), - message: 'going to create RFF', - tokenCollections, - }); - await vscCreateRFF( - this.input.options.networkConfig.VSC_DOMAIN, - intentID, - this.markStepDone, - tokenCollections, - ); - } else { - logger.debug('processRFF', { - message: 'going to publish RFF', - }); - await vscPublishRFF(this.input.options.networkConfig.VSC_DOMAIN, intentID); - } - - const destinationSigData = signatureData.find( - (s) => s.universe === intent.destination.universe, - ); - - if (!destinationSigData) { - throw new Error('requestHash not found for destination'); - } - - return { - explorerURL, - id: intentID, - requestHash: destinationSigData.requestHash, - waitForDoubleCheckTx: waitForDoubleCheckTx(doubleCheckTxs), - }; - } - - async setAllowances(input: Array) { - const originalChain = this.input.chain.id; - logger.debug('setAllowances', { originalChain }); - - const sponsoredApprovalParams: SponsoredApprovalDataArray = []; - try { - for (const source of input) { - logger.debug('setAllowances', { originalChain }); - const chain = this.chainList.getChainByID(source.chainID); - if (!chain) { - throw new Error('chain not supported'); - } - - const publicClient = createPublicClientWithFallback(chain); - - const vc = this.input.chainList.getVaultContractAddress(chain.id); - - const chainId = new OmniversalChainID(Universe.ETHEREUM, source.chainID); - const chainDatum = ChaindataMap.get(chainId); - if (!chainDatum) { - throw new Error('Chain data not found'); - } - const currency = chainDatum.CurrencyMap.get(convertTo32Bytes(source.tokenContract)); - if (!currency) { - throw new Error('Currency not found'); - } - logger.debug('setAllowances chain switching to ', { chain }); - await switchChain(this.input.evm.client, chain); - logger.debug('setAllowances chain switched to ', { - originalChain, - switchedTo: await this.input.evm.client?.getChainId(), - chain, - }); - - // FIXME: should be fixed on refactor - if (currency.permitVariant === PermitVariant.Unsupported || chain.id === 1) { - const h = await this.input.evm.client.writeContract({ - abi: ERC20ABI, - account: this.input.evm.address, - address: source.tokenContract, - args: [vc, BigInt(source.amount)], - chain, - functionName: 'approve', - }); - - this.markStepDone(ALLOWANCE_APPROVAL_REQ(source.chainID)); - - await publicClient.waitForTransactionReceipt({ - hash: h, - }); - - this.markStepDone(ALLOWANCE_APPROVAL_MINED(source.chainID)); - } else { - const account: JsonRpcAccount = { - address: this.input.evm.address, - type: 'json-rpc', - }; - - const signed = parseSignature( - await signPermitForAddressAndValue( - currency, - this.input.evm.client, - publicClient, - account, - vc, - source.amount, - ), - ); - - this.markStepDone(ALLOWANCE_APPROVAL_REQ(source.chainID)); - - sponsoredApprovalParams.push({ - address: convertTo32Bytes(account.address), - chain_id: chainDatum.ChainID32, - operations: [ - { - sig_r: hexToBytes(signed.r), - sig_s: hexToBytes(signed.s), - sig_v: signed.yParity < 27 ? signed.yParity + 27 : signed.yParity, - token_address: currency.tokenAddress, - value: convertTo32Bytes(source.amount), - variant: currency.permitVariant === PermitVariant.PolygonEMT ? 2 : 1, - }, - ], - universe: chainDatum.Universe, - }); - } - } - - if (sponsoredApprovalParams.length) { - logger.debug('setAllowances:sponsoredApprovals', { - sponsoredApprovalParams, - }); - await vscCreateSponsoredApprovals( - this.input.options.networkConfig.VSC_DOMAIN, - sponsoredApprovalParams, - this.markStepDone, - ); - } - } catch (e) { - console.error('Error setting allowances', e); - throw ErrorUserDeniedAllowance; - } finally { - if (this.input.chain.universe === Universe.ETHEREUM) { - await switchChain(this.input.evm.client, this.input.chain); - } - this.markStepDone(ALLOWANCE_COMPLETE); - } - } - - abstract simulateTx(): Promise; - - abstract waitForFill( - requestHash: `0x${string}`, - intentID: Long, - waitForDoubleCheckTx: () => Promise, - ): Promise; - - async waitForOnAllowanceHook(sources: onAllowanceHookSource[]): Promise { - if (sources.length === 0) { - return false; - } - - await new Promise((resolve, reject) => { - const allow = (allowances: Array<'max' | 'min' | bigint | string>) => { - if (sources.length !== allowances.length) { - return reject( - new Error( - `invalid input length for allow(). expected: ${sources.length} got: ${allowances.length}`, - ), - ); - } - - logger.debug('CA:BaseRequest:Allowances', { - allowances, - sources, - }); - const val: Array = []; - for (let i = 0; i < sources.length; i++) { - const source = sources[i]; - const allowance = allowances[i]; - let amount = 0n; - if (typeof allowance === 'string' && equalFold(allowance, 'max')) { - amount = maxUint256; - } else if (typeof allowance === 'string' && equalFold(allowance, 'min')) { - amount = BigInt(source.allowance.minimum); - } else if (typeof allowance === 'string') { - amount = mulDecimals(allowance, source.token.decimals); - } else { - amount = allowance; - } - val.push({ - amount, - chainID: source.chain.id, - tokenContract: source.token.contractAddress, - }); - } - this.setAllowances(val).then(resolve).catch(reject); - }; - - const deny = () => { - return reject(ErrorUserDeniedAllowance); - }; - - this.input.hooks.onAllowance({ - allow, - deny, - sources, - }); - }); - return true; - } - - protected createExpectedSteps(intent: Intent, unallowedSources?: onAllowanceHookSource[]) { - this.steps = createSteps(intent, this.chainList, unallowedSources); - - this.input.options.emit('expected_steps', this.steps); - logger.debug('ExpectedSteps', this.steps); - } - - protected createIntent(input: { - amount: Decimal; - assets: UserAssets; - feeStore: FeeStore; - gas: Decimal; - gasInToken: Decimal; - sourceChains: number[]; - token: TokenInfo; - }) { - const { amount, assets, feeStore, gas, gasInToken, token } = input; - const intent: Intent = { - allSources: [], - destination: { - amount: new Decimal('0'), - chainID: this.input.chain.id, - decimals: token.decimals, - gas: 0n, - tokenContract: token.contractAddress, - universe: this.destinationUniverse, - }, - fees: { - caGas: '0', - collection: '0', - fulfilment: '0', - gasSupplied: input.gasInToken.toFixed(), - protocol: '0', - solver: '0', - }, - isAvailableBalanceInsufficient: false, - sources: [], - }; - - const asset = assets.find(token.symbol); - if (!asset) { - throw new Error(`Asset ${token.symbol} not found in UserAssets`); - } - - const allSources = asset.iterate(feeStore).map((v) => ({ ...v, amount: v.balance })); - - intent.allSources = allSources; - - const destinationBalance = asset.getBalanceOnChain(this.input.chain.id, token.contractAddress); - - let borrow = new Decimal(0); - if (this.input.options.bridge) { - borrow = amount; - } else { - if (amount.greaterThan(destinationBalance)) { - borrow = amount.minus(destinationBalance); - } - if (destinationBalance !== '0') { - intent.sources.push({ - amount: amount.greaterThan(destinationBalance) ? new Decimal(destinationBalance) : amount, - chainID: this.input.chain.id, - tokenContract: token.contractAddress, - universe: this.destinationUniverse, - }); - } - } - - const protocolFee = feeStore.calculateProtocolFee(borrow); - intent.fees.protocol = protocolFee.toFixed(); - - let borrowWithFee = borrow.add(gasInToken).add(protocolFee); - - logger.debug('createIntent:0', { - borrow: borrow.toFixed(), - borrowWithFee: borrowWithFee.toFixed(), - destinationBalance, - gasInToken: gasInToken.toFixed(), - protocolFee: protocolFee.toFixed(), - }); - - const fulfilmentFee = feeStore.calculateFulfilmentFee({ - decimals: token.decimals, - destinationChainID: this.input.chain.id, - destinationTokenAddress: token.contractAddress, - }); - logger.debug('createIntent:1', { fulfilmentFee }); - - intent.fees.fulfilment = fulfilmentFee.toFixed(); - - borrowWithFee = borrowWithFee.add(fulfilmentFee); - - let accountedAmount = new Decimal(0); - - const allowedSources = allSources.filter((b) => { - if (input.sourceChains.length === 0) { - return true; - } - return input.sourceChains.includes(b.chainID); - }); - - logger.debug('createIntent:1.1', { allowedSources }); - - for (const assetC of allowedSources) { - if (accountedAmount.greaterThanOrEqualTo(borrowWithFee)) { - break; - } - - if (assetC.chainID === this.input.chain.id) { - continue; - } - - if (assetC.chainID === CHAIN_IDS.fuel.mainnet) { - const fuelChain = this.chainList.getChainByID(CHAIN_IDS.fuel.mainnet); - const baseAssetBalanceOnFuel = assets.getNativeBalance(fuelChain!); - if (new Decimal(baseAssetBalanceOnFuel).lessThan('0.000_003')) { - logger.debug('fuel base asset balance is lesser than min expected deposit fee, so skip', { - current: baseAssetBalanceOnFuel, - minimum: '0.000_003', - }); - continue; - } - } - - if (!isNativeAddress(assetC.universe, assetC.tokenContract)) { - const collectionFee = feeStore.calculateCollectionFee({ - decimals: assetC.decimals, - sourceChainID: assetC.chainID, - sourceTokenAddress: assetC.tokenContract, - }); - - intent.fees.collection = collectionFee.add(intent.fees.collection).toFixed(); - - borrowWithFee = borrowWithFee.add(collectionFee); - - logger.debug('createIntent:2', { collectionFee }); - } - - const unaccountedAmount = borrowWithFee.minus(accountedAmount); - - let borrowFromThisChain = new Decimal(assetC.balance).lessThanOrEqualTo(unaccountedAmount) - ? new Decimal(assetC.balance) - : unaccountedAmount; - - logger.debug('createIntent:2.1', { - accountedAmount: accountedAmount.toFixed(), - asset: assetC, - balance: assetC.balance.toFixed(), - borrowFromThisChain: borrowFromThisChain.toFixed(), - unaccountedAmount: unaccountedAmount.toFixed(), - }); - - const solverFee = feeStore.calculateSolverFee({ - borrowAmount: borrowFromThisChain, - decimals: assetC.decimals, - destinationChainID: this.input.chain.id, - destinationTokenAddress: token.contractAddress, - sourceChainID: assetC.chainID, - sourceTokenAddress: assetC.tokenContract, - }); - intent.fees.solver = solverFee.add(intent.fees.solver).toFixed(); - - logger.debug('createIntent:3', { solverFee }); - - borrowWithFee = borrowWithFee.add(solverFee); - - const unaccountedBalance = borrowWithFee.minus(accountedAmount); - - borrowFromThisChain = new Decimal(assetC.balance).lessThanOrEqualTo(unaccountedBalance) - ? new Decimal(assetC.balance) - : unaccountedBalance; - - intent.sources.push({ - amount: borrowFromThisChain, - chainID: assetC.chainID, - tokenContract: assetC.tokenContract, - universe: assetC.universe, - }); - - accountedAmount = accountedAmount.add(borrowFromThisChain); - } - - intent.destination.amount = borrow; - - if (accountedAmount.lt(borrowWithFee)) { - intent.isAvailableBalanceInsufficient = true; - } - - if (!gas.equals(0)) { - intent.destination.gas = mulDecimals(gas, this.input.chain.nativeCurrency.decimals); - } - - logger.debug('createIntent:4', { intent }); - - return intent; - } - - protected markStepDone = (step: StepInfo, data?: { [k: string]: unknown }) => { - const s = this.steps.find((s) => s.typeID === step.typeID); - if (s) { - this.input.options.emit('step_complete', { - ...s, - ...(data ? { data } : {}), - }); - } - }; -} - -const waitForDoubleCheckTx = (input: Array<() => Promise>) => { - return async () => { - await Promise.allSettled(input.map((i) => i())); - }; -}; - -export default BaseRequest; diff --git a/packages/core/sdk/ca-base/requestHandlers/common/utils.ts b/packages/core/sdk/ca-base/requestHandlers/common/utils.ts deleted file mode 100644 index 672ae225..00000000 --- a/packages/core/sdk/ca-base/requestHandlers/common/utils.ts +++ /dev/null @@ -1,121 +0,0 @@ -import Decimal from 'decimal.js'; - -import { SOPHON_CHAIN_ID } from '../../constants'; -import { getLogger } from '../../logger'; -import { Chain, SimulateReturnType } from '@nexus/commons'; -import { divDecimals, UserAssets } from '../../utils'; - -const logger = getLogger(); - -const tokenRequestParseSimulation = ({ - assets, - bridge, - chain, - iGas, - simulation, -}: { - assets: UserAssets; - bridge: boolean; - chain: Chain; - iGas: bigint; - simulation: SimulateReturnType; -}) => { - const tokenContract = simulation.token.contractAddress; - const amount = simulation.amount ?? new Decimal(0); - const nativeToken = chain.nativeCurrency; - - logger.debug('ERC20RequestBase:ParseSimulation:1', { - assets, - tokenContract, - }); - const { chainsWithBalance, destinationAssetBalance, destinationGasBalance } = - assets.getAssetDetails(chain, tokenContract); - - const gasMultiple = simulation.gasFee - .mul(chain.id === SOPHON_CHAIN_ID ? 3 : 2) - .add(divDecimals(iGas, nativeToken.decimals)); - - logger.debug('ERC20RequestBase:ParseSimulation:0', { - destinationGasBalance, - expectedGas: gasMultiple.toFixed(), - simGas: simulation.gasFee.toFixed(), - }); - - const isGasRequiredToBeBorrowed = bridge - ? gasMultiple.greaterThan(0) - : gasMultiple.greaterThan(destinationGasBalance); - - let isIntentRequired = false; - if (bridge) { - isIntentRequired = true; - } - - let gas = new Decimal(0); - - logger.debug('ERC20RequestBase:parseSimulation:1', { - chainsWithBalance, - destinationAssetBalance, - isGasRequiredToBeBorrowed, - }); - if (chainsWithBalance) { - if (amount.greaterThan(destinationAssetBalance)) { - isIntentRequired = true; - } - - if (isGasRequiredToBeBorrowed) { - isIntentRequired = true; - gas = bridge ? gasMultiple : gasMultiple.minus(destinationGasBalance); - } - } - - return { - amount, - gas, - isIntentRequired, - }; -}; - -const nativeRequestParseSimulation = ({ - assets, - bridge, - chain, - simulation, -}: { - assets: UserAssets; - bridge: boolean; - chain: Chain; - simulation: SimulateReturnType; -}) => { - const { chainsWithBalance, destinationGasBalance } = assets.getAssetDetails( - chain, - simulation.token.contractAddress, - ); - - const gasMultiple = simulation.gasFee.mul(2); - - let isIntentRequired = false; - - if (bridge) { - isIntentRequired = true; - } - - if (chainsWithBalance) { - if (simulation.amount.add(gasMultiple).greaterThan(destinationGasBalance)) { - isIntentRequired = true; - } - } - - logger.debug('parseSimulation', { - amount: simulation.amount.toFixed(), - destinationGasBalance: destinationGasBalance, - gas: gasMultiple.toFixed(), - }); - - return { - amount: simulation.amount, - gas: gasMultiple, - isIntentRequired, - }; -}; - -export { nativeRequestParseSimulation, tokenRequestParseSimulation }; diff --git a/packages/core/sdk/ca-base/requestHandlers/evm/common.ts b/packages/core/sdk/ca-base/requestHandlers/evm/common.ts deleted file mode 100644 index ab0007a0..00000000 --- a/packages/core/sdk/ca-base/requestHandlers/evm/common.ts +++ /dev/null @@ -1,35 +0,0 @@ -import { RequestHandlerInput } from '@nexus/commons'; -import { getTokenTxFunction } from '../../utils'; - -const isERC20TokenTransfer = (input: RequestHandlerInput) => { - if (input.evm.tx) { - const { data, to } = input.evm.tx; - if (!data) { - return false; - } - const token = input.chainList.getTokenByAddress(input.chain.id, to); - const isTokenSupported = !!token; - if (isTokenSupported && data) { - const { functionName } = getTokenTxFunction(data as `0x${string}`); - if (functionName === 'transfer') { - return true; - } - } - } - return false; -}; - -const isNativeTokenTransfer = (input: RequestHandlerInput) => { - if (input.evm.tx) { - const { value } = input.evm.tx; - if (!value) return false; - try { - return BigInt(value) > 0n; - } catch { - return false; - } - } - return false; -}; - -export { isERC20TokenTransfer, isNativeTokenTransfer }; diff --git a/packages/core/sdk/ca-base/requestHandlers/evm/erc20.ts b/packages/core/sdk/ca-base/requestHandlers/evm/erc20.ts deleted file mode 100644 index 44eac2e2..00000000 --- a/packages/core/sdk/ca-base/requestHandlers/evm/erc20.ts +++ /dev/null @@ -1,246 +0,0 @@ -import { Universe } from '@arcana/ca-common'; -import Decimal from 'decimal.js'; -import Long from 'long'; -import { - createPublicClient, - decodeFunctionData, - PublicClient, - serializeTransaction, - webSocket, - WebSocketTransport, -} from 'viem'; -import type { RequestHandlerInput, SimulateReturnType } from '@nexus/commons'; -import { ERC20TransferABI } from '../../abi/erc20'; -import { KAIA_CHAIN_ID, SOPHON_CHAIN_ID } from '../../chains'; -import { - AaveTokenContracts, - HYPEREVM_CHAIN_ID, - MONAD_TESTNET_CHAIN_ID, - TOKEN_MINTER_CONTRACTS, - TOP_OWNER, -} from '../../constants'; -import { getLogger } from '../../logger'; -import { simulateTransaction, SimulationRequest } from '../../simulate'; -import { divDecimals, evmWaitForFill, getL1Fee, UserAssets } from '../../utils'; -import RequestBase from '../common/base'; -import { tokenRequestParseSimulation } from '../common/utils'; - -const logger = getLogger(); - -class ERC20Transfer extends RequestBase { - destinationUniverse = Universe.ETHEREUM; - publicClient: PublicClient; - simulateTxRes?: SimulateReturnType; - - constructor(readonly input: RequestHandlerInput) { - super(input); - this.publicClient = createPublicClient({ - transport: webSocket(this.input.chain.rpcUrls.default.webSocket[0]), - }); - } - - parseSimulation({ assets, simulation }: { assets: UserAssets; simulation: SimulateReturnType }) { - return tokenRequestParseSimulation({ - assets, - bridge: this.input.options.bridge, - chain: this.input.chain, - iGas: this.input.options.gas, - simulation, - }); - } - - async simulateTx(): Promise { - const { data, to } = this.input.evm.tx!; - const from = this.input.evm.address; - const token = this.chainList.getTokenByAddress(this.input.chain.id, to); - const nativeToken = this.chainList.getNativeToken(this.input.chain.id); - if (!token) { - return; - } - - const { args } = decodeFunctionData({ - abi: [ERC20TransferABI], - data: data ?? '0x00', - }); - - const amount = args[1]; - const amountInDecimal = divDecimals(amount, token.decimals); - - if (this.input.options.bridge) { - this.simulateTxRes = { - amount: amountInDecimal, - gas: this.input.options.gas, - gasFee: new Decimal(0), - token, - }; - } else if ( - [HYPEREVM_CHAIN_ID, KAIA_CHAIN_ID, MONAD_TESTNET_CHAIN_ID].includes(this.input.chain.id) - ) { - this.simulateTxRes = { - amount: amountInDecimal, - gas: 100_000n, - gasFee: new Decimal(0), - token, - }; - } - - if (this.simulateTxRes) { - let gasFee = 0n; - - if (this.simulateTxRes.gas > 0n) { - const [{ gasPrice, maxFeePerGas }, l1Fee] = await Promise.all([ - this.publicClient.estimateFeesPerGas(), - this.input.options.bridge - ? Promise.resolve(0n) - : getL1Fee( - this.input.chain, - serializeTransaction({ - chainId: this.input.chain.id, - data: data ?? '0x00', - to: to, - type: 'eip1559', - }), - ), - ]); - - const gasUnitPrice = maxFeePerGas ?? gasPrice ?? 0n; - if (gasUnitPrice === 0n) { - throw new Error('could not get maxFeePerGas or gasPrice from RPC'); - } - - gasFee = this.simulateTxRes.gas * gasUnitPrice + l1Fee; - } - - return { - ...this.simulateTxRes, - gasFee: divDecimals(gasFee, nativeToken.decimals), - }; - } - - const amountToAdd = new Decimal(args[1].toString()) - .toHexadecimal() - .split('0x')[1] - .padStart(40, '0'); - - let txsToSimulate: SimulationRequest[] = []; - if (AaveTokenContracts[this.input.chain.id]?.[token.symbol]) { - txsToSimulate.push({ - from: AaveTokenContracts[this.input.chain.id][token.symbol], - input: `0xa9059cbb000000000000000000000000${from - .replace('0x', '') - .toLowerCase()}000000000000000000000000${amountToAdd}`, - to: token.contractAddress, - }); - } else if (TOKEN_MINTER_CONTRACTS[this.input.chain.id]?.[token.symbol]) { - txsToSimulate.push({ - from: TOKEN_MINTER_CONTRACTS[this.input.chain.id]?.[token.symbol], - input: `0x40c10f19000000000000000000000000${from - .replace('0x', '') - .toLowerCase()}000000000000000000000000000000000000000000000000000000003b9aca00`, - to: token.contractAddress, - }); - } - txsToSimulate.push({ - from, - input: data, - to, - }); - - if (TOP_OWNER[this.input.chain.id]?.[token.symbol]) { - const ownerAddress = TOP_OWNER[this.input.chain.id][token.symbol]; - txsToSimulate = [ - { - from: ownerAddress, - input: data as `0x${string}`, - to, - }, - ]; - } - - const [simulation, feeData, l1Fee] = await Promise.all([ - simulateTransaction( - this.input.chain.id, - txsToSimulate, - this.input.options.networkConfig.SIMULATION_URL, - ), - this.publicClient.estimateFeesPerGas(), - getL1Fee( - this.input.chain, - serializeTransaction({ - chainId: this.input.chain.id, - data: data ?? '0x00', - to: to, - type: 'eip1559', - }), - ), - ]); - - logger.debug('simulateTx', { feeData }); - - const gasUnitPrice = feeData.maxFeePerGas ?? feeData.gasPrice ?? 0n; - if (gasUnitPrice === 0n) { - throw new Error('could not get maxFeePerGas or gasPrice from RPC'); - } - - let gasFee = - (this.input.chain.id === SOPHON_CHAIN_ID - ? BigInt(simulation.data.gas) - : BigInt(simulation.data.gas_used)) * - gasUnitPrice + - l1Fee; - - logger.debug('erc20:simulateTx', { - args, - feeData, - l1Fee, - maxFeePerGas: gasUnitPrice, - simulation, - totalGas: gasFee, - totalGasInDecimal: divDecimals(gasFee, nativeToken.decimals).toFixed(), - }); - - if (this.input.options.bridge) { - gasFee = 0n; - } - - this.simulateTxRes = { - amount: divDecimals(amount, token.decimals), - gas: - this.input.chain.id === SOPHON_CHAIN_ID - ? BigInt(simulation.data.gas) - : BigInt(simulation.data.gas_used), - gasFee: divDecimals(gasFee, nativeToken.decimals), - token, - }; - return this.simulateTxRes; - } - - async waitForFill( - requestHash: `0x${string}`, - intentID: Long, - waitForDoubleCheckTx: () => Promise, - ) { - logger.debug('waitForFill', { - intentID, - requestHash, - waitForDoubleCheckTx, - }); - - waitForDoubleCheckTx(); - - try { - await evmWaitForFill( - this.input.chainList.getVaultContractAddress(this.input.chain.id), - this.publicClient, - requestHash, - intentID, - this.input.options.networkConfig.GRPC_URL, - this.input.options.networkConfig.COSMOS_URL, - ); - } finally { - (await this.publicClient.transport.getRpcClient()).close(); - } - } -} - -export default ERC20Transfer; diff --git a/packages/core/sdk/ca-base/requestHandlers/evm/native.ts b/packages/core/sdk/ca-base/requestHandlers/evm/native.ts deleted file mode 100644 index b2197eb2..00000000 --- a/packages/core/sdk/ca-base/requestHandlers/evm/native.ts +++ /dev/null @@ -1,178 +0,0 @@ -import { Universe } from '@arcana/ca-common'; -import Long from 'long'; -import { - createPublicClient, - hexToBigInt, - PublicClient, - serializeTransaction, - webSocket, - WebSocketTransport, -} from 'viem'; - -import { ZERO_ADDRESS } from '../../constants'; -import { getLogger } from '../../logger'; -import { simulateTransaction, SimulationRequest } from '../../simulate'; -import { RequestHandlerInput, SimulateReturnType } from '@nexus/commons'; -import { divDecimals, evmWaitForFill, getL1Fee, UserAssets } from '../../utils'; -import RequestBase from '../common/base'; -import { nativeRequestParseSimulation } from '../common/utils'; -import Decimal from 'decimal.js'; - -const logger = getLogger(); - -class NativeTransfer extends RequestBase { - destinationUniverse = Universe.ETHEREUM; - private publicClient: PublicClient; - private simulateTxRes?: SimulateReturnType; - - constructor(readonly input: RequestHandlerInput) { - super(input); - const wsUrls = this.input.chain.rpcUrls?.default?.webSocket; - if (!wsUrls?.length) { - throw new Error(`Web-Socket RPC URL missing for chain ${this.input.chain.id}`); - } - - this.publicClient = createPublicClient({ - transport: webSocket(wsUrls[0]), - }); - } - - parseSimulation({ assets, simulation }: { assets: UserAssets; simulation: SimulateReturnType }) { - return nativeRequestParseSimulation({ - assets, - bridge: this.input.options.bridge, - chain: this.input.chain, - simulation, - }); - } - - async simulateTx() { - const { data, to, value } = this.input.evm.tx!; - const nativeToken = this.input.chainList.getNativeToken(this.input.chain.id); - - const amount = hexToBigInt((value as `0x${string}`) ?? `0x00`); - const amountInDecimal = divDecimals(amount, nativeToken.decimals); - - if (this.input.options.bridge) { - this.simulateTxRes = { - amount: amountInDecimal, - gas: this.input.options.gas, - gasFee: new Decimal(0), - token: nativeToken, - }; - } - - if (this.simulateTxRes) { - let gasFee = 0n; - - if (this.simulateTxRes.gas > 0n) { - const [{ gasPrice, maxFeePerGas }, l1Fee] = await Promise.all([ - this.publicClient.estimateFeesPerGas(), - this.input.options.bridge - ? Promise.resolve(0n) - : getL1Fee( - this.input.chain, - serializeTransaction({ - chainId: this.input.chain.id, - data: data ?? '0x00', - to: to, - type: 'eip1559', - value: amount, - }), - ), - ]); - - const gasUnitPrice = maxFeePerGas ?? gasPrice ?? 0n; - if (gasUnitPrice === 0n) { - throw new Error('could not get maxFeePerGas or gasPrice from RPC'); - } - - gasFee = this.simulateTxRes.gas * gasUnitPrice + l1Fee; - } - - return { - ...this.simulateTxRes, - gasFee: divDecimals(gasFee, nativeToken.decimals), - }; - } - - const txsToSimulate: SimulationRequest[] = [ - { - from: ZERO_ADDRESS, - input: data ?? '0x00', - to, - value: (value as `0x${string}`) ?? '0x00', - }, - ]; - - const [simulation, feeData, l1Fee] = await Promise.all([ - simulateTransaction( - this.input.chain.id, - txsToSimulate, - this.input.options.networkConfig.SIMULATION_URL, - ), - this.publicClient.estimateFeesPerGas(), - getL1Fee( - this.input.chain, - serializeTransaction({ - chainId: this.input.chain.id, - data: data ?? '0x00', - to: to, - type: 'eip1559', - value: hexToBigInt((value as `0x${string}`) ?? '0x00'), - }), - ), - ]); - - const gasUnitPrice = feeData.maxFeePerGas ?? feeData.gasPrice ?? 0n; - if (gasUnitPrice === 0n) { - throw new Error('could not get maxFeePerGas or gasPrice from RPC'); - } - - let gasFee = BigInt(simulation.data.gas_used) * gasUnitPrice + l1Fee; - - logger.debug('native:simulateTx', { - feeData, - l1Fee, - maxFeePerGas: gasUnitPrice, - simulation, - totalGas: gasFee, - totalGasInDecimal: divDecimals(gasFee, nativeToken.decimals), - }); - - this.simulateTxRes = { - amount: amountInDecimal, - gas: BigInt(simulation.data.gas_used), - gasFee: divDecimals(gasFee, nativeToken.decimals), - token: { - contractAddress: ZERO_ADDRESS, - decimals: nativeToken.decimals, - name: nativeToken.name, - symbol: nativeToken.symbol, - }, - }; - return this.simulateTxRes; - } - - async waitForFill( - requestHash: `0x${string}`, - intentID: Long, - waitForDoubleCheckTx: () => Promise, - ) { - waitForDoubleCheckTx(); - try { - await evmWaitForFill( - this.input.chainList.getVaultContractAddress(this.input.chain.id), - this.publicClient, - requestHash, - intentID, - this.input.options.networkConfig.GRPC_URL, - this.input.options.networkConfig.COSMOS_URL, - ); - } finally { - (await this.publicClient.transport.getRpcClient()).close(); - } - } -} - -export default NativeTransfer; diff --git a/packages/core/sdk/ca-base/requestHandlers/fuel/common.ts b/packages/core/sdk/ca-base/requestHandlers/fuel/common.ts deleted file mode 100644 index 62b5cc8c..00000000 --- a/packages/core/sdk/ca-base/requestHandlers/fuel/common.ts +++ /dev/null @@ -1,143 +0,0 @@ -import Decimal from 'decimal.js'; -import { - Account, - bn, - CHAIN_IDS, - hexlify, - OutputType, - Provider, - TransactionRequest, - TransactionRequestLike, -} from 'fuels'; -import { Hex } from 'viem'; - -import { FUEL_BASE_ASSET_ID } from '../../constants'; -import { getLogger } from '../../logger'; -import { divDecimals } from '../../utils'; -import { ChainListType } from '@nexus/commons'; - -const logger = getLogger(); - -const simulate = async ( - tx: TransactionRequestLike, - address: string, - provider: Provider, - chainList: ChainListType, -) => { - const outputs = tx.outputs?.filter((o) => o.type === OutputType.Coin) ?? []; - const tokens = outputs - .map((o) => { - const token = chainList.getTokenByAddress(CHAIN_IDS.fuel.mainnet, o.assetId as Hex); - if (!token) return null; - return { - from: hexlify(address).toLowerCase(), - to: hexlify(o.to).toLowerCase(), - token: { - address: hexlify(o.assetId) as Hex, - amount: divDecimals(o.amount.toString(), token.decimals), - decimals: token.decimals, - logo: token.logo, - name: token.name, - symbol: token.symbol, - }, - }; - }) - .filter((o) => !!o) - .reduce((acc, o) => { - const existingCoin = acc.find( - (a) => o.from === a.from && o.token.address === a.token.contractAddress, - ); - if (existingCoin) { - existingCoin.token.amount = new Decimal(existingCoin.token.amount).plus(o.token.amount); - return acc; - } - acc.push({ - from: o.from, - to: o.to, - token: { - amount: new Decimal(o.token.amount), - contractAddress: o.token.address, - decimals: o.token.decimals, - logo: o.token.logo, - name: o.token.name, - symbol: o.token.symbol, - }, - }); - return acc; - }, [] as CoinTransfer[]) - .sort((a, b) => (new Decimal(a.token.amount).lessThan(b.token.amount) ? 1 : -1)); - - const { assembledRequest } = await provider.assembleTx({ - feePayerAccount: new Account(address), - request: tx as TransactionRequest, - }); - - logger.debug('Fuel Simulate: mappedOutputsToInputs', { - assembledRequest, - }); - - const coin = tokens?.length ? tokens[0] : null; - if (!coin) { - return; - } - - logger.debug('FuelSimulate', { - amount: coin.token.amount.toFixed(), - coin: coin, - }); - - const { amount, ...token } = coin.token; - return { - amount: amount, - gas: BigInt(0), - gasFee: divDecimals(BigInt(assembledRequest.maxFee.toString()) * 2n, 9), - token: { ...token, type: 'src20' }, - }; -}; - -const fixTx = async (address: string, tx: TransactionRequestLike, provider: Provider) => { - delete tx.inputs; - - const outputQuantities = tx.outputs - ?.filter((o) => o.type === OutputType.Coin) - .map(({ amount, assetId }) => ({ - amount: bn(amount), - assetId: String(assetId), - })); - - const aResponse = await provider.assembleTx({ - accountCoinQuantities: outputQuantities, - estimatePredicates: true, - feePayerAccount: new Account(address), - // @ts-ignore - request: tx, - }); - - logger.debug('fixTx:sendTransaction:3', { - assembleTxResponse: aResponse, - request: tx, - }); - - return aResponse.assembledRequest as TransactionRequestLike; -}; - -type CoinTransfer = { - from: string; - to: string; - token: { - amount: Decimal; - contractAddress: Hex; - decimals: number; - logo?: string; - name: string; - symbol: string; - }; -}; - -const isFuelNativeTransfer = (tx: TransactionRequestLike) => { - return tx.outputs?.every((o) => { - return 'assetId' in o && o.assetId === FUEL_BASE_ASSET_ID; - }); -}; - -export { fixTx, isFuelNativeTransfer, simulate }; diff --git a/packages/core/sdk/ca-base/requestHandlers/fuel/native.ts b/packages/core/sdk/ca-base/requestHandlers/fuel/native.ts deleted file mode 100644 index f95dd23f..00000000 --- a/packages/core/sdk/ca-base/requestHandlers/fuel/native.ts +++ /dev/null @@ -1,91 +0,0 @@ -import { Universe } from '@arcana/ca-common'; -import Decimal from 'decimal.js'; -import { Account, TransactionRequest, TransactionRequestLike } from 'fuels'; -import Long from 'long'; - -import { getLogger } from '../../logger'; -import { RequestHandlerInput, SimulateReturnType } from '@nexus/commons'; -import { cosmosFillCheck, divDecimals, UserAssets } from '../../utils'; -import { requestTimeout } from '../../utils'; -import RequestBase from '../common/base'; -import { nativeRequestParseSimulation } from '../common/utils'; -import { simulate } from './common'; - -const logger = getLogger(); - -class FuelNativeTransfer extends RequestBase { - allowances: { [k: number]: bigint | null } | null = null; - destinationUniverse = Universe.FUEL; - fuelAddress: string; - simulateTxRes?: SimulateReturnType; - tx: TransactionRequestLike; - constructor(readonly input: RequestHandlerInput) { - super(input); - if (!this.input.fuel?.tx) { - throw new Error('Invalid request'); - } - - if (!this.input.fuel.address) { - throw new Error('fuel address missing'); - } - - this.tx = this.input.fuel.tx; - this.fuelAddress = this.input.fuel.address; - } - parseSimulation(input: { assets: UserAssets; simulation: SimulateReturnType }) { - return nativeRequestParseSimulation({ - ...input, - bridge: this.input.options.bridge, - chain: this.input.chain, - }); - } - - async simulateTx() { - logger.debug('fuel: reached simulate tx'); - const nativeCurrency = this.input.chain.nativeCurrency; - if (this.simulateTxRes) { - let gasFee = new Decimal(0); - if (!this.input.options.bridge) { - const { assembledRequest } = await this.input.fuel!.provider.assembleTx({ - feePayerAccount: new Account(this.input.fuel!.address), - request: this.input.fuel!.tx as TransactionRequest, - }); - gasFee = divDecimals( - BigInt(assembledRequest.maxFee.toString()) * 2n, - nativeCurrency.decimals, - ); - } - return { - ...this.simulateTxRes, - gasFee, - }; - } - - this.simulateTxRes = await simulate( - this.tx, - this.fuelAddress, - this.input.fuel!.provider, - this.input.chainList, - ); - - if (this.input.options.bridge && this.simulateTxRes) { - this.simulateTxRes.gasFee = new Decimal(0); - } - return this.simulateTxRes; - } - - async waitForFill(_: `0x${string}`, intentID: Long) { - const ac = new AbortController(); - await Promise.race([ - requestTimeout(3, ac), - cosmosFillCheck( - intentID, - this.input.options.networkConfig.GRPC_URL, - this.input.options.networkConfig.COSMOS_URL, - ac, - ), - ]); - } -} - -export default FuelNativeTransfer; diff --git a/packages/core/sdk/ca-base/requestHandlers/fuel/provider.ts b/packages/core/sdk/ca-base/requestHandlers/fuel/provider.ts deleted file mode 100644 index 662743c5..00000000 --- a/packages/core/sdk/ca-base/requestHandlers/fuel/provider.ts +++ /dev/null @@ -1,149 +0,0 @@ -import { Universe } from '@arcana/ca-common'; -import { - Account, - Address, - AssembleTxParams, - AssembleTxResponse, - bn, - BN, - CoinTransactionRequestOutput, - FakeResources, - Provider as FuelProvider, - hexlify, - OutputType, - Provider, - ProviderOptions, - randomBytes, - Resource, - TransactionRequest, - UTXO_ID_LEN, -} from 'fuels'; - -import { FUEL_BASE_ASSET_ID, FUEL_NETWORK_URL } from '../../constants'; -import { getLogger } from '../../logger'; -import { Chain, UserAssetDatum } from '@nexus/commons'; -import { equalFold, mulDecimals } from '../../utils'; - -const logger = getLogger(); - -const getFuelProvider = ( - getBalances: () => Promise, - address: string, - chain: Chain, -): Provider => { - return new (class Provider extends FuelProvider { - constructor(url: string, options?: ProviderOptions) { - super(url, { ...options, resourceCacheTTL: -1 }); - } - - async assembleTx( - params: AssembleTxParams, - ): Promise> { - const { request } = params; - logger.debug('ffProvider', { - request, - }); - const addr = new Address(address); - - const balances = await getBalances(); - const assetIdsOnFuel = chain.custom.knownTokens.map((c) => c.contractAddress); - - const outputAssetList: CoinTransactionRequestOutput[] = request.outputs.filter( - (o) => o.type === OutputType.Coin, - ); - - const allAssetSupported = outputAssetList.every((a) => - assetIdsOnFuel.includes(hexlify(a.assetId) as `0x${string}`), - ); - - logger.debug('FuelProvide:1', { - allAssetSupported, - assetIdsOnFuel, - outputAssetList, - }); - - if (!allAssetSupported) { - return super.assembleTx({ - ...params, - feePayerAccount: new Account(addr), - request, - }); - } - - const al = []; - for (const a of assetIdsOnFuel) { - if (!outputAssetList.map((al) => al.assetId).includes(a) && a !== FUEL_BASE_ASSET_ID) { - continue; - } - const asset = balances.find((asset) => - asset.breakdown.find( - (b) => equalFold(b.contractAddress, hexlify(a)) && b.universe === Universe.FUEL, - ), - ); - - const chainAsset = asset?.breakdown.find( - (b) => equalFold(b.contractAddress, hexlify(a)) && b.universe === Universe.FUEL, - ); - - logger.debug('FuelProvider:2', { - asset, - chainAsset, - }); - - if (asset && chainAsset) { - const decimals = equalFold(FUEL_BASE_ASSET_ID, chainAsset.contractAddress) - ? 9 - : asset.decimals; - - const amount = new BN(mulDecimals(asset.balance, decimals).toString()); - - logger.debug('FuelProvider:3', { - amount, - assetId: hexlify(a), - }); - - al.push({ - amount, - assetId: hexlify(a), - }); - } - } - - request.addResources(generateFakeResources(al, new Address(address))); - - const { accountCoinQuantities, ...rest } = params; - - logger.debug('FuelProvider:4', { - accountCoinQuantities, - params: { ...params }, - request, - rest, - }); - - const response = await super.assembleTx({ - ...rest, - request, - }); - - logger.debug('FuelProvider:4', { - accountCoinQuantities, - params: { ...params }, - request, - response, - }); - return response as AssembleTxResponse; - } - })(FUEL_NETWORK_URL); -}; - -const generateFakeResources = (coins: FakeResources[], address: Address): Array => { - return coins.map((coin) => ({ - blockCreated: bn(1), - id: hexlify(randomBytes(UTXO_ID_LEN)), - owner: address, - txCreatedIdx: bn(1), - ...coin, - })); -}; - -export { getFuelProvider }; diff --git a/packages/core/sdk/ca-base/requestHandlers/fuel/token.ts b/packages/core/sdk/ca-base/requestHandlers/fuel/token.ts deleted file mode 100644 index 0e803ea6..00000000 --- a/packages/core/sdk/ca-base/requestHandlers/fuel/token.ts +++ /dev/null @@ -1,92 +0,0 @@ -import { Universe } from '@arcana/ca-common'; -import Decimal from 'decimal.js'; -import { Account, TransactionRequest, TransactionRequestLike } from 'fuels'; -import Long from 'long'; - -import { getLogger } from '../../logger'; -import { RequestHandlerInput, SimulateReturnType } from '@nexus/commons'; -import { cosmosFillCheck, divDecimals, requestTimeout, UserAssets } from '../../utils'; -import RequestBase from '../common/base'; -import { tokenRequestParseSimulation } from '../common/utils'; -import { simulate } from './common'; - -const logger = getLogger(); - -class FuelTokenTransfer extends RequestBase { - allowances: { [k: number]: bigint | null } | null = null; - destinationUniverse = Universe.FUEL; - fuelAddress: string; - simulateTxRes?: SimulateReturnType; - tx: TransactionRequestLike; - constructor(readonly input: RequestHandlerInput) { - super(input); - if (!this.input.fuel?.tx) { - throw new Error('Invalid request'); - } - if (!this.input.fuel.address) { - throw new Error('fuel address missing'); - } - this.tx = this.input.fuel.tx; - this.fuelAddress = this.input.fuel.address; - } - - parseSimulation({ assets, simulation }: { assets: UserAssets; simulation: SimulateReturnType }) { - return tokenRequestParseSimulation({ - assets, - bridge: this.input.options.bridge, - chain: this.input.chain, - iGas: this.input.options.gas, - simulation, - }); - } - - async simulateTx() { - logger.debug('fuel: reached simulate tx'); - const nativeCurrency = this.input.chain.nativeCurrency; - - if (this.simulateTxRes) { - let gasFee = new Decimal(0); - if (!this.input.options.bridge) { - const { assembledRequest } = await this.input.fuel!.provider.assembleTx({ - feePayerAccount: new Account(this.input.fuel!.address), - request: this.input.fuel!.tx as TransactionRequest, - }); - gasFee = divDecimals( - BigInt(assembledRequest.maxFee.toString()) * 2n, - nativeCurrency.decimals, - ); - } - return { - ...this.simulateTxRes, - gasFee, - }; - } - - this.simulateTxRes = await simulate( - this.tx, - this.fuelAddress, - this.input.fuel!.provider, - this.input.chainList, - ); - if (this.input.options.bridge && this.simulateTxRes) { - this.simulateTxRes.gasFee = new Decimal(0); - } - - return this.simulateTxRes; - } - - async waitForFill(_: `0x${string}`, intentID: Long) { - const ac = new AbortController(); - await Promise.race([ - requestTimeout(3, ac), - cosmosFillCheck( - intentID, - this.input.options.networkConfig.GRPC_URL, - this.input.options.networkConfig.COSMOS_URL, - ac, - ), - ]); - } -} - -export default FuelTokenTransfer; diff --git a/packages/core/sdk/ca-base/requestHandlers/helpers.ts b/packages/core/sdk/ca-base/requestHandlers/helpers.ts new file mode 100644 index 00000000..cfca2762 --- /dev/null +++ b/packages/core/sdk/ca-base/requestHandlers/helpers.ts @@ -0,0 +1,26 @@ +import { Errors } from '../errors'; +import { mulDecimals } from '../utils'; +import { BridgeParams, ChainListType } from '@nexus/commons'; + +const createBridgeParams = (input: BridgeParams, chainList: ChainListType) => { + const { chain: dstChain, token: dstToken } = chainList.getChainAndTokenFromSymbol( + input.toChainId, + input.token, + ); + if (!dstToken) { + throw Errors.tokenNotFound(input.token, input.toChainId); + } + + const params = { + tokenAmount: mulDecimals(input.amount, dstToken.decimals), + nativeAmount: input.gas ?? 0n, + dstToken, + dstChain, + recipientAddress: input.recipient, + sourceChains: input.sourceChains ?? [], + }; + + return params; +}; + +export { createBridgeParams }; diff --git a/packages/core/sdk/ca-base/requestHandlers/router.ts b/packages/core/sdk/ca-base/requestHandlers/router.ts deleted file mode 100644 index 27237023..00000000 --- a/packages/core/sdk/ca-base/requestHandlers/router.ts +++ /dev/null @@ -1,86 +0,0 @@ -import { FUEL_NETWORK_URL } from '../constants'; -import { getLogger } from '../logger'; -import { CreateHandlerResponse, RequestHandler, RequestHandlerInput } from '@nexus/commons'; -import { switchChain } from '../utils'; -import { isERC20TokenTransfer, isNativeTokenTransfer } from './evm/common'; -import ERC20Transfer from './evm/erc20'; -import NativeTransfer from './evm/native'; -import { fixTx, isFuelNativeTransfer } from './fuel/common'; -import FuelNativeTransfer from './fuel/native'; -import FuelTokenTransfer from './fuel/token'; - -const logger = getLogger(); - -enum TxType { - EVMERC20Transfer, - EVMNativeTransfer, - FuelTokenTransfer, - FuelNativeTransfer, -} - -const handlers: Record = { - [TxType.EVMERC20Transfer]: ERC20Transfer, - [TxType.EVMNativeTransfer]: NativeTransfer, - [TxType.FuelNativeTransfer]: FuelNativeTransfer, - [TxType.FuelTokenTransfer]: FuelTokenTransfer, -}; - -const createHandler = (input: RequestHandlerInput): CreateHandlerResponse => { - logger.debug('router', { input }); - let handler: null | RequestHandler = null; - let processTx: () => Promise = async () => {}; - if (input.evm.tx) { - const tx = input.evm.tx; - if (isERC20TokenTransfer(input)) { - handler = handlers[TxType.EVMERC20Transfer]; - } else if (isNativeTokenTransfer(input)) { - handler = handlers[TxType.EVMNativeTransfer]; - } - processTx = async () => { - if (!input.options.bridge && !input.options.skipTx) { - logger.debug('in processTx', { - tx: input.evm.tx, - }); - await switchChain(input.evm.client, input.chain); - return input.evm.client.request({ - method: 'eth_sendTransaction', - params: [tx], - }); - } - return; - }; - } else if (input.fuel?.tx) { - if (isFuelNativeTransfer(input.fuel.tx)) { - handler = handlers[TxType.FuelNativeTransfer]; - } else { - handler = handlers[TxType.FuelTokenTransfer]; - } - - processTx = async () => { - if (!input.options.bridge && !input.options.skipTx) { - logger.debug('in processTx', { - address: input.fuel!.address, - provider: input.fuel!.provider, - tx: input.fuel?.tx, - }); - const tx = await fixTx(input.fuel!.address, input.fuel!.tx!, input.fuel!.provider); - - return input.fuel!.connector.sendTransaction(input.fuel!.address, tx, { - provider: { - url: FUEL_NETWORK_URL, - }, - }); - } - return; - }; - } else { - throw Error('Unknown handler'); - } - - return { - handler: handler ? new handler(input) : null, - processTx, - }; -}; - -export { createHandler }; diff --git a/packages/core/sdk/ca-base/simulate.ts b/packages/core/sdk/ca-base/simulate.ts deleted file mode 100644 index 10abe111..00000000 --- a/packages/core/sdk/ca-base/simulate.ts +++ /dev/null @@ -1,43 +0,0 @@ -import axios from "axios"; - -const simulateTransaction = async ( - chainID: number, - simulations: SimulationRequest[], - baseURL: string, -) => { - const url = new URL("/simulate", baseURL).toString(); - return await axios.post( - url, - { - chainID, - simulations, - }, - { - headers: { - "Content-Type": "application/json", - }, - }, - ); -}; - -type SimulationRequest = { - from: `0x${string}`; - input?: `0x${string}`; - to: `0x${string}`; - value?: `0x${string}`; -}; - -type SimulationResponse = { - amount: string; - gas: string; - gas_used: string; - token?: { - contract_address: `0x${string}`; - decimals: number; - name: string; - symbol: string; - type: string; - }; -}; - -export { simulateTransaction, type SimulationRequest, type SimulationResponse }; diff --git a/packages/core/sdk/ca-base/steps.ts b/packages/core/sdk/ca-base/steps.ts index 2ed1d305..10087a23 100644 --- a/packages/core/sdk/ca-base/steps.ts +++ b/packages/core/sdk/ca-base/steps.ts @@ -1,103 +1,34 @@ import { isNativeAddress } from './constants'; -import { ChainListType, Intent, onAllowanceHookSource, Step } from '@nexus/commons'; +import { + BridgeStepType, + BRIDGE_STEPS, + ChainListType, + Intent, + onAllowanceHookSource, +} from '@nexus/commons'; +import { Errors } from './errors'; -const INTENT_ACCEPTED = { - type: 'INTENT_ACCEPTED', - typeID: 'IA', -} as const; - -const INTENT_HASH_SIGNED = { - type: 'INTENT_HASH_SIGNED', - typeID: 'IHS', -} as const; - -const INTENT_SUBMITTED = { - type: 'INTENT_SUBMITTED', - typeID: 'IS', -} as const; - -const INTENT_INIT_STEPS = [ - INTENT_HASH_SIGNED, - { - ...INTENT_SUBMITTED, - data: { - explorerURL: '', - intentID: 0, - }, - }, -]; - -const INTENT_FULFILLED = { - type: 'INTENT_FULFILLED', - typeID: 'IF', -}; -const ALLOWANCE_APPROVAL_REQ = (chainID: number) => - ({ - type: 'ALLOWANCE_USER_APPROVAL', - typeID: `AUA_${chainID}`, - }) as const; - -const ALLOWANCE_APPROVAL_MINED = (chainID: number) => ({ - type: 'ALLOWANCE_APPROVAL_MINED', - typeID: `AAM_${chainID}`, -}); -const ALLOWANCE_COMPLETE = { - type: 'ALLOWANCE_ALL_DONE', - typeID: 'AAD', -}; - -const INTENT_DEPOSIT_REQ = (id: number) => ({ - type: 'INTENT_DEPOSIT', - typeID: `ID_${id}`, -}); - -const INTENT_DEPOSITS_CONFIRMED = { - type: 'INTENT_DEPOSITS_CONFIRMED', - typeID: 'UIDC', -}; - -const INTENT_COLLECTION_COMPLETE = { - type: 'INTENT_COLLECTION_COMPLETE', - typeID: 'ICC', -}; -const INTENT_COLLECTION = (id: number) => ({ - type: 'INTENT_COLLECTION', - typeID: `IC_${id}`, -}); - -const INTENT_FINISH_STEPS = [INTENT_FULFILLED]; +const INTENT_FINISH_STEPS = [BRIDGE_STEPS.INTENT_FULFILLED]; const createSteps = ( intent: Intent, chainList: ChainListType, unallowedSources?: onAllowanceHookSource[], ) => { - const steps: Step[] = []; + const steps: BridgeStepType[] = []; - steps.push(INTENT_ACCEPTED); + steps.push(BRIDGE_STEPS.INTENT_ACCEPTED); if (unallowedSources && unallowedSources?.length > 0) { for (const source of unallowedSources) { steps.push( - { - ...ALLOWANCE_APPROVAL_REQ(source.chain.id), - data: { - chainID: source.chain.id, - chainName: source.chain.name, - }, - }, - { - ...ALLOWANCE_APPROVAL_MINED(source.chain.id), - data: { - chainID: source.chain.id, - chainName: source.chain.name, - }, - }, + BRIDGE_STEPS.ALLOWANCE_APPROVAL_REQUEST(source.chain), + BRIDGE_STEPS.ALLOWANCE_APPROVAL_MINED(source.chain), ); } - steps.push(ALLOWANCE_COMPLETE); + steps.push(BRIDGE_STEPS.ALLOWANCE_COMPLETE); } - steps.push(...INTENT_INIT_STEPS); + steps.push(BRIDGE_STEPS.INTENT_HASH_SIGNED, BRIDGE_STEPS.INTENT_SUBMITTED()); const sources = intent.sources.filter((s) => s.chainID !== intent.destination.chainID); @@ -109,53 +40,26 @@ const createSteps = ( deposits++; const chain = chainList.getChainByID(s.chainID); if (!chain) { - throw new Error(`Unknown chain ID ${s.chainID} while building steps`); + throw Errors.chainNotFound(s.chainID); } - steps.push({ - ...INTENT_DEPOSIT_REQ(i + 1), - data: { - amount: s.amount.toString(), - chainID: chain.id, - chainName: chain.name, - symbol: chain.nativeCurrency.symbol, - }, - }); + steps.push(BRIDGE_STEPS.INTENT_DEPOSIT_REQUEST(i + 1, s.amount, chain)); } else { collections++; - steps.push({ - ...INTENT_COLLECTION(i + 1), - data: { - confirmed: i + 1, - total: sources.length, - }, - }); + steps.push(BRIDGE_STEPS.INTENT_COLLECTION(i + 1, sources.length)); } } if (collections > 0) { - steps.push(INTENT_COLLECTION_COMPLETE); + steps.push(BRIDGE_STEPS.INTENT_COLLECTION_COMPLETE); } if (deposits > 0) { - steps.push(INTENT_DEPOSITS_CONFIRMED); + steps.push(BRIDGE_STEPS.INTENT_DEPOSITS_CONFIRMED); } steps.push(...INTENT_FINISH_STEPS); return steps; }; -export { - ALLOWANCE_APPROVAL_MINED, - ALLOWANCE_APPROVAL_REQ, - ALLOWANCE_COMPLETE, - createSteps, - INTENT_ACCEPTED, - INTENT_COLLECTION, - INTENT_COLLECTION_COMPLETE, - INTENT_DEPOSIT_REQ, - INTENT_DEPOSITS_CONFIRMED, - INTENT_FULFILLED, - INTENT_HASH_SIGNED, - INTENT_SUBMITTED, -}; +export { createSteps }; diff --git a/packages/core/sdk/ca-base/swap/data.ts b/packages/core/sdk/ca-base/swap/data.ts index bbfdabd5..b07d4fc8 100644 --- a/packages/core/sdk/ca-base/swap/data.ts +++ b/packages/core/sdk/ca-base/swap/data.ts @@ -1,12 +1,12 @@ -import { Bytes, PermitVariant, Universe } from '@arcana/ca-common'; -import { Hex } from 'viem'; +import { Bytes, PermitVariant, Universe } from '@avail-project/ca-common'; +import { Hex, PublicClient } from 'viem'; import { toHex } from 'viem/utils'; import { ChainList } from '../chains'; import { TokenInfo } from '@nexus/commons'; import { convertTo32BytesHex, equalFold } from '../utils'; import { EADDRESS } from './constants'; -import { convertToEVMAddress } from './utils'; +import { convertToEVMAddress, determinePermitVariantAndVersion } from './utils'; export enum CurrencyID { AVAX = 5, @@ -326,6 +326,7 @@ export type FlatBalance = { tokenAddress: `0x${string}`; universe: Universe; value: number; + logo: string; }; const filterSupportedTokens = (tokens: FlatBalance[]) => { @@ -343,15 +344,11 @@ const filterSupportedTokens = (tokens: FlatBalance[]) => { return true; } - // if (token.PermitVariant === PermitVariant.Unsupported) { - // return false; - // } - return true; }); }; -const getTokenVersion = (tokenAddress: Hex) => { +const getTokenVersion = async (tokenAddress: Hex, client: PublicClient) => { for (const [, tokens] of chainData.entries()) { const t = tokens.find((t) => equalFold(convertTo32BytesHex(tokenAddress), t.TokenContractAddress), @@ -360,7 +357,9 @@ const getTokenVersion = (tokenAddress: Hex) => { return { variant: t.PermitVariant, version: t.PermitContractVersion }; } } - throw new Error('token not available or has no version'); + + const { variant, version } = await determinePermitVariantAndVersion(client, tokenAddress); + return { variant, version }; }; export const getTokenDecimals = (chainID: number | string, contractAddress: Bytes) => { diff --git a/packages/core/sdk/ca-base/swap/ob.ts b/packages/core/sdk/ca-base/swap/ob.ts index c2eba89b..5426d4b3 100644 --- a/packages/core/sdk/ca-base/swap/ob.ts +++ b/packages/core/sdk/ca-base/swap/ob.ts @@ -7,30 +7,22 @@ import { CurrencyID, Holding, liquidateInputHoldings, - OmniversalChainID, Quote, QuoteRequestExactInput, Universe, -} from '@arcana/ca-common'; +} from '@avail-project/ca-common'; import { DirectSecp256k1Wallet } from '@cosmjs/proto-signing'; import Decimal from 'decimal.js'; import { orderBy, retry } from 'es-toolkit'; import Long from 'long'; -import { ByteArray, Hex, PrivateKeyAccount, toBytes, WalletClient } from 'viem'; -import { getLogger } from '../logger'; +import { Hex, PrivateKeyAccount, toBytes, WalletClient } from 'viem'; +import { getLogger, SWAP_STEPS, SwapStepType } from '@nexus/commons'; import { divDecimals, equalFold, minutesToMs, waitForTxReceipt } from '../utils'; import { EADDRESS, SWEEPER_ADDRESS } from './constants'; import { getTokenDecimals } from './data'; import { createBridgeRFF } from './rff'; import { caliburExecute, checkAuthCodeSet, createSBCTxFromCalls, waitForSBCTxReceipt } from './sbc'; -import { - CREATE_PERMIT_FOR_SOURCE_SWAP, - DESTINATION_SWAP_BATCH_TX, - RFF_ID, - SOURCE_SWAP_HASH, - SWAP_COMPLETE, - SwapStep, -} from './steps'; + import { bytesEqual, Cache, @@ -57,6 +49,8 @@ import { SBCTx, Tx, } from '@nexus/commons'; +import { SwapRoute } from './route'; +import { Errors } from '../errors'; type Options = { address: { @@ -73,7 +67,7 @@ type Options = { }; destinationChainID: number; emitter: { - emit: (step: SwapStep) => void; + emit: (step: SwapStepType) => void; }; networkConfig: { COSMOS_URL: string; @@ -93,32 +87,13 @@ type SwapInput = { agg: Aggregator; cfee: bigint; cur: Currency; - originalHolding: Holding; + originalHolding: Holding & { decimals: number; symbol: string }; quote: Quote; req: QuoteRequestExactInput; }; const logger = getLogger(); -type DDSInput = { - aggregator: Aggregator; - createdAt: number; - dstChainCOT: Currency; - dstEOAToEphTx: { - amount: bigint; - contractAddress: Hex; - } | null; - inputAmount: Decimal; - inputAmountWithBuffer: Decimal; - outputAmount: bigint; - quote: null | Quote; - req: { - chain: OmniversalChainID; - inputToken: Buffer; - outputToken: ByteArray; - }; -}; - class BridgeHandler { private depositCalls: RFFDepositCallMap = {}; private eoaToEphCalls: EoaToEphemeralCallMap = {}; @@ -160,7 +135,7 @@ class BridgeHandler { for (const c in this.depositCalls) { const chain = this.options.chainList.getChainByID(Number(c)); if (!chain) { - throw new Error('chain not found'); + throw Errors.chainNotFound(Number(c)); } const publicClient = this.options.publicClientList.get(c); @@ -213,7 +188,7 @@ class BridgeHandler { if (sbcTx.length) { const ops = await vscSBCTx(sbcTx, this.options.networkConfig.VSC_DOMAIN); ops.forEach((op) => { - this.options.emitter.emit(SOURCE_SWAP_HASH(op, this.options.chainList)); + this.options.emitter.emit(SWAP_STEPS.SOURCE_SWAP_HASH(op, this.options.chainList)); }); waitingPromises.push( ...ops.map(([chainID, hash]) => @@ -292,7 +267,7 @@ class BridgeHandler { ); metadata.rff_id = BigInt(this.status.intentID.toNumber()); - this.options.emitter.emit(RFF_ID(this.status.intentID.toNumber())); + this.options.emitter.emit(SWAP_STEPS.RFF_ID(this.status.intentID.toNumber())); // will just resolve immediately if no CA was required logger.debug('Fill wait start'); @@ -319,7 +294,7 @@ class BridgeHandler { class DestinationSwapHandler { private destinationCalls: Tx[] = []; constructor( - private dstSwap: { getDDS: () => Promise } & DDSInput, + private data: SwapRoute['destination'], private dstTokenInfo: { contractAddress: `0x${string}`; decimals: number; @@ -332,10 +307,10 @@ class DestinationSwapHandler { }, private options: Options, ) { - if (dstSwap.dstEOAToEphTx) { + if (data.swap.dstEOAToEphTx) { options.cache.addAllowanceQuery({ chainID: dst.chainID, - contractAddress: dstSwap.dstEOAToEphTx.contractAddress, + contractAddress: data.swap.dstEOAToEphTx.contractAddress, owner: options.address.eoa, spender: options.address.ephemeral, }); @@ -360,19 +335,19 @@ class DestinationSwapHandler { options.cache.addAllowanceQuery({ chainID: dst.chainID, - contractAddress: convertToEVMAddress(dstSwap.req.inputToken), + contractAddress: convertToEVMAddress(data.swap.req.inputToken), owner: options.address.ephemeral, spender: SWEEPER_ADDRESS, }); } async createPermit() { - if (this.dstSwap.dstEOAToEphTx) { + if (this.data.swap.dstEOAToEphTx) { const txs = await createPermitAndTransferFromTx({ - amount: this.dstSwap.dstEOAToEphTx.amount, + amount: this.data.swap.dstEOAToEphTx.amount, cache: this.options.cache, chain: this.options.chainList.getChainByID(this.dst.chainID)!, - contractAddress: this.dstSwap.dstEOAToEphTx.contractAddress, + contractAddress: this.data.swap.dstEOAToEphTx.contractAddress, owner: this.options.address.eoa, ownerWallet: this.options.wallet.eoa, publicClient: this.options.publicClientList.get(this.dst.chainID), @@ -382,7 +357,7 @@ class DestinationSwapHandler { } } - // FIXME: Need to add retry and reqoute + // Retry only once, can't keep user waiting. async process( metadata: SwapMetadata, // inputAmount = this.dstSwap.quote?.inputAmount, @@ -390,45 +365,64 @@ class DestinationSwapHandler { await this.options.wallet.eoa.switchChain({ id: Number(this.options.destinationChainID), }); + try { + await this.executeSwap(metadata); + } catch (error) { + logger.warn('Destination swap failed, attempting single requote & retry.', { + error: (error as Error)?.message ?? error, + }); - let hasDestinationSwap = false; - if (this.dstSwap.quote) { - hasDestinationSwap = true; - await this.requoteIfRequired(/*inputAmount*/); - - const txs = getTxsFromQuote( - this.dstSwap.aggregator, - this.dstSwap.quote!, - this.dstSwap.req.inputToken, - true, - ); - - if (txs.approval) { - this.destinationCalls.push(txs.approval); + await this.requoteIfRequired(true); + try { + await this.executeSwap(metadata); + } catch (retryError) { + logger.error('Destination swap failed after single retry.', { + error: (retryError as Error)?.message ?? retryError, + }); + throw retryError; } + } + } - this.destinationCalls.push(txs.swap); + /** + * Executes swap + sweeper steps + */ + private async executeSwap(metadata: SwapMetadata) { + await this.requoteIfRequired(false); - logger.debug('swap:destinationCalls', { - destinationCalls: this.destinationCalls, - }); + const { swap } = this.data; + const txs = getTxsFromQuote( + { + agg: swap.aggregator, + originalHolding: swap.originalHolding, + quote: swap.quote!, + req: swap.req, + }, + true, + ); - metadata.dst.swaps.push({ - agg: 0, - input_amt: toBytes(txs.amount), - input_contract: this.dstSwap.req.inputToken, - input_decimals: this.dstSwap.dstChainCOT.decimals, - output_amt: convertTo32Bytes(this.dst.amount ?? 0), - output_contract: convertTo32Bytes(this.dst.token), - output_decimals: this.dstTokenInfo.decimals, - }); + if (txs.approval) { + this.destinationCalls.push(txs.approval); } + this.destinationCalls.push(txs.swap); - if (hasDestinationSwap) { - this.options.emitter.emit(DESTINATION_SWAP_BATCH_TX(false)); - } + logger.debug('swap:destinationCalls', { + destinationCalls: this.destinationCalls, + }); - // So whatever amount is swapped gets transferred ephemeral -> eoa + metadata.dst.swaps.push({ + agg: 0, + input_amt: toBytes(txs.amount), + input_contract: swap.req.inputToken, + input_decimals: swap.dstChainCOT.decimals, + output_amt: convertTo32Bytes(this.dst.amount ?? 0), + output_contract: convertTo32Bytes(this.dst.token), + output_decimals: this.dstTokenInfo.decimals, + }); + + this.options.emitter.emit(SWAP_STEPS.DESTINATION_SWAP_BATCH_TX(false)); + + // Add sweeper tx this.destinationCalls = this.destinationCalls.concat( createSweeperTxs({ cache: this.options.cache, @@ -440,7 +434,7 @@ class DestinationSwapHandler { }), ); - // Destination swap batched tx to VSC and waiting for receipt (sweep after) + // Execute batched destination tx const hash = await performDestinationSwap({ actualAddress: this.options.address.eoa, cache: this.options.cache, @@ -451,62 +445,65 @@ class DestinationSwapHandler { emitter: this.options.emitter, ephemeralAddress: this.options.address.ephemeral, ephemeralWallet: this.options.wallet.ephemeral, - hasDestinationSwap, + hasDestinationSwap: true, publicClientList: this.options.publicClientList, vscDomain: this.options.networkConfig.VSC_DOMAIN, }); - if (hasDestinationSwap) { - this.options.emitter.emit(DESTINATION_SWAP_BATCH_TX(true)); - } + this.options.emitter.emit(SWAP_STEPS.DESTINATION_SWAP_BATCH_TX(true)); + this.options.emitter.emit(SWAP_STEPS.SWAP_COMPLETE); - this.options.emitter.emit(SWAP_COMPLETE); performance.mark('xcs-ops-end'); - logger.debug('before dst metadata', { - metadata, - }); - + logger.debug('before dst metadata', { metadata }); metadata.dst.tx_hash = convertTo32Bytes(hash); } - async requoteIfRequired() { - let requote = false; - - if (this.dstSwap.aggregator instanceof BebopAggregator) { - const quote = this.dstSwap.quote as BebopQuote; - if (quote.originalResponse.quote.expiry * 1000 < Date.now()) { - logger.debug('DDS: BEBOP', { - expiry: quote.originalResponse.quote.expiry * 1000, - now: Date.now(), - }); + /** + * Requote if expired or invalid. + * If `force` = true, always requote regardless of expiry check. + */ + private async requoteIfRequired(force = false) { + const { swap } = this.data; + let requote = force; + + if (!force) { + if (swap.aggregator instanceof BebopAggregator) { + const quote = swap.quote as BebopQuote; + if (quote.originalResponse.quote.expiry * 1000 < Date.now()) requote = true; + } else if (Date.now() - swap.creationTime > minutesToMs(0.4)) { requote = true; } - } else if (Date.now() - this.dstSwap.createdAt > minutesToMs(0.4)) { - requote = true; } - // else if (this.dstSwap.quote?.inputAmount !== inputAmount) { - // requote = true; - // } - - if (requote) { - const ddsResponse = await this.dstSwap.getDDS(); - if (!ddsResponse.quote) { - throw new Error('could not requote DS'); - } - logger.debug('reqoutedDstSwap', { - inputAmountWithBuffer: this.dstSwap.inputAmountWithBuffer.toFixed(), - newInputAmount: ddsResponse.inputAmount.toFixed(), - }); - const isExactIn = this.dst.amount == undefined; - if (!isExactIn && ddsResponse.inputAmount.gt(this.dstSwap.inputAmountWithBuffer)) { - throw new Error( - `Rates changed for destination swap and could not be filled even with buffer. Before: ${this.dstSwap.inputAmountWithBuffer.toFixed()} ,After: ${ddsResponse.inputAmount.toFixed()}`, - ); - } - this.dstSwap = { ...ddsResponse, getDDS: this.dstSwap.getDDS }; + if (!requote) { + return; + } + + logger.debug('Requoting destination swap...'); + const newSwap = await this.data.fetchDestinationSwapDetails(); + if (!newSwap.quote) throw new Error('Failed to requote destination swap.'); + + const isExactIn = this.dst.amount == undefined; + if ( + !isExactIn && + newSwap.inputAmount.min.gte(swap.inputAmount.min) && + newSwap.inputAmount.min.lte(swap.inputAmount.max) + ) { + throw new Error( + `Rates changed beyond tolerance. Before: ${swap.inputAmount.min.toFixed()}, After: ${newSwap.inputAmount.min.toFixed()}`, + ); } + + this.data = { + swap: newSwap, + fetchDestinationSwapDetails: this.data.fetchDestinationSwapDetails, + }; + + logger.debug('Destination swap requoted successfully.', { + before: swap.inputAmount.min.toFixed(), + after: newSwap.inputAmount.min.toFixed(), + }); } } @@ -514,10 +511,10 @@ class SourceSwapsHandler { private disposableCache: { [k: string]: Tx } = {}; private swaps: Map; constructor( - quotes: SwapInput[], + data: SwapRoute['source'], private options: Options, ) { - this.swaps = this.groupAndOrder(quotes); + this.swaps = this.groupAndOrder(data.swaps); for (const [chainID, swapQuotes] of this.iterate(this.swaps)) { this.options.cache.addSetCodeQuery({ address: this.options.address.ephemeral, @@ -546,7 +543,11 @@ class SourceSwapsHandler { const swaps: { amount: bigint; approval: null | Tx; - inputToken: Bytes; + input: { + token: Bytes; + decimals: number; + symbol: string; + }; outputAmount: bigint; outputToken: Bytes; swap: { @@ -609,14 +610,9 @@ class SourceSwapsHandler { const publicClient = this.options.publicClientList.get(chainID); const chain = this.options.chainList.getChainByID(Number(chainID)); if (!chain) { - throw new Error(`chain not found: ${chainID}`); + throw Errors.chainNotFound(chainID); } - logger.debug('srcSwapHandler:process', { - swaps, - mtd, - }); - metadataTx.swaps = metadataTx.swaps.concat(mtd); // 1. Source swap calls @@ -624,14 +620,15 @@ class SourceSwapsHandler { { for (const swap of swaps) { amount += swap.outputAmount; - const { symbol } = getTokenDecimals(Number(chainID), swap.inputToken); - if (isNativeAddress(convertToEVMAddress(swap.inputToken))) { + if (isNativeAddress(convertToEVMAddress(swap.input.token))) { sbcCalls.value += swap.amount; } else { - this.options.emitter.emit(CREATE_PERMIT_FOR_SOURCE_SWAP(false, symbol, chain)); + this.options.emitter.emit( + SWAP_STEPS.CREATE_PERMIT_FOR_SOURCE_SWAP(false, swap.input.symbol, chain), + ); const allowanceCacheKey = getAllowanceCacheKey({ chainID: chain.id, - contractAddress: convertToEVMAddress(swap.inputToken), + contractAddress: convertToEVMAddress(swap.input.token), owner: this.options.address.eoa, spender: this.options.address.ephemeral, }); @@ -641,7 +638,7 @@ class SourceSwapsHandler { approval: this.disposableCache[allowanceCacheKey], cache: this.options.cache, chain, - contractAddress: convertToEVMAddress(swap.inputToken), + contractAddress: convertToEVMAddress(swap.input.token), owner: this.options.address.eoa, ownerWallet: this.options.wallet.eoa, publicClient, @@ -654,7 +651,9 @@ class SourceSwapsHandler { this.disposableCache[allowanceCacheKey] = approvalTx; } - this.options.emitter.emit(CREATE_PERMIT_FOR_SOURCE_SWAP(true, symbol, chain)); + this.options.emitter.emit( + SWAP_STEPS.CREATE_PERMIT_FOR_SOURCE_SWAP(true, swap.input.symbol, chain), + ); logger.debug('sourceSwap', { chainID, permitCalls: txs, @@ -730,7 +729,7 @@ class SourceSwapsHandler { }); metadataTx.tx_hash = convertTo32Bytes(hash); this.options.emitter.emit( - SOURCE_SWAP_HASH([BigInt(chain.id), hash], this.options.chainList), + SWAP_STEPS.SOURCE_SWAP_HASH([BigInt(chain.id), hash], this.options.chainList), ); waitingPromises.push(wrap(Number(chainID), waitForTxReceipt(hash, publicClient, 2))); @@ -758,7 +757,9 @@ class SourceSwapsHandler { const [chainID, hash] = ops[0]; metadataTx.tx_hash = convertTo32Bytes(hash); - this.options.emitter.emit(SOURCE_SWAP_HASH([chainID, hash], this.options.chainList)); + this.options.emitter.emit( + SWAP_STEPS.SOURCE_SWAP_HASH([chainID, hash], this.options.chainList), + ); return wrap( Number(chainID), @@ -888,7 +889,15 @@ class SourceSwapsHandler { returnData: {}, }); - return nq.quotes[0]; + const q = nq.quotes[0]; + return { + ...q, + originalHolding: { + ...q.originalHolding, + decimals: oq.originalHolding.decimals, + symbol: oq.originalHolding.symbol, + }, + }; }), ); } @@ -915,7 +924,7 @@ class SourceSwapsHandler { slippage: this.options.slippage, }) ) { - throw new Error('slippage greater than max slippage'); + throw Errors.slippageError('source swap retry slippage exceeded max'); } } @@ -979,10 +988,6 @@ class Swap { getMetadata() { const txs = this.getTxsData(); - const { decimals: inputDecimals } = getTokenDecimals( - Number(this.input.req.chain.chainID), - this.input.req.inputToken, - ); const { decimals: outputDecimals } = getTokenDecimals( Number(this.input.req.chain.chainID), @@ -992,7 +997,7 @@ class Swap { agg: 1, input_amt: convertTo32Bytes(this.input.req.inputAmount), input_contract: this.input.req.inputToken, - input_decimals: inputDecimals, + input_decimals: txs.input.decimals, output_amt: convertTo32Bytes(txs.amount), output_contract: this.input.req.outputToken, output_decimals: outputDecimals, @@ -1001,30 +1006,11 @@ class Swap { getTxsData() { return { - ...getTxsFromQuote( - this.input.agg, - this.input.quote, - this.input.req.inputToken, - !bytesEqual(EADDRESS_32_BYTES, this.input.req.inputToken), - ), + ...getTxsFromQuote(this.input, !bytesEqual(EADDRESS_32_BYTES, this.input.req.inputToken)), outputToken: this.input.req.outputToken, }; } } -// class SwapGroup { -// requoted = true; -// constructor( -// public swaps: Swap[], -// public chainID: number, -// ) {} - -// execute() { -// // Requote -// // Execute -// } - -// requote() {} -// } const wrap = async (chainID: number, promise: Promise) => { await promise; diff --git a/packages/core/sdk/ca-base/swap/rff.ts b/packages/core/sdk/ca-base/swap/rff.ts index ab180b9a..70d173d9 100644 --- a/packages/core/sdk/ca-base/swap/rff.ts +++ b/packages/core/sdk/ca-base/swap/rff.ts @@ -1,29 +1,19 @@ -import { - DepositVEPacket, - EVMRFF, - EVMVaultABI, - MsgDoubleCheckTx, - Universe, -} from '@arcana/ca-common'; +import { DepositVEPacket, EVMVaultABI, MsgDoubleCheckTx, Universe } from '@avail-project/ca-common'; import { DirectSecp256k1Wallet } from '@cosmjs/proto-signing'; import Decimal from 'decimal.js'; import Long from 'long'; import { bytesToNumber, createPublicClient, - encodeAbiParameters, encodeFunctionData, - getAbiItem, - keccak256, + Hex, PrivateKeyAccount, - toBytes, toHex, webSocket, } from 'viem'; -import { ErrorInsufficientBalance } from '../errors'; -import { getLogger } from '../logger'; +import { Errors } from '../errors'; import { createRFFromIntent } from '../utils'; -import { Intent, NetworkConfig } from '@nexus/commons'; +import { getLogger, Intent, NetworkConfig } from '@nexus/commons'; import { convertAddressByUniverse, evmWaitForFill, @@ -33,8 +23,10 @@ import { mulDecimals, removeIntentHashFromStore, storeIntentHashToStore, + cosmosCreateDoubleCheckTx, + cosmosCreateRFF, } from '../utils'; -import { cosmosCreateDoubleCheckTx, cosmosCreateRFF, packERC20Approve } from './utils'; +import { packERC20Approve } from './utils'; import { BridgeAsset, EoaToEphemeralCallMap, @@ -45,41 +37,15 @@ import { const logger = getLogger(); -const createEmptyIntent = ({ - chainID, - decimals, -}: { - decimals: number; - chainID: number; -}): Intent => ({ - allSources: [], - destination: { - amount: new Decimal(0), - chainID, - decimals, - gas: 0n, - tokenContract: '0x', - universe: Universe.ETHEREUM, - }, - fees: { - caGas: '0', - collection: '0', - fulfilment: '0', - gasSupplied: '0', - protocol: '0', - solver: '0', - }, - isAvailableBalanceInsufficient: false, - sources: [], -}); - export const createIntent = ({ assets, feeStore, output, + address, }: { assets: BridgeAsset[]; feeStore: FeeStore; + address: Hex; output: { amount: Decimal; chainID: number; @@ -88,7 +54,28 @@ export const createIntent = ({ }; }) => { const eoaToEphemeralCalls: EoaToEphemeralCallMap = {}; - const intent = createEmptyIntent({ chainID: output.chainID, decimals: output.decimals }); + const intent: Intent = { + allSources: [], + recipientAddress: address, + destination: { + amount: new Decimal(0), + chainID: output.chainID, + decimals: output.decimals, + gas: 0n, + tokenContract: '0x', + universe: Universe.ETHEREUM, + }, + fees: { + caGas: '0', + collection: '0', + fulfilment: '0', + gasSupplied: '0', + protocol: '0', + solver: '0', + }, + isAvailableBalanceInsufficient: false, + sources: [], + }; let borrow = output.amount; intent.destination.amount = borrow; @@ -132,6 +119,15 @@ export const createIntent = ({ break; } + const collectionFee = feeStore.calculateCollectionFee({ + decimals: asset.decimals, + sourceChainID: asset.chainID, + sourceTokenAddress: asset.contractAddress, + }); + + intent.fees.collection = collectionFee.add(intent.fees.collection).toFixed(); + borrow = borrow.add(collectionFee); + const unaccountedBalance = borrow.minus(accountedBalance); const estimatedBorrowFromThisChain = Decimal.add( @@ -201,6 +197,8 @@ export const createIntent = ({ chainID: asset.chainID, tokenContract: asset.contractAddress, universe: Universe.ETHEREUM, + // FIXME: + holderAddress: '0x', }); accountedBalance = accountedBalance.add(borrowFromThisChain); } @@ -249,10 +247,11 @@ export const createBridgeRFF = async ({ assets: input.assets, feeStore, output, + address: config.evm.address, }); if (intent.isAvailableBalanceInsufficient) { - throw ErrorInsufficientBalance; + throw Errors.insufficientBalance(); } const { msgBasicCosmos, omniversalRFF, signatureData, sources } = await createRFFromIntent( @@ -261,7 +260,7 @@ export const createBridgeRFF = async ({ chainList: config.chainList, cosmos: { address: config.cosmos.address, - client: config.cosmos.wallet, + wallet: config.cosmos.wallet, }, evm: { address: config.evm.address, @@ -315,8 +314,8 @@ export const createBridgeRFF = async ({ intent.sources.map((s) => ({ chainID: s.chainID, tokenContract: s.tokenContract, + holderAddress: config.evm.address, })), - config.evm.address, config.chainList, ); @@ -328,7 +327,7 @@ export const createBridgeRFF = async ({ const chain = config.chainList.getChainByID(Number(source.chainID)); if (!chain) { - throw new Error('chain not found'); + throw Errors.chainNotFound(source.chainID); } const allowance = allowances[Number(source.chainID)]; @@ -339,7 +338,7 @@ export const createBridgeRFF = async ({ const tx: Tx[] = []; - if (allowance < source.value) { + if (allowance < source.valueRaw) { const allowanceTx = { data: packERC20Approve(config.chainList.getVaultContractAddress(Number(source.chainID))), to: convertAddressByUniverse(source.tokenAddress, Universe.ETHEREUM), @@ -367,7 +366,7 @@ export const createBridgeRFF = async ({ }); depositCalls[Number(source.chainID)] = { - amount: source.value, + amount: source.valueRaw, tokenAddress: convertAddressByUniverse(source.tokenAddress, source.universe), tx: tx, }; @@ -375,7 +374,7 @@ export const createBridgeRFF = async ({ const chain = config.chainList.getChainByID(Number(output.chainID)); if (!chain) { - throw new Error('Unknown destination chain'); + throw Errors.chainNotFound(output.chainID); } const ws = webSocket(chain.rpcUrls.default.webSocket[0]); @@ -419,27 +418,6 @@ export const createBridgeRFF = async ({ }; }; -export const createRequestEVMSignature = async (evmRFF: EVMRFF, account: PrivateKeyAccount) => { - const abi = getAbiItem({ abi: EVMVaultABI, name: 'deposit' }); - const msg = encodeAbiParameters(abi.inputs[0].components, [ - evmRFF.sources, - evmRFF.destinationUniverse, - evmRFF.destinationChainID, - evmRFF.destinations, - evmRFF.nonce, - evmRFF.expiry, - evmRFF.parties, - ]); - const hash = keccak256(msg, 'bytes'); - const signature = toBytes( - await account.signMessage({ - message: { raw: hash }, - }), - ); - - return { requestHash: hash, signature }; -}; - export const createDoubleCheckTx = ( chainID: Uint8Array, cosmos: { diff --git a/packages/core/sdk/ca-base/swap/route.ts b/packages/core/sdk/ca-base/swap/route.ts index 06e524e5..b222ad57 100644 --- a/packages/core/sdk/ca-base/swap/route.ts +++ b/packages/core/sdk/ca-base/swap/route.ts @@ -2,19 +2,21 @@ import { Aggregator, autoSelectSources, ChaindataMap, + Currency, CurrencyID, destinationSwapWithExactIn, determineDestinationSwaps, - Environment, + Holding, liquidateInputHoldings, OmniversalChainID, + Quote, + QuoteRequestExactInput, Universe, - // ZeroExAggregator, -} from '@arcana/ca-common'; +} from '@avail-project/ca-common'; import Decimal from 'decimal.js'; -import { Hex, toBytes } from 'viem'; +import { ByteArray, Hex, toBytes } from 'viem'; import { ZERO_ADDRESS } from '../constants'; -import { getLogger } from '../logger'; +import { getLogger, OraclePriceResponse } from '@nexus/commons'; import { ExactInSwapInput, ExactOutSwapInput, @@ -23,95 +25,56 @@ import { SwapParams, } from '@nexus/commons'; import { + calculateMaxBridgeFees, convertTo32BytesHex, divDecimals, equalFold, - FeeStore, fetchPriceOracle, - getEVMBalancesForAddress, getFeeStore, - getFuelBalancesForAddress, mulDecimals, + getBalances, } from '../utils'; import { EADDRESS } from './constants'; -import { filterSupportedTokens, FlatBalance, getTokenDecimals } from './data'; +import { FlatBalance } from './data'; import { ErrorChainDataNotFound, ErrorCOTNotFound, ErrorInsufficientBalance, - // ErrorInsufficientBalance, - // ErrorSingleSourceHasNoSource, ErrorTokenNotFound, } from './errors'; import { createIntent } from './rff'; -import { - balancesToAssets, - calculateValue, - convertTo32Bytes, - convertToEVMAddress, - getAnkrBalances, - toFlatBalance, -} from './utils'; -import { ChainListType, BridgeAsset } from '@nexus/commons'; +import { calculateValue, convertTo32Bytes, convertToEVMAddress } from './utils'; +import { BridgeAsset } from '@nexus/commons'; +import { Errors } from '../errors'; const logger = getLogger(); -export const getBalances = async (input: { - evmAddress: Hex; - chainList: ChainListType; - removeTransferFee?: boolean; - filter?: boolean; - fuelAddress?: string; - isCA?: boolean; - vscDomain: string; - networkHint: Environment; -}) => { - const isCA = input.isCA ?? false; - const removeTransferFee = input.removeTransferFee ?? false; - const filter = input.filter ?? true; - const [ankrBalances, evmBalances, fuelBalances] = await Promise.all([ - input.networkHint === Environment.FOLLY - ? Promise.resolve([]) - : getAnkrBalances(input.evmAddress, input.chainList, removeTransferFee), - getEVMBalancesForAddress(input.vscDomain, input.evmAddress), - input.fuelAddress - ? getFuelBalancesForAddress(input.vscDomain, input.fuelAddress as `0x${string}`) - : Promise.resolve([]), - ]); - const assets = balancesToAssets(ankrBalances, evmBalances, fuelBalances, input.chainList, isCA); - let balances = toFlatBalance(assets); - if (filter) { - balances = filterSupportedTokens(balances); - } - - logger.debug('getBalances', { - assets, - balances, - removeTransferFee, - }); - - return { assets, balances }; -}; - export const determineSwapRoute = async ( input: SwapData, options: SwapParams & { aggregators: Aggregator[]; cotCurrencyID: CurrencyID }, -) => { +): Promise => { logger.debug('determineSwapRoute', { input, options, }); - if (input.mode === SwapMode.EXACT_OUT) { - return _exactOutRoute(input.data, options); - } else { - return _exactInRoute(input.data, options); - } + return input.mode === SwapMode.EXACT_OUT + ? _exactOutRoute(input.data, options) + : _exactInRoute(input.data, options); }; +export const applyBuffer = (amount: Decimal, bufferPercent: number): Decimal => + amount.mul(1 + bufferPercent / 100); + +// COT = currency of transfer +// DEF: The common currency which is supported by bridge on every supported chain and acts as a transient currency for swaps. +// FLOW: Source tokens get converted to COT, COT is bridged across chains to a destination chain, +// COT is then changed to desired destination token +// Currently COT is USDC. + const _exactOutRoute = async ( input: ExactOutSwapInput, params: SwapParams & { aggregators: Aggregator[]; cotCurrencyID: CurrencyID }, -) => { +): Promise => { const [feeStore, { assets, balances }, oraclePrices] = await Promise.all([ getFeeStore(params.networkConfig.GRPC_URL), getBalances({ @@ -125,16 +88,11 @@ const _exactOutRoute = async ( fetchPriceOracle(params.networkConfig.GRPC_URL), ]); - // Any existing COT balance on dst chain - let dstEOAToEphTx: { - amount: bigint; - contractAddress: Hex; - } | null = null; - logger.debug('determineSwapRoute', { assets, balances, input }); - const userAddressInBytes = convertTo32Bytes(params.address.ephemeral); const dstOmniversalChainID = new OmniversalChainID(Universe.ETHEREUM, input.toChainId); + logger.debug('determineSwapRoute', { assets, balances, input }); + logger.debug('determineSwapRoute:destinationSwapInput', { dstOmniversalChainID, s: { @@ -144,6 +102,9 @@ const _exactOutRoute = async ( userAddressInBytes, }); + // ------------------------------ + // 2. Fetch chain & COT information + // ------------------------------ const dstChainDataMap = ChaindataMap.get(dstOmniversalChainID); if (!dstChainDataMap) { throw ErrorChainDataNotFound; @@ -157,25 +118,30 @@ const _exactOutRoute = async ( } const dstChainCOTAddress = convertToEVMAddress(dstChainCOT.tokenAddress); + const dstChainCOTBalance = balances.find( (b) => b.chainID === Number(input.toChainId) && equalFold(convertToEVMAddress(b.tokenAddress), dstChainCOTAddress), ); - const getDDS = async () => { - let dds: Awaited> = { + // Track any existing COT that must be moved to ephemeral for swaps + let dstEOAToEphTx: { amount: bigint; contractAddress: Hex } | null = null; + + // Since its exact out, we start with desired destination amount and work our + // way backward from there + const fetchDestinationSwapDetails = async (): Promise => { + let destinationSwap: Awaited> = { aggregator: params.aggregators[0], inputAmount: divDecimals(input.toAmount, dstChainCOT.decimals), outputAmount: 0n, quote: null, }; - // If output token is not COT then only destination swap should exist + // If output token is not COT, calculate the actual destination swap if (!equalFold(input.toTokenAddress, dstChainCOTAddress)) { - dds = await determineDestinationSwaps( + destinationSwap = await determineDestinationSwaps( userAddressInBytes, - null, dstOmniversalChainID, { amount: BigInt(input.toAmount), @@ -187,21 +153,39 @@ const _exactOutRoute = async ( const createdAt = Date.now(); - // If destination has COT then need to send it to ephemeral so that it can be used in swap + // If user has existing COT on destination chain, it must be moved to ephemeral if (new Decimal(dstChainCOTBalance?.amount ?? 0).gt(0)) { dstEOAToEphTx = { amount: mulDecimals(dstChainCOTBalance?.amount ?? 0, dstChainCOTBalance?.decimals ?? 0), contractAddress: dstChainCOTAddress, }; } + + // Use min but perform everything as max - for buffer of (max - min) + const min = destinationSwap.inputAmount; + // Apply 2% buffer to destination input amount + const max = applyBuffer(destinationSwap.inputAmount, 2).toDP( + dstChainCOT.decimals, + Decimal.ROUND_CEIL, + ); + return { - ...dds, - createdAt, + ...destinationSwap, + originalHolding: { + chainID: dstOmniversalChainID, + tokenAddress: dstChainCOT.tokenAddress, + amount: mulDecimals(destinationSwap.inputAmount, dstChainCOT.decimals), + value: 0, + decimals: dstChainCOT.decimals, + symbol: CurrencyID[dstChainCOT.currencyID], + }, + creationTime: createdAt, dstChainCOT: dstChainCOT, dstEOAToEphTx, - inputAmountWithBuffer: dds.inputAmount - .mul(1.02) - .toDP(dstChainCOT.decimals, Decimal.ROUND_CEIL), + inputAmount: { + min, + max, + }, req: { chain: dstOmniversalChainID, inputToken: dstChainCOT.tokenAddress, @@ -210,36 +194,29 @@ const _exactOutRoute = async ( }; }; - const destinationSwap = await getDDS(); + const destinationSwap = await fetchDestinationSwapDetails(); logger.debug('destination swaps', destinationSwap); + // ------------------------------ + // 4. Compute source availability + // ------------------------------ + const cotAsset = assets.find((asset) => { return asset.abstracted && equalFold(asset.symbol, cotSymbol); }); - - const dstSwapInputAmountInDecimal = destinationSwap.inputAmount - .mul(1.02) - .toDP(dstChainCOT.decimals, Decimal.ROUND_CEIL); - - logger.debug('determineSwapRoute:3', { - cotAsset, - dstChainCOTAddress, - dstChainCOTBalance, - }); - + const dstSwapInputAmountInDecimal = destinationSwap.inputAmount.max; const cotTotalBalance = new Decimal(cotAsset?.balance ?? '0'); - - const fulfilmentFee = feeStore.calculateFulfilmentFee({ + const fees = feeStore.calculateFulfilmentFee({ decimals: dstChainCOT.decimals, destinationChainID: Number(input.toChainId), destinationTokenAddress: dstChainCOTAddress, }); - const fees = fulfilmentFee; - - logger.debug('determineSwapRoute:4', { + logger.debug('exact-out:3', { cotAsset, + dstChainCOTAddress, + dstChainCOTBalance, cotTotalBalance: cotTotalBalance.toFixed(), diff: fees.toFixed(), dstSwapInputAmountInDecimal: dstSwapInputAmountInDecimal.toFixed(), @@ -247,46 +224,64 @@ const _exactOutRoute = async ( console.log({ cotAsset, dstChainCOTBalance }); - let sourceSwaps: Awaited> = []; - let sourceSwapsRequired = false; - if (!dstChainCOTBalance) { - sourceSwapsRequired = true; - } - if (!cotAsset || new Decimal(cotAsset.balance).lt(dstSwapInputAmountInDecimal)) { - sourceSwapsRequired = true; - } + // ------------------------------ + // 5. Determine if source swaps are required + // ------------------------------ + + let sourceSwaps: QuoteResponse = []; + const sourceSwapsRequired = + !dstChainCOTBalance || + !cotAsset || + new Decimal(cotAsset.balance).lt(dstSwapInputAmountInDecimal); if (sourceSwapsRequired) { - sourceSwaps = await autoSelectSources( - userAddressInBytes, - balances.map((balance) => ({ - amount: mulDecimals(balance.amount, balance.decimals), - chainID: new OmniversalChainID(balance.universe, balance.chainID), - tokenAddress: toBytes(balance.tokenAddress), - value: balance.value, - })), - dstSwapInputAmountInDecimal - .add(fees) - .mul(1.01) - .minus(cotAsset?.balance ?? '0'), - params.aggregators, - feeStore.data.fee.collection.map((f) => ({ - ...f, - chainID: convertTo32Bytes(Number(f.chainID)), - fee: convertTo32Bytes(BigInt(f.fee)), - tokenAddress: convertTo32Bytes(f.tokenAddress as Hex), - })), - ); + sourceSwaps = ( + await autoSelectSources( + userAddressInBytes, + balances.map((balance) => ({ + amount: mulDecimals(balance.amount, balance.decimals), + chainID: new OmniversalChainID(balance.universe, balance.chainID), + tokenAddress: toBytes(balance.tokenAddress), + value: balance.value, + })), + applyBuffer(dstSwapInputAmountInDecimal.add(fees), 1).minus(cotAsset?.balance ?? '0'), + params.aggregators, + feeStore.data.fee.collection.map((f) => ({ + ...f, + chainID: convertTo32Bytes(Number(f.chainID)), + fee: convertTo32Bytes(BigInt(f.fee)), + tokenAddress: convertTo32Bytes(f.tokenAddress as Hex), + })), + ) + ).map((v) => { + const balance = balances.find((b) => + equalFold(b.tokenAddress, convertTo32BytesHex(v.req.inputToken)), + ); + if (!balance) { + throw Errors.internal('mapping error: balance for quote input not found'); + } + return { + ...v, + originalHolding: { + ...v.originalHolding, + decimals: balance.decimals, + symbol: balance.symbol, + }, + }; + }); } const sourceSwapCreationTime = Date.now(); - console.log({ + logger.debug('exact-out:4', { dstChainCOTBalance, inequality: new Decimal(dstChainCOTBalance?.amount ?? 0).lt( dstSwapInputAmountInDecimal.add(fees), ), }); + // ------------------------------ + // 6. Bridge input calculation (account for already existing COT + COT from swaps) + // ------------------------------ let bridgeInput: { amount: Decimal; assets: BridgeAsset[]; @@ -375,6 +370,10 @@ const _exactOutRoute = async ( } } + // ------------------------------ + // 7. Prepare assets used to show in intent + // ------------------------------ + const assetsUsed: { amount: string; chainID: number; @@ -384,17 +383,12 @@ const _exactOutRoute = async ( }[] = []; for (const swap of sourceSwaps) { - const { decimals, symbol } = getTokenDecimals( - Number(swap.req.chain.chainID), - swap.req.inputToken, - ); - assetsUsed.push({ - amount: divDecimals(swap.quote.inputAmount, decimals).toFixed(), + amount: divDecimals(swap.quote.inputAmount, swap.originalHolding.decimals).toFixed(), chainID: Number(swap.req.chain.chainID), contractAddress: convertToEVMAddress(swap.req.inputToken), - decimals, - symbol, + decimals: swap.originalHolding.decimals, + symbol: swap.originalHolding.symbol, }); } @@ -403,6 +397,7 @@ const _exactOutRoute = async ( assets: bridgeAssets, feeStore, output: bridgeInput, + address: params.address.ephemeral, }); for (const chain in eoaToEphemeralCalls) { @@ -418,18 +413,75 @@ const _exactOutRoute = async ( }); } } - return { - aggregators: params.aggregators, - assetsUsed, - balances, - bridgeInput, - cotSymbol, - destinationSwap, - getDDS, - oraclePrices, - sourceSwapCreationTime, - sourceSwaps, + source: { + swaps: sourceSwaps, + creationTime: sourceSwapCreationTime, + }, + bridge: bridgeInput, + destination: { + swap: destinationSwap, + fetchDestinationSwapDetails, + }, + extras: { + aggregators: params.aggregators, + oraclePrices, + balances, + assetsUsed, + cotSymbol, + }, + }; +}; + +type DestinationSwap = { + creationTime: number; + dstChainCOT: Currency; + dstEOAToEphTx: { + amount: bigint; + contractAddress: Hex; + } | null; + inputAmount: { min: Decimal; max: Decimal }; + req: { + chain: OmniversalChainID; + inputToken: Buffer; + outputToken: ByteArray; + }; + quote: Quote | null; + aggregator: Aggregator; + originalHolding: Holding & { symbol: string; decimals: number }; + outputAmount: bigint; +}; + +export type SwapRoute = { + source: { + swaps: ({ + req: QuoteRequestExactInput; + cfee: bigint; + originalHolding: Holding & { decimals: number; symbol: string }; + cur: Currency; + } & { + quote: Quote; + agg: Aggregator; + })[]; + creationTime: number; + }; + bridge: BridgeInput; + destination: { + swap: DestinationSwap; + fetchDestinationSwapDetails: () => Promise; + }; + extras: { + assetsUsed: { + amount: string; + chainID: number; + contractAddress: Hex; + decimals: number; + symbol: string; + }[]; + aggregators: Aggregator[]; + oraclePrices: OraclePriceResponse; + balances: FlatBalance[]; + cotSymbol: string; }; }; @@ -449,69 +501,28 @@ type BridgeInput = { tokenAddress: `0x${string}`; } | null; -const calculateMaxBridgeFees = ({ - assets, - feeStore, - dst, -}: { - dst: { - chainId: number; - tokenAddress: Hex; - decimals: number; - }; - assets: BridgeAsset[]; - feeStore: FeeStore; -}) => { - const borrow = assets.reduce((accumulator, asset) => { - return accumulator.add(Decimal.add(asset.eoaBalance, asset.ephemeralBalance)); - }, new Decimal(0)); - - const protocolFee = feeStore.calculateProtocolFee(new Decimal(borrow)); - let borrowWithFee = borrow.add(protocolFee); - - const fulfilmentFee = feeStore.calculateFulfilmentFee({ - decimals: dst.decimals, - destinationChainID: dst.chainId, - destinationTokenAddress: dst.tokenAddress, - }); - borrowWithFee = borrowWithFee.add(fulfilmentFee); - - logger.debug('calculateMaxBridgeFees:1', { - borrow: borrow.toFixed(), - protocolFee: protocolFee.toFixed(), - fulfilmentFee: fulfilmentFee.toFixed(), - borrowWithFee: borrowWithFee.toFixed(), - }); - - for (const asset of assets) { - const solverFee = feeStore.calculateSolverFee({ - borrowAmount: Decimal.add(asset.eoaBalance, asset.ephemeralBalance), - decimals: asset.decimals, - destinationChainID: dst.chainId, - destinationTokenAddress: dst.tokenAddress, - sourceChainID: asset.chainID, - sourceTokenAddress: convertToEVMAddress(asset.contractAddress), - }); - - borrowWithFee = borrowWithFee.add(solverFee); - logger.debug('calculateMaxBridgeFees:2', { - borrow: borrow.toFixed(), - borrowWithFee: borrowWithFee.toFixed(), - solverFee: solverFee.toFixed(), - }); - } +type QuoteResponse = { + agg: Aggregator; + quote: Quote; + req: QuoteRequestExactInput; + cfee: bigint; + originalHolding: Holding & { decimals: number; symbol: string }; + cur: Currency; +}[]; - return borrowWithFee.minus(borrow); -}; +// Helper to normalize token comparison tokens (preserve EADDRESS vs ZERO_ADDRESS handling) +const normalizeToComparisonAddr = (tokenHex: Hex) => + convertTo32BytesHex(equalFold(tokenHex, ZERO_ADDRESS) ? EADDRESS : tokenHex); const _exactInRoute = async ( input: ExactInSwapInput, params: SwapParams & { aggregators: Aggregator[]; cotCurrencyID: CurrencyID }, -) => { +): Promise => { logger.debug('exactInRoute', { input, params, }); + const [feeStore, balanceResponse, oraclePrices] = await Promise.all([ getFeeStore(params.networkConfig.GRPC_URL), getBalances({ @@ -519,10 +530,17 @@ const _exactInRoute = async ( evmAddress: params.address.eoa, chainList: params.chainList, removeTransferFee: true, + filter: false, vscDomain: params.networkConfig.VSC_DOMAIN, }), fetchPriceOracle(params.networkConfig.GRPC_URL), - ]); + ]).catch((e) => { + throw new Error('Error fetching fee, balance or oracle', { cause: e }); + }); + + if (balanceResponse.balances.length === 0) { + throw new Error('no balances returned for user'); + } let { balances } = balanceResponse; @@ -532,24 +550,25 @@ const _exactInRoute = async ( const assetsUsed: AssetUsed = []; let srcBalances: FlatBalance[] = []; - if (input.from) { + + if (input.from && input.from.length > 0) { + // Filter out sources user requested to be used for (const f of input.from) { - const srcBalance = balances.find((b) => { - logger.debug('ExactIN:2:input.src', { - a: b.tokenAddress, - b: convertTo32BytesHex(f.tokenAddress), - }); + if (typeof f.amount !== 'bigint') { + throw new Error('input.from.amount must be bigint'); + } - // We are keeping ZERO_ADDRESS as EAddress so have to make the comparisonAddr like this - let comparisonTokenAddress = convertTo32BytesHex(f.tokenAddress); - if (equalFold(comparisonTokenAddress, ZERO_ADDRESS)) { - comparisonTokenAddress = EADDRESS; - } + const comparison = normalizeToComparisonAddr(f.tokenAddress); - return equalFold(b.tokenAddress, comparisonTokenAddress) && f.chainId === b.chainID; - }); + const srcBalance = balances.find( + (b) => equalFold(b.tokenAddress, comparison) && f.chainId === b.chainID, + ); if (!srcBalance) { - throw ErrorInsufficientBalance(f.amount.toString(), '0'); + logger.error('ExactIN: no src balance found', { + token: f.tokenAddress, + chainId: f.chainId, + }); + throw ErrorInsufficientBalance('0', f.amount.toString()); } const requiredBalance = divDecimals(f.amount, srcBalance.decimals); @@ -571,28 +590,19 @@ const _exactInRoute = async ( symbol: srcBalance.symbol, }); } - // } else { - // throw new Error('should have gone to single source swap route'); - // } } else { - srcBalances = balances; + srcBalances = balances.slice(); } - logger.debug('ExactIN:3', { - srcBalances, - assetsUsed, - }); - const userAddressInBytes = convertTo32Bytes(params.address.ephemeral); const dstOmniversalChainID = new OmniversalChainID(Universe.ETHEREUM, input.toChainId); const dstChainDataMap = ChaindataMap.get(dstOmniversalChainID); if (!dstChainDataMap) { - throw new Error('chaindataMap not found'); + throw new Error(`chaindata map not found for chain ${input.toChainId}`); } const cotSymbol = CurrencyID[params.cotCurrencyID]; - const dstChainCOT = dstChainDataMap.Currencies.find((c) => c.currencyID === params.cotCurrencyID); if (!dstChainCOT) { throw ErrorCOTNotFound(input.toChainId); @@ -615,6 +625,7 @@ const _exactInRoute = async ( ) { cotSources.push(source); cotCombinedBalance = cotCombinedBalance.add(source.amount); + bridgeAssets.push({ chainID: source.chainID, contractAddress: convertToEVMAddress(source.tokenAddress), @@ -634,7 +645,6 @@ const _exactInRoute = async ( // Check if source swap is required (if all source balances are not COT currencyID) const isSrcSwapRequired = cotSources.length !== srcBalances.length; - // Check if bridge is required (if all source balances are not on destination chain) const isBridgeRequired = !srcBalances.every((b) => b.chainID === input.toChainId); @@ -643,7 +653,7 @@ const _exactInRoute = async ( isBridgeRequired, }); - let sourceSwaps: Awaited>['quotes'] = []; + let sourceSwaps: QuoteResponse = []; if (isSrcSwapRequired) { const response = await liquidateInputHoldings( userAddressInBytes, @@ -662,7 +672,29 @@ const _exactInRoute = async ( })), ); - sourceSwaps = response.quotes; + if (!response.quotes.length) { + throw new Error('source swap returned no quotes'); + } + + sourceSwaps = response.quotes.map((oq) => { + const balance = balances.find((b) => + equalFold(b.tokenAddress, convertTo32BytesHex(oq.req.inputToken)), + ); + if (!balance) { + logger.error('ExactIN: failed to map quote originalHolding to balance', { + quoteReq: oq.req, + }); + throw new Error('internal mapping error: balance for quote input not found'); + } + return { + ...oq, + originalHolding: { + ...oq.originalHolding, + decimals: balance.decimals, + symbol: balance.symbol, + }, + }; + }); } const sourceSwapCreationTime = Date.now(); @@ -712,11 +744,15 @@ const _exactInRoute = async ( feeStore, }); - dstSwapInputAmountInDecimal = dstSwapInputAmountInDecimal.minus(maxFee).mul(0.98); + dstSwapInputAmountInDecimal = dstSwapInputAmountInDecimal.minus(maxFee); logger.debug('ExactIN:7', { dstSwapInputAmountInDecimal: dstSwapInputAmountInDecimal.toFixed(), maxFee: maxFee.toFixed(), }); + if (dstSwapInputAmountInDecimal.isNegative()) { + throw new Error('bridge fees exceeds source amount'); + } + bridgeInput = { amount: dstSwapInputAmountInDecimal, assets: bridgeAssets, @@ -730,8 +766,8 @@ const _exactInRoute = async ( dstSwapInputAmountInDecimal: dstSwapInputAmountInDecimal.toFixed(), }); - const getDDS = async () => { - let dds: Awaited> = { + const fetchDestinationSwapDetails = async () => { + let destinationSwap: Awaited> = { aggregator: params.aggregators[0], inputAmount: dstSwapInputAmountInDecimal, outputAmount: mulDecimals(dstSwapInputAmountInDecimal, dstChainCOT.decimals), @@ -749,7 +785,7 @@ const _exactInRoute = async ( // If toTokenAddress is not same as cot then create dstSwap if (!equalFold(input.toTokenAddress, dstChainCOTAddress)) { - dds = await destinationSwapWithExactIn( + destinationSwap = await destinationSwapWithExactIn( userAddressInBytes, dstOmniversalChainID, mulDecimals(dstSwapInputAmountInDecimal, dstChainCOT.decimals), @@ -759,7 +795,7 @@ const _exactInRoute = async ( ); } - const createdAt = Date.now(); + // const createdAt = Date.now(); let dstEOAToEphTx: { amount: bigint; contractAddress: Hex; @@ -776,39 +812,54 @@ const _exactInRoute = async ( } logger.debug('ExactIN: getDDS: SingleSrcSwap: After', { - dds, + destinationSwap, dstSwapInputAmountInDecimal: dstSwapInputAmountInDecimal.toFixed(), }); return { - ...dds, - createdAt, + ...destinationSwap, + originalHolding: { + chainID: dstOmniversalChainID, + tokenAddress: dstChainCOT.tokenAddress, + amount: mulDecimals(dstSwapInputAmountInDecimal, dstChainCOT.decimals), + value: 0, + decimals: dstChainCOT.decimals, + symbol: CurrencyID[dstChainCOT.currencyID], + }, dstChainCOT: dstChainCOT, dstEOAToEphTx, - inputAmountWithBuffer: dstSwapInputAmountInDecimal, + inputAmount: { min: dstSwapInputAmountInDecimal, max: dstSwapInputAmountInDecimal }, req: { chain: dstOmniversalChainID, inputToken: dstChainCOT.tokenAddress, outputToken: toBytes(input.toTokenAddress), }, + creationTime: Date.now(), }; }; - const destinationSwap = await getDDS(); + const destinationSwap = await fetchDestinationSwapDetails(); logger.debug('getSwapRoute: ExactIN: After', { destinationSwap, dstSwapInputAmountInDecimal: dstSwapInputAmountInDecimal.toFixed(), }); + return { - aggregators: params.aggregators, - assetsUsed, - balances, - bridgeInput, - cotSymbol, - destinationSwap, - getDDS, - oraclePrices, - sourceSwapCreationTime, - sourceSwaps, + source: { + swaps: sourceSwaps, + creationTime: sourceSwapCreationTime, + }, + bridge: bridgeInput, + destination: { + swap: destinationSwap, + fetchDestinationSwapDetails, + }, + extras: { + assetsUsed, + aggregators: params.aggregators, + oraclePrices, + balances, + cotSymbol, + }, }; }; diff --git a/packages/core/sdk/ca-base/swap/sbc.ts b/packages/core/sdk/ca-base/swap/sbc.ts index 76b925ef..7bde7248 100644 --- a/packages/core/sdk/ca-base/swap/sbc.ts +++ b/packages/core/sdk/ca-base/swap/sbc.ts @@ -1,4 +1,4 @@ -import { Universe } from '@arcana/ca-common'; +import { Universe } from '@avail-project/ca-common'; import { bytesToBigInt, Chain, @@ -13,12 +13,11 @@ import { WalletClient, } from 'viem'; -import { getLogger } from '../logger'; import { waitForTxReceipt } from '../utils'; import CaliburABI from './calibur.abi'; import { CALIBUR_ADDRESS, CALIBUR_EIP712, ZERO_BYTES_20, ZERO_BYTES_32 } from './constants'; import { Cache, convertTo32Bytes, isAuthorizationCodeSet, PublicClientList } from './utils'; -import { ChainListType, CaliburSBCTypes, SBCTx, Tx } from '@nexus/commons'; +import { getLogger, ChainListType, CaliburSBCTypes, SBCTx, Tx } from '@nexus/commons'; const logger = getLogger(); diff --git a/packages/core/sdk/ca-base/swap/swap.ts b/packages/core/sdk/ca-base/swap/swap.ts index 5b5b1954..6e46969b 100644 --- a/packages/core/sdk/ca-base/swap/swap.ts +++ b/packages/core/sdk/ca-base/swap/swap.ts @@ -4,16 +4,23 @@ import { CurrencyID, LiFiAggregator, Universe, -} from '@arcana/ca-common'; +} from '@avail-project/ca-common'; -import { SwapMode, type SwapData, type SwapParams, SuccessfulSwapResult } from '@nexus/commons'; - -import { getLogger } from '../logger'; +import { + SwapMode, + type SwapData, + type SwapParams, + SuccessfulSwapResult, + NEXUS_EVENTS, + SWAP_STEPS, + SwapStepType, +} from '@nexus/commons'; + +import { getLogger } from '@nexus/commons'; import { divDecimals } from '../utils'; import { BEBOP_API_KEY, LIFI_API_KEY, ZERO_BYTES_32 } from './constants'; import { BridgeHandler, DestinationSwapHandler, SourceSwapsHandler } from './ob'; import { determineSwapRoute } from './route'; -import { DETERMINING_SWAP, SWAP_START, SwapStep } from './steps'; import { Cache, convertMetadataToSwapResult, @@ -24,6 +31,7 @@ import { PublicClientList, SwapMetadata, } from './utils'; +import { Errors } from '../errors'; const logger = getLogger(); @@ -40,24 +48,26 @@ export const swap = async ( const publicClientList = new PublicClientList(options.chainList); const cache = new Cache(publicClientList); const dstChain = options.chainList.getChainByID(input.data.toChainId); - if (!dstChain) { - throw new Error('destination chain not supported'); + throw Errors.chainNotFound(input.data.toChainId); } + performance.mark('swap-start'); const emitter = { - emit: (step: SwapStep) => { - options.emit('swap_step', step); + emit: (step: SwapStepType) => { + if (options.onEvent) { + options.onEvent({ name: NEXUS_EVENTS.SWAP_STEP_COMPLETE, args: step }); + } }, }; - emitter.emit(SWAP_START); + emitter.emit(SWAP_STEPS.SWAP_START); logger.debug('swapBegin', { options, input }); performance.mark('determine-swaps-start'); - emitter.emit(DETERMINING_SWAP()); + emitter.emit(SWAP_STEPS.DETERMINING_SWAP()); const aggregators: Aggregator[] = [ new LiFiAggregator(LIFI_API_KEY), @@ -77,77 +87,73 @@ export const swap = async ( swapRoute, }); - let { assetsUsed, bridgeInput, destinationSwap, sourceSwaps } = swapRoute; + let { source, destination, bridge, extras } = swapRoute; logger.debug('initial-swap-route', { - assetsUsed, - bridgeInput, - destinationSwap, + source, + destination, + bridge, + extras, dstTokenInfo, - sourceSwaps, swapRoute, }); - emitter.emit(DETERMINING_SWAP(true)); + emitter.emit(SWAP_STEPS.DETERMINING_SWAP(true)); performance.mark('determine-swaps-end'); performance.mark('xcs-ops-start'); // Swap Intent hook handling { - if (options?.swapIntentHook) { - const hook = options?.swapIntentHook; - - const destination = { - amount: divDecimals( - input.mode === SwapMode.EXACT_OUT ? input.data.toAmount : destinationSwap.outputAmount, - dstTokenInfo.decimals, - ).toFixed(), - chainID: input.data.toChainId, - contractAddress: input.data.toTokenAddress, - decimals: dstTokenInfo.decimals, - symbol: dstTokenInfo.symbol, + const destinationTokenDetails = { + amount: divDecimals( + input.mode === SwapMode.EXACT_OUT ? input.data.toAmount : destination.swap.outputAmount, + dstTokenInfo.decimals, + ).toFixed(), + chainID: input.data.toChainId, + contractAddress: input.data.toTokenAddress, + decimals: dstTokenInfo.decimals, + symbol: dstTokenInfo.symbol, + }; + + let accepted = false; + + const refresh = async () => { + if (accepted) { + logger.warn('Swap Intent refresh called after acceptance'); + return createSwapIntent(extras.assetsUsed, destinationTokenDetails, options.chainList); + } + + const swapRouteResponse = await determineSwapRoute(input, swapRouteParams); + + source = swapRouteResponse.source; + extras = swapRouteResponse.extras; + destination = swapRouteResponse.destination; + bridge = swapRouteResponse.bridge; + logger.debug('refresh-swap-route', { + dstTokenInfo, + swapRoute: swapRouteResponse, + }); + return createSwapIntent(extras.assetsUsed, destinationTokenDetails, options.chainList); + }; + // wait for intent acceptance hook + await new Promise((resolve, reject) => { + const allow = () => { + accepted = true; + return resolve('User allowed intent'); }; - let accepted = false; - - const refresh = async () => { - if (accepted) { - logger.warn('Swap Intent refresh called after acceptance'); - return createSwapIntent(assetsUsed, destination, options.chainList); - } - - const swapRouteResponse = await determineSwapRoute(input, swapRouteParams); - - sourceSwaps = swapRouteResponse.sourceSwaps; - assetsUsed = swapRouteResponse.assetsUsed; - destinationSwap = swapRouteResponse.destinationSwap; - bridgeInput = swapRouteResponse.bridgeInput; - logger.debug('refresh-swap-route', { - dstTokenInfo, - swapRoute: swapRouteResponse, - }); - return createSwapIntent(assetsUsed, destination, options.chainList); + const deny = () => { + return reject(ErrorUserDeniedIntent); }; - // wait for intent acceptance hook - await new Promise((resolve, reject) => { - const allow = () => { - accepted = true; - return resolve('User allowed intent'); - }; - - const deny = () => { - return reject(ErrorUserDeniedIntent); - }; - - hook({ - allow, - deny, - intent: createSwapIntent(assetsUsed, destination, options.chainList), - refresh, - }); + + options.onSwapIntent({ + allow, + deny, + intent: createSwapIntent(extras.assetsUsed, destinationTokenDetails, options.chainList), + refresh, }); - } + }); } const metadata: SwapMetadata = { @@ -179,16 +185,16 @@ export const swap = async ( wallet: options.wallet, }; - const srcSwapsHandler = new SourceSwapsHandler(sourceSwaps, opt); - const bridgeHandler = new BridgeHandler(bridgeInput, opt); + const srcSwapsHandler = new SourceSwapsHandler(source, opt); + const bridgeHandler = new BridgeHandler(bridge, opt); const dstSwapHandler = new DestinationSwapHandler( - { ...destinationSwap, getDDS: swapRoute.getDDS }, + destination, dstTokenInfo, { chainID: input.data.toChainId, token: input.data.toTokenAddress, amount: - input.mode === SwapMode.EXACT_OUT ? input.data.toAmount : destinationSwap.outputAmount, + input.mode === SwapMode.EXACT_OUT ? input.data.toAmount : destination.swap.outputAmount, }, opt, ); diff --git a/packages/core/sdk/ca-base/swap/utils.ts b/packages/core/sdk/ca-base/swap/utils.ts index ebb56509..ad207325 100644 --- a/packages/core/sdk/ca-base/swap/utils.ts +++ b/packages/core/sdk/ca-base/swap/utils.ts @@ -4,25 +4,18 @@ import { BebopQuote, Bytes, ChaindataMap, - createCosmosClient, CurrencyID, ERC20ABI, - EVMRFF, - EVMVaultABI, + Holding, LiFiAggregator, LiFiQuote, - MsgCreateRequestForFunds, - MsgCreateRequestForFundsResponse, - MsgDoubleCheckTx, msgpackableAxios, OmniversalChainID, PermitVariant, Quote, Universe, -} from '@arcana/ca-common'; +} from '@avail-project/ca-common'; import CaliburABI from './calibur.abi'; -import { DirectSecp256k1Wallet } from '@cosmjs/proto-signing'; -import { isDeliverTxFailure } from '@cosmjs/stargate'; import axios from 'axios'; import Decimal from 'decimal.js'; import { retry } from 'es-toolkit'; @@ -34,14 +27,11 @@ import { bytesToNumber, concat, createPublicClient, - encodeAbiParameters, encodeFunctionData, - getAbiItem, getContract, Hex, hexToBigInt, http, - keccak256, maxUint256, pad, parseSignature, @@ -50,17 +40,13 @@ import { toBytes, toHex, WalletClient, - WebSocketTransport, } from 'viem'; - import { ERC20PermitABI, ERC20PermitEIP2612PolygonType, ERC20PermitEIP712Type } from '../abi/erc20'; -import { FillEvent } from '../abi/vault'; import { getLogoFromSymbol, ZERO_ADDRESS } from '../constants'; -import { getLogger } from '../logger'; +import { getLogger } from '@nexus/commons'; import { Chain, SuccessfulSwapResult, - TokenInfo, UnifiedBalanceResponseData, UserAssetDatum, } from '@nexus/commons'; @@ -69,7 +55,6 @@ import { convertTo32BytesHex, divDecimals, equalFold, - getCosmosURL, getExplorerURL, getVSCURL, waitForTxReceipt, @@ -78,9 +63,18 @@ import { SWEEP_ABI } from './abi'; import { CALIBUR_ADDRESS, EADDRESS, SWEEPER_ADDRESS } from './constants'; import { chainData, getTokenVersion } from './data'; import { createSBCTxFromCalls, waitForSBCTxReceipt } from './sbc'; -import { DESTINATION_SWAP_HASH, SwapStep } from './steps'; -import { AnkrAsset, AnkrBalances, SBCTx, SwapIntent, Tx, ChainListType } from '@nexus/commons'; +import { + SWAP_STEPS, + SwapStepType, + AnkrAsset, + AnkrBalances, + SBCTx, + SwapIntent, + Tx, + ChainListType, +} from '@nexus/commons'; import Long from 'long'; +import { Errors } from '../errors'; const logger = getLogger(); @@ -305,103 +299,6 @@ export const vscSBCTx = async (input: SBCTx[], vscDomain: string) => { return ops; }; -export const createRequestEVMSignature = async (evmRFF: EVMRFF, client: WalletClient) => { - const account = (await client.getAddresses())[0]; - const abi = getAbiItem({ abi: EVMVaultABI, name: 'deposit' }); - const msg = encodeAbiParameters(abi.inputs[0].components, [ - evmRFF.sources, - evmRFF.destinationUniverse, - evmRFF.destinationChainID, - evmRFF.destinations, - evmRFF.nonce, - evmRFF.expiry, - evmRFF.parties, - ]); - const hash = keccak256(msg, 'bytes'); - const signature = toBytes( - await client.signMessage({ - account, - message: { raw: hash }, - }), - ); - - return { requestHash: hash, signature }; -}; - -export const cosmosCreateRFF = async ({ - address, - cosmosURL, - msg, - wallet, -}: { - address: string; - cosmosURL: string; - msg: MsgCreateRequestForFunds; - wallet: DirectSecp256k1Wallet; -}) => { - const client = await createCosmosClient(wallet, getCosmosURL(cosmosURL, 'rpc'), { - broadcastPollIntervalMs: 250, - }); - - const res = await client.signAndBroadcast( - address, - [ - { - typeUrl: '/xarchain.chainabstraction.MsgCreateRequestForFunds', - value: msg, - }, - ], - { - amount: [], - gas: 100_000n.toString(10), - }, - ); - - if (isDeliverTxFailure(res)) { - throw new Error('Error creating RFF'); - } - - const decoded = MsgCreateRequestForFundsResponse.decode(res.msgResponses[0].value); - return decoded.id; -}; -export const cosmosCreateDoubleCheckTx = async ({ - address, - cosmosURL, - msg, - wallet, -}: { - address: string; - cosmosURL: string; - msg: MsgDoubleCheckTx; - wallet: DirectSecp256k1Wallet; -}) => { - const client = await createCosmosClient(wallet, getCosmosURL(cosmosURL, 'rpc'), { - broadcastPollIntervalMs: 250, - }); - - logger.debug('cosmosCreateDoubleCheckTx:1', { doubleCheckMsg: msg }); - - const res = await client.signAndBroadcast( - address, - [ - { - typeUrl: '/xarchain.chainabstraction.MsgDoubleCheckTx', - value: msg, - }, - ], - { - amount: [], - gas: 100_000n.toString(10), - }, - ); - - if (isDeliverTxFailure(res)) { - throw new Error('Error creating MsgDoubleCheckTx'); - } - - logger.debug('cosmosCreateDoubleCheckTx:2', { doubleCheckTx: res }); -}; - export const EXPECTED_CALIBUR_CODE = concat(['0xef0100', CALIBUR_ADDRESS]); export const isAuthorizationCodeSet = async ( @@ -485,7 +382,7 @@ export const createPermitAndTransferFromTx = async ({ logger.debug('createPermitTx', { allowance, amount }); if (allowance < amount) { - const { variant, version } = getTokenVersion(contractAddress); + const { variant, version } = await getTokenVersion(contractAddress, publicClient); if (variant === PermitVariant.Unsupported) { const { request } = await publicClient.simulateContract({ chain, @@ -535,6 +432,115 @@ export const createPermitAndTransferFromTx = async ({ return txList; }; +export const determinePermitVariantAndVersion = async ( + client: PublicClient, + contractAddress: Hex, +) => { + const standardPermitData = encodeFunctionData({ + abi: [ + { + type: 'function', + name: 'permit', + inputs: [ + { type: 'address', name: 'owner' }, + { type: 'address', name: 'spender' }, + { type: 'uint256', name: 'value' }, + { type: 'uint256', name: 'deadline' }, + { type: 'uint8', name: 'v' }, + { type: 'bytes32', name: 'r' }, + { type: 'bytes32', name: 's' }, + ], + }, + ], + functionName: 'permit', + args: [ + '0x0000000000000000000000000000000000000000', + '0x0000000000000000000000000000000000000000', + 0n, + 0n, + 0, + '0x0000000000000000000000000000000000000000000000000000000000000000', + '0x0000000000000000000000000000000000000000000000000000000000000000', + ], + }); + + // Dummy data for DAI-style permit (holder=spender=zero, nonce=0, expiry=0, allowed=true, v=0, r=0, s=0) + const daiPermitData = encodeFunctionData({ + abi: [ + { + type: 'function', + name: 'permit', + inputs: [ + { type: 'address', name: 'holder' }, + { type: 'address', name: 'spender' }, + { type: 'uint256', name: 'nonce' }, + { type: 'uint256', name: 'expiry' }, + { type: 'bool', name: 'allowed' }, + { type: 'uint8', name: 'v' }, + { type: 'bytes32', name: 'r' }, + { type: 'bytes32', name: 's' }, + ], + }, + ], + functionName: 'permit', + args: [ + '0x0000000000000000000000000000000000000000', + '0x0000000000000000000000000000000000000000', + 0n, + 0n, + true, + 0, + '0x0000000000000000000000000000000000000000000000000000000000000000', + '0x0000000000000000000000000000000000000000000000000000000000000000', + ], + }); + + const promises = [ + functionExists(client, contractAddress, standardPermitData), + functionExists(client, contractAddress, daiPermitData), + getVersion(client, contractAddress), + ]; + const [canonicalPermitResponse, daiPermitResponse, versionResponse] = + await Promise.allSettled(promises); + + let variant = PermitVariant.Unsupported; + if (canonicalPermitResponse.status === 'fulfilled') { + variant = PermitVariant.EIP2612Canonical; + } else if (daiPermitResponse.status === 'fulfilled') { + variant = PermitVariant.DAI; + } + + return { + variant, + version: versionResponse.status === 'fulfilled' ? Number(versionResponse.value) : 1, + }; +}; + +async function getVersion(client: PublicClient, token: `0x${string}`): Promise { + try { + const result = await client.readContract({ + address: token, + abi: [ + { + type: 'function', + name: 'version', + inputs: [], + stateMutability: 'view', + outputs: [{ name: '', type: 'string' }], + }, + ] as const, + functionName: 'version', + }); + return result; + } catch { + return '1'; + } +} + +async function functionExists(client: PublicClient, token: `0x${string}`, data: `0x${string}`) { + return client.call({ to: token, data }); +} + export const createPermitApprovalTx = async ({ contractAddress, owner, @@ -708,6 +714,7 @@ export function getTokenSymbol(symbol: string) { export const toFlatBalance = ( assets: UserAssetDatum[], + convertAddressToBytes32 = true, currentChainID?: number, selectedTokenAddress?: `0x${string}`, ) => { @@ -717,16 +724,16 @@ export const toFlatBalance = ( return assets .map((a) => a.breakdown.map((b) => { + const tokenAddress = b.contractAddress === ZERO_ADDRESS ? EADDRESS : b.contractAddress; return { amount: b.balance, chainID: b.chain.id, decimals: b.decimals, symbol: a.symbol, - tokenAddress: convertTo32BytesHex( - b.contractAddress === ZERO_ADDRESS ? EADDRESS : b.contractAddress, - ), + tokenAddress: convertAddressToBytes32 ? convertTo32BytesHex(tokenAddress) : tokenAddress, universe: b.universe, value: b.balanceInFiat, + logo: a.icon ?? '', }; }), ) @@ -743,19 +750,21 @@ export const toFlatBalance = ( }; export const balancesToAssets = ( + isCA: boolean, ankrBalances: AnkrBalances, - evmBalances: UnifiedBalanceResponseData[], - fuelBalances: UnifiedBalanceResponseData[], chainList: ChainListType, - isCA: boolean, + evmBalances: UnifiedBalanceResponseData[] = [], + fuelBalances: UnifiedBalanceResponseData[] = [], + tronBalances: UnifiedBalanceResponseData[] = [], ) => { const assets: UserAssetDatum[] = []; - const vscBalances = evmBalances.concat(fuelBalances); + const vscBalances = evmBalances.concat(fuelBalances).concat(tronBalances); logger.debug('balanceToAssets', { ankrBalances, evmBalances, fuelBalances, + tronBalances, }); for (const balance of vscBalances) { for (const currency of balance.currencies) { @@ -771,7 +780,7 @@ export const balancesToAssets = ( const decimals = token ? token.decimals : chain.nativeCurrency.decimals; if (token) { - const asset = assets.find((s) => s.symbol === token.symbol); + const asset = assets.find((s) => equalFold(s.symbol, token.symbol)); if (asset) { asset.balance = new Decimal(asset.balance).add(currency.balance).toFixed(); asset.balanceInFiat = new Decimal(asset.balanceInFiat) @@ -897,37 +906,6 @@ export const balancesToAssets = ( return assets; }; -export const waitForIntentFulfilment = async ( - publicClient: PublicClient, - vaultContractAddr: `0x${string}`, - requestHash: `0x${string}`, -): Promise => { - logger.debug('waitForIntentFulfilment', { requestHash }); - return new Promise((resolve) => { - const unwatch = publicClient.watchContractEvent({ - abi: [FillEvent] as const, - address: vaultContractAddr, - args: { requestHash }, - eventName: 'Fill', - onLogs: (logs) => { - logger.debug('waitForIntentFulfilment', { logs }); - publicClient.transport.getRpcClient().then((c) => c.close()); - // ac?.abort(); - unwatch(); - return resolve(void 0); - }, - poll: false, - }); - // ac?.signal.addEventListener( - // "abort", - // () => { - // unwatch(); - // }, - // { once: true }, - // ); - }); -}; - export const average = (a: bigint, b: bigint) => { return (a & b) + ((a ^ b) >> 1n); }; @@ -1076,7 +1054,7 @@ export class PublicClientList { if (!client) { const chain = this.chainList.getChainByID(Number(chainID)); if (!chain) { - throw new Error(`Chain not found: ${chainID}`); + throw Errors.chainNotFound(Number(chainID)); } client = createPublicClient({ transport: http(chain.rpcUrls.default.http[0]), @@ -1101,323 +1079,31 @@ export const getAllowanceCacheKey = ({ export const getSetCodeKey = (input: SetCodeInput) => ('a' + input.chainID + input.address).toLowerCase(); -// const APPROVE_GAS_LIMIT = 63_000n; - -// export const swapToGasIfPossible = async ({ -// actualAddress, -// aggregators, -// assetsUsed, -// balances, -// chainList, -// ephemeralAddress, -// oraclePrices, -// }: { -// actualAddress: Bytes; -// aggregators: Aggregator[]; -// assetsUsed: { -// amount: string; -// chainID: number; -// contractAddress: `0x${string}`; -// }[]; -// balances: Balances; -// chainList: ChainList; -// ephemeralAddress: Bytes; -// grpcURL: string; -// oraclePrices: OraclePriceResponse; -// }) => { -// const aci: CreateAllowanceCacheInput = new Set(); -// const blacklist: Hex[] = []; -// const data: { -// [k: number]: { -// amount: bigint; -// contractAddress: Hex; -// txs: Tx[]; -// unsupportedTokens: Hex[]; -// }; -// } = {}; - -// let requote = false; -// const chainToUnsupportedTokens: Record = {}; - -// const assetsGroupedByChain = Map.groupBy( -// assetsUsed, -// (asset) => asset.chainID, -// ); - -// for (const [chainID, swapQuotes] of assetsGroupedByChain) { -// for (const sQuote of swapQuotes) { -// if (!isEIP2612Supported(sQuote.contractAddress, BigInt(chainID))) { -// if (!chainToUnsupportedTokens[Number(chainID)]) { -// chainToUnsupportedTokens[Number(chainID)] = []; -// } -// aci.add({ -// chainID: Number(chainID), -// contractAddress: sQuote.contractAddress, -// owner: convertToEVMAddress(actualAddress), -// spender: convertToEVMAddress(ephemeralAddress), -// }); -// chainToUnsupportedTokens[Number(chainID)].push(sQuote.contractAddress); -// } -// } -// } -// logger.debug("checkAndSupplyGasForApproval:1", { -// assetsGroupedByChain, -// chainToUnsupportedTokens, -// }); - -// const allowanceCache = await createAllowanceCache(aci, chainList); - -// if (Object.keys(chainToUnsupportedTokens).length === 0) { -// return { blacklist, data, requote: false }; -// } - -// for (const chainID in chainToUnsupportedTokens) { -// const tokens: Hex[] = []; -// for (const token of chainToUnsupportedTokens[chainID]) { -// const allowance = allowanceCache.gget({ -// chainID: Number(chainID), -// owner: convertToEVMAddress(actualAddress), -// spender: convertToEVMAddress(ephemeralAddress), -// tokenAddress: token, -// }); -// if (!allowance || allowance < 100000000n) { -// tokens.push(token); -// } -// } -// if (tokens.length) { -// chainToUnsupportedTokens[chainID] = tokens; -// } else { -// delete chainToUnsupportedTokens[chainID]; -// } - -// const quotes = assetsGroupedByChain.get(Number(chainID)); -// const balancesOnChain = balances.filter( -// (b) => -// b.chain_id === Number(chainID) && -// isEIP2612Supported(b.token_address, BigInt(chainID)), -// ); - -// const chain = chainList.getChainByID(Number(chainID)); -// if (!chain) { -// throw new Error(`chain not found: ${chainID}`); -// } - -// const publicClient = createPublicClient({ -// transport: http(chain.rpcUrls.default.http[0]), -// }); - -// const gasPrice = await publicClient.estimateFeesPerGas(); - -// const gas = -// APPROVE_GAS_LIMIT * -// gasPrice.maxFeePerGas * -// BigInt(chainToUnsupportedTokens[chainID].length) * -// 3n; - -// const nativeBalance = balances.find( -// (b) => -// b.chain_id === Number(chainID) && equalFold(b.token_address, EADDRESS), -// ); - -// logger.debug("checkAndSupplyGasForApproval:2", { -// gas, -// gasPrice, -// nativeBalance, -// }); - -// if (new Decimal(nativeBalance?.amount ?? 0).gte(gas)) { -// data[Number(chainID)] = { -// // Since txs.length == 0, amount and contractAddress should not get used, only unsupported token -// amount: 0n, -// contractAddress: "0x", -// txs: [], -// unsupportedTokens: chainToUnsupportedTokens[chainID], -// }; -// continue; -// } - -// let done = false; - -// // Split between sources included and excluded in source swaps -// const split = splitBalanceByQuotes(balancesOnChain, quotes!); -// logger.debug("checkAndSupplyGasForApproval:3", { -// chainID, -// split, -// }); -// for (const s of split.excluded) { -// const gasInToken = convertGasToToken( -// { -// contractAddress: s.token_address, -// decimals: s.decimals, -// priceUSD: s.priceUSD, -// }, -// oraclePrices, -// chain.id, -// divDecimals(gas, chain.nativeCurrency.decimals), -// ); - -// logger.debug("checkAndSupplyGasForApproval:3:excluded", { -// amount: s.amount, -// gasInToken: gasInToken.toFixed(), -// token: s, -// }); - -// if (gasInToken.lt(s.amount)) { -// const res = await swapToGasQuote( -// ephemeralAddress, -// actualAddress, -// new OmniversalChainID(Universe.ETHEREUM, chainID), -// { -// tokenAddress: EADDRESS_32_BYTES, -// }, -// aggregators, -// { -// amount: mulDecimals(gasInToken, s.decimals), -// decimals: s.decimals, -// tokenAddress: convertTo32Bytes(s.token_address), -// }, -// ); -// if (res.quote) { -// const txs = getTxsFromQuote( -// res.aggregator, -// res.quote, -// convertTo32Bytes(s.token_address), -// ); -// data[Number(chainID)] = { -// amount: mulDecimals(gasInToken, s.decimals), -// contractAddress: s.token_address, -// txs: [txs.approval!, txs.swap], -// unsupportedTokens: chainToUnsupportedTokens[chainID], -// }; -// done = true; -// break; -// } -// } -// } - -// if (!done) { -// for (const s of split.included) { -// const gasInToken = convertGasToToken( -// { -// contractAddress: s.token_address, -// decimals: s.decimals, -// priceUSD: s.priceUSD, -// }, -// oraclePrices, -// chain.id, -// divDecimals(gas, chain.nativeCurrency.decimals), -// ); - -// logger.debug("checkAndSupplyGasForApproval:3:included", { -// amount: s.amount, -// gasInToken: gasInToken.toFixed(), -// }); - -// if (gasInToken.gte(s.amount)) { -// const res = await swapToGasQuote( -// ephemeralAddress, -// actualAddress, -// new OmniversalChainID(Universe.ETHEREUM, chainID), -// { -// tokenAddress: EADDRESS_32_BYTES, -// }, -// aggregators, -// { -// amount: mulDecimals(gasInToken, s.decimals), -// decimals: s.decimals, -// tokenAddress: convertTo32Bytes(s.token_address), -// }, -// ); -// if (res.quote) { -// const txs = getTxsFromQuote( -// res.aggregator, -// res.quote, -// convertTo32Bytes(s.token_address), -// ); -// data[Number(chainID)] = { -// amount: mulDecimals(gasInToken, s.decimals), -// contractAddress: s.token_address, -// txs: [txs.approval!, txs.swap], -// unsupportedTokens: chainToUnsupportedTokens[chainID], -// }; -// // since we had to use source swap token for gas -// // TODO: Check if we have enough if we swap for gas otherwise throw error -// done = true; -// requote = true; -// break; -// } -// } -// } -// } - -// if (!done) { -// throw new Error(`could not swap token for gas on chain: ${chainID}`); -// } -// } - -// return { -// blacklist, -// data, -// requote, -// }; -// }; - -// const convertGasToToken = ( -// token: { contractAddress: Hex; decimals: number; priceUSD: string }, -// oraclePrices: OraclePriceResponse, -// destinationChainID: number, -// gas: Decimal, -// ) => { -// const gasTokenPerUSD = -// oraclePrices -// .find( -// (rate) => -// rate.chainId === destinationChainID && -// equalFold(rate.tokenAddress, ZERO_ADDRESS), -// ) -// ?.tokensPerUsd.toString() ?? "0"; -// const transferTokenPerUSD = Decimal.div(1, token.priceUSD); - -// logger.debug("convertGasToToken", { -// gas: gas.toFixed(), -// gasTokenPerUSD, -// transferTokenPerUSD, -// }); - -// const gasInUSD = new Decimal(1).div(gasTokenPerUSD).mul(gas); -// const totalRequired = new Decimal(gasInUSD).div(transferTokenPerUSD); - -// return totalRequired.toDP(token.decimals, Decimal.ROUND_CEIL); -// }; - export const getTxsFromQuote = ( - aggregator: Aggregator, - quote: Quote, - inputToken: Bytes, + input: { + agg: Aggregator; + originalHolding: Holding & { decimals: number; symbol: string }; + quote: Quote; + req: { inputToken: Bytes }; + }, createApproval = true, ) => { logger.debug('getTxsFromQuote', { - aggregator, createApproval, - inputToken, - quote, + input, }); - if (aggregator instanceof LiFiAggregator) { - const originalResponse = (quote as LiFiQuote).originalResponse; + if (input.agg instanceof LiFiAggregator) { + const originalResponse = (input.quote as LiFiQuote).originalResponse; const tx = originalResponse.transactionRequest; - logger.debug('getTxsFromQuote', { - 'approval.amount': quote.inputAmount, - 'approval.target': originalResponse.estimate.approvalAddress, - tx: tx, - 'tx.amount': quote.inputAmount, - 'tx.inputToken': inputToken, - 'tx.outputAmount': quote.outputAmountMinimum, - }); const val = { - amount: quote.inputAmount, + amount: input.quote.inputAmount, approval: null as null | Tx, - inputToken, - outputAmount: quote.outputAmountMinimum, + input: { + token: input.req.inputToken, + decimals: input.originalHolding.decimals, + symbol: input.originalHolding.symbol, + }, + outputAmount: input.quote.outputAmountMinimum, swap: { data: tx.data as Hex, to: tx.to as Hex, @@ -1426,29 +1112,36 @@ export const getTxsFromQuote = ( }; if (createApproval) { val.approval = { - data: packERC20Approve(originalResponse.estimate.approvalAddress as Hex, quote.inputAmount), - to: convertToEVMAddress(inputToken), + data: packERC20Approve( + originalResponse.estimate.approvalAddress as Hex, + input.quote.inputAmount, + ), + to: convertToEVMAddress(input.req.inputToken), value: 0n, }; } return val; - } else if (aggregator instanceof BebopAggregator) { - const originalResponse = (quote as BebopQuote).originalResponse; + } else if (input.agg instanceof BebopAggregator) { + const originalResponse = (input.quote as BebopQuote).originalResponse; const tx = originalResponse.quote.tx; logger.debug('getTxsFromQuote', { - 'approval.amount': quote.inputAmount, + 'approval.amount': input.quote.inputAmount, 'approval.target': originalResponse.quote.approvalTarget, tx: tx, - 'tx.amount': quote.inputAmount, - 'tx.inputToken': inputToken, - 'tx.outputAmount': quote.outputAmountMinimum, + 'tx.amount': input.quote.inputAmount, + 'tx.inputToken': input.req.inputToken, + 'tx.outputAmount': input.quote.outputAmountMinimum, }); const val = { - amount: quote.inputAmount, + amount: input.quote.inputAmount, approval: null as null | Tx, - inputToken, - outputAmount: quote.outputAmountMinimum, + input: { + token: input.req.inputToken, + decimals: input.originalHolding.decimals, + symbol: input.originalHolding.symbol, + }, + outputAmount: input.quote.outputAmountMinimum, swap: { data: tx.data, to: tx.to, @@ -1457,8 +1150,11 @@ export const getTxsFromQuote = ( }; if (createApproval) { val.approval = { - data: packERC20Approve(originalResponse.quote.approvalTarget as Hex, quote.inputAmount), - to: convertToEVMAddress(inputToken), + data: packERC20Approve( + originalResponse.quote.approvalTarget as Hex, + input.quote.inputAmount, + ), + to: convertToEVMAddress(input.req.inputToken), value: 0n, }; } @@ -1469,75 +1165,6 @@ export const getTxsFromQuote = ( throw new Error('Unknown aggregator'); }; -// const splitBalanceByQuotes = ( -// balances: Balances, -// quotes: { -// amount: string; -// chainID: number; -// contractAddress: `0x${string}`; -// }[], -// ) => { -// const [included, excluded] = partition(balances, (b) => { -// return !!quotes.find((q) => equalFold(q.contractAddress, b.token_address)); -// }); - -// return { -// excluded, -// included, -// }; -// }; - -// export async function swapToGasQuote( -// userAddress: Bytes, -// receiverAddress: Bytes | null, -// chainID: OmniversalChainID, -// requirement: { -// tokenAddress: Bytes; -// }, -// aggregators: Aggregator[], -// cur: { -// amount: bigint; -// decimals: number; -// tokenAddress: Bytes; -// }, -// ): Promise<{ -// aggregator: Aggregator; -// inputAmount: Decimal; -// quote: null | Quote; -// }> { -// // We spray and pray -// const buyQuoteResult = await aggregateAggregators( -// [ -// { -// chain: chainID, -// inputAmount: cur.amount, -// inputToken: cur.tokenAddress, -// outputToken: requirement.tokenAddress, -// receiverAddress, -// type: QuoteType.ExactIn, -// userAddress, -// }, -// ], -// aggregators, -// 0, -// ); -// if (buyQuoteResult.length !== 1) { -// throw new AutoSelectionError("???"); -// } - -// const buyQuote = buyQuoteResult[0]; -// if (buyQuote.quote == null) { -// throw new AutoSelectionError("Couldn't get buy quote"); -// } - -// return { -// ...buyQuote, -// inputAmount: convertBigIntToDecimal(buyQuote.quote.inputAmount).div( -// Decimal.pow(10, cur.decimals), -// ), -// }; -// } - /** * Creates Tx object depending on contractAddress being native or ERC20 */ @@ -1592,7 +1219,7 @@ export const createSwapIntent = ( ): SwapIntent => { const chain = chainList.getChainByID(destination.chainID); if (!chain) { - throw new Error(`chain not found: ${destination.chainID}`); + throw Errors.chainNotFound(destination.chainID); } const intent: SwapIntent = { @@ -1615,7 +1242,7 @@ export const createSwapIntent = ( for (const source of sources) { const chain = chainList.getChainByID(source.chainID); if (!chain) { - throw new Error(`chain not found: ${source.chainID}`); + throw Errors.chainNotFound(source.chainID); } intent.sources.push({ @@ -1813,7 +1440,7 @@ export const postSwap = async ({ }); const rffIDN = Number(metadata.rff_id); - // @ts-ignore + // @ts-expect-error delete metadata.rff_id; const res = await metadataAxios<{ value: number }>({ @@ -1939,7 +1566,7 @@ export const performDestinationSwap = async ({ chainList: ChainListType; COT: CurrencyID; emitter: { - emit: (step: SwapStep) => void; + emit: (step: SwapStepType) => void; }; ephemeralAddress: Hex; ephemeralWallet: PrivateKeyAccount; @@ -1972,7 +1599,7 @@ export const performDestinationSwap = async ({ performance.mark('destination-swap-end'); if (hasDestinationSwap) { - emitter.emit(DESTINATION_SWAP_HASH(ops[0], chainList)); + emitter.emit(SWAP_STEPS.DESTINATION_SWAP_HASH(ops[0], chainList)); } performance.mark('destination-swap-mining-start'); @@ -2009,43 +1636,11 @@ export const performDestinationSwap = async ({ }; export const getSwapSupportedChains = (chainList: ChainListType) => { - const chains: { - id: number; - logo: string; - name: string; - tokens: TokenInfo[]; - }[] = []; - for (const c of chainData.keys()) { - const chain = chainList.getChainByID(c); - if (!chain) { - continue; - } - - const data = { + return chainList.chains + .filter((chain) => chain.ankrName !== '') + .map((chain) => ({ id: chain.id, - logo: chain.custom.icon, name: chain.name, - tokens: [] as TokenInfo[], - }; - - const tokens = chainData.get(c); - if (!tokens) { - continue; - } - - tokens.forEach((t) => { - if (t.PermitVariant !== PermitVariant.Unsupported) { - data.tokens.push({ - contractAddress: convertToEVMAddress(t.TokenContractAddress), - decimals: t.TokenDecimals, - logo: '', - name: t.Name, - symbol: t.Name, - }); - } - }); - - chains.push(data); - } - return chains; + logo: chain.custom.icon, + })); }; diff --git a/packages/core/sdk/ca-base/utils/api.utils.ts b/packages/core/sdk/ca-base/utils/api.utils.ts index 68e392ee..791e10af 100644 --- a/packages/core/sdk/ca-base/utils/api.utils.ts +++ b/packages/core/sdk/ca-base/utils/api.utils.ts @@ -1,19 +1,26 @@ -import { Bytes, GrpcWebImpl, QueryClientImpl, RequestForFunds, Universe } from '@arcana/ca-common'; +import { + Bytes, + GrpcWebImpl, + QueryClientImpl, + RequestForFunds, + Universe, +} from '@avail-project/ca-common'; import axios, { AxiosInstance } from 'axios'; import Decimal from 'decimal.js'; import { connect } from 'it-ws/client'; import Long from 'long'; import { pack, unpack } from 'msgpackr'; import { bytesToBigInt, bytesToNumber, toHex } from 'viem'; -import { getLogger } from '../logger'; -import { ALLOWANCE_APPROVAL_MINED, INTENT_COLLECTION, INTENT_COLLECTION_COMPLETE } from '../steps'; import { + BRIDGE_STEPS, + BridgeStepType, + getLogger, FeeStoreData, OraclePriceResponse, RFF, SponsoredApprovalDataArray, - StepInfo, UnifiedBalanceResponseData, + ChainListType, } from '@nexus/commons'; import { convertAddressByUniverse, @@ -22,6 +29,7 @@ import { equalFold, minutesToMs, } from './common.utils'; +import { Errors } from '../errors'; const logger = getLogger(); @@ -47,33 +55,78 @@ async function fetchMyIntents(address: string, grpcURL: string, page = 1) { reverse: true, }, }); - return intentTransform(response.requestForFunds); + return response.requestForFunds; } catch (error) { logger.error('Failed to fetch intents', error); throw new Error('Failed to fetch intents'); } } -const intentTransform = (input: RequestForFunds[]): RFF[] => { - return input.map((rff) => ({ - deposited: rff.deposited, - destinationChainID: bytesToNumber(rff.destinationChainID), - destinations: rff.destinations.map((d) => ({ - tokenAddress: convertToHexAddressByUniverse(d.tokenAddress, rff.destinationUniverse), - value: bytesToBigInt(d.value), - })), - destinationUniverse: Universe[rff.destinationUniverse], - expiry: rff.expiry.toNumber(), - fulfilled: rff.fulfilled, - id: rff.id.toNumber(), - refunded: rff.refunded, - sources: rff.sources.map((s) => ({ - chainID: bytesToNumber(s.chainID), - tokenAddress: convertToHexAddressByUniverse(s.tokenAddress, s.universe), - universe: Universe[s.universe], - value: bytesToBigInt(s.value), - })), - })); +export const intentTransform = (input: RequestForFunds[], chainList: ChainListType): RFF[] => { + return input.map((rff) => { + const dstChainId = bytesToNumber(rff.destinationChainID); + const dstChain = chainList.getChainByID(dstChainId); + if (!dstChain) { + throw Errors.chainNotFound(dstChainId); + } + return { + deposited: rff.deposited, + destinationChain: { + id: dstChain.id, + name: dstChain.name, + logo: dstChain.custom.icon, + universe: Universe[rff.destinationUniverse], + }, + destinations: rff.destinations.map((d) => { + const contractAddress = convertToHexAddressByUniverse( + d.contractAddress, + rff.destinationUniverse, + ); + const token = chainList.getTokenByAddress(dstChainId, contractAddress); + if (!token) { + throw Errors.tokenNotSupported(contractAddress, dstChainId); + } + const valueRaw = bytesToBigInt(d.value); + return { + token: { + address: contractAddress, + symbol: token.symbol, + decimals: token.decimals, + }, + valueRaw, + value: divDecimals(valueRaw, token.decimals).toFixed(token.decimals), + }; + }), + expiry: rff.expiry.toNumber(), + fulfilled: rff.fulfilled, + id: rff.id.toNumber(), + refunded: rff.refunded, + sources: rff.sources.map((s) => { + const chainId = bytesToNumber(s.chainID); + const contractAddress = convertToHexAddressByUniverse(s.contractAddress, s.universe); + const result = chainList.getChainAndTokenByAddress(chainId, contractAddress); + if (!result || !result.token) { + throw Errors.tokenNotSupported(contractAddress, chainId); + } + const valueRaw = bytesToBigInt(s.value); + return { + chain: { + id: result.chain.id, + name: result.chain.name, + logo: result.chain.custom.icon, + universe: Universe[s.universe], + }, + value: divDecimals(valueRaw, result.token.decimals).toFixed(result.token.decimals), + valueRaw, + token: { + address: contractAddress, + symbol: result.token.symbol, + decimals: result.token.decimals, + }, + }; + }), + }; + }); }; async function fetchProtocolFees(grpcURL: string) { @@ -313,12 +366,13 @@ const getVscReq = (vscDomain: string) => { export const getBalancesFromVSC = async ( vscDomain: string, address: `0x${string}`, - namespace: 'ETHEREUM' | 'FUEL' = 'ETHEREUM', + namespace: 'ETHEREUM' | 'FUEL' | 'TRON' = 'ETHEREUM', ) => { const response = await getVscReq(vscDomain).get<{ balances: UnifiedBalanceResponseData[]; }>(`/get-balance/${namespace}/${address}`); - return response.data.balances; + logger.debug('getBalancesFromVSC', { response }); + return response.data.balances.filter((b) => b.errored !== true); }; export const getEVMBalancesForAddress = async (vscDomain: string, address: `0x${string}`) => { @@ -329,6 +383,10 @@ export const getFuelBalancesForAddress = async (vscDomain: string, address: `0x$ return getBalancesFromVSC(vscDomain, address, 'FUEL'); }; +export const getTronBalancesForAddress = async (vscDomain: string, address: `0x${string}`) => { + return getBalancesFromVSC(vscDomain, address, 'TRON'); +}; + const vscCreateFeeGrant = async (vscDomain: string, address: string) => { const response = await getVscReq(vscDomain).post(`/create-feegrant`, { cosmos_address: address, @@ -360,7 +418,7 @@ type CreateSponsoredApprovalResponse = const vscCreateSponsoredApprovals = async ( vscDomain: string, input: SponsoredApprovalDataArray, - msd?: (s: StepInfo, data?: { [k: string]: unknown }) => void, + msd?: (s: BridgeStepType) => void, ) => { const connection = connect( new URL('/api/v1/create-sponsored-approvals', getVSCURL(vscDomain, 'wss')).toString(), @@ -378,15 +436,19 @@ const vscCreateSponsoredApprovals = async ( logger.debug('vscCreateSponsoredApprovals', { data }); if ('errored' in data && data.errored) { - throw new Error(data.error); + throw Errors.vscError(`create-sponsored-approvals: ${data.error}`); } if ('error' in data && data.error) { - throw new Error(data.msg); + throw Errors.vscError(`create-sponsored-approvals: ${data.error}`); } if (msd) { - msd(ALLOWANCE_APPROVAL_MINED(bytesToNumber(input[data.part_idx].chain_id))); + msd( + BRIDGE_STEPS.ALLOWANCE_APPROVAL_MINED({ + id: bytesToNumber(input[data.part_idx].chain_id), + }), + ); } count += 1; @@ -417,7 +479,7 @@ type VSCCreateRFFResponse = const vscCreateRFF = async ( vscDomain: string, id: Long, - msd: (s: StepInfo, data?: { [k: string]: unknown }) => void, + msd: (s: BridgeStepType) => void, expectedCollectionIndexes: number[], ) => { const receivedCollectionsACKs = []; @@ -438,26 +500,28 @@ const vscCreateRFF = async ( if (data.status === 255) { if (expectedCollectionIndexes.length === receivedCollectionsACKs.length) { - msd(INTENT_COLLECTION_COMPLETE); + msd(BRIDGE_STEPS.INTENT_COLLECTION_COMPLETE); break; } else { logger.debug('(vsc)create-rff:collections failed', { expectedCollectionIndexes, receivedCollectionsACKs, }); - throw new Error('(vsc)create-rff: collections failed'); + throw Errors.vscError('create-rff: collections failed'); } } else if (data.status === 16) { if (expectedCollectionIndexes.includes(data.idx)) { receivedCollectionsACKs.push(data.idx); } - msd(INTENT_COLLECTION(receivedCollectionsACKs.length), { - confirmed: receivedCollectionsACKs.length, - total: expectedCollectionIndexes.length, - }); + msd( + BRIDGE_STEPS.INTENT_COLLECTION( + receivedCollectionsACKs.length, + expectedCollectionIndexes.length, + ), + ); } else { if (expectedCollectionIndexes.includes(data.idx)) { - throw new Error(`(vsc)create-rff: ${data.error}`); + throw Errors.vscError(`create-rff: ${data.error}`); } else { logger.debug('vscCreateRFF:ExpectedError:ignore', { data }); } @@ -473,6 +537,7 @@ const checkIntentFilled = async (intentID: Long, grpcURL: string) => { id: intentID, }); if (response.requestForFunds?.fulfilled) { + logger.debug('intent already filled', { response }); return 'ok'; } diff --git a/packages/core/sdk/ca-base/utils/balance.utils.ts b/packages/core/sdk/ca-base/utils/balance.utils.ts new file mode 100644 index 00000000..d302ddc3 --- /dev/null +++ b/packages/core/sdk/ca-base/utils/balance.utils.ts @@ -0,0 +1,227 @@ +import { Environment } from '@avail-project/ca-common'; +import { ChainListType, logger, SUPPORTED_CHAINS, UserAssetDatum } from '@nexus/commons'; +import { + // createPublicClientWithFallback, + equalFold, + getEVMBalancesForAddress, + getFuelBalancesForAddress, + getTronBalancesForAddress, + minutesToMs, +} from '.'; +import { encodePacked, Hex, keccak256, pad, toHex } from 'viem'; +import { balancesToAssets, getAnkrBalances, toFlatBalance } from '../swap/utils'; +import { filterSupportedTokens } from '../swap/data'; +// import { Errors } from '../errors'; + +const getKeyForStorage = ({ + evmAddress, + fuelAddress, + tronAddress, +}: { + evmAddress: Hex; + fuelAddress?: string; + tronAddress?: string; +}) => { + let key = evmAddress; + if (fuelAddress) { + key += `:${fuelAddress}`; + } + if (tronAddress) { + key += `:${tronAddress}`; + } + return key; +}; + +let balanceCache = { + value: {} as { [k: string]: { data: UserAssetDatum[]; lastUpdatedAt: number } }, +}; + +export const getBalancesForSwap = async (input: { evmAddress: Hex; chainList: ChainListType }) => { + const assets = balancesToAssets( + false, + await getAnkrBalances(input.evmAddress, input.chainList, true), + input.chainList, + ); + let balances = toFlatBalance(assets, false); + return balances; +}; + +export const getBalances = async (input: { + evmAddress: Hex; + chainList: ChainListType; + removeTransferFee?: boolean; + filter?: boolean; + fuelAddress?: string; + tronAddress?: string; + isCA?: boolean; + vscDomain: string; + networkHint: Environment; +}) => { + const isCA = input.isCA ?? false; + const removeTransferFee = input.removeTransferFee ?? false; + const filter = input.filter ?? true; + + const cacheKey = getKeyForStorage(input); + console.log({ balanceCache }); + + let cacheValue = balanceCache.value[cacheKey]; + if (!cacheValue || cacheValue.lastUpdatedAt + minutesToMs(0.5) < Date.now()) { + const [ankrBalances, evmBalances, fuelBalances, tronBalances] = await Promise.all([ + input.networkHint === Environment.FOLLY || isCA + ? Promise.resolve([]) + : getAnkrBalances(input.evmAddress, input.chainList, removeTransferFee), + getEVMBalancesForAddress(input.vscDomain, input.evmAddress), + input.fuelAddress + ? getFuelBalancesForAddress(input.vscDomain, input.fuelAddress as `0x${string}`) + : Promise.resolve([]), + input.tronAddress + ? getTronBalancesForAddress(input.vscDomain, input.tronAddress as Hex) + : Promise.resolve([]), + ]); + + balanceCache.value[cacheKey] = { + data: balancesToAssets( + isCA, + ankrBalances, + input.chainList, + evmBalances, + fuelBalances, + tronBalances, + ), + lastUpdatedAt: Date.now(), + }; + } + + const assets = balanceCache.value[cacheKey].data; + + let balances = toFlatBalance(assets); + if (filter) { + balances = filterSupportedTokens(balances); + } + + logger.debug('getBalances', { + assets, + balances, + removeTransferFee, + }); + + return { assets, balances }; +}; + +const getBalanceSlot = ({ + tokenSymbol, + chainId, + userAddress, +}: { + tokenSymbol: string; + chainId: number; + userAddress: Hex; +}) => { + const balanceSlot = getBalanceStorageSlot(tokenSymbol, chainId); + + // Calculate storage slot for user's balance: keccak256(user_address . balances_slot) + const userBalanceSlot = keccak256( + encodePacked(['bytes32', 'uint256'], [pad(userAddress, { size: 32 }), BigInt(balanceSlot)]), + ); + + logger.debug('getBalanceSlot', { + tokenSymbol, + chainId, + userAddress, + balanceSlot: userBalanceSlot, + }); + + return userBalanceSlot; +}; + +export const generateStateOverride = (params: { + tokenSymbol: string; + tokenAddress: Hex; + chainId: number; + userAddress: Hex; + amount: bigint; +}) => { + const amountInHex = toHex(params.amount * 2n); + // FIXME: it should estimate for any other native token also + if (equalFold(params.tokenSymbol, 'ETH')) { + return { + [params.userAddress]: { + balance: amountInHex, + }, + }; + } + const balanceSlot = getBalanceSlot(params); + + return { + [params.tokenAddress]: { + storage: { + [balanceSlot]: pad(amountInHex, { size: 32 }), + }, + }, + [params.userAddress]: { + balance: toHex(100000n), + }, + }; +}; + +const DEFAULT_SLOT = { + ETH: 0, + USDC: 9, + USDT: 2, +} as const; + +function getBalanceStorageSlot(token: string, chainId: number): number { + const storageSlotMapping: Record> = { + [SUPPORTED_CHAINS.ETHEREUM]: DEFAULT_SLOT, + [SUPPORTED_CHAINS.BASE]: DEFAULT_SLOT, + [SUPPORTED_CHAINS.ARBITRUM]: DEFAULT_SLOT, + [SUPPORTED_CHAINS.OPTIMISM]: DEFAULT_SLOT, + [SUPPORTED_CHAINS.POLYGON]: DEFAULT_SLOT, + [SUPPORTED_CHAINS.AVALANCHE]: DEFAULT_SLOT, + [SUPPORTED_CHAINS.SCROLL]: DEFAULT_SLOT, + // Testnets + [SUPPORTED_CHAINS.BASE_SEPOLIA]: DEFAULT_SLOT, + [SUPPORTED_CHAINS.ARBITRUM_SEPOLIA]: DEFAULT_SLOT, + [SUPPORTED_CHAINS.OPTIMISM_SEPOLIA]: DEFAULT_SLOT, + [SUPPORTED_CHAINS.POLYGON_AMOY]: DEFAULT_SLOT, + }; + + const chainMapping = storageSlotMapping[chainId]; + if (chainMapping) { + const slot = chainMapping[token]; + if (slot) { + logger.info(`Using storage slot ${slot} for ${token} on chain ${chainId}`); + return slot; + } + } + + logger.warn(`Unsupported chain ${chainId}, falling back to defaults`); + + return token === 'USDC' + ? DEFAULT_SLOT.USDC + : token === 'USDT' + ? DEFAULT_SLOT.USDT + : DEFAULT_SLOT.ETH; +} + +// export const getGasFeeFromBridgeParams = async (input: MaxBridgeParams, dstChain: Chain) => { +// let nativeAmount = 0n; +// if ('gas' in input && input.gas) { +// if ('gasPrice' in input && input.gasPrice) { +// nativeAmount = input.gas * input.gasPrice; +// } else { +// const pc = createPublicClientWithFallback(dstChain); +// const estimateGasPriceResponse = await pc.estimateFeesPerGas(); +// const gasUnitPrice = +// estimateGasPriceResponse.maxFeePerGas ?? estimateGasPriceResponse.gasPrice ?? 0n; +// if (gasUnitPrice == 0n) { +// throw Errors.gasPriceError({ +// chainId: dstChain.id, +// }); +// } +// nativeAmount = input.gas * gasUnitPrice; +// } +// } + +// return nativeAmount; +// }; diff --git a/packages/core/sdk/ca-base/utils/common.utils.ts b/packages/core/sdk/ca-base/utils/common.utils.ts index 739ab35f..ccccd823 100644 --- a/packages/core/sdk/ca-base/utils/common.utils.ts +++ b/packages/core/sdk/ca-base/utils/common.utils.ts @@ -1,12 +1,14 @@ import { ArcanaVault, + Bytes, DepositVEPacket, Environment, + ERC20ABI, EVMRFF, EVMVaultABI, MsgDoubleCheckTx, Universe, -} from '@arcana/ca-common'; +} from '@avail-project/ca-common'; import { DirectSecp256k1Wallet } from '@cosmjs/proto-signing'; import Decimal from 'decimal.js'; import { arrayify, CHAIN_IDS, FuelConnector, hexlify, Provider } from 'fuels'; @@ -14,23 +16,27 @@ import Long from 'long'; import { ByteArray, bytesToHex, + bytesToNumber, encodeAbiParameters, + encodeFunctionData, getAbiItem, hashMessage, Hex, + hexToBigInt, keccak256, pad, PrivateKeyAccount, PublicClient, toBytes, toHex, + UserRejectedRequestError, WalletClient, WebSocketTransport, } from 'viem'; - +import { TronWeb } from 'tronweb'; import { ChainList } from '../chains'; import { FUEL_BASE_ASSET_ID, isNativeAddress, ZERO_ADDRESS } from '../constants'; -import { getLogger } from '../logger'; +import { getLogger, IBridgeOptions } from '@nexus/commons'; import { EthereumProvider, Intent, @@ -40,7 +46,6 @@ import { ReadableIntent, SDKConfig, TokenInfo, - TxOptions, ChainListType, NexusNetwork, UserAssetDatum, @@ -49,6 +54,9 @@ import { import { FeeStore } from './api.utils'; import { requestTimeout, waitForIntentFulfilment } from './contract.utils'; import { cosmosCreateDoubleCheckTx, cosmosFillCheck, cosmosRefundIntent } from './cosmos.utils'; +import { AdapterProps } from '@tronweb3/tronwallet-abstract-adapter'; +import { Types, utils } from 'tronweb'; +import { Errors } from '../errors'; const logger = getLogger(); @@ -59,7 +67,7 @@ function convertAddressByUniverse(input: ByteArray | Hex, universe: Universe) { const inputIsString = typeof input === 'string'; const bytes = inputIsString ? toBytes(input) : input; - if (universe === Universe.ETHEREUM) { + if (universe === Universe.ETHEREUM || universe === Universe.TRON) { if (bytes.length === 20) { return inputIsString ? input : bytes; } @@ -234,7 +242,7 @@ const convertIntent = ( for (const s of intent.sources) { const chainInfo = chainList.getChainByID(s.chainID); if (!chainInfo) { - throw new Error('chain not supported'); + throw Errors.chainNotFound(s.chainID); } sources.push({ amount: s.amount.toFixed(), @@ -250,7 +258,7 @@ const convertIntent = ( for (const s of intent.allSources) { const chainInfo = chainList.getChainByID(s.chainID); if (!chainInfo) { - throw new Error('chain not supported'); + throw Errors.chainNotFound(s.chainID); } allSources.push({ amount: s.amount.toFixed(), @@ -263,7 +271,7 @@ const convertIntent = ( const destinationChainInfo = chainList.getChainByID(intent.destination.chainID); if (!destinationChainInfo) { - throw new Error('chain not supported'); + throw Errors.chainNotFound(intent.destination.chainID); } const destination = { @@ -323,6 +331,7 @@ const isArcanaWallet = (p: EthereumProvider) => { if ('isArcana' in p && p.isArcana) { return true; } + return false; }; @@ -337,22 +346,59 @@ const createRequestEVMSignature = async ( evmRFF.sources, evmRFF.destinationUniverse, evmRFF.destinationChainID, + evmRFF.recipientAddress, evmRFF.destinations, evmRFF.nonce, evmRFF.expiry, evmRFF.parties, ]); + const hash = keccak256(msg, 'bytes'); const signature = toBytes( - await client.signMessage({ - account: evmAddress, - message: { raw: hash }, - }), + await client + .signMessage({ + account: evmAddress, + message: { raw: hash }, + }) + .catch((e) => { + if (e instanceof UserRejectedRequestError) { + throw Errors.userRejectedIntentSignature(); + } + throw e; + }), ); return { requestHash: hashMessage({ raw: hash }), signature }; }; +const createRequestTronSignature = async (evmRFF: EVMRFF, client: AdapterProps) => { + logger.debug('createReqEVMSignature', { evmRFF }); + const abi = getAbiItem({ abi: EVMVaultABI, name: 'deposit' }); + const msg = encodeAbiParameters(abi.inputs[0].components, [ + evmRFF.sources, + evmRFF.destinationUniverse, + evmRFF.destinationChainID, + evmRFF.recipientAddress, + evmRFF.destinations, + evmRFF.nonce, + evmRFF.expiry, + evmRFF.parties, + ]); + const hash = toHex(keccak256(msg, 'bytes')); + + // FIXME: Hack - since tron doesn't supports binary decode of hex before signing + // const uppercaseHash = convertToUpperCaseHash(toHex(hash)); + const sig = await client.signMessage(hash); + return { + requestHash: utils.message.hashMessage(hash) as Hex, + signature: toBytes(sig), + }; +}; + +// const convertToUpperCaseHash = (input: Hex) => { +// return `0x${input.substring(2).toUpperCase()}`; +// }; + const convertGasToToken = ( token: TokenInfo, oraclePrices: OraclePriceResponse, @@ -360,7 +406,7 @@ const convertGasToToken = ( destinationUniverse: Universe, gas: Decimal, ) => { - if (isNativeAddress(destinationUniverse, token.contractAddress)) { + if (gas.isZero() || isNativeAddress(destinationUniverse, token.contractAddress)) { return gas; } @@ -380,6 +426,7 @@ const convertGasToToken = ( rate.chainId === destinationChainID && equalFold(rate.tokenAddress, token.contractAddress), ) ?.priceUsd.toFixed(); + if (!transferTokenInUSD) { throw new Error('could not find token in price oracle'); } @@ -406,24 +453,25 @@ const evmWaitForFill = async ( ]); }; -const convertTo32Bytes = (value: bigint | Hex | number) => { +const convertTo32Bytes = (value: bigint | Hex | number | Bytes) => { if (typeof value == 'bigint' || typeof value === 'number') { return toBytes(value, { size: 32, }); - } - - if (typeof value === 'string') { + } else if (typeof value === 'string') { return pad(toBytes(value), { dir: 'left', size: 32, }); + } else { + return pad(value, { + dir: 'left', + size: 32, + }); } - - throw new Error('invalid type'); }; -const convertTo32BytesHex = (value: Hex) => { +const convertTo32BytesHex = (value: Hex | Bytes) => { const bytes = convertTo32Bytes(value); return toHex(bytes); }; @@ -435,7 +483,7 @@ const convertToHexAddressByUniverse = (address: Uint8Array, universe: Universe) } else { throw new Error('fuel: invalid address length'); } - } else if (universe === Universe.ETHEREUM) { + } else if (universe === Universe.ETHEREUM || universe === Universe.TRON) { if (address.length === 20) { return bytesToHex(address); } else if (address.length === 32) { @@ -498,38 +546,14 @@ const getSDKConfig = (c: { network?: NexusNetwork; debug?: boolean }): Required< config.network = Environment.CORAL; break; } + case 'devnet': { + config.network = Environment.CERISE; + } } return config; }; -const getTxOptions = (options?: Partial) => { - const defaultOptions: TxOptions = { - bridge: false, - gas: 0n, - skipTx: false, - sourceChains: [], - }; - - if (options?.bridge !== undefined) { - defaultOptions.bridge = options.bridge; - } - - if (options?.gas !== undefined) { - defaultOptions.gas = options.gas; - } - - if (options?.skipTx !== undefined) { - defaultOptions.skipTx = options.skipTx; - } - - if (options?.sourceChains !== undefined) { - defaultOptions.sourceChains = options.sourceChains; - } - - return defaultOptions; -}; - class UserAsset { get balance() { return this.value.balance; @@ -537,6 +561,19 @@ class UserAsset { constructor(public value: UserAssetDatum) {} + getBridgeAssets(dstChainId: number) { + return this.value.breakdown + .filter((b) => b.chain.id !== dstChainId) + .map((b) => { + return { + chainID: b.chain.id, + contractAddress: b.contractAddress, + decimals: b.decimals, + balance: new Decimal(b.balance), + }; + }); + } + getBalanceOnChain(chainID: number, tokenAddress?: `0x${string}`) { return ( this.value.breakdown.find((b) => { @@ -685,7 +722,202 @@ class UserAssets { } } +// CHATGPT function below +async function waitForTronTxConfirmation( + txid: string, + tronWeb: TronWeb, + options: { timeout?: number; interval?: number } = {}, +): Promise { + const { timeout = 120000, interval = 3000 } = options; + + const startTime = Date.now(); + + logger.debug(`📡 Waiting for confirmation of tron tx`); + + while (Date.now() - startTime < timeout) { + try { + const txInfo = await tronWeb.trx.getTransactionInfo(txid); + + logger.debug(`tx info:`, { + txInfo, + }); + + if (txInfo && txInfo.receipt) { + const result = txInfo.receipt.result; + if (result === 'FAILED') { + throw new Error(`❌ Transaction reverted: ${txid}`); + } else { + return txInfo; + } + } + } catch (err) { + logger.error(`⚠️ Error while checking transaction:`, err); + // Don’t throw yet; continue polling + } + + logger.debug('⏳ Still waiting...'); + await new Promise((resolve) => setTimeout(resolve, interval)); + } + + throw new Error(`⏰ Timeout: Transaction not confirmed within ${timeout / 1000}s`); +} + +async function waitForTronDepositTxConfirmation( + hash: Hex, + vaultContractAddress: Hex, + tronWeb: TronWeb, + owner: Hex, + options: { timeout?: number; interval?: number } = {}, +): Promise { + const { timeout = 120000, interval = 3000 } = options; + + const startTime = Date.now(); + + logger.debug(`📡 Waiting for confirmation of tron tx`); + + const input = encodeFunctionData({ + abi: EVMVaultABI, + functionName: 'requestState', + args: [hash], + }); + while (Date.now() - startTime < timeout) { + try { + const result = await tronWeb.transactionBuilder.triggerConstantContract( + tronWeb.utils.address.fromHex(vaultContractAddress), + '', + { + input, + }, + [], + tronWeb.utils.address.fromHex(owner), + ); + + logger.debug('requestHashWitnessedOnTron', { + result, + }); + if (result.Error) { + throw new Error(result.Error); + } + + const requestState = bytesToNumber(result.constant_result[0]); + if (requestState === 0) { + throw new Error('Request not witnessed yet.'); + } + + return; + } catch (err) { + logger.error(`⚠️ Error while checking transaction:`, err); + // Don’t throw yet; continue polling + } + + logger.debug('⏳ Still waiting...'); + await new Promise((resolve) => setTimeout(resolve, interval)); + } + + throw new Error(`⏰ Timeout: Transaction not confirmed within ${timeout / 1000}s`); +} + +async function waitForTronApprovalTxConfirmation( + amount: bigint, + owner: Hex, + spender: Hex, + contractAddress: Hex, + tronWeb: TronWeb, + options: { timeout?: number; interval?: number } = {}, +): Promise { + const { timeout = 120000, interval = 3000 } = options; + + const startTime = Date.now(); + + logger.debug(`📡 Waiting for confirmation of tron approval tx`); + + const input = encodeFunctionData({ + abi: ERC20ABI, + functionName: 'allowance', + args: [owner, spender], + }); + + while (Date.now() - startTime < timeout) { + try { + const result = await tronWeb.transactionBuilder.triggerConstantContract( + tronWeb.utils.address.fromHex(contractAddress), + '', + { + input, + }, + [], + tronWeb.utils.address.fromHex(owner), + ); + + logger.debug('waitForTronApprovalTxConfirmation', { + result, + }); + + if (result.Error) { + throw new Error(result.Error); + } + + const allowance = hexToBigInt(`0x${result.constant_result[0]}`); + if (allowance < amount) { + throw new Error('Allowance not set yet.'); + } + + return; + } catch (err) { + logger.error(`⚠️ Error while checking transaction:`, err); + // Don’t throw yet; continue polling + } + + logger.debug('⏳ Still waiting...'); + await new Promise((resolve) => setTimeout(resolve, interval)); + } + + throw new Error(`⏰ Timeout: Transaction not confirmed within ${timeout / 1000}s`); +} + +const createExplorerTxURL = (txHash: Hex, explorerURL: string) => { + return new URL(`/tx/${txHash}`, explorerURL).href; +}; + +const retrieveAddress = ( + universe: Universe, + input: Pick, +): Hex => { + if (universe === Universe.ETHEREUM) { + return input.evm.address; + } else if (universe === Universe.FUEL) { + if (!input.fuel) { + throw Errors.internal('fuel source but no fuel input'); + } + return input.fuel.address as Hex; + } else if (universe === Universe.TRON) { + if (!input.tron) { + throw Errors.internal('tron source but no tron input'); + } + + return input.tron.address as Hex; + } + + throw Errors.internal('unknown universe'); +}; + +const SIWE_KEY = '_siwe_sig'; + +const storeSIWESignatureToLocalStorage = (address: Hex, signature: string) => { + window.localStorage.setItem(`${SIWE_KEY}-${address}`, signature); +}; + +const retrieveSIWESignatureFromLocalStorage = (address: Hex) => { + return window.localStorage.getItem(`${SIWE_KEY}-${address}`); +}; + export { + retrieveSIWESignatureFromLocalStorage, + storeSIWESignatureToLocalStorage, + retrieveAddress, + createExplorerTxURL, + waitForTronApprovalTxConfirmation, + waitForTronDepositTxConfirmation, UserAsset, UserAssets, convertAddressByUniverse, @@ -704,7 +936,6 @@ export { getExplorerURL, getSDKConfig, getSupportedChains, - getTxOptions, hexTo0xString, isArcanaWallet, minutesToMs, @@ -712,4 +943,6 @@ export { refundExpiredIntents, removeIntentHashFromStore, storeIntentHashToStore, + createRequestTronSignature, + waitForTronTxConfirmation, }; diff --git a/packages/core/sdk/ca-base/utils/contract.utils.ts b/packages/core/sdk/ca-base/utils/contract.utils.ts index 7d2f0a48..f7d0c0f9 100644 --- a/packages/core/sdk/ca-base/utils/contract.utils.ts +++ b/packages/core/sdk/ca-base/utils/contract.utils.ts @@ -5,8 +5,8 @@ import { PermitCreationError, PermitVariant, Universe, -} from '@arcana/ca-common'; -import { ERC20ABI as ERC20ABIC } from '@arcana/ca-common'; +} from '@avail-project/ca-common'; +import { ERC20ABI as ERC20ABIC } from '@avail-project/ca-common'; import { CHAIN_IDS } from 'fuels'; import { Account, @@ -26,23 +26,23 @@ import { pad, parseSignature, PublicClient, - SwitchChainError, WalletClient, WebSocketTransport, } from 'viem'; - import ERC20ABI from '../abi/erc20'; import gasOracleABI from '../abi/gasOracle'; import { FillEvent } from '../abi/vault'; import { ZERO_ADDRESS } from '../constants'; -import { ErrorLiquidityTimeout } from '../errors'; -import { getLogger } from '../logger'; +import { Errors } from '../errors'; +import { getLogger } from '@nexus/commons'; import { ChainListType, Chain, EVMTransaction, NetworkConfig, SponsoredApprovalData, + GetAllowanceParams, + SetAllowanceParams, } from '@nexus/commons'; import { vscCreateSponsoredApprovals } from './api.utils'; import { convertTo32Bytes, equalFold, minutesToMs } from './common.utils'; @@ -66,7 +66,7 @@ const isEVMTx = (tx: unknown): tx is EVMTransaction => { return true; }; -const getAllowance = ( +const getAllowance = async ( chain: Chain, address: `0x${string}`, tokenContract: `0x${string}`, @@ -75,6 +75,8 @@ const getAllowance = ( logger.debug('getAllowance', { tokenContract, ZERO_ADDRESS, + chain, + address, }); if (equalFold(ZERO_ADDRESS, tokenContract)) { @@ -83,11 +85,38 @@ const getAllowance = ( const publicClient = createPublicClientWithFallback(chain); - return publicClient.readContract({ + try { + const allowance = erc20GetAllowance( + { + contractAddress: tokenContract, + spender: chainList.getVaultContractAddress(chain.id), + owner: address, + }, + publicClient, + ); + return allowance; + } catch { + return 0n; + } +}; + +const erc20GetAllowance = (params: GetAllowanceParams, client: PublicClient) => { + return client.readContract({ + address: params.contractAddress, abi: ERC20ABI, - address: tokenContract, - args: [address, chainList.getVaultContractAddress(chain.id)], functionName: 'allowance', + args: [params.owner, params.spender], + }); +}; + +const erc20SetAllowance = (params: SetAllowanceParams & { chain: Chain }, client: WalletClient) => { + return client.writeContract({ + address: params.contractAddress, + abi: ERC20ABI, + functionName: 'approve', + args: [params.spender, params.amount], + chain: params.chain, + account: params.owner, }); }; @@ -95,8 +124,8 @@ const getAllowances = async ( input: { chainID: number; tokenContract: `0x${string}`; + holderAddress: `0x${string}`; }[], - address: `0x${string}`, chainList: ChainListType, ) => { const values: { [k: number]: bigint } = {}; @@ -107,9 +136,9 @@ const getAllowances = async ( } else { const chain = chainList.getChainByID(i.chainID); if (!chain) { - throw new Error('chain not found'); + throw Errors.chainNotFound(i.chainID); } - promises.push(getAllowance(chain, address, i.tokenContract, chainList)); + promises.push(getAllowance(chain, i.holderAddress, i.tokenContract, chainList)); } } const result = await Promise.all(promises); @@ -131,7 +160,7 @@ const waitForIntentFulfilment = async ( abi: [FillEvent] as const, address: vaultContractAddr, args: { requestHash }, - eventName: 'Fill', + eventName: 'Fulfilment', onLogs: (logs) => { logger.debug('waitForIntentFulfilment', { logs }); ac.abort(); @@ -154,7 +183,7 @@ const requestTimeout = (timeout: number, ac: AbortController) => { return new Promise((_, reject) => { const t = window.setTimeout(() => { ac.abort(); - return reject(ErrorLiquidityTimeout); + return reject(Errors.liquidityTimeout()); }, minutesToMs(timeout)); ac.signal.addEventListener( 'abort', @@ -194,7 +223,7 @@ const setAllowances = async ( const chainId = new OmniversalChainID(Universe.ETHEREUM, chain.id); const chainDatum = ChaindataMap.get(chainId); if (!chainDatum) { - throw new Error('Chain data not found'); + throw Errors.internal(`chain data not found for chain ${chainId}`); } const account: JsonRpcAccount = { @@ -218,18 +247,20 @@ const setAllowances = async ( for (const addr of tokenContractAddresses) { const currency = chainDatum.CurrencyMap.get(convertTo32Bytes(addr)); if (!currency) { - throw new Error('Currency not found'); + throw Errors.internal(`currency not found for token ${addr}`); } if (currency.permitVariant === PermitVariant.Unsupported) { - const hash = await client.writeContract({ - abi: ERC20ABI, - account: address, - address: addr, - args: [vaultAddr, amount], - chain, - functionName: 'approve', - }); + const hash = await erc20SetAllowance( + { + amount, + chain, + contractAddress: addr, + owner: address, + spender: vaultAddr, + }, + client, + ); p.push( (async function () { const result = await publicClient.waitForTransactionReceipt({ @@ -310,28 +341,29 @@ const waitForTxReceipt = async ( hash: `0x${string}`, publicClient: PublicClient, confirmations = 1, + timeout = 60000, ) => { const r = await publicClient.waitForTransactionReceipt({ confirmations, hash, + timeout, }); if (r.status === 'reverted') { throw new Error(`Transaction reverted: ${hash}`); } + + return r; }; const switchChain = async (client: WalletClient, chain: Chain) => { try { await client.switchChain({ id: chain.id }); } catch (e) { - if (e instanceof SwitchChainError && e.code === SwitchChainError.code) { - await client.addChain({ - chain, - }); - await client.switchChain({ id: chain.id }); - return; - } - throw e; + await client.addChain({ + chain, + }); + await client.switchChain({ id: chain.id }); + return; } }; @@ -537,6 +569,8 @@ const createPublicClientWithFallback = (chain: Chain): PublicClient => { }; export { + erc20GetAllowance, + erc20SetAllowance, createPublicClientWithFallback, getAllowance, getAllowances, diff --git a/packages/core/sdk/ca-base/utils/cosmos.utils.ts b/packages/core/sdk/ca-base/utils/cosmos.utils.ts index 365916f4..714377aa 100644 --- a/packages/core/sdk/ca-base/utils/cosmos.utils.ts +++ b/packages/core/sdk/ca-base/utils/cosmos.utils.ts @@ -5,22 +5,21 @@ import { MsgDoubleCheckTx, MsgRefundReq, MsgRefundReqResponse, -} from '@arcana/ca-common'; +} from '@avail-project/ca-common'; import { DirectSecp256k1Wallet } from '@cosmjs/proto-signing'; import { isDeliverTxFailure, isDeliverTxSuccess } from '@cosmjs/stargate'; import axios from 'axios'; import { connect } from 'it-ws/client'; import Long from 'long'; - -import { getLogger } from '../logger'; +import { getLogger } from '@nexus/commons'; import { checkIntentFilled, vscCreateFeeGrant } from './api.utils'; +import { Errors } from '../errors'; const logger = getLogger(); const getCosmosURL = (cosmosURL: string, kind: 'rest' | 'rpc') => { const u = new URL(cosmosURL); if (kind === 'rpc') { - // FIXME: don't hardcode port here u.port = '26650'; } return u.toString(); @@ -69,7 +68,7 @@ const cosmosCreateRFF = async ({ ); if (isDeliverTxFailure(res)) { - throw new Error(`Error creating RFF – code=${res.code} log=${res.rawLog ?? 'n/a'}`); + throw Errors.cosmosError(`Error creating RFF – code=${res.code} log=${res.rawLog ?? 'n/a'}`); } const decoded = MsgCreateRequestForFundsResponse.decode(res.msgResponses[0].value); @@ -102,7 +101,7 @@ const cosmosRefundIntent = async ( ], { amount: [], - gas: 100_000n.toString(10), + gas: 200_000n.toString(10), }, ); logger.debug('Refund response', { resp }); @@ -118,9 +117,9 @@ const cosmosRefundIntent = async ( ) { return resp; } - throw new Error('RFF is not expired yet.'); + throw Errors.cosmosError('RFF is not expired yet.'); } else { - throw new Error('unknown error'); + throw Errors.cosmosError(`unknown error: ${JSON.stringify(resp)}`); } } catch (e) { logger.error('Refund failed', e); @@ -164,7 +163,7 @@ const cosmosCreateDoubleCheckTx = async ({ ); if (isDeliverTxFailure(res)) { - throw new Error('Error creating MsgDoubleCheckTx'); + throw Errors.cosmosError('double check tx failed'); } logger.debug('double check response', { doubleCheckTx: res }); @@ -219,6 +218,9 @@ const waitForCosmosFillEvent = async (intentID: Long, cosmosURL: string, ac: Abo ); for await (const resp of connection.source) { + logger.debug('waitForCosmosFillEvent', { + resp, + }); const decodedResponse = JSON.parse(decoder.decode(resp)); if ( decodedResponse.result.events && diff --git a/packages/core/sdk/ca-base/utils/index.ts b/packages/core/sdk/ca-base/utils/index.ts index fa1d6d2b..ebf4ed61 100644 --- a/packages/core/sdk/ca-base/utils/index.ts +++ b/packages/core/sdk/ca-base/utils/index.ts @@ -1,5 +1,7 @@ -export * from "./api.utils"; -export * from "./common.utils"; -export * from "./contract.utils"; -export * from "./cosmos.utils"; -export * from "./rff.utils"; +export * from './api.utils'; +export * from './common.utils'; +export * from './contract.utils'; +export * from './cosmos.utils'; +export * from './rff.utils'; +export * from './balance.utils'; +export * from './tron.utils'; diff --git a/packages/core/sdk/ca-base/utils/rff.utils.ts b/packages/core/sdk/ca-base/utils/rff.utils.ts index 18106de0..6ffefe14 100644 --- a/packages/core/sdk/ca-base/utils/rff.utils.ts +++ b/packages/core/sdk/ca-base/utils/rff.utils.ts @@ -1,18 +1,23 @@ -import { MsgCreateRequestForFunds, OmniversalRFF, Universe } from '@arcana/ca-common'; +import { MsgCreateRequestForFunds, OmniversalRFF, Universe } from '@avail-project/ca-common'; import { FUEL_BASE_ASSET_ID, INTENT_EXPIRY, isNativeAddress, ZERO_ADDRESS } from '../constants'; -import { getLogger } from '../logger'; -import { ChainListType, Intent } from '@nexus/commons'; +import { getLogger, ChainListType, Intent, IBridgeOptions, BridgeAsset } from '@nexus/commons'; import { convertTo32Bytes, convertTo32BytesHex, createRequestEVMSignature, createRequestFuelSignature, + createRequestTronSignature, mulDecimals, } from './common.utils'; -import { DirectSecp256k1Wallet } from '@cosmjs/proto-signing'; import { Hex, PrivateKeyAccount, toBytes, WalletClient } from 'viem'; -import { CHAIN_IDS, FuelConnector, Provider } from 'fuels'; +import { CHAIN_IDS } from 'fuels'; import Long from 'long'; +import { TronWeb } from 'tronweb'; +import { tronHexToEvmAddress } from './tron.utils'; +import { Errors } from '../errors'; +import { convertToEVMAddress } from '../swap/utils'; +import Decimal from 'decimal.js'; +import { FeeStore } from './api.utils'; type Destination = { tokenAddress: `0x${string}`; @@ -24,7 +29,8 @@ type Source = { chainID: bigint; tokenAddress: `0x${string}`; universe: Universe; - value: bigint; + valueRaw: bigint; + value: Decimal; }; const logger = getLogger(); @@ -45,7 +51,7 @@ const getSourcesAndDestinationsForRFF = ( const token = chainList.getTokenByAddress(source.chainID, source.tokenContract); if (!token) { logger.error('Token not found', { source }); - throw new Error('token not found'); + throw Errors.tokenNotSupported(source.tokenContract, source.chainID); } universes.add(source.universe); @@ -54,7 +60,8 @@ const getSourcesAndDestinationsForRFF = ( chainID: BigInt(source.chainID), tokenAddress: convertTo32BytesHex(source.tokenContract), universe: source.universe, - value: mulDecimals(source.amount, token.decimals), + valueRaw: mulDecimals(source.amount, token.decimals), + value: source.amount, }); } @@ -87,11 +94,11 @@ const getSourcesAndDestinationsForRFF = ( const createRFFromIntent = async ( intent: Intent, - options: { - chainList: ChainListType; - cosmos: { address: string; client: DirectSecp256k1Wallet }; - evm: { address: Hex; client: PrivateKeyAccount | WalletClient }; - fuel?: { address: string; connector: FuelConnector; provider: Provider }; + options: Pick & { + evm: { + address: `0x${string}`; + client: WalletClient | PrivateKeyAccount; + }; }, destinationUniverse: Universe, ) => { @@ -116,6 +123,16 @@ const createRFFromIntent = async ( universe, }); } + + if (universe === Universe.TRON) { + console.log({ tronAddress: TronWeb.address.toHex(options.tron!.address) }); + parties.push({ + address: convertTo32BytesHex( + tronHexToEvmAddress(TronWeb.address.toHex(options.tron!.address)), + ), + universe, + }); + } } logger.debug('processRFF:1', { @@ -128,23 +145,24 @@ const createRFFromIntent = async ( const omniversalRFF = new OmniversalRFF({ destinationChainID: convertTo32Bytes(intent.destination.chainID), destinations: destinations.map((dest) => ({ - tokenAddress: toBytes(dest.tokenAddress), + contractAddress: toBytes(dest.tokenAddress), value: toBytes(dest.value), })), + recipientAddress: convertTo32Bytes(intent.recipientAddress), destinationUniverse: intent.destination.universe, expiry: Long.fromString((BigInt(Date.now() + INTENT_EXPIRY) / 1000n).toString()), nonce: window.crypto.getRandomValues(new Uint8Array(32)), - // @ts-ignore + // @ts-expect-error signatureData: parties.map((p) => ({ address: toBytes(p.address), universe: p.universe, })), - // @ts-ignore + // @ts-expect-error sources: sources.map((source) => ({ chainID: convertTo32Bytes(source.chainID), - tokenAddress: convertTo32Bytes(source.tokenAddress), + contractAddress: convertTo32Bytes(source.tokenAddress), universe: source.universe, - value: toBytes(source.value), + value: toBytes(source.valueRaw), })), }); @@ -176,7 +194,7 @@ const createRFFromIntent = async ( logger.error('universe has fuel but not expected input', { fuelInput: options.fuel, }); - throw new Error('universe has fuel but not expected input'); + throw Errors.internal('universe list includes fuel but not expected input'); } const { requestHash, signature } = await createRequestFuelSignature( @@ -192,12 +210,33 @@ const createRFFromIntent = async ( universe: Universe.FUEL, }); } + + if (universe === Universe.TRON) { + if (!options.tron) { + logger.error('universe has tron but not expected input', { + tronInput: options.tron, + }); + throw Errors.internal('universe has tron but not expected input'); + } + const { requestHash, signature } = await createRequestTronSignature( + omniversalRFF.asEVMRFF(), + options.tron.adapter, + ); + + signatureData.push({ + address: convertTo32Bytes(tronHexToEvmAddress(TronWeb.address.toHex(options.tron.address))), + requestHash, + signature, + universe, + }); + } } const msgBasicCosmos = MsgCreateRequestForFunds.create({ destinationChainID: omniversalRFF.protobufRFF.destinationChainID, destinations: omniversalRFF.protobufRFF.destinations, destinationUniverse: omniversalRFF.protobufRFF.destinationUniverse, + recipientAddress: omniversalRFF.protobufRFF.recipientAddress, expiry: omniversalRFF.protobufRFF.expiry, nonce: omniversalRFF.protobufRFF.nonce, signatureData: signatureData.map((s) => ({ @@ -224,4 +263,144 @@ const createRFFromIntent = async ( }; }; -export { createRFFromIntent, getSourcesAndDestinationsForRFF }; +const calculateMaxBridgeFees = ({ + assets, + feeStore, + dst, +}: { + dst: { + chainId: number; + tokenAddress: Hex; + decimals: number; + }; + assets: BridgeAsset[]; + feeStore: FeeStore; +}) => { + const borrow = assets.reduce((accumulator, asset) => { + return accumulator.add(Decimal.add(asset.eoaBalance, asset.ephemeralBalance)); + }, new Decimal(0)); + + const protocolFee = feeStore.calculateProtocolFee(new Decimal(borrow)); + let borrowWithFee = borrow.add(protocolFee); + + const fulfilmentFee = feeStore.calculateFulfilmentFee({ + decimals: dst.decimals, + destinationChainID: dst.chainId, + destinationTokenAddress: dst.tokenAddress, + }); + borrowWithFee = borrowWithFee.add(fulfilmentFee); + + logger.debug('calculateMaxBridgeFees:1', { + borrow: borrow.toFixed(), + protocolFee: protocolFee.toFixed(), + fulfilmentFee: fulfilmentFee.toFixed(), + borrowWithFee: borrowWithFee.toFixed(), + }); + + for (const asset of assets) { + const solverFee = feeStore.calculateSolverFee({ + borrowAmount: Decimal.add(asset.eoaBalance, asset.ephemeralBalance), + decimals: asset.decimals, + destinationChainID: dst.chainId, + destinationTokenAddress: dst.tokenAddress, + sourceChainID: asset.chainID, + sourceTokenAddress: convertToEVMAddress(asset.contractAddress), + }); + + borrowWithFee = borrowWithFee.add(solverFee); + logger.debug('calculateMaxBridgeFees:2', { + borrow: borrow.toFixed(), + borrowWithFee: borrowWithFee.toFixed(), + solverFee: solverFee.toFixed(), + }); + } + + return borrowWithFee.minus(borrow); +}; + +// FIXME: Remove the above function after updating the usage. +const calculateMaxBridgeFee = ({ + assets, + feeStore, + dst, +}: { + dst: { + chainId: number; + tokenAddress: Hex; + decimals: number; + }; + assets: { + chainID: number; + contractAddress: `0x${string}`; + decimals: number; + balance: Decimal; + }[]; + feeStore: FeeStore; +}) => { + const borrow = assets.reduce((accumulator, asset) => { + return accumulator.add(asset.balance); + }, new Decimal(0)); + + const sourceChainIds: number[] = []; + + const protocolFee = feeStore.calculateProtocolFee(new Decimal(borrow)); + let borrowWithFee = borrow.add(protocolFee); + + const fulfilmentFee = feeStore.calculateFulfilmentFee({ + decimals: dst.decimals, + destinationChainID: dst.chainId, + destinationTokenAddress: dst.tokenAddress, + }); + borrowWithFee = borrowWithFee.add(fulfilmentFee); + + logger.debug('calculateMaxBridgeFees:1', { + borrow: borrow.toFixed(), + protocolFee: protocolFee.toFixed(), + fulfilmentFee: fulfilmentFee.toFixed(), + borrowWithFee: borrowWithFee.toFixed(), + }); + + for (const asset of assets) { + if (!asset.balance.gt(0)) { + continue; + } + sourceChainIds.push(asset.chainID); + const collectionFee = feeStore.calculateCollectionFee({ + decimals: asset.decimals, + sourceChainID: asset.chainID, + sourceTokenAddress: asset.contractAddress, + }); + + borrowWithFee = borrowWithFee.add(collectionFee); + + const solverFee = feeStore.calculateSolverFee({ + borrowAmount: asset.balance, + decimals: asset.decimals, + destinationChainID: dst.chainId, + destinationTokenAddress: dst.tokenAddress, + sourceChainID: asset.chainID, + sourceTokenAddress: convertToEVMAddress(asset.contractAddress), + }); + + borrowWithFee = borrowWithFee.add(solverFee); + logger.debug('calculateMaxBridgeFees:2', { + borrow: borrow.toFixed(), + borrowWithFee: borrowWithFee.toFixed(), + solverFee: solverFee.toFixed(), + }); + } + + const fee = borrowWithFee.minus(borrow); + const maxAmount = fee.lt(borrow) + ? borrow.minus(fee).toFixed(dst.decimals, Decimal.ROUND_FLOOR) + : '0'; + + return { fee, maxAmount, sourceChainIds }; +}; + +export { + createRFFromIntent, + getSourcesAndDestinationsForRFF, + calculateMaxBridgeFee, + calculateMaxBridgeFees, +}; diff --git a/packages/core/sdk/ca-base/utils/tron.utils.ts b/packages/core/sdk/ca-base/utils/tron.utils.ts new file mode 100644 index 00000000..c2b95ac3 --- /dev/null +++ b/packages/core/sdk/ca-base/utils/tron.utils.ts @@ -0,0 +1,15 @@ +import { Hex } from 'viem'; + +function tronHexToEvmAddress(tronHex: string): Hex { + const normalized = tronHex.toLowerCase().replace(/^0x/, ''); + + // Validate length and prefix + if (!/^41[a-f0-9]{40}$/.test(normalized)) { + throw new Error(`Invalid TRON hex address: ${tronHex}`); + } + + // Extract last 20 bytes (40 hex chars) and return as EVM address + return `0x${normalized.slice(2)}`; +} + +export { tronHexToEvmAddress }; diff --git a/packages/core/sdk/index.ts b/packages/core/sdk/index.ts index b08308ac..1fcc6b6e 100644 --- a/packages/core/sdk/index.ts +++ b/packages/core/sdk/index.ts @@ -1,16 +1,13 @@ // src/core/sdk/index.ts import { NexusUtils } from './utils'; -import { initializeSimulationClient } from '../integrations/tenderly'; import type { BridgeParams, BridgeResult, TransferParams, TransferResult, - AllowanceResponse, OnIntentHook, OnAllowanceHook, EthereumProvider, - RequestArguments, UserAsset, SimulationResult, RequestForFunds, @@ -24,45 +21,30 @@ import type { SwapResult, SupportedChainsResult, ExactInSwapInput, - SwapInputOptionalParams, ExactOutSwapInput, + OnEventParam, + BridgeMaxResult, + OnSwapIntentHook, } from '@nexus/commons'; import { logger } from '@nexus/commons'; -import SafeEventEmitter from '@metamask/safe-event-emitter'; import { CA } from './ca-base'; -import { ChainAbstractionAdapter } from '../adapters/chain-abstraction-adapter'; +import { AdapterProps } from '@tronweb3/tronwallet-abstract-adapter'; export class NexusSDK extends CA { - private readonly nexusAdapter: ChainAbstractionAdapter; - public readonly nexusEvents: SafeEventEmitter; public readonly utils: NexusUtils; constructor(config?: { network?: NexusNetwork; debug?: boolean }) { super(config); logger.debug('Nexus SDK initialized with config:', config); - this.nexusAdapter = new ChainAbstractionAdapter(this); - this.nexusEvents = this._caEvents; - this.utils = new NexusUtils(this.nexusAdapter, () => this.isInitialized()); + this.utils = new NexusUtils(this.chainList); } /** * Initialize the SDK with a provider */ public async initialize(provider: EthereumProvider): Promise { - // Initialize the core adapter first - this._setEVMProvider(provider); + await this._setEVMProvider(provider); await this._init(); - const BACKEND_URL = 'https://nexus-backend.avail.so'; - if (BACKEND_URL) { - try { - const initResult = await initializeSimulationClient(BACKEND_URL); - if (!initResult.success) { - throw new Error('Backend initialization failed'); - } - } catch (error) { - throw new Error('Backend initialization failed'); - } - } } /** @@ -73,111 +55,69 @@ export class NexusSDK extends CA { } /** - * Get unified balance for a specific token + * Bridge to destination chain from auto-selected or provided source chains */ - public async getUnifiedBalance( - symbol: string, - includeSwappableBalances = false, - ): Promise { - return this._getUnifiedBalance(symbol, includeSwappableBalances); + public async bridge(params: BridgeParams, options?: OnEventParam): Promise { + const result = await this.createBridgeHandler(params, options).execute(); + return { + explorerUrl: result.explorerURL ?? '', + }; } - /** - * Cross chain token transfer - */ - public async bridge(params: BridgeParams): Promise { - try { - const result = await (await this._bridge(params)).exec(); - return { - success: true, - explorerUrl: result?.explorerURL ?? '', - }; - } catch (e) { - return { - success: false, - error: e instanceof Error ? e.message : String(e), - }; - } + public async calculateMaxForBridge( + params: Omit, + ): Promise { + return this._calculateMaxForBridge(params); } /** - * Cross chain token transfer to EOA + * Bridge & transfer to an address (Attribution) */ - public async transfer(params: TransferParams): Promise { - try { - const result = await (await this._transfer({ ...params, to: params.recipient })).exec(); - return { - success: true, - transactionHash: result.hash, - explorerUrl: result.explorerURL, - }; - } catch (e) { - return { - success: false, - error: e instanceof Error ? e.message : String(e), - }; - } + public async bridgeAndTransfer( + params: TransferParams, + options?: OnEventParam, + ): Promise { + const result = await this._bridgeAndTransfer(params, options); + return { + transactionHash: result.executeTransactionHash, + explorerUrl: result.executeExplorerUrl, + }; } public async swapWithExactIn( input: ExactInSwapInput, - options?: SwapInputOptionalParams, + options?: OnEventParam, ): Promise { - try { - const result = await this._swapWithExactIn(input, options); - return { - success: true, - result, - }; - } catch (error) { - console.error('Error in swap with exact out', error); - return { - success: false, - error: error instanceof Error ? error.message : String(error), - }; - } + const result = await this._swapWithExactIn(input, options); + return { + success: true, + result, + }; } public async swapWithExactOut( input: ExactOutSwapInput, - options?: SwapInputOptionalParams, + options?: OnEventParam, ): Promise { - try { - const result = await this._swapWithExactOut(input, options); - return { - success: true, - result, - }; - } catch (error) { - console.error('Error in swap with exact out', error); - return { - success: false, - error: error instanceof Error ? error.message : String(error), - }; - } - } - - /** - * Get chain abstracted provider allowing use of chain asbtraction - * @returns EthereumProvider - */ - - public getEVMProviderWithCA(): EthereumProvider { - return this._getEVMProviderWithCA(); + const result = await this._swapWithExactOut(input, options); + return { + success: true, + result, + }; } /** * Simulate bridge transaction to get costs and fees */ public async simulateBridge(params: BridgeParams): Promise { - return (await this._bridge(params)).simulate(); + return this.createBridgeHandler(params).simulate(); } /** * Simulate transfer transaction to get costs and fees */ - public async simulateTransfer(params: TransferParams): Promise { - return (await this._transfer({ ...params, to: params.recipient })).simulate(); + public async simulateTransfer(params: TransferParams): Promise { + return this._simulateBridgeAndTransfer(params); } /** @@ -188,31 +128,21 @@ export class NexusSDK extends CA { } /** - * Check allowance for tokens on a specific chain - */ - public async getAllowance(chainId?: number, tokens?: string[]): Promise { - return this._allowance().get({ chainID: chainId, tokens }); - } - - /** - * Set allowance for a token on a specific chain + * Set callback for intent status updates */ - public async setAllowance(chainId: number, tokens: string[], amount: bigint): Promise { - return this._allowance().set({ chainID: chainId, tokens, amount }); + public setOnIntentHook(callback: OnIntentHook): void { + this._setOnIntentHook(callback); } /** - * Revoke allowance for a token on a specific chain + * Set callback for swap intent details */ - public async revokeAllowance(chainId: number, tokens: string[]): Promise { - return this._allowance().revoke({ chainID: chainId, tokens }); + public setOnSwapIntentHook(callback: OnSwapIntentHook): void { + this._setOnSwapIntentHook(callback); } - /** - * Set callback for intent status updates - */ - public setOnIntentHook(callback: OnIntentHook): void { - this._setOnIntentHook(callback); + public addTron(adapter: AdapterProps) { + this._setTronAdapter(adapter); } /** @@ -226,17 +156,13 @@ export class NexusSDK extends CA { return this._deinit(); } - public async request(args: RequestArguments): Promise { - return this._handleEVMTx(args); - } - /** * Standalone function to execute funds into a smart contract * @param params execute parameters including contract details and transaction settings * @returns Promise resolving to execute result with transaction hash and explorer URL */ - public async execute(params: ExecuteParams): Promise { - return this.nexusAdapter.execute(params); + public async execute(params: ExecuteParams, options?: OnEventParam): Promise { + return this._execute(params, options); } /** @@ -245,7 +171,7 @@ export class NexusSDK extends CA { * @returns Promise resolving to simulation result with gas estimates */ public async simulateExecute(params: ExecuteParams): Promise { - return this.nexusAdapter.simulateExecute(params); + return this._simulateExecute(params); } /** @@ -253,8 +179,11 @@ export class NexusSDK extends CA { * @param params Enhanced bridge and execute parameters * @returns Promise resolving to comprehensive operation result */ - public async bridgeAndExecute(params: BridgeAndExecuteParams): Promise { - return this.nexusAdapter.bridgeAndExecute(params); + public async bridgeAndExecute( + params: BridgeAndExecuteParams, + options?: OnEventParam, + ): Promise { + return this._bridgeAndExecute(params, options); } /** @@ -266,11 +195,15 @@ export class NexusSDK extends CA { public async simulateBridgeAndExecute( params: BridgeAndExecuteParams, ): Promise { - return this.nexusAdapter.simulateBridgeAndExecute(params); + return this._simulateBridgeAndExecute(params); + } + + public getBalancesForSwap() { + return this._getBalancesForSwap(); } - public getSwapSupportedChainsAndTokens(): SupportedChainsResult { - return this._getSwapSupportedChainsAndTokens(); + public getSwapSupportedChains(): SupportedChainsResult { + return this._getSwapSupportedChains(); } public isInitialized() { diff --git a/packages/core/sdk/utils.ts b/packages/core/sdk/utils.ts index 5ff18dc3..7d3929cb 100644 --- a/packages/core/sdk/utils.ts +++ b/packages/core/sdk/utils.ts @@ -1,6 +1,5 @@ import { type SUPPORTED_CHAINS, - formatBalance as utilFormatBalance, parseUnits as utilParseUnits, formatUnits as utilFormatUnits, isValidAddress as utilIsValidAddress, @@ -11,29 +10,19 @@ import { getTestnetTokenMetadata as utilGetTestnetTokenMetadata, getTokenMetadata as utilGetTokenMetadata, getChainMetadata as utilGetChainMetadata, - formatTokenAmount as utilFormatTokenAmount, - formatTestnetTokenAmount as utilFormatTestnetTokenAmount, SupportedChainsResult, Network, + ChainListType, + formatTokenBalance, + formatTokenBalanceParts, } from '@nexus/commons'; -import { ChainAbstractionAdapter } from '../adapters/chain-abstraction-adapter'; +import { getCoinbasePrices, getSupportedChains } from './ca-base/utils'; +import { getSwapSupportedChains } from './ca-base/swap/utils'; export class NexusUtils { - constructor( - private readonly adapter: ChainAbstractionAdapter, - private readonly isReady: () => boolean, - ) {} - - private ensureInitialized(): void { - if (!this.isReady()) { - throw new Error( - 'NexusSDK must be initialized before using utils methods that require adapter access. Call sdk.initialize() first.', - ); - } - } - - // Pure utility functions (no adapter dependency) - formatBalance = utilFormatBalance; + constructor(private readonly chainList: ChainListType) {} + formatTokenBalance = formatTokenBalance; + formatTokenBalanceParts = formatTokenBalanceParts; parseUnits = utilParseUnits; formatUnits = utilFormatUnits; isValidAddress = utilIsValidAddress; @@ -44,28 +33,28 @@ export class NexusUtils { getTestnetTokenMetadata = utilGetTestnetTokenMetadata; getTokenMetadata = utilGetTokenMetadata; getChainMetadata = utilGetChainMetadata; - formatTokenAmount = utilFormatTokenAmount; - formatTestnetTokenAmount = utilFormatTestnetTokenAmount; + + getCoinbaseRates = async (): Promise> => { + return getCoinbasePrices(); + }; getSupportedChains(env?: Network): SupportedChainsResult { - this.ensureInitialized(); - return this.adapter.getSupportedChains(env); + return getSupportedChains(env); } getSwapSupportedChainsAndTokens(): SupportedChainsResult { - this.ensureInitialized(); - return this.adapter.nexusSDK.getSwapSupportedChainsAndTokens(); + return getSwapSupportedChains(this.chainList); } /* Same for isSupportedChain / isSupportedToken */ isSupportedChain(chainId: (typeof SUPPORTED_CHAINS)[keyof typeof SUPPORTED_CHAINS]): boolean { - this.ensureInitialized(); - return this.adapter.isSupportedChain(chainId); + return !!this.chainList.getChainByID(chainId); } + // ??? isSupportedToken(token: string): boolean { - this.ensureInitialized(); - return this.adapter.isSupportedToken(token); + const supportedTokens = ['ETH', 'USDC', 'USDT']; + return supportedTokens.includes(token.toUpperCase()); } } diff --git a/packages/widgets/package.json b/packages/widgets/package.json index 9b75999d..57c20dec 100644 --- a/packages/widgets/package.json +++ b/packages/widgets/package.json @@ -48,10 +48,10 @@ "tailwind-merge": "3.3.1" }, "devDependencies": { - "@rollup/plugin-commonjs": "^25.0.0", + "@rollup/plugin-commonjs": "^25.0.8", "@rollup/plugin-json": "6.1.0", - "@rollup/plugin-node-resolve": "^15.0.0", - "@rollup/plugin-typescript": "^11.0.0", + "@rollup/plugin-node-resolve": "^15.3.1", + "@rollup/plugin-typescript": "^11.1.6", "@tailwindcss/postcss": "4.1.10", "@types/react": "19.1.8", "@types/react-dom": "19.1.6", @@ -59,12 +59,12 @@ "postcss": "8.5.6", "postcss-import": "16.1.1", "postcss-nesting": "13.0.2", - "rollup": "^4.0.0", - "rollup-plugin-dts": "^6.0.0", + "rollup": "^4.52.4", + "rollup-plugin-dts": "^6.2.3", "rollup-plugin-postcss": "4.0.2", "rollup-plugin-typescript2": "0.36.0", "tailwindcss": "4.1.10", - "typescript": "^5.0.0" + "typescript": "^5.9.3" }, "peerDependencies": { "react": ">=16.8.0", diff --git a/packages/widgets/src/components/shared/chain-select.tsx b/packages/widgets/src/components/shared/chain-select.tsx index d790510a..791e90d2 100644 --- a/packages/widgets/src/components/shared/chain-select.tsx +++ b/packages/widgets/src/components/shared/chain-select.tsx @@ -1,6 +1,6 @@ import { useMemo } from 'react'; import { ChainSelectProps } from '../../types'; -import { CHAIN_METADATA, DESTINATION_SWAP_TOKENS } from '@nexus/commons'; +import { CHAIN_METADATA, DESTINATION_SWAP_TOKENS, NexusNetwork } from '@nexus/commons'; import { ChainIcon } from './icons'; import { cn } from '../../utils/utils'; import { Button } from '../motion/button-motion'; @@ -27,7 +27,7 @@ export function ChainSelect({ selectedToken, transactionType, }: ChainSelectProps & { - network?: 'mainnet' | 'testnet'; + network?: NexusNetwork; selectedToken?: string; transactionType?: TransactionType; }) { diff --git a/packages/widgets/src/components/shared/destination-drawer.tsx b/packages/widgets/src/components/shared/destination-drawer.tsx index 7cb51734..440ca551 100644 --- a/packages/widgets/src/components/shared/destination-drawer.tsx +++ b/packages/widgets/src/components/shared/destination-drawer.tsx @@ -10,7 +10,7 @@ import { } from '../motion/drawer'; import { ChevronDownIcon, CircleX } from '../icons'; import { FormField } from '../motion/form-field'; -import { CHAIN_METADATA, SUPPORTED_CHAINS } from '@nexus/commons'; +import { CHAIN_METADATA, NexusNetwork, SUPPORTED_CHAINS } from '@nexus/commons'; import { cn } from '../../utils/utils'; import { TokenIcon } from './icons'; import type { TransactionType as BalanceTransactionType } from '../../utils/balance-utils'; @@ -20,7 +20,7 @@ interface DestinationDrawerProps { tokenValue?: string; isChainSelectDisabled?: boolean; isTokenSelectDisabled?: boolean; - network?: 'mainnet' | 'testnet'; + network?: NexusNetwork; onChainValueChange: (chain: string) => void; onTokenValueChange: (token: string, iconUrl?: string) => void; fieldLabel?: string; diff --git a/packages/widgets/src/components/shared/token-select.tsx b/packages/widgets/src/components/shared/token-select.tsx index 8d444aa6..8bfeeef4 100644 --- a/packages/widgets/src/components/shared/token-select.tsx +++ b/packages/widgets/src/components/shared/token-select.tsx @@ -1,5 +1,5 @@ import { useMemo } from 'react'; -import { TOKEN_METADATA, TESTNET_TOKEN_METADATA } from '@nexus/commons'; +import { TOKEN_METADATA, TESTNET_TOKEN_METADATA, NexusNetwork } from '@nexus/commons'; import { TokenIcon } from './icons'; import { cn } from '../../utils/utils'; import { Button } from '../motion/button-motion'; @@ -19,7 +19,7 @@ export function TokenSelect({ chainId, isDestination = false, }: TokenSelectProps & { - network?: 'mainnet' | 'testnet'; + network?: NexusNetwork; chainId?: number; isDestination?: boolean; }) { diff --git a/packages/widgets/src/types/index.ts b/packages/widgets/src/types/index.ts index d83b1a16..e1e906a3 100644 --- a/packages/widgets/src/types/index.ts +++ b/packages/widgets/src/types/index.ts @@ -15,6 +15,7 @@ import type { UserAsset, EthereumProvider, ExactInSwapInput, + NexusNetwork, } from '@nexus/commons'; import { Abi } from 'viem'; @@ -130,9 +131,6 @@ interface TokenMetadata { isNative?: boolean; } -// Local network type for UI -type NexusNetwork = 'mainnet' | 'testnet'; - // # 1. High-Level State Machines export type TransactionType = 'bridge' | 'transfer' | 'bridgeAndExecute' | 'swap'; @@ -349,7 +347,7 @@ export interface TokenSelectProps extends BaseComponentProps { value?: string; onValueChange: (token: string, iconUrl?: string) => void; disabled?: boolean; - network?: 'mainnet' | 'testnet'; + network?: NexusNetwork; type?: TransactionType; chainId?: number; isDestination?: boolean; @@ -359,7 +357,7 @@ export interface ChainSelectProps extends BaseComponentProps { value?: string; onValueChange: (chain: string) => void; disabled?: boolean; - network?: 'mainnet' | 'testnet'; + network?: NexusNetwork; isSource?: boolean; } diff --git a/packages/widgets/src/utils/token-utils.ts b/packages/widgets/src/utils/token-utils.ts index 36e860bb..5d79cc93 100644 --- a/packages/widgets/src/utils/token-utils.ts +++ b/packages/widgets/src/utils/token-utils.ts @@ -7,6 +7,7 @@ import { DESTINATION_SWAP_TOKENS, type SupportedChainsResult, type TokenMetadata, + NexusNetwork, } from '@nexus/commons'; import type { TransactionType } from './balance-utils'; import type { NexusSDK } from '@avail-project/nexus-core'; @@ -34,7 +35,7 @@ export interface TokenSelectOption { export interface TokenResolutionParams { chainId?: number; type: TransactionType; - network?: 'mainnet' | 'testnet'; + network?: NexusNetwork; isDestination?: boolean; sdk?: NexusSDK; } @@ -162,9 +163,7 @@ function _processSdkData(sdkData: SupportedChainsResult | null): TransactionSupp /** * Get base token metadata based on network */ -function getBaseTokenMetadata( - _network: 'mainnet' | 'testnet' = 'mainnet', -): Record { +function getBaseTokenMetadata(_network: NexusNetwork = 'mainnet'): Record { return _network === 'testnet' ? TESTNET_TOKEN_METADATA : TOKEN_METADATA; } @@ -259,6 +258,7 @@ export function getAvailableTokens(params: TokenResolutionParams): EnhancedToken } const enhancedBaseTokens = baseTokens.map((token) => ({ ...token, + // @ts-expect-error contractAddress: TOKEN_CONTRACT_ADDRESSES[token.symbol]?.[chainId || 0], })); const result = [...enhancedBaseTokens, ...allDestinationTokens]; @@ -462,6 +462,7 @@ export function getAvailableTokens(params: TokenResolutionParams): EnhancedToken return { ...token, icon: finalIcon || token.icon, + // @ts-expect-error contractAddress: TOKEN_CONTRACT_ADDRESSES[token.symbol]?.[chainId || 0], }; }); @@ -503,6 +504,7 @@ export function getTokenAddress( type: TransactionType = 'transfer', ): `0x${string}` { // Try standard TOKEN_CONTRACT_ADDRESSES first + // @ts-expect-error const standardAddress = TOKEN_CONTRACT_ADDRESSES[tokenSymbol]?.[chainId]; if (standardAddress) { return standardAddress; @@ -532,6 +534,7 @@ export function isTokenAvailableOnChain( // For swaps, be more permissive to avoid aggressive token resets if (type === 'swap') { // Check if token exists in either base tokens or destination swap tokens + // @ts-expect-error const baseTokens = TOKEN_CONTRACT_ADDRESSES[tokenSymbol]; if (baseTokens && baseTokens[chainId]) { return true; @@ -562,7 +565,7 @@ export function getTokenMetadata( tokenSymbol: string, chainId?: number, type: TransactionType = 'transfer', - network: 'mainnet' | 'testnet' = 'mainnet', + network: NexusNetwork = 'mainnet', ): EnhancedTokenMetadata | null { // Try base tokens first const baseTokens = getBaseTokenMetadata(network); @@ -571,6 +574,7 @@ export function getTokenMetadata( if (baseToken) { return { ...baseToken, + // @ts-expect-error contractAddress: chainId ? TOKEN_CONTRACT_ADDRESSES[tokenSymbol]?.[chainId] : undefined, }; } @@ -622,6 +626,7 @@ export function getSupportedChainsForToken( } // Check base tokens (TOKEN_CONTRACT_ADDRESSES) + // @ts-expect-error const tokenContracts = TOKEN_CONTRACT_ADDRESSES[tokenSymbol]; if (tokenContracts) { Object.keys(tokenContracts).forEach((chainId) => supportedChains.add(Number(chainId))); @@ -651,6 +656,7 @@ export function getSupportedChainsForToken( const supportedChains = new Set(); // Add chains from TOKEN_CONTRACT_ADDRESSES (ERC20 tokens) + // @ts-expect-error const tokenContracts = TOKEN_CONTRACT_ADDRESSES[tokenSymbol]; if (tokenContracts) { Object.keys(tokenContracts).forEach((chainId) => supportedChains.add(Number(chainId))); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 86e102bc..3c65f5b2 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -4,74 +4,86 @@ settings: autoInstallPeers: true excludeLinksFromLockfile: false +overrides: + typescript: ^5.0.0 + rollup: ^4.0.0 + decimal.js: 10.6.0 + viem: ^2.0.0 + importers: .: devDependencies: '@rollup/plugin-alias': specifier: ^5.1.1 - version: 5.1.1(rollup@4.50.2) + version: 5.1.1(rollup@4.52.4) '@types/node': - specifier: ^20.0.0 - version: 20.19.17 + specifier: ^20.19.22 + version: 20.19.22 husky: - specifier: ^8.0.0 + specifier: ^8.0.3 version: 8.0.3 prettier: - specifier: ^3.0.0 + specifier: ^3.6.2 version: 3.6.2 rimraf: - specifier: ^5.0.0 + specifier: ^5.0.10 version: 5.0.10 typescript: specifier: ^5.0.0 - version: 5.9.2 + version: 5.9.3 packages/commons: dependencies: - '@arcana/ca-common': - specifier: 1.0.1-alpha.6 - version: 1.0.1-alpha.6(@cosmjs/proto-signing@0.34.0)(@cosmjs/stargate@0.34.0)(axios@1.12.2)(decimal.js@10.6.0)(fuels@0.101.1(vitest@3.0.9(@types/node@20.19.17)(jiti@2.5.1)(lightningcss@1.30.1)))(google-protobuf@3.21.4)(long@5.3.2)(msgpackr@1.11.5)(viem@2.37.6(typescript@5.9.2)) + '@avail-project/ca-common': + specifier: 1.0.0-beta.7 + version: 1.0.0-beta.7(@cosmjs/proto-signing@0.34.0)(@cosmjs/stargate@0.34.0)(axios@1.12.2)(decimal.js@10.6.0)(fuels@0.101.1(vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2)))(google-protobuf@3.21.4)(long@5.3.2)(msgpackr@1.11.5)(viem@2.38.3(typescript@5.9.3)) '@cosmjs/proto-signing': specifier: ^0.34.0 version: 0.34.0 + '@tronweb3/tronwallet-abstract-adapter': + specifier: ^1.1.9 + version: 1.1.9 decimal.js: - specifier: ^10.6.0 + specifier: 10.6.0 version: 10.6.0 fuels: specifier: 0.101.1 - version: 0.101.1(vitest@3.0.9(@types/node@20.19.17)(jiti@2.5.1)(lightningcss@1.30.1)) + version: 0.101.1(vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2)) + tronweb: + specifier: ^6.0.4 + version: 6.0.4 viem: - specifier: ^2.31.7 - version: 2.37.6(typescript@5.9.2) + specifier: ^2.0.0 + version: 2.38.3(typescript@5.9.3) devDependencies: '@rollup/plugin-commonjs': - specifier: ^25.0.0 - version: 25.0.8(rollup@4.50.2) + specifier: ^25.0.8 + version: 25.0.8(rollup@4.52.4) '@rollup/plugin-json': specifier: 6.1.0 - version: 6.1.0(rollup@4.50.2) + version: 6.1.0(rollup@4.52.4) '@rollup/plugin-node-resolve': - specifier: ^15.0.0 - version: 15.3.1(rollup@4.50.2) + specifier: ^15.3.1 + version: 15.3.1(rollup@4.52.4) '@rollup/plugin-typescript': - specifier: ^11.0.0 - version: 11.1.6(rollup@4.50.2)(tslib@2.8.1)(typescript@5.9.2) + specifier: ^11.1.6 + version: 11.1.6(rollup@4.52.4)(tslib@2.8.1)(typescript@5.9.3) rollup: specifier: ^4.0.0 - version: 4.50.2 + version: 4.52.4 rollup-plugin-dts: - specifier: ^6.0.0 - version: 6.2.3(rollup@4.50.2)(typescript@5.9.2) + specifier: ^6.2.3 + version: 6.2.3(rollup@4.52.4)(typescript@5.9.3) typescript: specifier: ^5.0.0 - version: 5.9.2 + version: 5.9.3 packages/core: dependencies: - '@arcana/ca-common': - specifier: 1.0.1-alpha.6 - version: 1.0.1-alpha.6(@cosmjs/proto-signing@0.34.0)(@cosmjs/stargate@0.34.0)(axios@1.12.2)(decimal.js@10.6.0)(fuels@0.101.1(vitest@3.0.9(@types/node@20.19.17)(jiti@2.5.1)(lightningcss@1.30.1)))(google-protobuf@3.21.4)(long@5.3.2)(msgpackr@1.11.5)(viem@2.37.6(typescript@5.9.2)) + '@avail-project/ca-common': + specifier: 1.0.0-beta.7 + version: 1.0.0-beta.7(@cosmjs/proto-signing@0.34.0)(@cosmjs/stargate@0.34.0)(axios@1.12.2)(decimal.js@10.6.0)(fuels@0.101.1(vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2)))(google-protobuf@3.21.4)(long@5.3.2)(msgpackr@1.11.5)(viem@2.38.3(typescript@5.9.3)) '@cosmjs/proto-signing': specifier: ^0.34.0 version: 0.34.0 @@ -84,18 +96,21 @@ importers: '@starkware-industries/starkware-crypto-utils': specifier: ^0.2.1 version: 0.2.1 + '@tronweb3/tronwallet-abstract-adapter': + specifier: ^1.1.9 + version: 1.1.9 axios: - specifier: ^1.7.7 + specifier: ^1.12.2 version: 1.12.2 decimal.js: - specifier: ^10.6.0 + specifier: 10.6.0 version: 10.6.0 es-toolkit: - specifier: ^1.39.8 - version: 1.39.10 + specifier: ^1.40.0 + version: 1.40.0 fuels: specifier: 0.101.1 - version: 0.101.1(vitest@3.0.9(@types/node@20.19.17)(jiti@2.5.1)(lightningcss@1.30.1)) + version: 0.101.1(vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2)) it-ws: specifier: ^6.1.5 version: 6.1.5 @@ -103,51 +118,54 @@ importers: specifier: ^5.3.2 version: 5.3.2 msgpackr: - specifier: ^1.11.4 + specifier: ^1.11.5 version: 1.11.5 + tronweb: + specifier: ^6.0.4 + version: 6.0.4 tslib: specifier: 2.8.1 version: 2.8.1 viem: specifier: ^2.0.0 - version: 2.37.6(typescript@5.9.2) + version: 2.38.3(typescript@5.9.3) devDependencies: '@rollup/plugin-commonjs': - specifier: ^25.0.0 - version: 25.0.8(rollup@4.50.2) + specifier: ^25.0.8 + version: 25.0.8(rollup@4.52.4) '@rollup/plugin-json': specifier: 6.1.0 - version: 6.1.0(rollup@4.50.2) + version: 6.1.0(rollup@4.52.4) '@rollup/plugin-node-resolve': - specifier: ^15.0.0 - version: 15.3.1(rollup@4.50.2) + specifier: ^15.3.1 + version: 15.3.1(rollup@4.52.4) '@rollup/plugin-typescript': - specifier: ^11.0.0 - version: 11.1.6(rollup@4.50.2)(tslib@2.8.1)(typescript@5.9.2) + specifier: ^11.1.6 + version: 11.1.6(rollup@4.52.4)(tslib@2.8.1)(typescript@5.9.3) rollup: specifier: ^4.0.0 - version: 4.50.2 + version: 4.52.4 rollup-plugin-dts: - specifier: ^6.0.0 - version: 6.2.3(rollup@4.50.2)(typescript@5.9.2) + specifier: ^6.2.3 + version: 6.2.3(rollup@4.52.4)(typescript@5.9.3) rollup-plugin-typescript2: specifier: 0.36.0 - version: 0.36.0(rollup@4.50.2)(typescript@5.9.2) + version: 0.36.0(rollup@4.52.4)(typescript@5.9.3) typescript: specifier: ^5.0.0 - version: 5.9.2 + version: 5.9.3 packages/widgets: dependencies: + '@avail-project/nexus-core': + specifier: workspace:* + version: link:../core '@lottiefiles/dotlottie-react': specifier: 0.14.2 - version: 0.14.2(react@19.1.1) + version: 0.14.2(react@19.2.0) '@nexus/commons': specifier: workspace:* version: link:../commons - '@nexus/core': - specifier: workspace:* - version: link:../core class-variance-authority: specifier: 0.7.1 version: 0.7.1 @@ -155,36 +173,36 @@ importers: specifier: 2.1.1 version: 2.1.1 decimal.js: - specifier: 10.4.3 - version: 10.4.3 + specifier: 10.6.0 + version: 10.6.0 motion: specifier: 12.23.0 - version: 12.23.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + version: 12.23.0(react-dom@19.2.0(react@19.2.0))(react@19.2.0) react: specifier: '>=16.8.0' - version: 19.1.1 + version: 19.2.0 react-dom: specifier: '>=16.8.0' - version: 19.1.1(react@19.1.1) + version: 19.2.0(react@19.2.0) tailwind-merge: specifier: 3.3.1 version: 3.3.1 viem: specifier: ^2.0.0 - version: 2.37.6(typescript@5.9.2) + version: 2.38.3(typescript@5.9.3) devDependencies: '@rollup/plugin-commonjs': - specifier: ^25.0.0 - version: 25.0.8(rollup@4.50.2) + specifier: ^25.0.8 + version: 25.0.8(rollup@4.52.4) '@rollup/plugin-json': specifier: 6.1.0 - version: 6.1.0(rollup@4.50.2) + version: 6.1.0(rollup@4.52.4) '@rollup/plugin-node-resolve': - specifier: ^15.0.0 - version: 15.3.1(rollup@4.50.2) + specifier: ^15.3.1 + version: 15.3.1(rollup@4.52.4) '@rollup/plugin-typescript': - specifier: ^11.0.0 - version: 11.1.6(rollup@4.50.2)(tslib@2.8.1)(typescript@5.9.2) + specifier: ^11.1.6 + version: 11.1.6(rollup@4.52.4)(tslib@2.8.1)(typescript@5.9.3) '@tailwindcss/postcss': specifier: 4.1.10 version: 4.1.10 @@ -208,27 +226,30 @@ importers: version: 13.0.2(postcss@8.5.6) rollup: specifier: ^4.0.0 - version: 4.50.2 + version: 4.52.4 rollup-plugin-dts: - specifier: ^6.0.0 - version: 6.2.3(rollup@4.50.2)(typescript@5.9.2) + specifier: ^6.2.3 + version: 6.2.3(rollup@4.52.4)(typescript@5.9.3) rollup-plugin-postcss: specifier: 4.0.2 version: 4.0.2(postcss@8.5.6) rollup-plugin-typescript2: specifier: 0.36.0 - version: 0.36.0(rollup@4.50.2)(typescript@5.9.2) + version: 0.36.0(rollup@4.52.4)(typescript@5.9.3) tailwindcss: specifier: 4.1.10 version: 4.1.10 typescript: specifier: ^5.0.0 - version: 5.9.2 + version: 5.9.3 packages: - '@adraffy/ens-normalize@1.11.0': - resolution: {integrity: sha512-/3DDPKHqqIqxUULp8yP4zODUY1i+2xvVWsv8A79xGWdCAG+8sb0hRh0Rk2QyOJUnnbyPUAZYcpBuRe3nS2OIUg==} + '@adraffy/ens-normalize@1.10.1': + resolution: {integrity: sha512-96Z2IP3mYmF1Xg2cDm8f1gWGf/HUVedQ3FMifV4kG/PQ4yEP51xDtRAEfhVNt5f/uzpNkZHwWQuUcu6D6K+Ekw==} + + '@adraffy/ens-normalize@1.11.1': + resolution: {integrity: sha512-nhCBV3quEgesuf7c7KYfperqSS14T8bYuvJ8PcLJp6znkZpFc0AuW4qBtr8eKVyPPe/8RSr7sglCWPU5eaxwKQ==} '@alloc/quick-lru@5.2.0': resolution: {integrity: sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==} @@ -238,17 +259,17 @@ packages: resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==} engines: {node: '>=6.0.0'} - '@arcana/ca-common@1.0.1-alpha.6': - resolution: {integrity: sha512-v7+aaqPDOncpXAU/KkhM7G66zPnzrPzRO3HbCfvcGtMDEbil6KK5xB3Ayd5w6OzlWWHMBpRiqEfH29h0RQVupQ==} + '@avail-project/ca-common@1.0.0-beta.7': + resolution: {integrity: sha512-TCRrAM5aW0A+DoQiqmY0UJcZn6R3Mtpbt7V57V6LG4Tu52j4CC8Eye2a8Uo37YoFDXilB+AKyK6Ia+U9Kjximw==} peerDependencies: '@cosmjs/proto-signing': ^0.34.0 '@cosmjs/stargate': ^0.34.0 axios: ^1.10.0 - decimal.js: ^10.6.0 - fuels: 0.101.1 + decimal.js: 10.6.0 + fuels: ^0.101.1 long: ^5.3.2 msgpackr: ^1.11.4 - viem: ^2.31.7 + viem: ^2.0.0 '@babel/code-frame@7.27.1': resolution: {integrity: sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==} @@ -258,8 +279,12 @@ packages: resolution: {integrity: sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==} engines: {node: '>=6.9.0'} - '@bufbuild/protobuf@2.8.0': - resolution: {integrity: sha512-r1/0w5C9dkbcdjyxY8ZHsC5AOWg4Pnzhm2zu7LO4UHSounp2tMm6Y+oioV9zlGbLveE7YaWRDUk48WLxRDgoqg==} + '@babel/runtime@7.26.10': + resolution: {integrity: sha512-2WJMeRQPHKSPemqk/awGrAiuFfzBmOIPXKizAsVhWH9YJqLZ0H+HS4c8loHGgW6utJ3E/ejXQUsiGaQy2NZ9Fw==} + engines: {node: '>=6.9.0'} + + '@bufbuild/protobuf@2.9.0': + resolution: {integrity: sha512-rnJenoStJ8nvmt9Gzye8nkYd6V22xUAnu4086ER7h1zJ508vStko4pMvDeQ446ilDTFpV5wnoc5YS7XvMwwMqA==} '@cosmjs/amino@0.34.0': resolution: {integrity: sha512-wvVMmsr5cM7BSY1Z6QkOuJOjWaC4u5xjvfEO9tSpFhxjXeYlkZapU+Zp88pK6hG/UJUkGD301MN+STFbfWW2xA==} @@ -312,8 +337,8 @@ packages: cpu: [ppc64] os: [aix] - '@esbuild/aix-ppc64@0.25.10': - resolution: {integrity: sha512-0NFWnA+7l41irNuaSVlLfgNT12caWJVLzp5eAVhZ0z1qpxbockccEt3s+149rE64VUI3Ml2zt8Nv5JVc4QXTsw==} + '@esbuild/aix-ppc64@0.25.11': + resolution: {integrity: sha512-Xt1dOL13m8u0WE8iplx9Ibbm+hFAO0GsU2P34UNoDGvZYkY8ifSiy6Zuc1lYxfG7svWE2fzqCUmFp5HCn51gJg==} engines: {node: '>=18'} cpu: [ppc64] os: [aix] @@ -324,8 +349,8 @@ packages: cpu: [arm64] os: [android] - '@esbuild/android-arm64@0.25.10': - resolution: {integrity: sha512-LSQa7eDahypv/VO6WKohZGPSJDq5OVOo3UoFR1E4t4Gj1W7zEQMUhI+lo81H+DtB+kP+tDgBp+M4oNCwp6kffg==} + '@esbuild/android-arm64@0.25.11': + resolution: {integrity: sha512-9slpyFBc4FPPz48+f6jyiXOx/Y4v34TUeDDXJpZqAWQn/08lKGeD8aDp9TMn9jDz2CiEuHwfhRmGBvpnd/PWIQ==} engines: {node: '>=18'} cpu: [arm64] os: [android] @@ -336,8 +361,8 @@ packages: cpu: [arm] os: [android] - '@esbuild/android-arm@0.25.10': - resolution: {integrity: sha512-dQAxF1dW1C3zpeCDc5KqIYuZ1tgAdRXNoZP7vkBIRtKZPYe2xVr/d3SkirklCHudW1B45tGiUlz2pUWDfbDD4w==} + '@esbuild/android-arm@0.25.11': + resolution: {integrity: sha512-uoa7dU+Dt3HYsethkJ1k6Z9YdcHjTrSb5NUy66ZfZaSV8hEYGD5ZHbEMXnqLFlbBflLsl89Zke7CAdDJ4JI+Gg==} engines: {node: '>=18'} cpu: [arm] os: [android] @@ -348,8 +373,8 @@ packages: cpu: [x64] os: [android] - '@esbuild/android-x64@0.25.10': - resolution: {integrity: sha512-MiC9CWdPrfhibcXwr39p9ha1x0lZJ9KaVfvzA0Wxwz9ETX4v5CHfF09bx935nHlhi+MxhA63dKRRQLiVgSUtEg==} + '@esbuild/android-x64@0.25.11': + resolution: {integrity: sha512-Sgiab4xBjPU1QoPEIqS3Xx+R2lezu0LKIEcYe6pftr56PqPygbB7+szVnzoShbx64MUupqoE0KyRlN7gezbl8g==} engines: {node: '>=18'} cpu: [x64] os: [android] @@ -360,8 +385,8 @@ packages: cpu: [arm64] os: [darwin] - '@esbuild/darwin-arm64@0.25.10': - resolution: {integrity: sha512-JC74bdXcQEpW9KkV326WpZZjLguSZ3DfS8wrrvPMHgQOIEIG/sPXEN/V8IssoJhbefLRcRqw6RQH2NnpdprtMA==} + '@esbuild/darwin-arm64@0.25.11': + resolution: {integrity: sha512-VekY0PBCukppoQrycFxUqkCojnTQhdec0vevUL/EDOCnXd9LKWqD/bHwMPzigIJXPhC59Vd1WFIL57SKs2mg4w==} engines: {node: '>=18'} cpu: [arm64] os: [darwin] @@ -372,8 +397,8 @@ packages: cpu: [x64] os: [darwin] - '@esbuild/darwin-x64@0.25.10': - resolution: {integrity: sha512-tguWg1olF6DGqzws97pKZ8G2L7Ig1vjDmGTwcTuYHbuU6TTjJe5FXbgs5C1BBzHbJ2bo1m3WkQDbWO2PvamRcg==} + '@esbuild/darwin-x64@0.25.11': + resolution: {integrity: sha512-+hfp3yfBalNEpTGp9loYgbknjR695HkqtY3d3/JjSRUyPg/xd6q+mQqIb5qdywnDxRZykIHs3axEqU6l1+oWEQ==} engines: {node: '>=18'} cpu: [x64] os: [darwin] @@ -384,8 +409,8 @@ packages: cpu: [arm64] os: [freebsd] - '@esbuild/freebsd-arm64@0.25.10': - resolution: {integrity: sha512-3ZioSQSg1HT2N05YxeJWYR+Libe3bREVSdWhEEgExWaDtyFbbXWb49QgPvFH8u03vUPX10JhJPcz7s9t9+boWg==} + '@esbuild/freebsd-arm64@0.25.11': + resolution: {integrity: sha512-CmKjrnayyTJF2eVuO//uSjl/K3KsMIeYeyN7FyDBjsR3lnSJHaXlVoAK8DZa7lXWChbuOk7NjAc7ygAwrnPBhA==} engines: {node: '>=18'} cpu: [arm64] os: [freebsd] @@ -396,8 +421,8 @@ packages: cpu: [x64] os: [freebsd] - '@esbuild/freebsd-x64@0.25.10': - resolution: {integrity: sha512-LLgJfHJk014Aa4anGDbh8bmI5Lk+QidDmGzuC2D+vP7mv/GeSN+H39zOf7pN5N8p059FcOfs2bVlrRr4SK9WxA==} + '@esbuild/freebsd-x64@0.25.11': + resolution: {integrity: sha512-Dyq+5oscTJvMaYPvW3x3FLpi2+gSZTCE/1ffdwuM6G1ARang/mb3jvjxs0mw6n3Lsw84ocfo9CrNMqc5lTfGOw==} engines: {node: '>=18'} cpu: [x64] os: [freebsd] @@ -408,8 +433,8 @@ packages: cpu: [arm64] os: [linux] - '@esbuild/linux-arm64@0.25.10': - resolution: {integrity: sha512-5luJWN6YKBsawd5f9i4+c+geYiVEw20FVW5x0v1kEMWNq8UctFjDiMATBxLvmmHA4bf7F6hTRaJgtghFr9iziQ==} + '@esbuild/linux-arm64@0.25.11': + resolution: {integrity: sha512-Qr8AzcplUhGvdyUF08A1kHU3Vr2O88xxP0Tm8GcdVOUm25XYcMPp2YqSVHbLuXzYQMf9Bh/iKx7YPqECs6ffLA==} engines: {node: '>=18'} cpu: [arm64] os: [linux] @@ -420,8 +445,8 @@ packages: cpu: [arm] os: [linux] - '@esbuild/linux-arm@0.25.10': - resolution: {integrity: sha512-oR31GtBTFYCqEBALI9r6WxoU/ZofZl962pouZRTEYECvNF/dtXKku8YXcJkhgK/beU+zedXfIzHijSRapJY3vg==} + '@esbuild/linux-arm@0.25.11': + resolution: {integrity: sha512-TBMv6B4kCfrGJ8cUPo7vd6NECZH/8hPpBHHlYI3qzoYFvWu2AdTvZNuU/7hsbKWqu/COU7NIK12dHAAqBLLXgw==} engines: {node: '>=18'} cpu: [arm] os: [linux] @@ -432,8 +457,8 @@ packages: cpu: [ia32] os: [linux] - '@esbuild/linux-ia32@0.25.10': - resolution: {integrity: sha512-NrSCx2Kim3EnnWgS4Txn0QGt0Xipoumb6z6sUtl5bOEZIVKhzfyp/Lyw4C1DIYvzeW/5mWYPBFJU3a/8Yr75DQ==} + '@esbuild/linux-ia32@0.25.11': + resolution: {integrity: sha512-TmnJg8BMGPehs5JKrCLqyWTVAvielc615jbkOirATQvWWB1NMXY77oLMzsUjRLa0+ngecEmDGqt5jiDC6bfvOw==} engines: {node: '>=18'} cpu: [ia32] os: [linux] @@ -444,8 +469,8 @@ packages: cpu: [loong64] os: [linux] - '@esbuild/linux-loong64@0.25.10': - resolution: {integrity: sha512-xoSphrd4AZda8+rUDDfD9J6FUMjrkTz8itpTITM4/xgerAZZcFW7Dv+sun7333IfKxGG8gAq+3NbfEMJfiY+Eg==} + '@esbuild/linux-loong64@0.25.11': + resolution: {integrity: sha512-DIGXL2+gvDaXlaq8xruNXUJdT5tF+SBbJQKbWy/0J7OhU8gOHOzKmGIlfTTl6nHaCOoipxQbuJi7O++ldrxgMw==} engines: {node: '>=18'} cpu: [loong64] os: [linux] @@ -456,8 +481,8 @@ packages: cpu: [mips64el] os: [linux] - '@esbuild/linux-mips64el@0.25.10': - resolution: {integrity: sha512-ab6eiuCwoMmYDyTnyptoKkVS3k8fy/1Uvq7Dj5czXI6DF2GqD2ToInBI0SHOp5/X1BdZ26RKc5+qjQNGRBelRA==} + '@esbuild/linux-mips64el@0.25.11': + resolution: {integrity: sha512-Osx1nALUJu4pU43o9OyjSCXokFkFbyzjXb6VhGIJZQ5JZi8ylCQ9/LFagolPsHtgw6himDSyb5ETSfmp4rpiKQ==} engines: {node: '>=18'} cpu: [mips64el] os: [linux] @@ -468,8 +493,8 @@ packages: cpu: [ppc64] os: [linux] - '@esbuild/linux-ppc64@0.25.10': - resolution: {integrity: sha512-NLinzzOgZQsGpsTkEbdJTCanwA5/wozN9dSgEl12haXJBzMTpssebuXR42bthOF3z7zXFWH1AmvWunUCkBE4EA==} + '@esbuild/linux-ppc64@0.25.11': + resolution: {integrity: sha512-nbLFgsQQEsBa8XSgSTSlrnBSrpoWh7ioFDUmwo158gIm5NNP+17IYmNWzaIzWmgCxq56vfr34xGkOcZ7jX6CPw==} engines: {node: '>=18'} cpu: [ppc64] os: [linux] @@ -480,8 +505,8 @@ packages: cpu: [riscv64] os: [linux] - '@esbuild/linux-riscv64@0.25.10': - resolution: {integrity: sha512-FE557XdZDrtX8NMIeA8LBJX3dC2M8VGXwfrQWU7LB5SLOajfJIxmSdyL/gU1m64Zs9CBKvm4UAuBp5aJ8OgnrA==} + '@esbuild/linux-riscv64@0.25.11': + resolution: {integrity: sha512-HfyAmqZi9uBAbgKYP1yGuI7tSREXwIb438q0nqvlpxAOs3XnZ8RsisRfmVsgV486NdjD7Mw2UrFSw51lzUk1ww==} engines: {node: '>=18'} cpu: [riscv64] os: [linux] @@ -492,8 +517,8 @@ packages: cpu: [s390x] os: [linux] - '@esbuild/linux-s390x@0.25.10': - resolution: {integrity: sha512-3BBSbgzuB9ajLoVZk0mGu+EHlBwkusRmeNYdqmznmMc9zGASFjSsxgkNsqmXugpPk00gJ0JNKh/97nxmjctdew==} + '@esbuild/linux-s390x@0.25.11': + resolution: {integrity: sha512-HjLqVgSSYnVXRisyfmzsH6mXqyvj0SA7pG5g+9W7ESgwA70AXYNpfKBqh1KbTxmQVaYxpzA/SvlB9oclGPbApw==} engines: {node: '>=18'} cpu: [s390x] os: [linux] @@ -504,8 +529,8 @@ packages: cpu: [x64] os: [linux] - '@esbuild/linux-x64@0.25.10': - resolution: {integrity: sha512-QSX81KhFoZGwenVyPoberggdW1nrQZSvfVDAIUXr3WqLRZGZqWk/P4T8p2SP+de2Sr5HPcvjhcJzEiulKgnxtA==} + '@esbuild/linux-x64@0.25.11': + resolution: {integrity: sha512-HSFAT4+WYjIhrHxKBwGmOOSpphjYkcswF449j6EjsjbinTZbp8PJtjsVK1XFJStdzXdy/jaddAep2FGY+wyFAQ==} engines: {node: '>=18'} cpu: [x64] os: [linux] @@ -516,8 +541,8 @@ packages: cpu: [arm64] os: [netbsd] - '@esbuild/netbsd-arm64@0.25.10': - resolution: {integrity: sha512-AKQM3gfYfSW8XRk8DdMCzaLUFB15dTrZfnX8WXQoOUpUBQ+NaAFCP1kPS/ykbbGYz7rxn0WS48/81l9hFl3u4A==} + '@esbuild/netbsd-arm64@0.25.11': + resolution: {integrity: sha512-hr9Oxj1Fa4r04dNpWr3P8QKVVsjQhqrMSUzZzf+LZcYjZNqhA3IAfPQdEh1FLVUJSiu6sgAwp3OmwBfbFgG2Xg==} engines: {node: '>=18'} cpu: [arm64] os: [netbsd] @@ -528,8 +553,8 @@ packages: cpu: [x64] os: [netbsd] - '@esbuild/netbsd-x64@0.25.10': - resolution: {integrity: sha512-7RTytDPGU6fek/hWuN9qQpeGPBZFfB4zZgcz2VK2Z5VpdUxEI8JKYsg3JfO0n/Z1E/6l05n0unDCNc4HnhQGig==} + '@esbuild/netbsd-x64@0.25.11': + resolution: {integrity: sha512-u7tKA+qbzBydyj0vgpu+5h5AeudxOAGncb8N6C9Kh1N4n7wU1Xw1JDApsRjpShRpXRQlJLb9wY28ELpwdPcZ7A==} engines: {node: '>=18'} cpu: [x64] os: [netbsd] @@ -540,8 +565,8 @@ packages: cpu: [arm64] os: [openbsd] - '@esbuild/openbsd-arm64@0.25.10': - resolution: {integrity: sha512-5Se0VM9Wtq797YFn+dLimf2Zx6McttsH2olUBsDml+lm0GOCRVebRWUvDtkY4BWYv/3NgzS8b/UM3jQNh5hYyw==} + '@esbuild/openbsd-arm64@0.25.11': + resolution: {integrity: sha512-Qq6YHhayieor3DxFOoYM1q0q1uMFYb7cSpLD2qzDSvK1NAvqFi8Xgivv0cFC6J+hWVw2teCYltyy9/m/14ryHg==} engines: {node: '>=18'} cpu: [arm64] os: [openbsd] @@ -552,14 +577,14 @@ packages: cpu: [x64] os: [openbsd] - '@esbuild/openbsd-x64@0.25.10': - resolution: {integrity: sha512-XkA4frq1TLj4bEMB+2HnI0+4RnjbuGZfet2gs/LNs5Hc7D89ZQBHQ0gL2ND6Lzu1+QVkjp3x1gIcPKzRNP8bXw==} + '@esbuild/openbsd-x64@0.25.11': + resolution: {integrity: sha512-CN+7c++kkbrckTOz5hrehxWN7uIhFFlmS/hqziSFVWpAzpWrQoAG4chH+nN3Be+Kzv/uuo7zhX716x3Sn2Jduw==} engines: {node: '>=18'} cpu: [x64] os: [openbsd] - '@esbuild/openharmony-arm64@0.25.10': - resolution: {integrity: sha512-AVTSBhTX8Y/Fz6OmIVBip9tJzZEUcY8WLh7I59+upa5/GPhh2/aM6bvOMQySspnCCHvFi79kMtdJS1w0DXAeag==} + '@esbuild/openharmony-arm64@0.25.11': + resolution: {integrity: sha512-rOREuNIQgaiR+9QuNkbkxubbp8MSO9rONmwP5nKncnWJ9v5jQ4JxFnLu4zDSRPf3x4u+2VN4pM4RdyIzDty/wQ==} engines: {node: '>=18'} cpu: [arm64] os: [openharmony] @@ -570,8 +595,8 @@ packages: cpu: [x64] os: [sunos] - '@esbuild/sunos-x64@0.25.10': - resolution: {integrity: sha512-fswk3XT0Uf2pGJmOpDB7yknqhVkJQkAQOcW/ccVOtfx05LkbWOaRAtn5SaqXypeKQra1QaEa841PgrSL9ubSPQ==} + '@esbuild/sunos-x64@0.25.11': + resolution: {integrity: sha512-nq2xdYaWxyg9DcIyXkZhcYulC6pQ2FuCgem3LI92IwMgIZ69KHeY8T4Y88pcwoLIjbed8n36CyKoYRDygNSGhA==} engines: {node: '>=18'} cpu: [x64] os: [sunos] @@ -582,8 +607,8 @@ packages: cpu: [arm64] os: [win32] - '@esbuild/win32-arm64@0.25.10': - resolution: {integrity: sha512-ah+9b59KDTSfpaCg6VdJoOQvKjI33nTaQr4UluQwW7aEwZQsbMCfTmfEO4VyewOxx4RaDT/xCy9ra2GPWmO7Kw==} + '@esbuild/win32-arm64@0.25.11': + resolution: {integrity: sha512-3XxECOWJq1qMZ3MN8srCJ/QfoLpL+VaxD/WfNRm1O3B4+AZ/BnLVgFbUV3eiRYDMXetciH16dwPbbHqwe1uU0Q==} engines: {node: '>=18'} cpu: [arm64] os: [win32] @@ -594,8 +619,8 @@ packages: cpu: [ia32] os: [win32] - '@esbuild/win32-ia32@0.25.10': - resolution: {integrity: sha512-QHPDbKkrGO8/cz9LKVnJU22HOi4pxZnZhhA2HYHez5Pz4JeffhDjf85E57Oyco163GnzNCVkZK0b/n4Y0UHcSw==} + '@esbuild/win32-ia32@0.25.11': + resolution: {integrity: sha512-3ukss6gb9XZ8TlRyJlgLn17ecsK4NSQTmdIXRASVsiS2sQ6zPPZklNJT5GR5tE/MUarymmy8kCEf5xPCNCqVOA==} engines: {node: '>=18'} cpu: [ia32] os: [win32] @@ -606,8 +631,8 @@ packages: cpu: [x64] os: [win32] - '@esbuild/win32-x64@0.25.10': - resolution: {integrity: sha512-9KpxSVFCu0iK1owoez6aC/s/EdUQLDN3adTxGCqxMVhrPDj6bt5dbrHDXUuq+Bs2vATFBBrQS5vdQ/Ed2P+nbw==} + '@esbuild/win32-x64@0.25.11': + resolution: {integrity: sha512-D7Hpz6A2L4hzsRpPaCYkQnGOotdUpDzSGRIv9I+1ITdHROSFUWW95ZPZWQmGka1Fg7W3zFJowyn9WGwMJ0+KPA==} engines: {node: '>=18'} cpu: [x64] os: [win32] @@ -760,6 +785,12 @@ packages: resolution: {integrity: sha512-2I0gnIVPtfnMw9ee9h1dJG7tp81+8Ob3OJb3Mv37rx5L40/b0i7djjCVvGOVqc9AEIQyvyu1i6ypKdFw8R8gQw==} engines: {node: ^14.21.3 || >=16} + '@noble/curves@1.2.0': + resolution: {integrity: sha512-oYclrNgRaM9SsBUBVbb8M6DTV7ZHRTKugureoYEncY5c65HOmRzvSiTE3y5CYaPYJA/GVkrhXEoF0M3Ya9PMnw==} + + '@noble/curves@1.4.2': + resolution: {integrity: sha512-TavHr8qycMChk8UwMld0ZDRvatedkzWfH8IiaeGCfymOP5i0hSCozz9vHOL0nkwk7HRMlFnAiKpS2jrUmSybcw==} + '@noble/curves@1.8.1': resolution: {integrity: sha512-warwspo+UYUPep0Q+vtdVB4Ugn8GGQj8iyB3gnRWsztmUHTI3S1nhdiWNsPUGL0vud7JlRRk1XEu7Lq1KGTnMQ==} engines: {node: ^14.21.3 || >=16} @@ -772,6 +803,14 @@ packages: resolution: {integrity: sha512-gbKGcRUYIjA3/zCCNaWDciTMFI0dCkvou3TL8Zmy5Nc7sJ47a0jtOeZoTaMxkuqRo9cRhjOdZJXegxYE5FN/xw==} engines: {node: ^14.21.3 || >=16} + '@noble/hashes@1.3.2': + resolution: {integrity: sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ==} + engines: {node: '>= 16'} + + '@noble/hashes@1.4.0': + resolution: {integrity: sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==} + engines: {node: '>= 16'} + '@noble/hashes@1.7.1': resolution: {integrity: sha512-B8XBPsn4vT/KJAGqDzbwztd+6Yte3P4V7iafm24bxgDe/mlRuK6xmWPuCNrKt2vDafZ8MfJLlchDG/vYafQEjQ==} engines: {node: ^14.21.3 || >=16} @@ -788,7 +827,7 @@ packages: resolution: {integrity: sha512-PR9zDb+rOzkRb2VD+EuKB7UC41vU5DIwZ5qqCpk0KJudcWAyi8rvYOhS7+L5aZCspw1stTViLgN5v6FF1p5cgQ==} engines: {node: '>=14.0.0'} peerDependencies: - rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 + rollup: ^4.0.0 peerDependenciesMeta: rollup: optional: true @@ -797,7 +836,7 @@ packages: resolution: {integrity: sha512-ZEZWTK5n6Qde0to4vS9Mr5x/0UZoqCxPVR9KRUjU4kA2sO7GEUn1fop0DAwpO6z0Nw/kJON9bDmSxdWxO/TT1A==} engines: {node: '>=14.0.0'} peerDependencies: - rollup: ^2.68.0||^3.0.0||^4.0.0 + rollup: ^4.0.0 peerDependenciesMeta: rollup: optional: true @@ -806,7 +845,7 @@ packages: resolution: {integrity: sha512-EGI2te5ENk1coGeADSIwZ7G2Q8CJS2sF120T7jLw4xFw9n7wIOXHo+kIYRAoVpJAN+kmqZSoO3Fp4JtoNF4ReA==} engines: {node: '>=14.0.0'} peerDependencies: - rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 + rollup: ^4.0.0 peerDependenciesMeta: rollup: optional: true @@ -815,7 +854,7 @@ packages: resolution: {integrity: sha512-tgg6b91pAybXHJQMAAwW9VuWBO6Thi+q7BCNARLwSqlmsHz0XYURtGvh/AuwSADXSI4h/2uHbs7s4FzlZDGSGA==} engines: {node: '>=14.0.0'} peerDependencies: - rollup: ^2.78.0||^3.0.0||^4.0.0 + rollup: ^4.0.0 peerDependenciesMeta: rollup: optional: true @@ -824,9 +863,9 @@ packages: resolution: {integrity: sha512-R92yOmIACgYdJ7dJ97p4K69I8gg6IEHt8M7dUBxN3W6nrO8uUxX5ixl0yU/N3aZTi8WhPuICvOHXQvF6FaykAA==} engines: {node: '>=14.0.0'} peerDependencies: - rollup: ^2.14.0||^3.0.0||^4.0.0 + rollup: ^4.0.0 tslib: '*' - typescript: '>=3.7.0' + typescript: ^5.0.0 peerDependenciesMeta: rollup: optional: true @@ -841,122 +880,136 @@ packages: resolution: {integrity: sha512-5EdhGZtnu3V88ces7s53hhfK5KSASnJZv8Lulpc04cWO3REESroJXg73DFsOmgbU2BhwV0E20bu2IDZb3VKW4Q==} engines: {node: '>=14.0.0'} peerDependencies: - rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 + rollup: ^4.0.0 peerDependenciesMeta: rollup: optional: true - '@rollup/rollup-android-arm-eabi@4.50.2': - resolution: {integrity: sha512-uLN8NAiFVIRKX9ZQha8wy6UUs06UNSZ32xj6giK/rmMXAgKahwExvK6SsmgU5/brh4w/nSgj8e0k3c1HBQpa0A==} + '@rollup/rollup-android-arm-eabi@4.52.4': + resolution: {integrity: sha512-BTm2qKNnWIQ5auf4deoetINJm2JzvihvGb9R6K/ETwKLql/Bb3Eg2H1FBp1gUb4YGbydMA3jcmQTR73q7J+GAA==} cpu: [arm] os: [android] - '@rollup/rollup-android-arm64@4.50.2': - resolution: {integrity: sha512-oEouqQk2/zxxj22PNcGSskya+3kV0ZKH+nQxuCCOGJ4oTXBdNTbv+f/E3c74cNLeMO1S5wVWacSws10TTSB77g==} + '@rollup/rollup-android-arm64@4.52.4': + resolution: {integrity: sha512-P9LDQiC5vpgGFgz7GSM6dKPCiqR3XYN1WwJKA4/BUVDjHpYsf3iBEmVz62uyq20NGYbiGPR5cNHI7T1HqxNs2w==} cpu: [arm64] os: [android] - '@rollup/rollup-darwin-arm64@4.50.2': - resolution: {integrity: sha512-OZuTVTpj3CDSIxmPgGH8en/XtirV5nfljHZ3wrNwvgkT5DQLhIKAeuFSiwtbMto6oVexV0k1F1zqURPKf5rI1Q==} + '@rollup/rollup-darwin-arm64@4.52.4': + resolution: {integrity: sha512-QRWSW+bVccAvZF6cbNZBJwAehmvG9NwfWHwMy4GbWi/BQIA/laTIktebT2ipVjNncqE6GLPxOok5hsECgAxGZg==} cpu: [arm64] os: [darwin] - '@rollup/rollup-darwin-x64@4.50.2': - resolution: {integrity: sha512-Wa/Wn8RFkIkr1vy1k1PB//VYhLnlnn5eaJkfTQKivirOvzu5uVd2It01ukeQstMursuz7S1bU+8WW+1UPXpa8A==} + '@rollup/rollup-darwin-x64@4.52.4': + resolution: {integrity: sha512-hZgP05pResAkRJxL1b+7yxCnXPGsXU0fG9Yfd6dUaoGk+FhdPKCJ5L1Sumyxn8kvw8Qi5PvQ8ulenUbRjzeCTw==} cpu: [x64] os: [darwin] - '@rollup/rollup-freebsd-arm64@4.50.2': - resolution: {integrity: sha512-QkzxvH3kYN9J1w7D1A+yIMdI1pPekD+pWx7G5rXgnIlQ1TVYVC6hLl7SOV9pi5q9uIDF9AuIGkuzcbF7+fAhow==} + '@rollup/rollup-freebsd-arm64@4.52.4': + resolution: {integrity: sha512-xmc30VshuBNUd58Xk4TKAEcRZHaXlV+tCxIXELiE9sQuK3kG8ZFgSPi57UBJt8/ogfhAF5Oz4ZSUBN77weM+mQ==} cpu: [arm64] os: [freebsd] - '@rollup/rollup-freebsd-x64@4.50.2': - resolution: {integrity: sha512-dkYXB0c2XAS3a3jmyDkX4Jk0m7gWLFzq1C3qUnJJ38AyxIF5G/dyS4N9B30nvFseCfgtCEdbYFhk0ChoCGxPog==} + '@rollup/rollup-freebsd-x64@4.52.4': + resolution: {integrity: sha512-WdSLpZFjOEqNZGmHflxyifolwAiZmDQzuOzIq9L27ButpCVpD7KzTRtEG1I0wMPFyiyUdOO+4t8GvrnBLQSwpw==} cpu: [x64] os: [freebsd] - '@rollup/rollup-linux-arm-gnueabihf@4.50.2': - resolution: {integrity: sha512-9VlPY/BN3AgbukfVHAB8zNFWB/lKEuvzRo1NKev0Po8sYFKx0i+AQlCYftgEjcL43F2h9Ui1ZSdVBc4En/sP2w==} + '@rollup/rollup-linux-arm-gnueabihf@4.52.4': + resolution: {integrity: sha512-xRiOu9Of1FZ4SxVbB0iEDXc4ddIcjCv2aj03dmW8UrZIW7aIQ9jVJdLBIhxBI+MaTnGAKyvMwPwQnoOEvP7FgQ==} cpu: [arm] os: [linux] - '@rollup/rollup-linux-arm-musleabihf@4.50.2': - resolution: {integrity: sha512-+GdKWOvsifaYNlIVf07QYan1J5F141+vGm5/Y8b9uCZnG/nxoGqgCmR24mv0koIWWuqvFYnbURRqw1lv7IBINw==} + '@rollup/rollup-linux-arm-musleabihf@4.52.4': + resolution: {integrity: sha512-FbhM2p9TJAmEIEhIgzR4soUcsW49e9veAQCziwbR+XWB2zqJ12b4i/+hel9yLiD8pLncDH4fKIPIbt5238341Q==} cpu: [arm] os: [linux] - '@rollup/rollup-linux-arm64-gnu@4.50.2': - resolution: {integrity: sha512-df0Eou14ojtUdLQdPFnymEQteENwSJAdLf5KCDrmZNsy1c3YaCNaJvYsEUHnrg+/DLBH612/R0xd3dD03uz2dg==} + '@rollup/rollup-linux-arm64-gnu@4.52.4': + resolution: {integrity: sha512-4n4gVwhPHR9q/g8lKCyz0yuaD0MvDf7dV4f9tHt0C73Mp8h38UCtSCSE6R9iBlTbXlmA8CjpsZoujhszefqueg==} cpu: [arm64] os: [linux] - '@rollup/rollup-linux-arm64-musl@4.50.2': - resolution: {integrity: sha512-iPeouV0UIDtz8j1YFR4OJ/zf7evjauqv7jQ/EFs0ClIyL+by++hiaDAfFipjOgyz6y6xbDvJuiU4HwpVMpRFDQ==} + '@rollup/rollup-linux-arm64-musl@4.52.4': + resolution: {integrity: sha512-u0n17nGA0nvi/11gcZKsjkLj1QIpAuPFQbR48Subo7SmZJnGxDpspyw2kbpuoQnyK+9pwf3pAoEXerJs/8Mi9g==} cpu: [arm64] os: [linux] - '@rollup/rollup-linux-loong64-gnu@4.50.2': - resolution: {integrity: sha512-OL6KaNvBopLlj5fTa5D5bau4W82f+1TyTZRr2BdnfsrnQnmdxh4okMxR2DcDkJuh4KeoQZVuvHvzuD/lyLn2Kw==} + '@rollup/rollup-linux-loong64-gnu@4.52.4': + resolution: {integrity: sha512-0G2c2lpYtbTuXo8KEJkDkClE/+/2AFPdPAbmaHoE870foRFs4pBrDehilMcrSScrN/fB/1HTaWO4bqw+ewBzMQ==} cpu: [loong64] os: [linux] - '@rollup/rollup-linux-ppc64-gnu@4.50.2': - resolution: {integrity: sha512-I21VJl1w6z/K5OTRl6aS9DDsqezEZ/yKpbqlvfHbW0CEF5IL8ATBMuUx6/mp683rKTK8thjs/0BaNrZLXetLag==} + '@rollup/rollup-linux-ppc64-gnu@4.52.4': + resolution: {integrity: sha512-teSACug1GyZHmPDv14VNbvZFX779UqWTsd7KtTM9JIZRDI5NUwYSIS30kzI8m06gOPB//jtpqlhmraQ68b5X2g==} cpu: [ppc64] os: [linux] - '@rollup/rollup-linux-riscv64-gnu@4.50.2': - resolution: {integrity: sha512-Hq6aQJT/qFFHrYMjS20nV+9SKrXL2lvFBENZoKfoTH2kKDOJqff5OSJr4x72ZaG/uUn+XmBnGhfr4lwMRrmqCQ==} + '@rollup/rollup-linux-riscv64-gnu@4.52.4': + resolution: {integrity: sha512-/MOEW3aHjjs1p4Pw1Xk4+3egRevx8Ji9N6HUIA1Ifh8Q+cg9dremvFCUbOX2Zebz80BwJIgCBUemjqhU5XI5Eg==} cpu: [riscv64] os: [linux] - '@rollup/rollup-linux-riscv64-musl@4.50.2': - resolution: {integrity: sha512-82rBSEXRv5qtKyr0xZ/YMF531oj2AIpLZkeNYxmKNN6I2sVE9PGegN99tYDLK2fYHJITL1P2Lgb4ZXnv0PjQvw==} + '@rollup/rollup-linux-riscv64-musl@4.52.4': + resolution: {integrity: sha512-1HHmsRyh845QDpEWzOFtMCph5Ts+9+yllCrREuBR/vg2RogAQGGBRC8lDPrPOMnrdOJ+mt1WLMOC2Kao/UwcvA==} cpu: [riscv64] os: [linux] - '@rollup/rollup-linux-s390x-gnu@4.50.2': - resolution: {integrity: sha512-4Q3S3Hy7pC6uaRo9gtXUTJ+EKo9AKs3BXKc2jYypEcMQ49gDPFU2P1ariX9SEtBzE5egIX6fSUmbmGazwBVF9w==} + '@rollup/rollup-linux-s390x-gnu@4.52.4': + resolution: {integrity: sha512-seoeZp4L/6D1MUyjWkOMRU6/iLmCU2EjbMTyAG4oIOs1/I82Y5lTeaxW0KBfkUdHAWN7j25bpkt0rjnOgAcQcA==} cpu: [s390x] os: [linux] - '@rollup/rollup-linux-x64-gnu@4.50.2': - resolution: {integrity: sha512-9Jie/At6qk70dNIcopcL4p+1UirusEtznpNtcq/u/C5cC4HBX7qSGsYIcG6bdxj15EYWhHiu02YvmdPzylIZlA==} + '@rollup/rollup-linux-x64-gnu@4.52.4': + resolution: {integrity: sha512-Wi6AXf0k0L7E2gteNsNHUs7UMwCIhsCTs6+tqQ5GPwVRWMaflqGec4Sd8n6+FNFDw9vGcReqk2KzBDhCa1DLYg==} cpu: [x64] os: [linux] - '@rollup/rollup-linux-x64-musl@4.50.2': - resolution: {integrity: sha512-HPNJwxPL3EmhzeAnsWQCM3DcoqOz3/IC6de9rWfGR8ZCuEHETi9km66bH/wG3YH0V3nyzyFEGUZeL5PKyy4xvw==} + '@rollup/rollup-linux-x64-musl@4.52.4': + resolution: {integrity: sha512-dtBZYjDmCQ9hW+WgEkaffvRRCKm767wWhxsFW3Lw86VXz/uJRuD438/XvbZT//B96Vs8oTA8Q4A0AfHbrxP9zw==} cpu: [x64] os: [linux] - '@rollup/rollup-openharmony-arm64@4.50.2': - resolution: {integrity: sha512-nMKvq6FRHSzYfKLHZ+cChowlEkR2lj/V0jYj9JnGUVPL2/mIeFGmVM2mLaFeNa5Jev7W7TovXqXIG2d39y1KYA==} + '@rollup/rollup-openharmony-arm64@4.52.4': + resolution: {integrity: sha512-1ox+GqgRWqaB1RnyZXL8PD6E5f7YyRUJYnCqKpNzxzP0TkaUh112NDrR9Tt+C8rJ4x5G9Mk8PQR3o7Ku2RKqKA==} cpu: [arm64] os: [openharmony] - '@rollup/rollup-win32-arm64-msvc@4.50.2': - resolution: {integrity: sha512-eFUvvnTYEKeTyHEijQKz81bLrUQOXKZqECeiWH6tb8eXXbZk+CXSG2aFrig2BQ/pjiVRj36zysjgILkqarS2YA==} + '@rollup/rollup-win32-arm64-msvc@4.52.4': + resolution: {integrity: sha512-8GKr640PdFNXwzIE0IrkMWUNUomILLkfeHjXBi/nUvFlpZP+FA8BKGKpacjW6OUUHaNI6sUURxR2U2g78FOHWQ==} cpu: [arm64] os: [win32] - '@rollup/rollup-win32-ia32-msvc@4.50.2': - resolution: {integrity: sha512-cBaWmXqyfRhH8zmUxK3d3sAhEWLrtMjWBRwdMMHJIXSjvjLKvv49adxiEz+FJ8AP90apSDDBx2Tyd/WylV6ikA==} + '@rollup/rollup-win32-ia32-msvc@4.52.4': + resolution: {integrity: sha512-AIy/jdJ7WtJ/F6EcfOb2GjR9UweO0n43jNObQMb6oGxkYTfLcnN7vYYpG+CN3lLxrQkzWnMOoNSHTW54pgbVxw==} cpu: [ia32] os: [win32] - '@rollup/rollup-win32-x64-msvc@4.50.2': - resolution: {integrity: sha512-APwKy6YUhvZaEoHyM+9xqmTpviEI+9eL7LoCH+aLcvWYHJ663qG5zx7WzWZY+a9qkg5JtzcMyJ9z0WtQBMDmgA==} + '@rollup/rollup-win32-x64-gnu@4.52.4': + resolution: {integrity: sha512-UF9KfsH9yEam0UjTwAgdK0anlQ7c8/pWPU2yVjyWcF1I1thABt6WXE47cI71pGiZ8wGvxohBoLnxM04L/wj8mQ==} cpu: [x64] os: [win32] + '@rollup/rollup-win32-x64-msvc@4.52.4': + resolution: {integrity: sha512-bf9PtUa0u8IXDVxzRToFQKsNCRz9qLYfR/MpECxl4mRoWYjAeFjgxj1XdZr2M/GNVpT05p+LgQOHopYDlUu6/w==} + cpu: [x64] + os: [win32] + + '@scure/base@1.1.9': + resolution: {integrity: sha512-8YKhl8GHiNI/pU2VMaofa2Tor7PJRAjwQLBBuilkJ9L5+13yVbC7JO/wS7piioAvPSwR3JKM1IJ/u4xQzbcXKg==} + '@scure/base@1.2.6': resolution: {integrity: sha512-g/nm5FgUa//MCj1gV09zTJTaM6KBAHqLN907YVQqf7zC49+DcO4B1so4ZX07Ef10Twr6nuqYEH9GEggFXA4Fmg==} + '@scure/bip32@1.4.0': + resolution: {integrity: sha512-sVUpc0Vq3tXCkDGYVWGIZTRfnvu8LoTDaev7vbwh0omSvVORONr960MQWdKqJDCReIEmTj3PAr73O3aoxz7OPg==} + '@scure/bip32@1.7.0': resolution: {integrity: sha512-E4FFX/N3f4B80AKWp5dP6ow+flD1LQZo/w8UnLGYZO674jS6YnYeepycOOksv+vLPSpgN35wgKgy+ybfTb2SMw==} + '@scure/bip39@1.3.0': + resolution: {integrity: sha512-disdg7gHuTDZtY+ZdkmLpPCk7fxZSu3gBiEGuoC1XYxv9cGx3Z6cpTggCgW6odSOOIXCiDjuGejW+aJKCY/pIQ==} + '@scure/bip39@1.6.0': resolution: {integrity: sha512-+lF0BbLiJNwVlev4eKelw1WWLaiKXw7sSl8T6FvBlWkdX+94aGJ4o8XjUdlyhTCjd8c+B3KT3JfS8P0bLRNU6A==} @@ -1051,6 +1104,10 @@ packages: '@tailwindcss/postcss@4.1.10': resolution: {integrity: sha512-B+7r7ABZbkXJwpvt2VMnS6ujcDoR2OOcFaqrLIo1xbcdxje4Vf+VgJdBzNNbrAjBj/rLZ66/tlQ1knIGNLKOBQ==} + '@tronweb3/tronwallet-abstract-adapter@1.1.9': + resolution: {integrity: sha512-2wev5T/Z+Yt96nv2upZeq54v8zk8aXCg0p6yx1BpfY2y25lC0jEiul+F/6o5s2uIUXe2ENdbpMiGQz8+/Jy1EQ==} + engines: {node: '>=16', pnpm: '>=7'} + '@trysound/sax@0.2.0': resolution: {integrity: sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==} engines: {node: '>=10.13.0'} @@ -1064,8 +1121,14 @@ packages: '@types/estree@1.0.8': resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==} - '@types/node@20.19.17': - resolution: {integrity: sha512-gfehUI8N1z92kygssiuWvLiwcbOB3IRktR6hTDgJlXMYh5OvkPSRmgfoBUmfZt+vhwJtX7v1Yw4KvvAf7c5QKQ==} + '@types/node@20.19.22': + resolution: {integrity: sha512-hRnu+5qggKDSyWHlnmThnUqg62l29Aj/6vcYgUaSFL9oc7DVjeWEQN3PRgdSc6F8d9QRMWkf36CLMch1Do/+RQ==} + + '@types/node@22.7.5': + resolution: {integrity: sha512-jML7s2NAzMWc//QSJ1a3prpk78cOPchGvXJsC3C6R6PSMoooztvRVQEz89gmBTBY1SPMaqo5teB4uNHPdetShQ==} + + '@types/node@24.8.1': + resolution: {integrity: sha512-alv65KGRadQVfVcG69MuB4IzdYVpRwMG/mq8KWOaoOdyY617P5ivaDiMCGOFDWD2sAn5Q0mR3mRtUOgm99hL9Q==} '@types/pbkdf2@3.1.2': resolution: {integrity: sha512-uRwJqmiXmh9++aSu1VNEn3iIxWOhd8AHXNSdlaLfdAAdSTY9jYVeGWnzejM3dvrkbqE3/hyQkQQ29IFATEGlew==} @@ -1081,8 +1144,8 @@ packages: '@types/resolve@1.20.2': resolution: {integrity: sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==} - '@types/secp256k1@4.0.6': - resolution: {integrity: sha512-hHxJU6PAEUn0TP4S/ZOzuTUvJWuZ6eIKeNKb5RBpODvSl6hp1Wrw4s7ATY50rklRCScUDpHzVA/DQdSjJ3UoYQ==} + '@types/secp256k1@4.0.7': + resolution: {integrity: sha512-Rcvjl6vARGAKRO6jHeKMatGrvOMGrR/AR11N1x2LqintPCyDZ7NBhrh238Z2VZc7aM7KIwnFpFQ7fnfK4H/9Qw==} '@types/ws@8.18.1': resolution: {integrity: sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==} @@ -1122,7 +1185,18 @@ packages: abitype@1.1.0: resolution: {integrity: sha512-6Vh4HcRxNMLA0puzPjM5GBgT4aAcFGKZzSgAXvuZ27shJP6NEpielTuqbBmZILR5/xd0PizkBGy5hReKz9jl5A==} peerDependencies: - typescript: '>=5.0.4' + typescript: ^5.0.0 + zod: ^3.22.0 || ^4.0.0 + peerDependenciesMeta: + typescript: + optional: true + zod: + optional: true + + abitype@1.1.1: + resolution: {integrity: sha512-Loe5/6tAgsBukY95eGaPSDmQHIjRZYQq8PB1MpsNccDIK8WiV+Uw6WzaIXipvaxTEL2yEB0OpEaQv3gs8pkS9Q==} + peerDependencies: + typescript: ^5.0.0 zod: ^3.22.0 || ^4.0.0 peerDependenciesMeta: typescript: @@ -1133,6 +1207,9 @@ packages: aes-js@3.1.2: resolution: {integrity: sha512-e5pEa2kBnBOgR4Y/p20pskXI74UEz7de8ZGVo58asOtvSVG5YAbJeELPZxOmt+Bnz3rX753YKhfIn4X4l1PPRQ==} + aes-js@4.0.0-beta.5: + resolution: {integrity: sha512-G965FqalsNyrPqgEGON7nIx1e/OVENSgiEIzyC63haUMuvNnwIgIjMs52hlTCKhkBny7A2ORNlfY9Zu+jmGk1Q==} + ansi-regex@5.0.1: resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} engines: {node: '>=8'} @@ -1180,6 +1257,9 @@ packages: resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==} engines: {node: '>= 0.4'} + axios@1.11.0: + resolution: {integrity: sha512-1Lx3WLFQWm3ooKDYZD1eXmoGO9fxYQjrycfHFC8P0sCfQVXyROp0p9PFWBehewBOdCwHc+f/b8I0fMto5eSfwA==} + axios@1.12.2: resolution: {integrity: sha512-vMJzPewAlRyOgxV2dU0Cuz2O8zzzx9VYtbJOaBgXFeLc4IV/Eg50n4LowmehOOR61S8ZMpc2K5Sa7g6A4jfkUw==} @@ -1192,13 +1272,16 @@ packages: base64-js@1.5.1: resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} - baseline-browser-mapping@2.8.6: - resolution: {integrity: sha512-wrH5NNqren/QMtKUEEJf7z86YjfqW/2uw3IL3/xpqZUC95SSVIFXYQeeGjL6FT/X68IROu6RMehZQS5foy2BXw==} + baseline-browser-mapping@2.8.17: + resolution: {integrity: sha512-j5zJcx6golJYTG6c05LUZ3Z8Gi+M62zRT/ycz4Xq4iCOdpcxwg7ngEYD4KA0eWZC7U17qh/Smq8bYbACJ0ipBA==} hasBin: true bech32@1.1.4: resolution: {integrity: sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ==} + bignumber.js@9.1.2: + resolution: {integrity: sha512-2/mKyZH9K85bzOEfhXDBFZTGd1CTs+5IHpeFQo9luiBG7hghdC851Pj2WAhb6E3R6b9tZj/XKhbg4fum+Kepug==} + binary-extensions@2.3.0: resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==} engines: {node: '>=8'} @@ -1247,12 +1330,12 @@ packages: resolution: {integrity: sha512-YBjSAiTqM04ZVei6sXighu679a3SqWORA3qZTEqZImnlkDIFtKc6pNutpjyZ8RJTjQtuYfeetkxM11GwoYXMIQ==} engines: {node: '>= 0.10'} - browserify-sign@4.2.3: - resolution: {integrity: sha512-JWCZW6SKhfhjJxO8Tyiiy+XYB7cqd2S5/+WeYHsKdNKFlCBhKbblba1A/HN/90YwtxKc8tCErjffZl++UNmGiw==} - engines: {node: '>= 0.12'} + browserify-sign@4.2.5: + resolution: {integrity: sha512-C2AUdAJg6rlM2W5QMp2Q4KGQMVBwR1lIimTsUnutJ8bMpW5B52pGpR2gEnNBNwijumDo5FojQ0L9JrXA8m4YEw==} + engines: {node: '>= 0.10'} - browserslist@4.26.2: - resolution: {integrity: sha512-ECFzp6uFOSB+dcZ5BK/IBaGWssbSYBHvuMeMt3MMFyhI0Z8SqGgEkBLARgpRH3hutIgPVsALcMwbDrJqPxQ65A==} + browserslist@4.26.3: + resolution: {integrity: sha512-lAUU+02RFBuCKQPj/P6NgjlbCnLBMp4UtgTx7vNHd3XSIJF87s9a5rA3aH2yw3GS9DqZAUbOtZdCCiZeVRqt0w==} engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} hasBin: true @@ -1293,8 +1376,8 @@ packages: caniuse-api@3.0.0: resolution: {integrity: sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw==} - caniuse-lite@1.0.30001743: - resolution: {integrity: sha512-e6Ojr7RV14Un7dz6ASD0aZDmQPT/A+eZU+nuTNfjqmRrmkmQlnTNWH0SKmqagx9PeW87UVqapSurtAXifmtdmw==} + caniuse-lite@1.0.30001751: + resolution: {integrity: sha512-A0QJhug0Ly64Ii3eIqHu5X51ebln3k4yTUkY1j8drqpWHVreg/VLijN48cZ1bYPiqOQuqpkIKnzr/Ul8V+p6Cw==} chai@5.3.3: resolution: {integrity: sha512-4zNhdJD/iOjSH0A05ea+Ke6MU5mmpQcbQsSOkgdaUMJ9zTlDTD/GYlwohmIE2u0gaxHYiVHEn1Fw9mZ/ktJWgw==} @@ -1316,8 +1399,8 @@ packages: resolution: {integrity: sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==} engines: {node: '>=18'} - cipher-base@1.0.6: - resolution: {integrity: sha512-3Ek9H3X6pj5TgenXYtNWdaBon1tgYCaebd+XPg0keyjEbEfkD4KkmAxkQ/i1vYvxdcT5nscLBfq9VJRmCBcFSw==} + cipher-base@1.0.7: + resolution: {integrity: sha512-Mz9QMT5fJe7bKI7MH31UilT5cEK5EHHRCccw/YRFsRY47AuNgaV6HY3rscp0/I4Q+tTW/5zoqpSeRRI54TkDWA==} engines: {node: '>= 0.10'} class-variance-authority@0.7.1: @@ -1372,9 +1455,6 @@ packages: create-ecdh@4.0.4: resolution: {integrity: sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A==} - create-hash@1.1.3: - resolution: {integrity: sha512-snRpch/kwQhcdlnZKYanNF1m0RDlrCdSKQaH87w1FCFPVPNCQ/Il9QJKAX2jVBZddRdaHBMC+zXa9Gw9tmkNUA==} - create-hash@1.2.0: resolution: {integrity: sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==} @@ -1459,9 +1539,6 @@ packages: supports-color: optional: true - decimal.js@10.4.3: - resolution: {integrity: sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==} - decimal.js@10.6.0: resolution: {integrity: sha512-YpgQiITW3JXGntzdUmyUR1V812Hn8T1YVXhCu+wO3OpS4eU9l4YdD3qjyiKdV6mvV29zapkMeD390UVEf2lkUg==} @@ -1488,8 +1565,8 @@ packages: des.js@1.1.0: resolution: {integrity: sha512-r17GxjhUCjSRy8aiJpr8/UadFIzMzJGexI3Nmz4ADi9LYSFx4gTBp80+NaX/YsXWWLhpZ7v/v/ubEc/bCNfKwg==} - detect-libc@2.1.0: - resolution: {integrity: sha512-vEtk+OcP7VBRtQZ1EJ3bdgzSfBjgnEalLTp5zjJrS+2Z1w2KZly4SBdac/WDU3hhsNAZ9E8SC96ME4Ey8MZ7cg==} + detect-libc@2.1.2: + resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==} engines: {node: '>=8'} diffie-hellman@5.0.3: @@ -1515,8 +1592,8 @@ packages: eastasianwidth@0.2.0: resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} - electron-to-chromium@1.5.221: - resolution: {integrity: sha512-/1hFJ39wkW01ogqSyYoA4goOXOtMRy6B+yvA1u42nnsEGtHzIzmk93aPISumVQeblj47JUHLC9coCjUxb1EvtQ==} + electron-to-chromium@1.5.237: + resolution: {integrity: sha512-icUt1NvfhGLar5lSWH3tHNzablaA5js3HVHacQimfP8ViEBOQv+L7DKEuHdbTZ0SKCO1ogTJTIL1Gwk9S6Qvcg==} elliptic@6.6.1: resolution: {integrity: sha512-RaddvvMatK2LJHqFJ+YA4WysVN5Ita9E35botqIYspQ4TkRAlCicdzKOjlyv/1Za5RyTNn7di//eEV0uTAfe3g==} @@ -1556,16 +1633,16 @@ packages: resolution: {integrity: sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==} engines: {node: '>= 0.4'} - es-toolkit@1.39.10: - resolution: {integrity: sha512-E0iGnTtbDhkeczB0T+mxmoVlT4YNweEKBLq7oaU4p11mecdsZpNWOglI4895Vh4usbQ+LsJiuLuI2L0Vdmfm2w==} + es-toolkit@1.40.0: + resolution: {integrity: sha512-8o6w0KFmU0CiIl0/Q/BCEOabF2IJaELM1T2PWj6e8KqzHv1gdx+7JtFnDwOx1kJH/isJ5NwlDG1nCr1HrRF94Q==} esbuild@0.25.1: resolution: {integrity: sha512-BGO5LtrGC7vxnqucAe/rmvKdJllfGaYWdyABvyMoXQlfYMb2bbRuReWR5tEGE//4LcNJj9XrkovTqNYRFZHAMQ==} engines: {node: '>=18'} hasBin: true - esbuild@0.25.10: - resolution: {integrity: sha512-9RiGKvCwaqxO2owP61uQ4BgNborAQskMR6QusfWzQqv7AZOg5oGehdY2pRJMTKuwxd1IDBP4rSbI5lHzU7SMsQ==} + esbuild@0.25.11: + resolution: {integrity: sha512-KohQwyzrKTQmhXDW1PjCv3Tyspn9n5GcY2RTDqeORIdIJY8yKIF7sTSopFmn/wpMPW4rdPXI0UE5LJLuq3bx0Q==} engines: {node: '>=18'} hasBin: true @@ -1585,6 +1662,9 @@ packages: ethereum-cryptography@0.1.3: resolution: {integrity: sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ==} + ethereum-cryptography@2.2.1: + resolution: {integrity: sha512-r/W8lkHSiTLxUxW8Rf3u4HGB0xQweG2RyETjywylKZSzLWoWAijRz8WCuOtJ6wah+avllXBqZuk29HCCvhEIRg==} + ethereumjs-util@7.1.5: resolution: {integrity: sha512-SDl5kKrQAudFBUe5OJM9Ac6WmMyYmXX/6sTmLZ3ffG2eY6ZIGBes3pEDxNN6V72WyOw4CPD5RomKdsa8DAAwLg==} engines: {node: '>=10.0.0'} @@ -1593,6 +1673,10 @@ packages: resolution: {integrity: sha512-CCWV4RESJgRdHIvFciVQFnCHfqyhXWchTPlkfp28Qc53ufs+doi5I/cV2+xeK9+qEo25XCWfP9MiL+WEPAZfdA==} deprecated: 'New package name format for new versions: @ethereumjs/wallet. Please update.' + ethers@6.13.5: + resolution: {integrity: sha512-+knKNieu5EKRThQJWwqaJ10a6HE9sSehGeqWN65//wE7j47ZpFhKAnHB/JJFibwwg61I/koxaPsXbXpD/skNOQ==} + engines: {node: '>=14.0.0'} + event-iterator@2.0.0: resolution: {integrity: sha512-KGft0ldl31BZVV//jj+IAIGCxkvvUkkON+ScH6zfoX+l+omX6001ggyRSpI0Io2Hlro0ThXotswCtfzS8UkIiQ==} @@ -1661,8 +1745,8 @@ packages: fraction.js@4.3.7: resolution: {integrity: sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==} - framer-motion@12.23.15: - resolution: {integrity: sha512-MBxUEHjWr/fRQ2aHg2CgdcjJpHMJ9ttHiPeClHDGiOJOYgmde3OXZUrbWDeeE8yvFrWA62hsPS4+rKQ9OJaoQA==} + framer-motion@12.23.24: + resolution: {integrity: sha512-HMi5HRoRCTou+3fb3h9oTLyJGBxHfW+HnNE25tAXOvVx/IvwMHK0cx7IR4a2ZU6sh3IX1Z+4ts32PcYBOqka8w==} peerDependencies: '@emotion/is-prop-valid': '*' react: ^18.0.0 || ^19.0.0 @@ -1695,6 +1779,10 @@ packages: function-bind@1.1.2: resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} + generator-function@2.0.1: + resolution: {integrity: sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g==} + engines: {node: '>= 0.4'} + generic-names@4.0.0: resolution: {integrity: sha512-ySFolZQfw9FoDb3ed9d80Cm9f0+r7qj+HJkWjeD9RBfpxEVTlVhol+gvaQB/78WbwYfbnNh8nWHHBSlg072y6A==} @@ -1768,13 +1856,14 @@ packages: resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==} engines: {node: '>= 0.4'} - hash-base@2.0.2: - resolution: {integrity: sha512-0TROgQ1/SxE6KmxWSvXHvRj90/Xo1JvZShofnYF+f6ZsGtR4eES7WfrQzPalmyagfKZCXpVnitiRebZulWsbiw==} - hash-base@3.0.5: resolution: {integrity: sha512-vXm0l45VbcHEVlTCzs8M+s0VeYsB2lnlAaThoLKGXr3bE/VWDOelNUnycUPEhKEaXARL2TEFjBOyUiM6+55KBg==} engines: {node: '>= 0.10'} + hash-base@3.1.2: + resolution: {integrity: sha512-Bb33KbowVTIj5s7Ked1OsqHUeCpz//tPwR+E2zJgJKo9Z5XolZ9b6bdUgjmYlwnWhoOQKoTd1TYToZGn5mAYOg==} + engines: {node: '>= 0.8'} + hash.js@1.1.7: resolution: {integrity: sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==} @@ -1841,8 +1930,8 @@ packages: resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} engines: {node: '>=8'} - is-generator-function@1.1.0: - resolution: {integrity: sha512-nPUB5km40q9e8UfN/Zc24eLlzdSf9OfKByBw9CIdw4H1giPMeA0OIJvbchsCu4npfI2QcMVBsGEBHKZ7wLTWmQ==} + is-generator-function@1.1.2: + resolution: {integrity: sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA==} engines: {node: '>= 0.4'} is-glob@4.0.3: @@ -1903,8 +1992,8 @@ packages: jackspeak@3.4.3: resolution: {integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==} - jiti@2.5.1: - resolution: {integrity: sha512-twQoecYPiVA5K/h6SxtORw/Bs3ar+mLUtoPSc7iMXzQzK8d7eJ/R09wmTwAjiamETn1cXYPGfNnu7DMoHgu12w==} + jiti@2.6.1: + resolution: {integrity: sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==} hasBin: true joycon@3.1.1: @@ -2081,8 +2170,8 @@ packages: resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==} engines: {node: '>=16 || 14 >=14.17'} - minizlib@3.0.2: - resolution: {integrity: sha512-oG62iEk+CYt5Xj2YqI5Xi9xWUeZhDI8jjQmC5oThVH5JGCTgIjr7ciJDzC7MBzYd//WvR1OTmP5Q38Q8ShQtVA==} + minizlib@3.1.0: + resolution: {integrity: sha512-KZxYo1BUkWD2TVFLr0MQoM8vUUigWD3LlD83a/75BqC+4qE0Hb1Vo5v1FgcfaNXvfXzr+5EhQ6ing/CaBijTlw==} engines: {node: '>= 18'} mkdirp@0.5.6: @@ -2094,8 +2183,8 @@ packages: engines: {node: '>=10'} hasBin: true - motion-dom@12.23.12: - resolution: {integrity: sha512-RcR4fvMCTESQBD/uKQe49D5RUeDOokkGRmz4ceaJKDBgHYtZtntC/s2vLvY38gqGaytinij/yi3hMcWVcEF5Kw==} + motion-dom@12.23.23: + resolution: {integrity: sha512-n5yolOs0TQQBRUFImrRfs/+6X4p3Q4n1dUEqt/H58Vx7OW6RF+foWEgmTVDhIWJIMXOuNNL0apKH2S16en9eiA==} motion-utils@12.23.6: resolution: {integrity: sha512-eAWoPgr4eFEOFfg2WjIsMoqJTW6Z8MTUCgn/GZ3VRpClWBdnbjryiA3ZSNLyxCTmCQx4RmYX6jX1iWHbenUPNQ==} @@ -2158,8 +2247,8 @@ packages: resolution: {integrity: sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ==} hasBin: true - node-releases@2.0.21: - resolution: {integrity: sha512-5b0pgg78U3hwXkCM8Z9b2FJdPZlr9Psr9V2gQPESdGHqbntyFJKFW4r5TeWGFzafGY3hzs1JC62VEQMbl1JFkw==} + node-releases@2.0.25: + resolution: {integrity: sha512-4auku8B/vw5psvTiiN9j1dAOsXvMoGqJuKJcR+dTdqiXEK20mMTk1UEo3HS16LeGQsVG6+qKTPM9u/qQ2LqATA==} normalize-path@3.0.0: resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} @@ -2191,10 +2280,10 @@ packages: once@1.4.0: resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} - ox@0.9.3: - resolution: {integrity: sha512-KzyJP+fPV4uhuuqrTZyok4DC7vFzi7HLUFiUNEmpbyh59htKWkOC98IONC1zgXJPbHAhQgqs6B0Z6StCGhmQvg==} + ox@0.9.6: + resolution: {integrity: sha512-8SuCbHPvv2eZLYXrNmC0EC12rdzXQLdhnOMlHDW2wiCPLxBrOOJwX5L5E61by+UjTPOryqQiRSnjIKCI+GykKg==} peerDependencies: - typescript: '>=5.4.0' + typescript: ^5.0.0 peerDependenciesMeta: typescript: optional: true @@ -2226,8 +2315,8 @@ packages: package-json-from-dist@1.0.1: resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==} - parse-asn1@5.1.7: - resolution: {integrity: sha512-CTM5kuWR3sx9IFamcl5ErfPl6ea/N8IYwiJ+vpeB2g+1iknv7zBl5uPwbMbRVznRVbrNY6lGuDoE5b30grmbqg==} + parse-asn1@5.1.9: + resolution: {integrity: sha512-fIYNuZ/HastSb80baGOuPRo1O9cf4baWw5WsAp7dBuUzeTD/BoaG8sVTdlPFksBE2lF21dN+A1AnrpIjSWqHHg==} engines: {node: '>= 0.10'} path-exists@4.0.0: @@ -2252,9 +2341,9 @@ packages: resolution: {integrity: sha512-//nshmD55c46FuFw26xV/xFAaB5HF9Xdap7HJBBnrKdAd6/GxDBaNA1870O79+9ueg61cZLSVc+OaFlfmObYVQ==} engines: {node: '>= 14.16'} - pbkdf2@3.1.3: - resolution: {integrity: sha512-wfRLBZ0feWRhCIkoMB6ete7czJcnNnqRpcoWQBLqatqXXmelSRqfdDK4F3u9T2s2cXas/hQJcryI/4lAL+XTlA==} - engines: {node: '>=0.12'} + pbkdf2@3.1.5: + resolution: {integrity: sha512-Q3CG/cYvCO1ye4QKkuH7EXxs3VC/rI1/trd+qX2+PolbaKG0H+bgcZzrTt96mMyRtejk+JMCiLUn3y29W8qmFQ==} + engines: {node: '>= 0.10'} picocolors@1.1.1: resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} @@ -2546,13 +2635,13 @@ packages: randomfill@1.0.4: resolution: {integrity: sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==} - react-dom@19.1.1: - resolution: {integrity: sha512-Dlq/5LAZgF0Gaz6yiqZCf6VCcZs1ghAJyrsu84Q/GT0gV+mCxbfmKNoGRKBYMJ8IEdGPqu49YWXD02GCknEDkw==} + react-dom@19.2.0: + resolution: {integrity: sha512-UlbRu4cAiGaIewkPyiRGJk0imDN2T3JjieT6spoL2UeSf5od4n5LB/mQ4ejmxhCFT1tYe8IvaFulzynWovsEFQ==} peerDependencies: - react: ^19.1.1 + react: ^19.2.0 - react@19.1.1: - resolution: {integrity: sha512-w8nqGImo45dmMIfljjMwOGtbmC/mk4CMYhWIicdSflH91J9TyCyczcPFXJzrZ/ZXcgGRFeP6BU0BEJTw6tZdfQ==} + react@19.2.0: + resolution: {integrity: sha512-tmbWg6W31tQLeB5cdIBOicJDJRR2KzXsV7uSK9iNfLWQ5bIZfxuPEHp7M8wiHyHnn0DD1i7w3Zmin0FtkrwoCQ==} engines: {node: '>=0.10.0'} read-cache@1.0.0: @@ -2572,6 +2661,9 @@ packages: readonly-date@1.0.0: resolution: {integrity: sha512-tMKIV7hlk0h4mO3JTmmVuIlJVXjKk3Sep9Bf5OH0O+758ruuVkUy2J9SttDLm91IEX/WHlXPSpxMGjPj4beMIQ==} + regenerator-runtime@0.14.1: + resolution: {integrity: sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==} + resolve-from@5.0.0: resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==} engines: {node: '>=8'} @@ -2585,11 +2677,9 @@ packages: resolution: {integrity: sha512-l0OE8wL34P4nJH/H2ffoaniAokM2qSmrtXHmlpvYr5AVVX8msAyW0l8NVJFDxlSK4u3Uh/f41cQheDVdnYijwQ==} hasBin: true - ripemd160@2.0.1: - resolution: {integrity: sha512-J7f4wutN8mdbV08MJnXibYpCOPHR+yzy+iQ/AsjMv2j8cLavQ8VGagDFUwwTAdF8FmRKVeNpbTTEwNHCW1g94w==} - - ripemd160@2.0.2: - resolution: {integrity: sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==} + ripemd160@2.0.3: + resolution: {integrity: sha512-5Di9UC0+8h1L6ZD2d7awM7E/T4uA1fJRlx6zk/NvdCCVEoAnFqvHmCuNeIKoCeIixBX/q8uM+6ycDvF8woqosA==} + engines: {node: '>= 0.8'} rlp@2.2.7: resolution: {integrity: sha512-d5gdPmgQ0Z+AklL2NVXr/IoSjNZFfTVvQWzL/AM2AOcSzYP2xjlb0AC8YyCLc41MSNf6P6QVtjgPdmVtzb+4lQ==} @@ -2599,8 +2689,8 @@ packages: resolution: {integrity: sha512-UgnEsfciXSPpASuOelix7m4DrmyQgiaWBnvI0TM4GxuDh5FkqW8E5hu57bCxXB90VvR1WNfLV80yEDN18UogSA==} engines: {node: '>=16'} peerDependencies: - rollup: ^3.29.4 || ^4 - typescript: ^4.5 || ^5.0 + rollup: ^4.0.0 + typescript: ^5.0.0 rollup-plugin-postcss@4.0.2: resolution: {integrity: sha512-05EaY6zvZdmvPUDi3uCcAQoESDcYnv8ogJJQRp6V5kZ6J6P7uAVJlrTZcaaA20wTH527YTnKfkAoPxWI/jPp4w==} @@ -2611,14 +2701,14 @@ packages: rollup-plugin-typescript2@0.36.0: resolution: {integrity: sha512-NB2CSQDxSe9+Oe2ahZbf+B4bh7pHwjV5L+RSYpCu7Q5ROuN94F9b6ioWwKfz3ueL3KTtmX4o2MUH2cgHDIEUsw==} peerDependencies: - rollup: '>=1.26.3' - typescript: '>=2.4.0' + rollup: ^4.0.0 + typescript: ^5.0.0 rollup-pluginutils@2.8.2: resolution: {integrity: sha512-EEp9NhnUkwY8aif6bxgovPHMoMoNr2FulJziTndpt5H9RdwC47GSGuII9XxpSdzVGM0GWrNPHV6ie1LTNJPaLQ==} - rollup@4.50.2: - resolution: {integrity: sha512-BgLRGy7tNS9H66aIMASq1qSYbAAJV6Z6WR4QYTvj5FgF15rZ/ympT1uixHXwzbZUBDbkvqUI1KR0fH1FhMaQ9w==} + rollup@4.52.4: + resolution: {integrity: sha512-CLEVl+MnPAiKh5pl4dEWSyMTpuflgNQiLGhMv8ezD5W/qP8AKvmYpCOKRRNOh7oRKnauBZ4SyeYkMS+1VSyKwQ==} engines: {node: '>=18.0.0', npm: '>=8.0.0'} hasBin: true @@ -2635,8 +2725,8 @@ packages: resolution: {integrity: sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==} engines: {node: '>= 0.4'} - scheduler@0.26.0: - resolution: {integrity: sha512-NlHwttCI/l5gCPR3D1nNXtWABUmBwvZpEQiD4IXSbIDq8BzLIK/7Ir5gTFSGZDUu37K5cMNp0hFtzO38sC7gWA==} + scheduler@0.27.0: + resolution: {integrity: sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==} scrypt-js@3.0.1: resolution: {integrity: sha512-cdwTTnqPu0Hyvf5in5asVdZocVDTNRmR7XEcJuIzMjJeSHybHl7vpB66AzwTaIg6CLSbtjcxc8fqcySfnTkccA==} @@ -2649,8 +2739,13 @@ packages: resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} hasBin: true - semver@7.7.2: - resolution: {integrity: sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==} + semver@7.7.1: + resolution: {integrity: sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==} + engines: {node: '>=10'} + hasBin: true + + semver@7.7.3: + resolution: {integrity: sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==} engines: {node: '>=10'} hasBin: true @@ -2696,8 +2791,8 @@ packages: stackback@0.0.2: resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==} - std-env@3.9.0: - resolution: {integrity: sha512-UGvjygr6F6tpH7o2qyqR6QYpwraIjKSdtzyBdyytFOHmPZY917kwdwLG0RbOjWOnKmnm3PeHjaoLLMie7kPLQw==} + std-env@3.10.0: + resolution: {integrity: sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==} stream-browserify@3.0.0: resolution: {integrity: sha512-H73RAHsVBapbim0tU2JwwOiXUj+fikfiaoYAKHF3VJfA0pe2BCzkhAHBlLG6REzE+2WNZcxOXjK7lkso+9euLA==} @@ -2759,12 +2854,12 @@ packages: tailwindcss@4.1.10: resolution: {integrity: sha512-P3nr6WkvKV/ONsTzj6Gb57sWPMX29EPNPopo7+FcpkQaNsrNpZ1pv8QmrYI2RqEKD7mlGqLnGovlcYnBK0IqUA==} - tapable@2.2.3: - resolution: {integrity: sha512-ZL6DDuAlRlLGghwcfmSn9sK3Hr6ArtyudlSAiCqQ6IfE+b+HHbydbYDIG15IfS5do+7XQQBdBiubF/cV2dnDzg==} + tapable@2.3.0: + resolution: {integrity: sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg==} engines: {node: '>=6'} - tar@7.4.3: - resolution: {integrity: sha512-5S7Va8hKfV7W5U6g3aYxXmlPoZVAwUMy9AOKyF2fVuZa2UD3qZjg578OrLRt8PcNN1PleVaL/5/yYATNL0ICUw==} + tar@7.5.1: + resolution: {integrity: sha512-nlGpxf+hv0v7GkWBK2V9spgactGOp0qvfWRxUMjqHyzrt3SgwE48DIv/FhqPHJYLHpgW1opq3nERbz5Anq7n1g==} engines: {node: '>=18'} tiny-case@1.0.3: @@ -2792,8 +2887,8 @@ packages: resolution: {integrity: sha512-n1cw8k1k0x4pgA2+9XrOkFydTerNcJ1zWCO5Nn9scWHTD+5tp8dghT2x1uduQePZTZgd3Tupf+x9BxJjeJi77Q==} engines: {node: '>=14.0.0'} - to-buffer@1.2.1: - resolution: {integrity: sha512-tB82LpAIWjhLYbqjx3X4zEeHN6M8CiuOEy2JY8SEQVdYRe3CCHOFaqrBW1doLDrfpWhplcW7BL+bO3/6S3pcDQ==} + to-buffer@1.2.2: + resolution: {integrity: sha512-db0E3UJjcFhpDhAF4tLo03oli3pwl3dbnzXOUIlRKrp+ldk/VUxzpWYZENsw2SZiuBjHAk7DfB0VU7NKdpb6sw==} engines: {node: '>= 0.4'} to-regex-range@5.0.1: @@ -2809,6 +2904,12 @@ packages: tr46@0.0.3: resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} + tronweb@6.0.4: + resolution: {integrity: sha512-+9Nc7H4FYVh2DcOnQG93WLm3UdlHSf9W+GXkfrXI77oLjTB1cptROJDKRSSxQBiOAyjjAJOOTuYDzlAkaLT85w==} + + tslib@2.7.0: + resolution: {integrity: sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==} + tslib@2.8.1: resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} @@ -2827,8 +2928,8 @@ packages: typedarray-to-buffer@3.1.5: resolution: {integrity: sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==} - typescript@5.9.2: - resolution: {integrity: sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A==} + typescript@5.9.3: + resolution: {integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==} engines: {node: '>=14.17'} hasBin: true @@ -2840,9 +2941,15 @@ packages: uint8arrays@5.1.0: resolution: {integrity: sha512-vA6nFepEmlSKkMBnLBaUMVvAC4G3CTmO58C12y4sq6WPDOR7mOFYOi7GlrQ4djeSbP6JG9Pv9tJDM97PedRSww==} + undici-types@6.19.8: + resolution: {integrity: sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==} + undici-types@6.21.0: resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==} + undici-types@7.14.0: + resolution: {integrity: sha512-QQiYxHuyZ9gQUIrmPo3IA+hUl4KYk8uSA7cHrcKd/l3p1OTpZcM0Tbp9x7FAtXdAYhlasd60ncPpgu6ihG6TOA==} + universalify@2.0.1: resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==} engines: {node: '>= 10.0.0'} @@ -2866,10 +2973,14 @@ packages: resolution: {integrity: sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==} hasBin: true - viem@2.37.6: - resolution: {integrity: sha512-b+1IozQ8TciVQNdQUkOH5xtFR0z7ZxR8pyloENi/a+RA408lv4LoX12ofwoiT3ip0VRhO5ni1em//X0jn/eW0g==} + validator@13.12.0: + resolution: {integrity: sha512-c1Q0mCiPlgdTVVVIJIrBuxNicYE+t/7oKeI9MWLj3fh/uq2Pxh/3eeWbVZ4OcGW1TUf53At0njHw5SMdA3tmMg==} + engines: {node: '>= 0.10'} + + viem@2.38.3: + resolution: {integrity: sha512-By2TutLv07iNHHtWqHHzjGipevYsfGqT7KQbGEmqLco1qTJxKnvBbSviqiu6/v/9REV6Q/FpmIxf2Z7/l5AbcQ==} peerDependencies: - typescript: '>=5.0.4' + typescript: ^5.0.0 peerDependenciesMeta: typescript: optional: true @@ -2879,8 +2990,8 @@ packages: engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} hasBin: true - vite@6.3.6: - resolution: {integrity: sha512-0msEVHJEScQbhkbVTb/4iHZdJ6SXp/AvxL2sjwYQFfBqleHtnCqv1J3sa9zbWz/6kW1m9Tfzn92vW+kZ1WV6QA==} + vite@6.4.0: + resolution: {integrity: sha512-oLnWs9Hak/LOlKjeSpOwD6JMks8BeICEdYMJBf6P4Lac/pO9tKiv/XhXnAM7nNfSkZahjlCZu9sS50zL8fSnsw==} engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} hasBin: true peerDependencies: @@ -2993,6 +3104,18 @@ packages: utf-8-validate: optional: true + ws@8.17.1: + resolution: {integrity: sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==} + engines: {node: '>=10.0.0'} + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: '>=5.0.2' + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + ws@8.18.3: resolution: {integrity: sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==} engines: {node: '>=10.0.0'} @@ -3021,7 +3144,9 @@ packages: snapshots: - '@adraffy/ens-normalize@1.11.0': {} + '@adraffy/ens-normalize@1.10.1': {} + + '@adraffy/ens-normalize@1.11.1': {} '@alloc/quick-lru@5.2.0': {} @@ -3030,21 +3155,21 @@ snapshots: '@jridgewell/gen-mapping': 0.3.13 '@jridgewell/trace-mapping': 0.3.31 - '@arcana/ca-common@1.0.1-alpha.6(@cosmjs/proto-signing@0.34.0)(@cosmjs/stargate@0.34.0)(axios@1.12.2)(decimal.js@10.6.0)(fuels@0.101.1(vitest@3.0.9(@types/node@20.19.17)(jiti@2.5.1)(lightningcss@1.30.1)))(google-protobuf@3.21.4)(long@5.3.2)(msgpackr@1.11.5)(viem@2.37.6(typescript@5.9.2))': + '@avail-project/ca-common@1.0.0-beta.7(@cosmjs/proto-signing@0.34.0)(@cosmjs/stargate@0.34.0)(axios@1.12.2)(decimal.js@10.6.0)(fuels@0.101.1(vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2)))(google-protobuf@3.21.4)(long@5.3.2)(msgpackr@1.11.5)(viem@2.38.3(typescript@5.9.3))': dependencies: - '@bufbuild/protobuf': 2.8.0 + '@bufbuild/protobuf': 2.9.0 '@cosmjs/proto-signing': 0.34.0 '@cosmjs/stargate': 0.34.0 '@improbable-eng/grpc-web': 0.15.0(google-protobuf@3.21.4) axios: 1.12.2 browser-headers: 0.4.1 decimal.js: 10.6.0 - es-toolkit: 1.39.10 - fuels: 0.101.1(vitest@3.0.9(@types/node@20.19.17)(jiti@2.5.1)(lightningcss@1.30.1)) + es-toolkit: 1.40.0 + fuels: 0.101.1(vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2)) long: 5.3.2 msgpackr: 1.11.5 tslib: 2.8.1 - viem: 2.37.6(typescript@5.9.2) + viem: 2.38.3(typescript@5.9.3) transitivePeerDependencies: - google-protobuf @@ -3058,7 +3183,11 @@ snapshots: '@babel/helper-validator-identifier@7.27.1': optional: true - '@bufbuild/protobuf@2.8.0': {} + '@babel/runtime@7.26.10': + dependencies: + regenerator-runtime: 0.14.1 + + '@bufbuild/protobuf@2.9.0': {} '@cosmjs/amino@0.34.0': dependencies: @@ -3160,171 +3289,171 @@ snapshots: '@esbuild/aix-ppc64@0.25.1': optional: true - '@esbuild/aix-ppc64@0.25.10': + '@esbuild/aix-ppc64@0.25.11': optional: true '@esbuild/android-arm64@0.25.1': optional: true - '@esbuild/android-arm64@0.25.10': + '@esbuild/android-arm64@0.25.11': optional: true '@esbuild/android-arm@0.25.1': optional: true - '@esbuild/android-arm@0.25.10': + '@esbuild/android-arm@0.25.11': optional: true '@esbuild/android-x64@0.25.1': optional: true - '@esbuild/android-x64@0.25.10': + '@esbuild/android-x64@0.25.11': optional: true '@esbuild/darwin-arm64@0.25.1': optional: true - '@esbuild/darwin-arm64@0.25.10': + '@esbuild/darwin-arm64@0.25.11': optional: true '@esbuild/darwin-x64@0.25.1': optional: true - '@esbuild/darwin-x64@0.25.10': + '@esbuild/darwin-x64@0.25.11': optional: true '@esbuild/freebsd-arm64@0.25.1': optional: true - '@esbuild/freebsd-arm64@0.25.10': + '@esbuild/freebsd-arm64@0.25.11': optional: true '@esbuild/freebsd-x64@0.25.1': optional: true - '@esbuild/freebsd-x64@0.25.10': + '@esbuild/freebsd-x64@0.25.11': optional: true '@esbuild/linux-arm64@0.25.1': optional: true - '@esbuild/linux-arm64@0.25.10': + '@esbuild/linux-arm64@0.25.11': optional: true '@esbuild/linux-arm@0.25.1': optional: true - '@esbuild/linux-arm@0.25.10': + '@esbuild/linux-arm@0.25.11': optional: true '@esbuild/linux-ia32@0.25.1': optional: true - '@esbuild/linux-ia32@0.25.10': + '@esbuild/linux-ia32@0.25.11': optional: true '@esbuild/linux-loong64@0.25.1': optional: true - '@esbuild/linux-loong64@0.25.10': + '@esbuild/linux-loong64@0.25.11': optional: true '@esbuild/linux-mips64el@0.25.1': optional: true - '@esbuild/linux-mips64el@0.25.10': + '@esbuild/linux-mips64el@0.25.11': optional: true '@esbuild/linux-ppc64@0.25.1': optional: true - '@esbuild/linux-ppc64@0.25.10': + '@esbuild/linux-ppc64@0.25.11': optional: true '@esbuild/linux-riscv64@0.25.1': optional: true - '@esbuild/linux-riscv64@0.25.10': + '@esbuild/linux-riscv64@0.25.11': optional: true '@esbuild/linux-s390x@0.25.1': optional: true - '@esbuild/linux-s390x@0.25.10': + '@esbuild/linux-s390x@0.25.11': optional: true '@esbuild/linux-x64@0.25.1': optional: true - '@esbuild/linux-x64@0.25.10': + '@esbuild/linux-x64@0.25.11': optional: true '@esbuild/netbsd-arm64@0.25.1': optional: true - '@esbuild/netbsd-arm64@0.25.10': + '@esbuild/netbsd-arm64@0.25.11': optional: true '@esbuild/netbsd-x64@0.25.1': optional: true - '@esbuild/netbsd-x64@0.25.10': + '@esbuild/netbsd-x64@0.25.11': optional: true '@esbuild/openbsd-arm64@0.25.1': optional: true - '@esbuild/openbsd-arm64@0.25.10': + '@esbuild/openbsd-arm64@0.25.11': optional: true '@esbuild/openbsd-x64@0.25.1': optional: true - '@esbuild/openbsd-x64@0.25.10': + '@esbuild/openbsd-x64@0.25.11': optional: true - '@esbuild/openharmony-arm64@0.25.10': + '@esbuild/openharmony-arm64@0.25.11': optional: true '@esbuild/sunos-x64@0.25.1': optional: true - '@esbuild/sunos-x64@0.25.10': + '@esbuild/sunos-x64@0.25.11': optional: true '@esbuild/win32-arm64@0.25.1': optional: true - '@esbuild/win32-arm64@0.25.10': + '@esbuild/win32-arm64@0.25.11': optional: true '@esbuild/win32-ia32@0.25.1': optional: true - '@esbuild/win32-ia32@0.25.10': + '@esbuild/win32-ia32@0.25.11': optional: true '@esbuild/win32-x64@0.25.1': optional: true - '@esbuild/win32-x64@0.25.10': + '@esbuild/win32-x64@0.25.11': optional: true - '@fuel-ts/abi-coder@0.101.1(vitest@3.0.9(@types/node@20.19.17)(jiti@2.5.1)(lightningcss@1.30.1))': + '@fuel-ts/abi-coder@0.101.1(vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2))': dependencies: - '@fuel-ts/crypto': 0.101.1(vitest@3.0.9(@types/node@20.19.17)(jiti@2.5.1)(lightningcss@1.30.1)) + '@fuel-ts/crypto': 0.101.1(vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2)) '@fuel-ts/errors': 0.101.1 - '@fuel-ts/hasher': 0.101.1(vitest@3.0.9(@types/node@20.19.17)(jiti@2.5.1)(lightningcss@1.30.1)) + '@fuel-ts/hasher': 0.101.1(vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2)) '@fuel-ts/math': 0.101.1 - '@fuel-ts/utils': 0.101.1(vitest@3.0.9(@types/node@20.19.17)(jiti@2.5.1)(lightningcss@1.30.1)) + '@fuel-ts/utils': 0.101.1(vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2)) type-fest: 4.34.1 transitivePeerDependencies: - vitest - '@fuel-ts/abi-typegen@0.101.1(vitest@3.0.9(@types/node@20.19.17)(jiti@2.5.1)(lightningcss@1.30.1))': + '@fuel-ts/abi-typegen@0.101.1(vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2))': dependencies: '@fuel-ts/errors': 0.101.1 - '@fuel-ts/utils': 0.101.1(vitest@3.0.9(@types/node@20.19.17)(jiti@2.5.1)(lightningcss@1.30.1)) + '@fuel-ts/utils': 0.101.1(vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2)) '@fuel-ts/versions': 0.101.1 commander: 13.1.0 glob: 10.4.5 @@ -3335,17 +3464,17 @@ snapshots: transitivePeerDependencies: - vitest - '@fuel-ts/account@0.101.1(vitest@3.0.9(@types/node@20.19.17)(jiti@2.5.1)(lightningcss@1.30.1))': + '@fuel-ts/account@0.101.1(vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2))': dependencies: - '@fuel-ts/abi-coder': 0.101.1(vitest@3.0.9(@types/node@20.19.17)(jiti@2.5.1)(lightningcss@1.30.1)) - '@fuel-ts/address': 0.101.1(vitest@3.0.9(@types/node@20.19.17)(jiti@2.5.1)(lightningcss@1.30.1)) - '@fuel-ts/crypto': 0.101.1(vitest@3.0.9(@types/node@20.19.17)(jiti@2.5.1)(lightningcss@1.30.1)) + '@fuel-ts/abi-coder': 0.101.1(vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2)) + '@fuel-ts/address': 0.101.1(vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2)) + '@fuel-ts/crypto': 0.101.1(vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2)) '@fuel-ts/errors': 0.101.1 - '@fuel-ts/hasher': 0.101.1(vitest@3.0.9(@types/node@20.19.17)(jiti@2.5.1)(lightningcss@1.30.1)) + '@fuel-ts/hasher': 0.101.1(vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2)) '@fuel-ts/math': 0.101.1 - '@fuel-ts/merkle': 0.101.1(vitest@3.0.9(@types/node@20.19.17)(jiti@2.5.1)(lightningcss@1.30.1)) - '@fuel-ts/transactions': 0.101.1(vitest@3.0.9(@types/node@20.19.17)(jiti@2.5.1)(lightningcss@1.30.1)) - '@fuel-ts/utils': 0.101.1(vitest@3.0.9(@types/node@20.19.17)(jiti@2.5.1)(lightningcss@1.30.1)) + '@fuel-ts/merkle': 0.101.1(vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2)) + '@fuel-ts/transactions': 0.101.1(vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2)) + '@fuel-ts/utils': 0.101.1(vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2)) '@fuel-ts/versions': 0.101.1 '@fuels/vm-asm': 0.60.2 '@noble/curves': 1.8.1 @@ -3358,37 +3487,37 @@ snapshots: - encoding - vitest - '@fuel-ts/address@0.101.1(vitest@3.0.9(@types/node@20.19.17)(jiti@2.5.1)(lightningcss@1.30.1))': + '@fuel-ts/address@0.101.1(vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2))': dependencies: - '@fuel-ts/crypto': 0.101.1(vitest@3.0.9(@types/node@20.19.17)(jiti@2.5.1)(lightningcss@1.30.1)) + '@fuel-ts/crypto': 0.101.1(vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2)) '@fuel-ts/errors': 0.101.1 - '@fuel-ts/utils': 0.101.1(vitest@3.0.9(@types/node@20.19.17)(jiti@2.5.1)(lightningcss@1.30.1)) + '@fuel-ts/utils': 0.101.1(vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2)) '@noble/hashes': 1.7.1 transitivePeerDependencies: - vitest - '@fuel-ts/contract@0.101.1(vitest@3.0.9(@types/node@20.19.17)(jiti@2.5.1)(lightningcss@1.30.1))': + '@fuel-ts/contract@0.101.1(vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2))': dependencies: - '@fuel-ts/abi-coder': 0.101.1(vitest@3.0.9(@types/node@20.19.17)(jiti@2.5.1)(lightningcss@1.30.1)) - '@fuel-ts/account': 0.101.1(vitest@3.0.9(@types/node@20.19.17)(jiti@2.5.1)(lightningcss@1.30.1)) - '@fuel-ts/crypto': 0.101.1(vitest@3.0.9(@types/node@20.19.17)(jiti@2.5.1)(lightningcss@1.30.1)) + '@fuel-ts/abi-coder': 0.101.1(vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2)) + '@fuel-ts/account': 0.101.1(vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2)) + '@fuel-ts/crypto': 0.101.1(vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2)) '@fuel-ts/errors': 0.101.1 - '@fuel-ts/hasher': 0.101.1(vitest@3.0.9(@types/node@20.19.17)(jiti@2.5.1)(lightningcss@1.30.1)) + '@fuel-ts/hasher': 0.101.1(vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2)) '@fuel-ts/math': 0.101.1 - '@fuel-ts/merkle': 0.101.1(vitest@3.0.9(@types/node@20.19.17)(jiti@2.5.1)(lightningcss@1.30.1)) - '@fuel-ts/program': 0.101.1(vitest@3.0.9(@types/node@20.19.17)(jiti@2.5.1)(lightningcss@1.30.1)) - '@fuel-ts/transactions': 0.101.1(vitest@3.0.9(@types/node@20.19.17)(jiti@2.5.1)(lightningcss@1.30.1)) - '@fuel-ts/utils': 0.101.1(vitest@3.0.9(@types/node@20.19.17)(jiti@2.5.1)(lightningcss@1.30.1)) + '@fuel-ts/merkle': 0.101.1(vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2)) + '@fuel-ts/program': 0.101.1(vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2)) + '@fuel-ts/transactions': 0.101.1(vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2)) + '@fuel-ts/utils': 0.101.1(vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2)) '@fuels/vm-asm': 0.60.2 ramda: 0.30.1 transitivePeerDependencies: - encoding - vitest - '@fuel-ts/crypto@0.101.1(vitest@3.0.9(@types/node@20.19.17)(jiti@2.5.1)(lightningcss@1.30.1))': + '@fuel-ts/crypto@0.101.1(vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2))': dependencies: '@fuel-ts/errors': 0.101.1 - '@fuel-ts/utils': 0.101.1(vitest@3.0.9(@types/node@20.19.17)(jiti@2.5.1)(lightningcss@1.30.1)) + '@fuel-ts/utils': 0.101.1(vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2)) '@noble/hashes': 1.7.1 transitivePeerDependencies: - vitest @@ -3397,10 +3526,10 @@ snapshots: dependencies: '@fuel-ts/versions': 0.101.1 - '@fuel-ts/hasher@0.101.1(vitest@3.0.9(@types/node@20.19.17)(jiti@2.5.1)(lightningcss@1.30.1))': + '@fuel-ts/hasher@0.101.1(vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2))': dependencies: - '@fuel-ts/crypto': 0.101.1(vitest@3.0.9(@types/node@20.19.17)(jiti@2.5.1)(lightningcss@1.30.1)) - '@fuel-ts/utils': 0.101.1(vitest@3.0.9(@types/node@20.19.17)(jiti@2.5.1)(lightningcss@1.30.1)) + '@fuel-ts/crypto': 0.101.1(vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2)) + '@fuel-ts/utils': 0.101.1(vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2)) '@noble/hashes': 1.7.1 transitivePeerDependencies: - vitest @@ -3411,73 +3540,73 @@ snapshots: '@types/bn.js': 5.1.6 bn.js: 5.2.1 - '@fuel-ts/merkle@0.101.1(vitest@3.0.9(@types/node@20.19.17)(jiti@2.5.1)(lightningcss@1.30.1))': + '@fuel-ts/merkle@0.101.1(vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2))': dependencies: - '@fuel-ts/hasher': 0.101.1(vitest@3.0.9(@types/node@20.19.17)(jiti@2.5.1)(lightningcss@1.30.1)) + '@fuel-ts/hasher': 0.101.1(vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2)) '@fuel-ts/math': 0.101.1 transitivePeerDependencies: - vitest - '@fuel-ts/program@0.101.1(vitest@3.0.9(@types/node@20.19.17)(jiti@2.5.1)(lightningcss@1.30.1))': + '@fuel-ts/program@0.101.1(vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2))': dependencies: - '@fuel-ts/abi-coder': 0.101.1(vitest@3.0.9(@types/node@20.19.17)(jiti@2.5.1)(lightningcss@1.30.1)) - '@fuel-ts/account': 0.101.1(vitest@3.0.9(@types/node@20.19.17)(jiti@2.5.1)(lightningcss@1.30.1)) - '@fuel-ts/address': 0.101.1(vitest@3.0.9(@types/node@20.19.17)(jiti@2.5.1)(lightningcss@1.30.1)) + '@fuel-ts/abi-coder': 0.101.1(vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2)) + '@fuel-ts/account': 0.101.1(vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2)) + '@fuel-ts/address': 0.101.1(vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2)) '@fuel-ts/errors': 0.101.1 '@fuel-ts/math': 0.101.1 - '@fuel-ts/transactions': 0.101.1(vitest@3.0.9(@types/node@20.19.17)(jiti@2.5.1)(lightningcss@1.30.1)) - '@fuel-ts/utils': 0.101.1(vitest@3.0.9(@types/node@20.19.17)(jiti@2.5.1)(lightningcss@1.30.1)) + '@fuel-ts/transactions': 0.101.1(vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2)) + '@fuel-ts/utils': 0.101.1(vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2)) '@fuels/vm-asm': 0.60.2 ramda: 0.30.1 transitivePeerDependencies: - encoding - vitest - '@fuel-ts/recipes@0.101.1(vitest@3.0.9(@types/node@20.19.17)(jiti@2.5.1)(lightningcss@1.30.1))': + '@fuel-ts/recipes@0.101.1(vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2))': dependencies: - '@fuel-ts/abi-coder': 0.101.1(vitest@3.0.9(@types/node@20.19.17)(jiti@2.5.1)(lightningcss@1.30.1)) - '@fuel-ts/abi-typegen': 0.101.1(vitest@3.0.9(@types/node@20.19.17)(jiti@2.5.1)(lightningcss@1.30.1)) - '@fuel-ts/account': 0.101.1(vitest@3.0.9(@types/node@20.19.17)(jiti@2.5.1)(lightningcss@1.30.1)) - '@fuel-ts/address': 0.101.1(vitest@3.0.9(@types/node@20.19.17)(jiti@2.5.1)(lightningcss@1.30.1)) - '@fuel-ts/contract': 0.101.1(vitest@3.0.9(@types/node@20.19.17)(jiti@2.5.1)(lightningcss@1.30.1)) - '@fuel-ts/program': 0.101.1(vitest@3.0.9(@types/node@20.19.17)(jiti@2.5.1)(lightningcss@1.30.1)) - '@fuel-ts/transactions': 0.101.1(vitest@3.0.9(@types/node@20.19.17)(jiti@2.5.1)(lightningcss@1.30.1)) - '@fuel-ts/utils': 0.101.1(vitest@3.0.9(@types/node@20.19.17)(jiti@2.5.1)(lightningcss@1.30.1)) + '@fuel-ts/abi-coder': 0.101.1(vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2)) + '@fuel-ts/abi-typegen': 0.101.1(vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2)) + '@fuel-ts/account': 0.101.1(vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2)) + '@fuel-ts/address': 0.101.1(vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2)) + '@fuel-ts/contract': 0.101.1(vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2)) + '@fuel-ts/program': 0.101.1(vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2)) + '@fuel-ts/transactions': 0.101.1(vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2)) + '@fuel-ts/utils': 0.101.1(vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2)) transitivePeerDependencies: - encoding - vitest - '@fuel-ts/script@0.101.1(vitest@3.0.9(@types/node@20.19.17)(jiti@2.5.1)(lightningcss@1.30.1))': + '@fuel-ts/script@0.101.1(vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2))': dependencies: - '@fuel-ts/abi-coder': 0.101.1(vitest@3.0.9(@types/node@20.19.17)(jiti@2.5.1)(lightningcss@1.30.1)) - '@fuel-ts/account': 0.101.1(vitest@3.0.9(@types/node@20.19.17)(jiti@2.5.1)(lightningcss@1.30.1)) + '@fuel-ts/abi-coder': 0.101.1(vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2)) + '@fuel-ts/account': 0.101.1(vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2)) '@fuel-ts/errors': 0.101.1 '@fuel-ts/math': 0.101.1 - '@fuel-ts/program': 0.101.1(vitest@3.0.9(@types/node@20.19.17)(jiti@2.5.1)(lightningcss@1.30.1)) - '@fuel-ts/transactions': 0.101.1(vitest@3.0.9(@types/node@20.19.17)(jiti@2.5.1)(lightningcss@1.30.1)) - '@fuel-ts/utils': 0.101.1(vitest@3.0.9(@types/node@20.19.17)(jiti@2.5.1)(lightningcss@1.30.1)) + '@fuel-ts/program': 0.101.1(vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2)) + '@fuel-ts/transactions': 0.101.1(vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2)) + '@fuel-ts/utils': 0.101.1(vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2)) transitivePeerDependencies: - encoding - vitest - '@fuel-ts/transactions@0.101.1(vitest@3.0.9(@types/node@20.19.17)(jiti@2.5.1)(lightningcss@1.30.1))': + '@fuel-ts/transactions@0.101.1(vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2))': dependencies: - '@fuel-ts/abi-coder': 0.101.1(vitest@3.0.9(@types/node@20.19.17)(jiti@2.5.1)(lightningcss@1.30.1)) - '@fuel-ts/address': 0.101.1(vitest@3.0.9(@types/node@20.19.17)(jiti@2.5.1)(lightningcss@1.30.1)) + '@fuel-ts/abi-coder': 0.101.1(vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2)) + '@fuel-ts/address': 0.101.1(vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2)) '@fuel-ts/errors': 0.101.1 - '@fuel-ts/hasher': 0.101.1(vitest@3.0.9(@types/node@20.19.17)(jiti@2.5.1)(lightningcss@1.30.1)) + '@fuel-ts/hasher': 0.101.1(vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2)) '@fuel-ts/math': 0.101.1 - '@fuel-ts/utils': 0.101.1(vitest@3.0.9(@types/node@20.19.17)(jiti@2.5.1)(lightningcss@1.30.1)) + '@fuel-ts/utils': 0.101.1(vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2)) transitivePeerDependencies: - vitest - '@fuel-ts/utils@0.101.1(vitest@3.0.9(@types/node@20.19.17)(jiti@2.5.1)(lightningcss@1.30.1))': + '@fuel-ts/utils@0.101.1(vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2))': dependencies: '@fuel-ts/errors': 0.101.1 '@fuel-ts/math': 0.101.1 '@fuel-ts/versions': 0.101.1 fflate: 0.8.2 - vitest: 3.0.9(@types/node@20.19.17)(jiti@2.5.1)(lightningcss@1.30.1) + vitest: 3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2) '@fuel-ts/versions@0.101.1': dependencies: @@ -3522,10 +3651,10 @@ snapshots: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.5.5 - '@lottiefiles/dotlottie-react@0.14.2(react@19.1.1)': + '@lottiefiles/dotlottie-react@0.14.2(react@19.2.0)': dependencies: '@lottiefiles/dotlottie-web': 0.47.0 - react: 19.1.1 + react: 19.2.0 '@lottiefiles/dotlottie-web@0.47.0': {} @@ -3551,6 +3680,14 @@ snapshots: '@noble/ciphers@1.3.0': {} + '@noble/curves@1.2.0': + dependencies: + '@noble/hashes': 1.3.2 + + '@noble/curves@1.4.2': + dependencies: + '@noble/hashes': 1.4.0 + '@noble/curves@1.8.1': dependencies: '@noble/hashes': 1.7.1 @@ -3563,6 +3700,10 @@ snapshots: dependencies: '@noble/hashes': 1.8.0 + '@noble/hashes@1.3.2': {} + + '@noble/hashes@1.4.0': {} + '@noble/hashes@1.7.1': {} '@noble/hashes@1.8.0': {} @@ -3570,44 +3711,44 @@ snapshots: '@pkgjs/parseargs@0.11.0': optional: true - '@rollup/plugin-alias@5.1.1(rollup@4.50.2)': + '@rollup/plugin-alias@5.1.1(rollup@4.52.4)': optionalDependencies: - rollup: 4.50.2 + rollup: 4.52.4 - '@rollup/plugin-commonjs@25.0.8(rollup@4.50.2)': + '@rollup/plugin-commonjs@25.0.8(rollup@4.52.4)': dependencies: - '@rollup/pluginutils': 5.3.0(rollup@4.50.2) + '@rollup/pluginutils': 5.3.0(rollup@4.52.4) commondir: 1.0.1 estree-walker: 2.0.2 glob: 8.1.0 is-reference: 1.2.1 magic-string: 0.30.19 optionalDependencies: - rollup: 4.50.2 + rollup: 4.52.4 - '@rollup/plugin-json@6.1.0(rollup@4.50.2)': + '@rollup/plugin-json@6.1.0(rollup@4.52.4)': dependencies: - '@rollup/pluginutils': 5.3.0(rollup@4.50.2) + '@rollup/pluginutils': 5.3.0(rollup@4.52.4) optionalDependencies: - rollup: 4.50.2 + rollup: 4.52.4 - '@rollup/plugin-node-resolve@15.3.1(rollup@4.50.2)': + '@rollup/plugin-node-resolve@15.3.1(rollup@4.52.4)': dependencies: - '@rollup/pluginutils': 5.3.0(rollup@4.50.2) + '@rollup/pluginutils': 5.3.0(rollup@4.52.4) '@types/resolve': 1.20.2 deepmerge: 4.3.1 is-module: 1.0.0 resolve: 1.22.10 optionalDependencies: - rollup: 4.50.2 + rollup: 4.52.4 - '@rollup/plugin-typescript@11.1.6(rollup@4.50.2)(tslib@2.8.1)(typescript@5.9.2)': + '@rollup/plugin-typescript@11.1.6(rollup@4.52.4)(tslib@2.8.1)(typescript@5.9.3)': dependencies: - '@rollup/pluginutils': 5.3.0(rollup@4.50.2) + '@rollup/pluginutils': 5.3.0(rollup@4.52.4) resolve: 1.22.10 - typescript: 5.9.2 + typescript: 5.9.3 optionalDependencies: - rollup: 4.50.2 + rollup: 4.52.4 tslib: 2.8.1 '@rollup/pluginutils@4.2.1': @@ -3615,85 +3756,101 @@ snapshots: estree-walker: 2.0.2 picomatch: 2.3.1 - '@rollup/pluginutils@5.3.0(rollup@4.50.2)': + '@rollup/pluginutils@5.3.0(rollup@4.52.4)': dependencies: '@types/estree': 1.0.8 estree-walker: 2.0.2 picomatch: 4.0.3 optionalDependencies: - rollup: 4.50.2 + rollup: 4.52.4 - '@rollup/rollup-android-arm-eabi@4.50.2': + '@rollup/rollup-android-arm-eabi@4.52.4': optional: true - '@rollup/rollup-android-arm64@4.50.2': + '@rollup/rollup-android-arm64@4.52.4': optional: true - '@rollup/rollup-darwin-arm64@4.50.2': + '@rollup/rollup-darwin-arm64@4.52.4': optional: true - '@rollup/rollup-darwin-x64@4.50.2': + '@rollup/rollup-darwin-x64@4.52.4': optional: true - '@rollup/rollup-freebsd-arm64@4.50.2': + '@rollup/rollup-freebsd-arm64@4.52.4': optional: true - '@rollup/rollup-freebsd-x64@4.50.2': + '@rollup/rollup-freebsd-x64@4.52.4': optional: true - '@rollup/rollup-linux-arm-gnueabihf@4.50.2': + '@rollup/rollup-linux-arm-gnueabihf@4.52.4': optional: true - '@rollup/rollup-linux-arm-musleabihf@4.50.2': + '@rollup/rollup-linux-arm-musleabihf@4.52.4': optional: true - '@rollup/rollup-linux-arm64-gnu@4.50.2': + '@rollup/rollup-linux-arm64-gnu@4.52.4': optional: true - '@rollup/rollup-linux-arm64-musl@4.50.2': + '@rollup/rollup-linux-arm64-musl@4.52.4': optional: true - '@rollup/rollup-linux-loong64-gnu@4.50.2': + '@rollup/rollup-linux-loong64-gnu@4.52.4': optional: true - '@rollup/rollup-linux-ppc64-gnu@4.50.2': + '@rollup/rollup-linux-ppc64-gnu@4.52.4': optional: true - '@rollup/rollup-linux-riscv64-gnu@4.50.2': + '@rollup/rollup-linux-riscv64-gnu@4.52.4': optional: true - '@rollup/rollup-linux-riscv64-musl@4.50.2': + '@rollup/rollup-linux-riscv64-musl@4.52.4': optional: true - '@rollup/rollup-linux-s390x-gnu@4.50.2': + '@rollup/rollup-linux-s390x-gnu@4.52.4': optional: true - '@rollup/rollup-linux-x64-gnu@4.50.2': + '@rollup/rollup-linux-x64-gnu@4.52.4': optional: true - '@rollup/rollup-linux-x64-musl@4.50.2': + '@rollup/rollup-linux-x64-musl@4.52.4': optional: true - '@rollup/rollup-openharmony-arm64@4.50.2': + '@rollup/rollup-openharmony-arm64@4.52.4': optional: true - '@rollup/rollup-win32-arm64-msvc@4.50.2': + '@rollup/rollup-win32-arm64-msvc@4.52.4': optional: true - '@rollup/rollup-win32-ia32-msvc@4.50.2': + '@rollup/rollup-win32-ia32-msvc@4.52.4': optional: true - '@rollup/rollup-win32-x64-msvc@4.50.2': + '@rollup/rollup-win32-x64-gnu@4.52.4': optional: true + '@rollup/rollup-win32-x64-msvc@4.52.4': + optional: true + + '@scure/base@1.1.9': {} + '@scure/base@1.2.6': {} + '@scure/bip32@1.4.0': + dependencies: + '@noble/curves': 1.4.2 + '@noble/hashes': 1.4.0 + '@scure/base': 1.1.9 + '@scure/bip32@1.7.0': dependencies: - '@noble/curves': 1.9.1 + '@noble/curves': 1.9.7 '@noble/hashes': 1.8.0 '@scure/base': 1.2.6 + '@scure/bip39@1.3.0': + dependencies: + '@noble/hashes': 1.4.0 + '@scure/base': 1.1.9 + '@scure/bip39@1.6.0': dependencies: '@noble/hashes': 1.8.0 @@ -3722,7 +3879,7 @@ snapshots: dependencies: '@ampproject/remapping': 2.3.0 enhanced-resolve: 5.18.3 - jiti: 2.5.1 + jiti: 2.6.1 lightningcss: 1.30.1 magic-string: 0.30.19 source-map-js: 1.2.1 @@ -3766,8 +3923,8 @@ snapshots: '@tailwindcss/oxide@4.1.10': dependencies: - detect-libc: 2.1.0 - tar: 7.4.3 + detect-libc: 2.1.2 + tar: 7.5.1 optionalDependencies: '@tailwindcss/oxide-android-arm64': 4.1.10 '@tailwindcss/oxide-darwin-arm64': 4.1.10 @@ -3790,25 +3947,42 @@ snapshots: postcss: 8.5.6 tailwindcss: 4.1.10 + '@tronweb3/tronwallet-abstract-adapter@1.1.9': + dependencies: + eventemitter3: 4.0.7 + tronweb: 6.0.4 + transitivePeerDependencies: + - bufferutil + - debug + - utf-8-validate + '@trysound/sax@0.2.0': {} '@types/bn.js@5.1.6': dependencies: - '@types/node': 20.19.17 + '@types/node': 24.8.1 '@types/bn.js@5.2.0': dependencies: - '@types/node': 20.19.17 + '@types/node': 24.8.1 '@types/estree@1.0.8': {} - '@types/node@20.19.17': + '@types/node@20.19.22': dependencies: undici-types: 6.21.0 + '@types/node@22.7.5': + dependencies: + undici-types: 6.19.8 + + '@types/node@24.8.1': + dependencies: + undici-types: 7.14.0 + '@types/pbkdf2@3.1.2': dependencies: - '@types/node': 20.19.17 + '@types/node': 24.8.1 '@types/react-dom@19.1.6(@types/react@19.1.8)': dependencies: @@ -3820,13 +3994,13 @@ snapshots: '@types/resolve@1.20.2': {} - '@types/secp256k1@4.0.6': + '@types/secp256k1@4.0.7': dependencies: - '@types/node': 20.19.17 + '@types/node': 24.8.1 '@types/ws@8.18.1': dependencies: - '@types/node': 20.19.17 + '@types/node': 24.8.1 '@vitest/expect@3.0.9': dependencies: @@ -3835,13 +4009,13 @@ snapshots: chai: 5.3.3 tinyrainbow: 2.0.0 - '@vitest/mocker@3.0.9(vite@6.3.6(@types/node@20.19.17)(jiti@2.5.1)(lightningcss@1.30.1))': + '@vitest/mocker@3.0.9(vite@6.4.0(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2))': dependencies: '@vitest/spy': 3.0.9 estree-walker: 3.0.3 magic-string: 0.30.19 optionalDependencies: - vite: 6.3.6(@types/node@20.19.17)(jiti@2.5.1)(lightningcss@1.30.1) + vite: 6.4.0(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2) '@vitest/pretty-format@3.0.9': dependencies: @@ -3872,12 +4046,18 @@ snapshots: loupe: 3.2.1 tinyrainbow: 2.0.0 - abitype@1.1.0(typescript@5.9.2): + abitype@1.1.0(typescript@5.9.3): optionalDependencies: - typescript: 5.9.2 + typescript: 5.9.3 + + abitype@1.1.1(typescript@5.9.3): + optionalDependencies: + typescript: 5.9.3 aes-js@3.1.2: {} + aes-js@4.0.0-beta.5: {} + ansi-regex@5.0.1: {} ansi-regex@6.2.2: {} @@ -3917,8 +4097,8 @@ snapshots: autoprefixer@10.4.21(postcss@8.5.6): dependencies: - browserslist: 4.26.2 - caniuse-lite: 1.0.30001743 + browserslist: 4.26.3 + caniuse-lite: 1.0.30001751 fraction.js: 4.3.7 normalize-range: 0.1.2 picocolors: 1.1.1 @@ -3929,6 +4109,14 @@ snapshots: dependencies: possible-typed-array-names: 1.1.0 + axios@1.11.0: + dependencies: + follow-redirects: 1.15.11 + form-data: 4.0.4 + proxy-from-env: 1.1.0 + transitivePeerDependencies: + - debug + axios@1.12.2: dependencies: follow-redirects: 1.15.11 @@ -3945,10 +4133,12 @@ snapshots: base64-js@1.5.1: {} - baseline-browser-mapping@2.8.6: {} + baseline-browser-mapping@2.8.17: {} bech32@1.1.4: {} + bignumber.js@9.1.2: {} + binary-extensions@2.3.0: {} bip39@3.1.0: @@ -3980,7 +4170,7 @@ snapshots: browserify-aes@1.2.0: dependencies: buffer-xor: 1.0.3 - cipher-base: 1.0.6 + cipher-base: 1.0.7 create-hash: 1.2.0 evp_bytestokey: 1.0.3 inherits: 2.0.4 @@ -3994,7 +4184,7 @@ snapshots: browserify-des@1.0.2: dependencies: - cipher-base: 1.0.6 + cipher-base: 1.0.7 des.js: 1.1.0 inherits: 2.0.4 safe-buffer: 5.2.1 @@ -4005,26 +4195,25 @@ snapshots: randombytes: 2.1.0 safe-buffer: 5.2.1 - browserify-sign@4.2.3: + browserify-sign@4.2.5: dependencies: bn.js: 5.2.2 browserify-rsa: 4.1.1 create-hash: 1.2.0 create-hmac: 1.1.7 elliptic: 6.6.1 - hash-base: 3.0.5 inherits: 2.0.4 - parse-asn1: 5.1.7 + parse-asn1: 5.1.9 readable-stream: 2.3.8 safe-buffer: 5.2.1 - browserslist@4.26.2: + browserslist@4.26.3: dependencies: - baseline-browser-mapping: 2.8.6 - caniuse-lite: 1.0.30001743 - electron-to-chromium: 1.5.221 - node-releases: 2.0.21 - update-browserslist-db: 1.1.3(browserslist@4.26.2) + baseline-browser-mapping: 2.8.17 + caniuse-lite: 1.0.30001751 + electron-to-chromium: 1.5.237 + node-releases: 2.0.25 + update-browserslist-db: 1.1.3(browserslist@4.26.3) bs58@4.0.1: dependencies: @@ -4069,12 +4258,12 @@ snapshots: caniuse-api@3.0.0: dependencies: - browserslist: 4.26.2 - caniuse-lite: 1.0.30001743 + browserslist: 4.26.3 + caniuse-lite: 1.0.30001751 lodash.memoize: 4.1.2 lodash.uniq: 4.5.0 - caniuse-lite@1.0.30001743: {} + caniuse-lite@1.0.30001751: {} chai@5.3.3: dependencies: @@ -4105,10 +4294,11 @@ snapshots: chownr@3.0.0: {} - cipher-base@1.0.6: + cipher-base@1.0.7: dependencies: inherits: 2.0.4 safe-buffer: 5.2.1 + to-buffer: 1.2.2 class-variance-authority@0.7.1: dependencies: @@ -4153,27 +4343,20 @@ snapshots: bn.js: 4.12.2 elliptic: 6.6.1 - create-hash@1.1.3: - dependencies: - cipher-base: 1.0.6 - inherits: 2.0.4 - ripemd160: 2.0.1 - sha.js: 2.4.12 - create-hash@1.2.0: dependencies: - cipher-base: 1.0.6 + cipher-base: 1.0.7 inherits: 2.0.4 md5.js: 1.3.5 - ripemd160: 2.0.2 + ripemd160: 2.0.3 sha.js: 2.4.12 create-hmac@1.1.7: dependencies: - cipher-base: 1.0.6 + cipher-base: 1.0.7 create-hash: 1.2.0 inherits: 2.0.4 - ripemd160: 2.0.2 + ripemd160: 2.0.3 safe-buffer: 5.2.1 sha.js: 2.4.12 @@ -4198,14 +4381,14 @@ snapshots: crypto-browserify@3.12.1: dependencies: browserify-cipher: 1.0.1 - browserify-sign: 4.2.3 + browserify-sign: 4.2.5 create-ecdh: 4.0.4 create-hash: 1.2.0 create-hmac: 1.1.7 diffie-hellman: 5.0.3 hash-base: 3.0.5 inherits: 2.0.4 - pbkdf2: 3.1.3 + pbkdf2: 3.1.5 public-encrypt: 4.0.3 randombytes: 2.1.0 randomfill: 1.0.4 @@ -4289,8 +4472,6 @@ snapshots: dependencies: ms: 2.1.3 - decimal.js@10.4.3: {} - decimal.js@10.6.0: {} deep-eql@5.0.2: {} @@ -4316,7 +4497,7 @@ snapshots: inherits: 2.0.4 minimalistic-assert: 1.0.1 - detect-libc@2.1.0: {} + detect-libc@2.1.2: {} diffie-hellman@5.0.3: dependencies: @@ -4350,7 +4531,7 @@ snapshots: eastasianwidth@0.2.0: {} - electron-to-chromium@1.5.221: {} + electron-to-chromium@1.5.237: {} elliptic@6.6.1: dependencies: @@ -4374,7 +4555,7 @@ snapshots: enhanced-resolve@5.18.3: dependencies: graceful-fs: 4.2.11 - tapable: 2.2.3 + tapable: 2.3.0 entities@2.2.0: {} @@ -4395,7 +4576,7 @@ snapshots: has-tostringtag: 1.0.2 hasown: 2.0.2 - es-toolkit@1.39.10: {} + es-toolkit@1.40.0: {} esbuild@0.25.1: optionalDependencies: @@ -4425,34 +4606,34 @@ snapshots: '@esbuild/win32-ia32': 0.25.1 '@esbuild/win32-x64': 0.25.1 - esbuild@0.25.10: + esbuild@0.25.11: optionalDependencies: - '@esbuild/aix-ppc64': 0.25.10 - '@esbuild/android-arm': 0.25.10 - '@esbuild/android-arm64': 0.25.10 - '@esbuild/android-x64': 0.25.10 - '@esbuild/darwin-arm64': 0.25.10 - '@esbuild/darwin-x64': 0.25.10 - '@esbuild/freebsd-arm64': 0.25.10 - '@esbuild/freebsd-x64': 0.25.10 - '@esbuild/linux-arm': 0.25.10 - '@esbuild/linux-arm64': 0.25.10 - '@esbuild/linux-ia32': 0.25.10 - '@esbuild/linux-loong64': 0.25.10 - '@esbuild/linux-mips64el': 0.25.10 - '@esbuild/linux-ppc64': 0.25.10 - '@esbuild/linux-riscv64': 0.25.10 - '@esbuild/linux-s390x': 0.25.10 - '@esbuild/linux-x64': 0.25.10 - '@esbuild/netbsd-arm64': 0.25.10 - '@esbuild/netbsd-x64': 0.25.10 - '@esbuild/openbsd-arm64': 0.25.10 - '@esbuild/openbsd-x64': 0.25.10 - '@esbuild/openharmony-arm64': 0.25.10 - '@esbuild/sunos-x64': 0.25.10 - '@esbuild/win32-arm64': 0.25.10 - '@esbuild/win32-ia32': 0.25.10 - '@esbuild/win32-x64': 0.25.10 + '@esbuild/aix-ppc64': 0.25.11 + '@esbuild/android-arm': 0.25.11 + '@esbuild/android-arm64': 0.25.11 + '@esbuild/android-x64': 0.25.11 + '@esbuild/darwin-arm64': 0.25.11 + '@esbuild/darwin-x64': 0.25.11 + '@esbuild/freebsd-arm64': 0.25.11 + '@esbuild/freebsd-x64': 0.25.11 + '@esbuild/linux-arm': 0.25.11 + '@esbuild/linux-arm64': 0.25.11 + '@esbuild/linux-ia32': 0.25.11 + '@esbuild/linux-loong64': 0.25.11 + '@esbuild/linux-mips64el': 0.25.11 + '@esbuild/linux-ppc64': 0.25.11 + '@esbuild/linux-riscv64': 0.25.11 + '@esbuild/linux-s390x': 0.25.11 + '@esbuild/linux-x64': 0.25.11 + '@esbuild/netbsd-arm64': 0.25.11 + '@esbuild/netbsd-x64': 0.25.11 + '@esbuild/openbsd-arm64': 0.25.11 + '@esbuild/openbsd-x64': 0.25.11 + '@esbuild/openharmony-arm64': 0.25.11 + '@esbuild/sunos-x64': 0.25.11 + '@esbuild/win32-arm64': 0.25.11 + '@esbuild/win32-ia32': 0.25.11 + '@esbuild/win32-x64': 0.25.11 escalade@3.2.0: {} @@ -4467,7 +4648,7 @@ snapshots: ethereum-cryptography@0.1.3: dependencies: '@types/pbkdf2': 3.1.2 - '@types/secp256k1': 4.0.6 + '@types/secp256k1': 4.0.7 blakejs: 1.2.1 browserify-aes: 1.2.0 bs58check: 2.1.2 @@ -4475,13 +4656,20 @@ snapshots: create-hmac: 1.1.7 hash.js: 1.1.7 keccak: 3.0.4 - pbkdf2: 3.1.3 + pbkdf2: 3.1.5 randombytes: 2.1.0 safe-buffer: 5.2.1 scrypt-js: 3.0.1 secp256k1: 4.0.4 setimmediate: 1.0.5 + ethereum-cryptography@2.2.1: + dependencies: + '@noble/curves': 1.4.2 + '@noble/hashes': 1.4.0 + '@scure/bip32': 1.4.0 + '@scure/bip39': 1.3.0 + ethereumjs-util@7.1.5: dependencies: '@types/bn.js': 5.2.0 @@ -4501,6 +4689,19 @@ snapshots: utf8: 3.0.0 uuid: 8.3.2 + ethers@6.13.5: + dependencies: + '@adraffy/ens-normalize': 1.10.1 + '@noble/curves': 1.2.0 + '@noble/hashes': 1.3.2 + '@types/node': 22.7.5 + aes-js: 4.0.0-beta.5 + tslib: 2.7.0 + ws: 8.17.1 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + event-iterator@2.0.0: {} eventemitter3@4.0.7: {} @@ -4558,14 +4759,14 @@ snapshots: fraction.js@4.3.7: {} - framer-motion@12.23.15(react-dom@19.1.1(react@19.1.1))(react@19.1.1): + framer-motion@12.23.24(react-dom@19.2.0(react@19.2.0))(react@19.2.0): dependencies: - motion-dom: 12.23.12 + motion-dom: 12.23.23 motion-utils: 12.23.6 tslib: 2.8.1 optionalDependencies: - react: 19.1.1 - react-dom: 19.1.1(react@19.1.1) + react: 19.2.0 + react-dom: 19.2.0(react@19.2.0) fs-extra@10.1.0: dependencies: @@ -4578,22 +4779,22 @@ snapshots: fsevents@2.3.3: optional: true - fuels@0.101.1(vitest@3.0.9(@types/node@20.19.17)(jiti@2.5.1)(lightningcss@1.30.1)): + fuels@0.101.1(vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2)): dependencies: - '@fuel-ts/abi-coder': 0.101.1(vitest@3.0.9(@types/node@20.19.17)(jiti@2.5.1)(lightningcss@1.30.1)) - '@fuel-ts/abi-typegen': 0.101.1(vitest@3.0.9(@types/node@20.19.17)(jiti@2.5.1)(lightningcss@1.30.1)) - '@fuel-ts/account': 0.101.1(vitest@3.0.9(@types/node@20.19.17)(jiti@2.5.1)(lightningcss@1.30.1)) - '@fuel-ts/address': 0.101.1(vitest@3.0.9(@types/node@20.19.17)(jiti@2.5.1)(lightningcss@1.30.1)) - '@fuel-ts/contract': 0.101.1(vitest@3.0.9(@types/node@20.19.17)(jiti@2.5.1)(lightningcss@1.30.1)) - '@fuel-ts/crypto': 0.101.1(vitest@3.0.9(@types/node@20.19.17)(jiti@2.5.1)(lightningcss@1.30.1)) + '@fuel-ts/abi-coder': 0.101.1(vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2)) + '@fuel-ts/abi-typegen': 0.101.1(vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2)) + '@fuel-ts/account': 0.101.1(vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2)) + '@fuel-ts/address': 0.101.1(vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2)) + '@fuel-ts/contract': 0.101.1(vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2)) + '@fuel-ts/crypto': 0.101.1(vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2)) '@fuel-ts/errors': 0.101.1 - '@fuel-ts/hasher': 0.101.1(vitest@3.0.9(@types/node@20.19.17)(jiti@2.5.1)(lightningcss@1.30.1)) + '@fuel-ts/hasher': 0.101.1(vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2)) '@fuel-ts/math': 0.101.1 - '@fuel-ts/program': 0.101.1(vitest@3.0.9(@types/node@20.19.17)(jiti@2.5.1)(lightningcss@1.30.1)) - '@fuel-ts/recipes': 0.101.1(vitest@3.0.9(@types/node@20.19.17)(jiti@2.5.1)(lightningcss@1.30.1)) - '@fuel-ts/script': 0.101.1(vitest@3.0.9(@types/node@20.19.17)(jiti@2.5.1)(lightningcss@1.30.1)) - '@fuel-ts/transactions': 0.101.1(vitest@3.0.9(@types/node@20.19.17)(jiti@2.5.1)(lightningcss@1.30.1)) - '@fuel-ts/utils': 0.101.1(vitest@3.0.9(@types/node@20.19.17)(jiti@2.5.1)(lightningcss@1.30.1)) + '@fuel-ts/program': 0.101.1(vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2)) + '@fuel-ts/recipes': 0.101.1(vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2)) + '@fuel-ts/script': 0.101.1(vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2)) + '@fuel-ts/transactions': 0.101.1(vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2)) + '@fuel-ts/utils': 0.101.1(vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2)) '@fuel-ts/versions': 0.101.1 '@fuels/vm-asm': 0.60.2 bundle-require: 5.1.0(esbuild@0.25.1) @@ -4616,6 +4817,8 @@ snapshots: function-bind@1.1.2: {} + generator-function@2.0.1: {} + generic-names@4.0.0: dependencies: loader-utils: 3.3.1 @@ -4706,14 +4909,17 @@ snapshots: dependencies: has-symbols: 1.1.0 - hash-base@2.0.2: + hash-base@3.0.5: dependencies: inherits: 2.0.4 + safe-buffer: 5.2.1 - hash-base@3.0.5: + hash-base@3.1.2: dependencies: inherits: 2.0.4 + readable-stream: 2.3.8 safe-buffer: 5.2.1 + to-buffer: 1.2.2 hash.js@1.1.7: dependencies: @@ -4774,9 +4980,10 @@ snapshots: is-fullwidth-code-point@3.0.0: {} - is-generator-function@1.1.0: + is-generator-function@1.1.2: dependencies: call-bound: 1.0.4 + generator-function: 2.0.1 get-proto: 1.0.1 has-tostringtag: 1.0.2 safe-regex-test: 1.1.0 @@ -4844,7 +5051,7 @@ snapshots: optionalDependencies: '@pkgjs/parseargs': 0.11.0 - jiti@2.5.1: {} + jiti@2.6.1: {} joycon@3.1.1: {} @@ -4903,7 +5110,7 @@ snapshots: lightningcss@1.30.1: dependencies: - detect-libc: 2.1.0 + detect-libc: 2.1.2 optionalDependencies: lightningcss-darwin-arm64: 1.30.1 lightningcss-darwin-x64: 1.30.1 @@ -4985,7 +5192,7 @@ snapshots: minipass@7.1.2: {} - minizlib@3.0.2: + minizlib@3.1.0: dependencies: minipass: 7.1.2 @@ -4995,19 +5202,19 @@ snapshots: mkdirp@3.0.1: {} - motion-dom@12.23.12: + motion-dom@12.23.23: dependencies: motion-utils: 12.23.6 motion-utils@12.23.6: {} - motion@12.23.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1): + motion@12.23.0(react-dom@19.2.0(react@19.2.0))(react@19.2.0): dependencies: - framer-motion: 12.23.15(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + framer-motion: 12.23.24(react-dom@19.2.0(react@19.2.0))(react@19.2.0) tslib: 2.8.1 optionalDependencies: - react: 19.1.1 - react-dom: 19.1.1(react@19.1.1) + react: 19.2.0 + react-dom: 19.2.0(react@19.2.0) ms@2.1.3: {} @@ -5043,12 +5250,12 @@ snapshots: node-gyp-build-optional-packages@5.2.2: dependencies: - detect-libc: 2.1.0 + detect-libc: 2.1.2 optional: true node-gyp-build@4.8.4: {} - node-releases@2.0.21: {} + node-releases@2.0.25: {} normalize-path@3.0.0: {} @@ -5080,18 +5287,18 @@ snapshots: dependencies: wrappy: 1.0.2 - ox@0.9.3(typescript@5.9.2): + ox@0.9.6(typescript@5.9.3): dependencies: - '@adraffy/ens-normalize': 1.11.0 + '@adraffy/ens-normalize': 1.11.1 '@noble/ciphers': 1.3.0 '@noble/curves': 1.9.1 '@noble/hashes': 1.8.0 '@scure/bip32': 1.7.0 '@scure/bip39': 1.6.0 - abitype: 1.1.0(typescript@5.9.2) + abitype: 1.1.1(typescript@5.9.3) eventemitter3: 5.0.1 optionalDependencies: - typescript: 5.9.2 + typescript: 5.9.3 transitivePeerDependencies: - zod @@ -5118,13 +5325,12 @@ snapshots: package-json-from-dist@1.0.1: {} - parse-asn1@5.1.7: + parse-asn1@5.1.9: dependencies: asn1.js: 4.10.1 browserify-aes: 1.2.0 evp_bytestokey: 1.0.3 - hash-base: 3.0.5 - pbkdf2: 3.1.3 + pbkdf2: 3.1.5 safe-buffer: 5.2.1 path-exists@4.0.0: {} @@ -5142,14 +5348,14 @@ snapshots: pathval@2.0.1: {} - pbkdf2@3.1.3: + pbkdf2@3.1.5: dependencies: - create-hash: 1.1.3 + create-hash: 1.2.0 create-hmac: 1.1.7 - ripemd160: 2.0.1 + ripemd160: 2.0.3 safe-buffer: 5.2.1 sha.js: 2.4.12 - to-buffer: 1.2.1 + to-buffer: 1.2.2 picocolors@1.1.1: {} @@ -5183,7 +5389,7 @@ snapshots: postcss-colormin@5.3.1(postcss@8.5.6): dependencies: - browserslist: 4.26.2 + browserslist: 4.26.3 caniuse-api: 3.0.0 colord: 2.9.3 postcss: 8.5.6 @@ -5191,7 +5397,7 @@ snapshots: postcss-convert-values@5.1.3(postcss@8.5.6): dependencies: - browserslist: 4.26.2 + browserslist: 4.26.3 postcss: 8.5.6 postcss-value-parser: 4.2.0 @@ -5233,7 +5439,7 @@ snapshots: postcss-merge-rules@5.1.4(postcss@8.5.6): dependencies: - browserslist: 4.26.2 + browserslist: 4.26.3 caniuse-api: 3.0.0 cssnano-utils: 3.1.0(postcss@8.5.6) postcss: 8.5.6 @@ -5253,7 +5459,7 @@ snapshots: postcss-minify-params@5.1.4(postcss@8.5.6): dependencies: - browserslist: 4.26.2 + browserslist: 4.26.3 cssnano-utils: 3.1.0(postcss@8.5.6) postcss: 8.5.6 postcss-value-parser: 4.2.0 @@ -5334,7 +5540,7 @@ snapshots: postcss-normalize-unicode@5.1.1(postcss@8.5.6): dependencies: - browserslist: 4.26.2 + browserslist: 4.26.3 postcss: 8.5.6 postcss-value-parser: 4.2.0 @@ -5357,7 +5563,7 @@ snapshots: postcss-reduce-initial@5.1.2(postcss@8.5.6): dependencies: - browserslist: 4.26.2 + browserslist: 4.26.3 caniuse-api: 3.0.0 postcss: 8.5.6 @@ -5410,7 +5616,7 @@ snapshots: bn.js: 4.12.2 browserify-rsa: 4.1.1 create-hash: 1.2.0 - parse-asn1: 5.1.7 + parse-asn1: 5.1.9 randombytes: 2.1.0 safe-buffer: 5.2.1 @@ -5425,12 +5631,12 @@ snapshots: randombytes: 2.1.0 safe-buffer: 5.2.1 - react-dom@19.1.1(react@19.1.1): + react-dom@19.2.0(react@19.2.0): dependencies: - react: 19.1.1 - scheduler: 0.26.0 + react: 19.2.0 + scheduler: 0.27.0 - react@19.1.1: {} + react@19.2.0: {} read-cache@1.0.0: dependencies: @@ -5458,6 +5664,8 @@ snapshots: readonly-date@1.0.0: {} + regenerator-runtime@0.14.1: {} + resolve-from@5.0.0: {} resolve@1.22.10: @@ -5470,25 +5678,20 @@ snapshots: dependencies: glob: 10.4.5 - ripemd160@2.0.1: - dependencies: - hash-base: 2.0.2 - inherits: 2.0.4 - - ripemd160@2.0.2: + ripemd160@2.0.3: dependencies: - hash-base: 3.0.5 + hash-base: 3.1.2 inherits: 2.0.4 rlp@2.2.7: dependencies: bn.js: 5.2.2 - rollup-plugin-dts@6.2.3(rollup@4.50.2)(typescript@5.9.2): + rollup-plugin-dts@6.2.3(rollup@4.52.4)(typescript@5.9.3): dependencies: magic-string: 0.30.19 - rollup: 4.50.2 - typescript: 5.9.2 + rollup: 4.52.4 + typescript: 5.9.3 optionalDependencies: '@babel/code-frame': 7.27.1 @@ -5511,45 +5714,46 @@ snapshots: transitivePeerDependencies: - ts-node - rollup-plugin-typescript2@0.36.0(rollup@4.50.2)(typescript@5.9.2): + rollup-plugin-typescript2@0.36.0(rollup@4.52.4)(typescript@5.9.3): dependencies: '@rollup/pluginutils': 4.2.1 find-cache-dir: 3.3.2 fs-extra: 10.1.0 - rollup: 4.50.2 - semver: 7.7.2 + rollup: 4.52.4 + semver: 7.7.3 tslib: 2.8.1 - typescript: 5.9.2 + typescript: 5.9.3 rollup-pluginutils@2.8.2: dependencies: estree-walker: 0.6.1 - rollup@4.50.2: + rollup@4.52.4: dependencies: '@types/estree': 1.0.8 optionalDependencies: - '@rollup/rollup-android-arm-eabi': 4.50.2 - '@rollup/rollup-android-arm64': 4.50.2 - '@rollup/rollup-darwin-arm64': 4.50.2 - '@rollup/rollup-darwin-x64': 4.50.2 - '@rollup/rollup-freebsd-arm64': 4.50.2 - '@rollup/rollup-freebsd-x64': 4.50.2 - '@rollup/rollup-linux-arm-gnueabihf': 4.50.2 - '@rollup/rollup-linux-arm-musleabihf': 4.50.2 - '@rollup/rollup-linux-arm64-gnu': 4.50.2 - '@rollup/rollup-linux-arm64-musl': 4.50.2 - '@rollup/rollup-linux-loong64-gnu': 4.50.2 - '@rollup/rollup-linux-ppc64-gnu': 4.50.2 - '@rollup/rollup-linux-riscv64-gnu': 4.50.2 - '@rollup/rollup-linux-riscv64-musl': 4.50.2 - '@rollup/rollup-linux-s390x-gnu': 4.50.2 - '@rollup/rollup-linux-x64-gnu': 4.50.2 - '@rollup/rollup-linux-x64-musl': 4.50.2 - '@rollup/rollup-openharmony-arm64': 4.50.2 - '@rollup/rollup-win32-arm64-msvc': 4.50.2 - '@rollup/rollup-win32-ia32-msvc': 4.50.2 - '@rollup/rollup-win32-x64-msvc': 4.50.2 + '@rollup/rollup-android-arm-eabi': 4.52.4 + '@rollup/rollup-android-arm64': 4.52.4 + '@rollup/rollup-darwin-arm64': 4.52.4 + '@rollup/rollup-darwin-x64': 4.52.4 + '@rollup/rollup-freebsd-arm64': 4.52.4 + '@rollup/rollup-freebsd-x64': 4.52.4 + '@rollup/rollup-linux-arm-gnueabihf': 4.52.4 + '@rollup/rollup-linux-arm-musleabihf': 4.52.4 + '@rollup/rollup-linux-arm64-gnu': 4.52.4 + '@rollup/rollup-linux-arm64-musl': 4.52.4 + '@rollup/rollup-linux-loong64-gnu': 4.52.4 + '@rollup/rollup-linux-ppc64-gnu': 4.52.4 + '@rollup/rollup-linux-riscv64-gnu': 4.52.4 + '@rollup/rollup-linux-riscv64-musl': 4.52.4 + '@rollup/rollup-linux-s390x-gnu': 4.52.4 + '@rollup/rollup-linux-x64-gnu': 4.52.4 + '@rollup/rollup-linux-x64-musl': 4.52.4 + '@rollup/rollup-openharmony-arm64': 4.52.4 + '@rollup/rollup-win32-arm64-msvc': 4.52.4 + '@rollup/rollup-win32-ia32-msvc': 4.52.4 + '@rollup/rollup-win32-x64-gnu': 4.52.4 + '@rollup/rollup-win32-x64-msvc': 4.52.4 fsevents: 2.3.3 safe-buffer@5.1.2: {} @@ -5564,7 +5768,7 @@ snapshots: es-errors: 1.3.0 is-regex: 1.2.1 - scheduler@0.26.0: {} + scheduler@0.27.0: {} scrypt-js@3.0.1: {} @@ -5576,7 +5780,9 @@ snapshots: semver@6.3.1: {} - semver@7.7.2: {} + semver@7.7.1: {} + + semver@7.7.3: {} set-function-length@1.2.2: dependencies: @@ -5593,7 +5799,7 @@ snapshots: dependencies: inherits: 2.0.4 safe-buffer: 5.2.1 - to-buffer: 1.2.1 + to-buffer: 1.2.2 shebang-command@2.0.0: dependencies: @@ -5613,7 +5819,7 @@ snapshots: stackback@0.0.2: {} - std-env@3.9.0: {} + std-env@3.10.0: {} stream-browserify@3.0.0: dependencies: @@ -5654,7 +5860,7 @@ snapshots: stylehacks@5.1.1(postcss@8.5.6): dependencies: - browserslist: 4.26.2 + browserslist: 4.26.3 postcss: 8.5.6 postcss-selector-parser: 6.1.2 @@ -5680,15 +5886,14 @@ snapshots: tailwindcss@4.1.10: {} - tapable@2.2.3: {} + tapable@2.3.0: {} - tar@7.4.3: + tar@7.5.1: dependencies: '@isaacs/fs-minipass': 4.0.1 chownr: 3.0.0 minipass: 7.1.2 - minizlib: 3.0.2 - mkdirp: 3.0.1 + minizlib: 3.1.0 yallist: 5.0.0 tiny-case@1.0.3: {} @@ -5708,7 +5913,7 @@ snapshots: tinyspy@3.0.2: {} - to-buffer@1.2.1: + to-buffer@1.2.2: dependencies: isarray: 2.0.5 safe-buffer: 5.2.1 @@ -5724,6 +5929,24 @@ snapshots: tr46@0.0.3: {} + tronweb@6.0.4: + dependencies: + '@babel/runtime': 7.26.10 + axios: 1.11.0 + bignumber.js: 9.1.2 + ethereum-cryptography: 2.2.1 + ethers: 6.13.5 + eventemitter3: 5.0.1 + google-protobuf: 3.21.4 + semver: 7.7.1 + validator: 13.12.0 + transitivePeerDependencies: + - bufferutil + - debug + - utf-8-validate + + tslib@2.7.0: {} + tslib@2.8.1: {} type-fest@2.19.0: {} @@ -5740,7 +5963,7 @@ snapshots: dependencies: is-typedarray: 1.0.0 - typescript@5.9.2: {} + typescript@5.9.3: {} uglify-js@3.19.3: {} @@ -5748,13 +5971,17 @@ snapshots: dependencies: multiformats: 13.4.1 + undici-types@6.19.8: {} + undici-types@6.21.0: {} + undici-types@7.14.0: {} + universalify@2.0.1: {} - update-browserslist-db@1.1.3(browserslist@4.26.2): + update-browserslist-db@1.1.3(browserslist@4.26.3): dependencies: - browserslist: 4.26.2 + browserslist: 4.26.3 escalade: 3.2.0 picocolors: 1.1.1 @@ -5766,36 +5993,38 @@ snapshots: dependencies: inherits: 2.0.4 is-arguments: 1.2.0 - is-generator-function: 1.1.0 + is-generator-function: 1.1.2 is-typed-array: 1.1.15 which-typed-array: 1.1.19 uuid@8.3.2: {} - viem@2.37.6(typescript@5.9.2): + validator@13.12.0: {} + + viem@2.38.3(typescript@5.9.3): dependencies: '@noble/curves': 1.9.1 '@noble/hashes': 1.8.0 '@scure/bip32': 1.7.0 '@scure/bip39': 1.6.0 - abitype: 1.1.0(typescript@5.9.2) + abitype: 1.1.0(typescript@5.9.3) isows: 1.0.7(ws@8.18.3) - ox: 0.9.3(typescript@5.9.2) + ox: 0.9.6(typescript@5.9.3) ws: 8.18.3 optionalDependencies: - typescript: 5.9.2 + typescript: 5.9.3 transitivePeerDependencies: - bufferutil - utf-8-validate - zod - vite-node@3.0.9(@types/node@20.19.17)(jiti@2.5.1)(lightningcss@1.30.1): + vite-node@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2): dependencies: cac: 6.7.14 debug: 4.4.3 es-module-lexer: 1.7.0 pathe: 2.0.3 - vite: 6.3.6(@types/node@20.19.17)(jiti@2.5.1)(lightningcss@1.30.1) + vite: 6.4.0(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2) transitivePeerDependencies: - '@types/node' - jiti @@ -5810,24 +6039,25 @@ snapshots: - tsx - yaml - vite@6.3.6(@types/node@20.19.17)(jiti@2.5.1)(lightningcss@1.30.1): + vite@6.4.0(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2): dependencies: - esbuild: 0.25.10 + esbuild: 0.25.11 fdir: 6.5.0(picomatch@4.0.3) picomatch: 4.0.3 postcss: 8.5.6 - rollup: 4.50.2 + rollup: 4.52.4 tinyglobby: 0.2.15 optionalDependencies: - '@types/node': 20.19.17 + '@types/node': 20.19.22 fsevents: 2.3.3 - jiti: 2.5.1 + jiti: 2.6.1 lightningcss: 1.30.1 + yaml: 1.10.2 - vitest@3.0.9(@types/node@20.19.17)(jiti@2.5.1)(lightningcss@1.30.1): + vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2): dependencies: '@vitest/expect': 3.0.9 - '@vitest/mocker': 3.0.9(vite@6.3.6(@types/node@20.19.17)(jiti@2.5.1)(lightningcss@1.30.1)) + '@vitest/mocker': 3.0.9(vite@6.4.0(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2)) '@vitest/pretty-format': 3.2.4 '@vitest/runner': 3.0.9 '@vitest/snapshot': 3.0.9 @@ -5838,16 +6068,16 @@ snapshots: expect-type: 1.2.2 magic-string: 0.30.19 pathe: 2.0.3 - std-env: 3.9.0 + std-env: 3.10.0 tinybench: 2.9.0 tinyexec: 0.3.2 tinypool: 1.1.1 tinyrainbow: 2.0.0 - vite: 6.3.6(@types/node@20.19.17)(jiti@2.5.1)(lightningcss@1.30.1) - vite-node: 3.0.9(@types/node@20.19.17)(jiti@2.5.1)(lightningcss@1.30.1) + vite: 6.4.0(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2) + vite-node: 3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2) why-is-node-running: 2.3.0 optionalDependencies: - '@types/node': 20.19.17 + '@types/node': 20.19.22 transitivePeerDependencies: - jiti - less @@ -5906,6 +6136,8 @@ snapshots: ws@7.5.10: {} + ws@8.17.1: {} + ws@8.18.3: {} xstream@11.14.0: diff --git a/scripts/local-pack.sh b/scripts/local-pack.sh index c8511153..c5f1008b 100755 --- a/scripts/local-pack.sh +++ b/scripts/local-pack.sh @@ -1,6 +1,6 @@ #!/bin/bash -# Create local installable tarballs for @nexus/core and @nexus/widgets without publishing. +# Create a local installable tarball for @avail-project/nexus-core without publishing. # This script builds packages, rewrites workspace deps for packaging, packs to dist-tarballs/, and restores files. set -e @@ -31,7 +31,6 @@ info "Cleaning and building packages..." pnpm run clean pnpm -F @nexus/commons build pnpm -F @avail-project/nexus-core build -pnpm -F @avail-project/nexus-widgets build # Pack core (already named @avail-project/nexus-core; remove workspace-only deps) info "Packing core as @avail-project/nexus-core (local tarball)..." @@ -47,27 +46,11 @@ popd >/dev/null info "Created core tarball: $DEST_DIR/$CORE_TARBALL (name: @avail-project/nexus-core)" -# Pack widgets (already named @avail-project/nexus-widgets; remove workspace-only deps; pin @avail-project/nexus-core to current version) -info "Packing widgets as @avail-project/nexus-widgets (local tarball)..." -pushd packages/widgets >/dev/null -cp package.json package.json.backup - -CORE_VERSION=$(node -p "require('../core/package.json').version") -export CORE_VERSION - -node -e "const fs=require('fs');const p=JSON.parse(fs.readFileSync('package.json','utf8'));p.dependencies=p.dependencies||{};if(p.dependencies['@nexus/commons']){delete p.dependencies['@nexus/commons'];}p.dependencies['@avail-project/nexus-core']=process.env.CORE_VERSION;fs.writeFileSync('package.json',JSON.stringify(p,null,2)+'\n');" - -WIDGETS_TARBALL=$(npm pack --pack-destination "$DEST_DIR" --silent) -mv package.json.backup package.json -popd >/dev/null - -info "Created widgets tarball: $DEST_DIR/$WIDGETS_TARBALL (name: @avail-project/nexus-widgets)" - info "Done. Tarballs are in $DEST_DIR" echo "" echo "Install in a project with:" -echo " pnpm add $DEST_DIR/$CORE_TARBALL $DEST_DIR/$WIDGETS_TARBALL" +echo " pnpm add $DEST_DIR/$CORE_TARBALL" echo "or" -echo " npm i $DEST_DIR/$CORE_TARBALL $DEST_DIR/$WIDGETS_TARBALL" +echo " npm i $DEST_DIR/$CORE_TARBALL" diff --git a/scripts/release-core.sh b/scripts/release-core.sh index 2789f036..e43aec1e 100755 --- a/scripts/release-core.sh +++ b/scripts/release-core.sh @@ -80,6 +80,17 @@ if [[ $NON_INTERACTIVE -eq 0 ]]; then print_error "Invalid release type. Use 'dev' or 'prod'" exit 1 fi + + # Second prompt: allow custom version override + read -p "Would you like to enter a custom version? (y/N): " _cv + if [[ $_cv == "y" || $_cv == "Y" ]]; then + read -p "Enter custom version (e.g., 1.2.3 or 1.2.3-beta.0): " _custom_version + if [[ -n "$_custom_version" ]]; then + CUSTOM_VERSION="$_custom_version" + print_status "Custom version set to $CUSTOM_VERSION" + fi + fi + if [[ "$RELEASE_TYPE" == "dev" ]]; then read -p "Pre-release tag (e.g. beta, alpha, dev) (default: $PRERELEASE_ID): " _pre if [[ -n "$_pre" ]]; then PRERELEASE_ID="$_pre"; fi @@ -114,7 +125,7 @@ print_header "Starting @avail-project/nexus-core $RELEASE_TYPE release ($VERSION # Run type checking print_status "Running type check..." -pnpm run typecheck +pnpm run typecheck:core # Clean previous builds print_status "Cleaning previous builds..." @@ -147,9 +158,13 @@ if [[ "$RELEASE_TYPE" == "prod" ]]; then fi # Version bump - print_status "Bumping version ($VERSION_TYPE)..." + print_status "Bumping version (${CUSTOM_VERSION:+custom $CUSTOM_VERSION}${CUSTOM_VERSION:+, }$VERSION_TYPE)..." cd packages/core - npm version $VERSION_TYPE --no-git-tag-version + if [[ -n "$CUSTOM_VERSION" ]]; then + npm version "$CUSTOM_VERSION" --no-git-tag-version --allow-same-version + else + npm version $VERSION_TYPE --no-git-tag-version + fi CORE_VERSION=$(node -p "require('./package.json').version") cd ../.. @@ -223,10 +238,13 @@ else # Compute next prerelease version with 0-9 rollover by publication time print_status "Computing next $PRERELEASE_ID version with rollover logic..." cd packages/core - export PRERELEASE_ID - export VERSION_TYPE - export PKG='@avail-project/nexus-core' - PRERELEASE_VERSION=$(node -e ' + if [[ -n "$CUSTOM_VERSION" ]]; then + PRERELEASE_VERSION="$CUSTOM_VERSION" + else + export PRERELEASE_ID + export VERSION_TYPE + export PKG='@avail-project/nexus-core' + PRERELEASE_VERSION=$(node -e ' const cp=require("child_process"); const fs=require("fs"); const pkg=process.env.PKG; @@ -258,6 +276,7 @@ if(latestPre){ } console.log(next); ') + fi export PRERELEASE_VERSION npm version "$PRERELEASE_VERSION" --no-git-tag-version --allow-same-version cd ../.. diff --git a/scripts/release-widgets.sh b/scripts/release-widgets.sh index 4d044dcf..3c9107eb 100755 --- a/scripts/release-widgets.sh +++ b/scripts/release-widgets.sh @@ -113,7 +113,7 @@ print_header "Starting @avail-project/nexus-widgets $RELEASE_TYPE release ($VERS # Run type checking print_status "Running type check..." -pnpm run typecheck +pnpm run typecheck:widgets # Clean previous builds print_status "Cleaning previous builds..." From 981fbfb26d4361fb2afc5b30c6bc0b58787a5a22 Mon Sep 17 00:00:00 2001 From: Amartya Singh <53113365+decocereus@users.noreply.github.com> Date: Wed, 12 Nov 2025 17:10:30 +0530 Subject: [PATCH 02/51] feat: removed widgets ^-^ (#63) --- README.md | 51 +- package.json | 17 +- packages/widgets/README.md | 758 ------------ packages/widgets/package.json | 85 -- packages/widgets/postcss.config.js | 7 - packages/widgets/rollup.config.mjs | 127 -- .../bridge-execute/bridge-execute-button.tsx | 47 - .../bridge-execute/bridge-execute-modal.tsx | 129 -- .../src/components/bridge/bridge-button.tsx | 21 - .../src/components/bridge/bridge-modal.tsx | 99 -- .../src/components/icons/AvailLogo.tsx | 29 - .../src/components/icons/CheckIcon.tsx | 22 - .../src/components/icons/ChevronDownIcon.tsx | 22 - .../src/components/icons/ChevronUpIcon.tsx | 22 - .../widgets/src/components/icons/CircleX.tsx | 24 - .../widgets/src/components/icons/Clock.tsx | 14 - .../src/components/icons/ExternalLink.tsx | 24 - .../widgets/src/components/icons/Maximize.tsx | 39 - .../widgets/src/components/icons/Minimize.tsx | 41 - .../src/components/icons/MoneyCircles.tsx | 22 - .../widgets/src/components/icons/Plus.tsx | 23 - .../src/components/icons/SmallAvailLogo.tsx | 550 --------- .../src/components/icons/SolarWallet.tsx | 18 - .../src/components/icons/TwoCircles.tsx | 15 - .../widgets/src/components/icons/index.ts | 10 - .../src/components/motion/base-modal.tsx | 25 - .../src/components/motion/button-motion.tsx | 63 - .../src/components/motion/dialog-motion.tsx | 246 ---- .../components/motion/drag-constraints.tsx | 33 - .../widgets/src/components/motion/drawer.tsx | 187 --- .../src/components/motion/form-field.tsx | 32 - .../widgets/src/components/motion/input.tsx | 20 - .../src/components/motion/label-motion.tsx | 22 - .../src/components/motion/loading-dots.tsx | 38 - .../src/components/motion/progress-motion.tsx | 47 - .../src/components/motion/pull-up-words.tsx | 29 - .../widgets/src/components/motion/shimmer.tsx | 5 - .../components/motion/slide-transition.tsx | 70 -- .../src/components/motion/success-ripple.tsx | 86 -- .../src/components/motion/text-loader.tsx | 36 - .../motion/three-stage-progress.tsx | 140 --- .../processing/processor-full-card.tsx | 420 ------- .../processing/processor-mini-card.tsx | 268 ---- .../transaction-processor-shell.tsx | 234 ---- .../processing/transaction-simulation.tsx | 77 -- .../src/components/shared/action-buttons.tsx | 67 - .../src/components/shared/address-field.tsx | 44 - .../src/components/shared/allowance-form.tsx | 265 ---- .../src/components/shared/amount-input.tsx | 136 --- .../src/components/shared/chain-select.tsx | 145 --- .../components/shared/destination-drawer.tsx | 157 --- .../shared/enhanced-info-message.tsx | 143 --- .../widgets/src/components/shared/icons.tsx | 116 -- .../src/components/shared/info-message.tsx | 39 - .../components/shared/prefilled-inputs.tsx | 78 -- .../shared/swap-prefilled-inputs.tsx | 89 -- .../src/components/shared/token-select.tsx | 139 --- .../shared/transaction-details-drawer.tsx | 390 ------ .../src/components/shared/unified-balance.tsx | 287 ----- .../shared/unified-transaction-form.tsx | 378 ------ .../shared/unified-transaction-modal.tsx | 324 ----- .../src/components/swap/swap-button.tsx | 27 - .../src/components/swap/swap-modal.tsx | 67 - .../components/transfer/transfer-button.tsx | 26 - .../components/transfer/transfer-modal.tsx | 93 -- .../BridgeAndExecuteController.tsx | 198 --- .../src/controllers/BridgeController.tsx | 125 -- .../src/controllers/TransferController.tsx | 135 --- .../src/hooks/useListenTransaction.tsx | 363 ------ packages/widgets/src/hooks/useNexus.tsx | 16 - .../widgets/src/hooks/useOutsideClick.tsx | 25 - packages/widgets/src/index.ts | 13 - .../src/providers/InternalNexusProvider.tsx | 1073 ----------------- .../widgets/src/providers/NexusProvider.tsx | 21 - packages/widgets/src/styles/globals.css | 248 ---- packages/widgets/src/types/index.ts | 420 ------- packages/widgets/src/utils/balance-utils.ts | 95 -- packages/widgets/src/utils/token-utils.ts | 721 ----------- packages/widgets/src/utils/utils.ts | 626 ---------- packages/widgets/tsconfig.json | 21 - scripts/README.md | 24 +- scripts/release-widgets.sh | 361 ------ 82 files changed, 8 insertions(+), 11781 deletions(-) delete mode 100644 packages/widgets/README.md delete mode 100644 packages/widgets/package.json delete mode 100644 packages/widgets/postcss.config.js delete mode 100644 packages/widgets/rollup.config.mjs delete mode 100644 packages/widgets/src/components/bridge-execute/bridge-execute-button.tsx delete mode 100644 packages/widgets/src/components/bridge-execute/bridge-execute-modal.tsx delete mode 100644 packages/widgets/src/components/bridge/bridge-button.tsx delete mode 100644 packages/widgets/src/components/bridge/bridge-modal.tsx delete mode 100644 packages/widgets/src/components/icons/AvailLogo.tsx delete mode 100644 packages/widgets/src/components/icons/CheckIcon.tsx delete mode 100644 packages/widgets/src/components/icons/ChevronDownIcon.tsx delete mode 100644 packages/widgets/src/components/icons/ChevronUpIcon.tsx delete mode 100644 packages/widgets/src/components/icons/CircleX.tsx delete mode 100644 packages/widgets/src/components/icons/Clock.tsx delete mode 100644 packages/widgets/src/components/icons/ExternalLink.tsx delete mode 100644 packages/widgets/src/components/icons/Maximize.tsx delete mode 100644 packages/widgets/src/components/icons/Minimize.tsx delete mode 100644 packages/widgets/src/components/icons/MoneyCircles.tsx delete mode 100644 packages/widgets/src/components/icons/Plus.tsx delete mode 100644 packages/widgets/src/components/icons/SmallAvailLogo.tsx delete mode 100644 packages/widgets/src/components/icons/SolarWallet.tsx delete mode 100644 packages/widgets/src/components/icons/TwoCircles.tsx delete mode 100644 packages/widgets/src/components/icons/index.ts delete mode 100644 packages/widgets/src/components/motion/base-modal.tsx delete mode 100644 packages/widgets/src/components/motion/button-motion.tsx delete mode 100644 packages/widgets/src/components/motion/dialog-motion.tsx delete mode 100644 packages/widgets/src/components/motion/drag-constraints.tsx delete mode 100644 packages/widgets/src/components/motion/drawer.tsx delete mode 100644 packages/widgets/src/components/motion/form-field.tsx delete mode 100644 packages/widgets/src/components/motion/input.tsx delete mode 100644 packages/widgets/src/components/motion/label-motion.tsx delete mode 100644 packages/widgets/src/components/motion/loading-dots.tsx delete mode 100644 packages/widgets/src/components/motion/progress-motion.tsx delete mode 100644 packages/widgets/src/components/motion/pull-up-words.tsx delete mode 100644 packages/widgets/src/components/motion/shimmer.tsx delete mode 100644 packages/widgets/src/components/motion/slide-transition.tsx delete mode 100644 packages/widgets/src/components/motion/success-ripple.tsx delete mode 100644 packages/widgets/src/components/motion/text-loader.tsx delete mode 100644 packages/widgets/src/components/motion/three-stage-progress.tsx delete mode 100644 packages/widgets/src/components/processing/processor-full-card.tsx delete mode 100644 packages/widgets/src/components/processing/processor-mini-card.tsx delete mode 100644 packages/widgets/src/components/processing/transaction-processor-shell.tsx delete mode 100644 packages/widgets/src/components/processing/transaction-simulation.tsx delete mode 100644 packages/widgets/src/components/shared/action-buttons.tsx delete mode 100644 packages/widgets/src/components/shared/address-field.tsx delete mode 100644 packages/widgets/src/components/shared/allowance-form.tsx delete mode 100644 packages/widgets/src/components/shared/amount-input.tsx delete mode 100644 packages/widgets/src/components/shared/chain-select.tsx delete mode 100644 packages/widgets/src/components/shared/destination-drawer.tsx delete mode 100644 packages/widgets/src/components/shared/enhanced-info-message.tsx delete mode 100644 packages/widgets/src/components/shared/icons.tsx delete mode 100644 packages/widgets/src/components/shared/info-message.tsx delete mode 100644 packages/widgets/src/components/shared/prefilled-inputs.tsx delete mode 100644 packages/widgets/src/components/shared/swap-prefilled-inputs.tsx delete mode 100644 packages/widgets/src/components/shared/token-select.tsx delete mode 100644 packages/widgets/src/components/shared/transaction-details-drawer.tsx delete mode 100644 packages/widgets/src/components/shared/unified-balance.tsx delete mode 100644 packages/widgets/src/components/shared/unified-transaction-form.tsx delete mode 100644 packages/widgets/src/components/shared/unified-transaction-modal.tsx delete mode 100644 packages/widgets/src/components/swap/swap-button.tsx delete mode 100644 packages/widgets/src/components/swap/swap-modal.tsx delete mode 100644 packages/widgets/src/components/transfer/transfer-button.tsx delete mode 100644 packages/widgets/src/components/transfer/transfer-modal.tsx delete mode 100644 packages/widgets/src/controllers/BridgeAndExecuteController.tsx delete mode 100644 packages/widgets/src/controllers/BridgeController.tsx delete mode 100644 packages/widgets/src/controllers/TransferController.tsx delete mode 100644 packages/widgets/src/hooks/useListenTransaction.tsx delete mode 100644 packages/widgets/src/hooks/useNexus.tsx delete mode 100644 packages/widgets/src/hooks/useOutsideClick.tsx delete mode 100644 packages/widgets/src/index.ts delete mode 100644 packages/widgets/src/providers/InternalNexusProvider.tsx delete mode 100644 packages/widgets/src/providers/NexusProvider.tsx delete mode 100644 packages/widgets/src/styles/globals.css delete mode 100644 packages/widgets/src/types/index.ts delete mode 100644 packages/widgets/src/utils/balance-utils.ts delete mode 100644 packages/widgets/src/utils/token-utils.ts delete mode 100644 packages/widgets/src/utils/utils.ts delete mode 100644 packages/widgets/tsconfig.json delete mode 100755 scripts/release-widgets.sh diff --git a/README.md b/README.md index 6954e509..1ecd52c8 100644 --- a/README.md +++ b/README.md @@ -19,19 +19,6 @@ npm install @avail-project/nexus-core [📖 Core Documentation](./packages/core/README.md) -### [@avail-project/nexus-widgets](./packages/widgets/) - -**React components for cross-chain transactions** - -- Ready-to-use React widgets -- Drop-in bridge, transfer, bridge-and-execute and execute components - -```bash -npm install @avail-project/nexus-widgets -``` - -[Widgets Documentation](./packages/widgets/README.md) - ## Supported Networks ### Mainnet Chains @@ -87,30 +74,9 @@ const result = await sdk.bridge({ }); ``` -### React Widgets - -```typescript -import { NexusProvider, BridgeButton } from '@avail-project/nexus-widgets'; - -function App() { - return ( - - - {({ onClick, isLoading }) => ( - - )} - - - ); -} -``` - ## Documentation - [Core SDK Documentation](./packages/core/README.md) - Headless SDK API reference -- [Widgets Documentation](./packages/widgets/README.md) - React components guide - [API Documentation](https://docs.availproject.org/api-reference/avail-nexus-sdk) ## 🛠️ Development @@ -132,7 +98,6 @@ pnpm test - Internal shared code stays in `@nexus/commons` (private). It is imported in source during development and bundled into `dist/commons` at build so consumers never install it directly. - Published package names used everywhere (dev and build): - `@avail-project/nexus-core` - - `@avail-project/nexus-widgets` ### TS path mapping for local DX @@ -183,19 +148,6 @@ pnpm -r up typescript rollup decimal.js viem ./scripts/release-core.sh prod patch --yes ``` -### Widgets examples - -```bash -# Interactive dev prerelease (requires a matching core prerelease on npm) -./scripts/release-widgets.sh - -# Non-interactive dev prerelease (beta), resolves latest core beta by timestamp, dry-run -./scripts/release-widgets.sh dev patch beta --yes --dry-run - -# Production release (patch) – ensure core is published first -./scripts/release-widgets.sh prod patch --yes -``` - ### Local tarballs (no publish) ```bash @@ -203,8 +155,7 @@ pnpm -r up typescript rollup decimal.js viem ./scripts/local-pack.sh # In another project -pnpm add /absolute/path/to/dist-tarballs/avail-project-nexus-core-*.tgz \ - /absolute/path/to/dist-tarballs/avail-project-nexus-widgets-*.tgz +pnpm add /absolute/path/to/dist-tarballs/avail-project-nexus-core-*.tgz ``` ## License diff --git a/package.json b/package.json index 286d7a8a..a8a718d5 100644 --- a/package.json +++ b/package.json @@ -6,22 +6,17 @@ "scripts": { "build:commons": "pnpm -F @nexus/commons build", "build:core": "pnpm -F @nexus/commons build && pnpm -F @avail-project/nexus-core build", - "build:widgets": "pnpm -F @nexus/commons build && pnpm -F @avail-project/nexus-widgets build", - "build": "pnpm run build:core && pnpm run build:widgets", + "build": "pnpm run build:core", "dev:core": "pnpm -F @avail-project/nexus-core dev", - "dev:widgets": "pnpm -F @avail-project/nexus-widgets dev", - "dev": "pnpm run dev:core & pnpm run dev:widgets", + "dev": "pnpm run dev:core", "format": "prettier --write \"packages/**/*.{ts,tsx}\"", "prepare": "husky install", "typecheck:core": "pnpm -F @avail-project/nexus-core typecheck", - "typecheck:widgets": "pnpm -F @avail-project/nexus-widgets typecheck", "typecheck": "pnpm -r typecheck", - "clean": "rimraf packages/widgets/dist packages/core/dist packages/commons/dist", - "clean:modules": "rimraf node_modules packages/widgets/node_modules packages/core/node_modules packages/commons/node_modules", + "clean": "rimraf packages/core/dist packages/commons/dist", + "clean:modules": "rimraf node_modules packages/core/node_modules packages/commons/node_modules", "release:core:dev": "./scripts/release-core.sh dev", - "release:core:prod": "./scripts/release-core.sh prod", - "release:widgets:dev": "./scripts/release-widgets.sh dev", - "release:widgets:prod": "./scripts/release-widgets.sh prod" + "release:core:prod": "./scripts/release-core.sh prod" }, "keywords": [ "nexus", @@ -37,7 +32,7 @@ "balance", "sdk" ], - "author": "decocereus", + "author": "decocereus, makyl", "license": "MIT", "pnpm": { "overrides": { diff --git a/packages/widgets/README.md b/packages/widgets/README.md deleted file mode 100644 index af29f1c1..00000000 --- a/packages/widgets/README.md +++ /dev/null @@ -1,758 +0,0 @@ -# @avail-project/nexus-widgets - -Ready-to-use React components for cross-chain transactions. Drop-in widgets that provide complete bridge, transfer, and execute flows with customizable styling. - -## Installation - -```bash -npm install @avail-project/nexus-widgets -``` - -**Required peer dependencies:** - -```bash -npm install react react-dom viem -``` - -## Quick Start - -### Wrap your app with `NexusProvider` - -```tsx -import { NexusProvider } from '@avail-project/nexus-widgets'; - -export default function App() { - return ( - - - - ); -} -``` - -### Forward the user's wallet provider - -```tsx -import { useEffect } from 'react'; -import { useAccount } from '@wagmi/react'; // any wallet lib works -import { useNexus } from '@avail-project/nexus-widgets'; - -export function WalletBridge() { - const { connector, isConnected } = useAccount(); - const { setProvider } = useNexus(); - - useEffect(() => { - if (isConnected && connector?.getProvider) { - connector.getProvider().then(setProvider); - } - }, [isConnected, connector, setProvider]); - - return null; -} -``` - -### Alternative: Manual SDK Initialization - -For developers who need to use SDK methods directly (like `getUnifiedBalances`) before using UI components: - -```tsx -import { useNexus } from '@avail-project/nexus-widgets'; - -function MyComponent() { - const { initializeSdk, sdk, isSdkInitialized } = useNexus(); - - const handleInitialize = async () => { - const provider = await window.ethereum; // or get from your wallet library - await initializeSdk(provider); // Initializes both SDK and UI state - - // Now you can use SDK methods directly - // false by default to get CA applicable token balances - // true to get all the balances including the swappable tokens - const balances = await sdk.getUnifiedBalances(); - console.log('Balances:', balances); - - // UI components will already be initialized when used - }; - - return ( - - ); -} -``` - -**Benefits of manual initialization:** - -- Use SDK methods immediately after initialization -- No duplicate initialization when UI components are used -- Full control over initialization timing -- Access to unified balances and other SDK features before transactions - -### Use Widgets - -```tsx -import { - BridgeButton, - TransferButton, - BridgeAndExecuteButton, - SwapButton, - TOKEN_CONTRACT_ADDRESSES, - TOKEN_METADATA, - SUPPORTED_CHAINS, - DESTINATION_SWAP_TOKENS, - type SUPPORTED_TOKENS, - type SUPPORTED_CHAIN_IDS -} from '@avail-project/nexus-widgets'; -import { parseUnits } from 'viem'; - -/* Bridge ----------------------------------------------------------- */ - - {({ onClick, isLoading }) => ( - - )} - - -/* Transfer --------------------------------------------------------- */ - - {({ onClick }) => Send Funds} - - -/* Bridge + Execute ------------------------------------------------- */ - { - const decimals = TOKEN_METADATA[token].decimals - const amountWei = parseUnits(amount, decimals) - const tokenAddr = TOKEN_CONTRACT_ADDRESSES[token][_chainId] - return { functionParams: [tokenAddr, amountWei, user, 0] } - }} - prefill={{ - toChainId: 42161, - token: 'USDT', - }} - > - {({ onClick, isLoading }) => ( - - )} - - -/* Swap | EXACT_IN only ------------------------------------------------------------- */ - - {({ onClick, isLoading }) => ( - - )} - -``` - -## Component APIs - -### `BridgeButton` - -Bridge tokens between chains with a customizable button interface. - -```tsx -interface BridgeButtonProps { - title?: string; // Will appear once intialization is completed - prefill?: Partial; // chainId, token, amount - className?: string; - children(props: { onClick(): void; isLoading: boolean }): React.ReactNode; -} -``` - -**Example:** - -```tsx - - {({ onClick, isLoading }) => ( - - )} - -``` - -### `TransferButton` - -Send tokens to any address with automatic optimization (direct transfer when possible). - -```tsx -interface TransferButtonProps { - title?: string; // Will appear once intialization is completed - prefill?: Partial; // chainId, token, amount, recipient - className?: string; - children(props: { onClick(): void; isLoading: boolean }): React.ReactNode; -} -``` - -**Example:** - -```tsx - - {({ onClick, isLoading }) => ( - - )} - -``` - -### `BridgeAndExecuteButton` - -Bridge tokens and execute a smart contract function in a single flow. - -```tsx -type DynamicParamBuilder = ( - token: SUPPORTED_TOKENS, - amount: string, - chainId: SUPPORTED_CHAINS_IDS, - userAddress: `0x${string}`, -) => { - functionParams: readonly unknown[]; - value?: string; // wei; defaults to "0" -}; - -interface BridgeAndExecuteButtonProps { - title?: string; // Will appear once intialization is completed - contractAddress: `0x${string}`; // REQUIRED - contractAbi: Abi; // REQUIRED - functionName: string; // REQUIRED - buildFunctionParams: DynamicParamBuilder; // REQUIRED - prefill?: { toChainId?: number; token?: SUPPORTED_TOKENS; amount?: string }; - className?: string; - children(props: { onClick(): void; isLoading: boolean; disabled: boolean }): React.ReactNode; -} -``` - -**Example - Aave Supply:** - -```tsx - { - const decimals = TOKEN_METADATA[token].decimals; - const amountWei = parseUnits(amount, decimals); - const tokenAddress = TOKEN_CONTRACT_ADDRESSES[token][chainId]; - return { - functionParams: [tokenAddress, amountWei, userAddress, 0], - }; - }} - prefill={{ toChainId: 1, token: 'USDC' }} -> - {({ onClick, isLoading, disabled }) => ( - - )} - -``` - -`buildFunctionParams` receives the validated UX input (token, amount, destination chainId) plus the **connected wallet address** and must return the encoded `functionParams` (and optional ETH `value`) used in the destination call. - -Nexus then: - -1. Bridges the asset to `toChainId` -2. Sets ERC-20 allowance if required -3. Executes `contractAddress.functionName(functionParams, { value })` - -### `SwapButton` - -Cross-chain token swapping with support for both EXACT_IN and EXACT_OUT modes. - -```tsx -interface SwapButtonProps { - title?: string; // Will appear once initialization is completed - prefill?: Omit; // fromChainID, toChainID, fromTokenAddress, toTokenAddress, fromAmount - className?: string; - children(props: { onClick(): void; isLoading: boolean }): React.ReactNode; -} - -interface SwapInputData { - fromChainID?: number; - toChainID?: number; - fromTokenAddress?: string; - toTokenAddress?: string; - fromAmount?: string | number; - toAmount?: string | number; -} -``` - -**EXACT_IN Swap Example:** - -```tsx -// Swap exactly 100 USDC from Polygon to LDO on Arbitrum - - {({ onClick, isLoading }) => ( - - )} - -``` - -## Swap Utilities - -### Discovering Available Swap Options - -```tsx -import { useNexus, DESTINATION_SWAP_TOKENS } from '@avail-project/nexus-widgets'; - -function SwapOptionsExample() { - const { sdk, isSdkInitialized } = useNexus(); - const [swapOptions, setSwapOptions] = useState(null); - - useEffect(() => { - if (isSdkInitialized) { - // Get supported source chains and tokens for swaps - const supportedOptions = sdk.utils.getSwapSupportedChainsAndTokens(); - setSwapOptions(supportedOptions); - } - }, [sdk, isSdkInitialized]); - - return ( -
- {/* Source chains and tokens */} - {swapOptions?.map(chain => ( -
-

{chain.name} (Chain ID: {chain.id})

- {chain.tokens.map(token => ( -
- {token.symbol}: {token.tokenAddress} -
- ))} -
- ))} - - {/* Popular destination options */} -

Popular Destinations:

- {Array.from(DESTINATION_SWAP_TOKENS.entries()).map(([chainId, tokens]) => ( -
-

Chain {chainId}

- {tokens.map(token => ( -
- {token.symbol} - {token.name} -
- ))} -
- ))} -
- ); -} -``` - -**Key Points:** -- **Source restrictions**: Source chains/tokens are limited to what `getSwapSupportedChainsAndTokens()` returns -- **Destination flexibility**: Destination can be any supported chain and token address -- **DESTINATION_SWAP_TOKENS**: Provides popular destination options for UI building, but is not exhaustive - -## Prefill Behavior - -| Widget | Supported keys | Locked in UI | -| ------------------------ | ------------------------------------------------------------------ | ------------ | -| `BridgeButton` | `chainId`, `token`, `amount` | ✅ | -| `TransferButton` | `chainId`, `token`, `amount`, `recipient` | ✅ | -| `BridgeAndExecuteButton` | `toChainId`, `token`, `amount` | ✅ | -| `SwapButton` | `fromChainID`, `toChainID`, `fromTokenAddress`, `toTokenAddress`, `fromAmount`, `toAmount` | ✅ | - -Values passed in `prefill` appear as **read-only** fields, enforcing your desired flow. - -## 📱 Widget Examples - -### Cross-Chain Swapping - -```tsx -// Multi-step cross-chain swap with destination selection - - {({ onClick, isLoading }) => ( -
-

Cross-Chain Swap

-

Swap tokens across any supported chains

- -
- )} -
- -// Fixed-route swap for arbitrage or specific pairs - - {({ onClick, isLoading }) => ( -
-

Arbitrage Opportunity

-

Better WETH rates on Optimism

- -
- )} -
-``` - -### DeFi Protocol Integration - -```tsx -// Compound V3 Supply Widget - { - const decimals = TOKEN_METADATA[token].decimals; - const amountWei = parseUnits(amount, decimals); - const tokenAddress = TOKEN_CONTRACT_ADDRESSES[token][chainId]; - return { - functionParams: [tokenAddress, amountWei], - }; - }} - prefill={{ toChainId: 1, token: 'USDC' }} -> - {({ onClick, isLoading }) => ( -
-

Earn with Compound

- -
- )} -
-``` - -### Simple Payment Flow - -```tsx -// Payment button for e-commerce - - {({ onClick, isLoading }) => ( - - )} - -``` - -### Multi-Chain Liquidity - -```tsx -// Bridge to specific chain for better rates - - {({ onClick, isLoading }) => ( -
-

Better rates on Arbitrum

-

Save 60% on gas fees

- -
- )} -
-``` - -## Advanced Usage - -### Custom Loading States - -```tsx - - {({ onClick, isLoading }) => ( - - )} - -``` - -### Error Handling - -```tsx -function MyBridgeComponent() { - const [error, setError] = useState(null); - - return ( -
- {error &&
{error}
} - - - {({ onClick, isLoading }) => ( - - )} - -
- ); -} -``` - -### Access to SDK Methods - -```tsx -function BalanceAwareWidget() { - const { sdk, isSdkInitialized } = useNexus(); - const [balances, setBalances] = useState([]); - - useEffect(() => { - if (isSdkInitialized) { - sdk.getUnifiedBalances().then(setBalances); - } - }, [sdk, isSdkInitialized]); - - return ( -
-
- {balances.map((balance) => ( -
- {balance.symbol}: {balance.balance} -
- ))} -
- - - {({ onClick, isLoading }) => ( - - )} - -
- ); -} -``` - -## Best Practices - -### 1. Always simulate first - -```tsx -// Good: Let the widget handle simulation internally - - {({ onClick, isLoading }) => ( - - )} - -``` - -### 2. Handle loading states gracefully - -```tsx -// Good: Provide clear feedback - - {({ onClick, isLoading }) => ( - - )} - -``` - -### 3. Use appropriate confirmation levels - -```tsx -// Good: For high-value transactions, the widget will automatically -// request higher confirmation levels - - {/* Widget handles confirmation requirements */} - -``` - -### 4. Clean up resources - -```tsx -function MyComponent() { - const { deinitializeSdk } = useNexus(); - - useEffect(() => { - return () => { - deinitializeSdk(); - }; - }, []); - - return {/* ... */}; -} -``` - -## Supported Networks & Tokens - -### Mainnet Chains - -| Network | Chain ID | Native Currency | Status | -| --------- | -------- | --------------- | ------ | -| Ethereum | 1 | ETH | ✅ | -| Optimism | 10 | ETH | ✅ | -| Polygon | 137 | MATIC | ✅ | -| Arbitrum | 42161 | ETH | ✅ | -| Avalanche | 43114 | AVAX | ✅ | -| Base | 8453 | ETH | ✅ | -| Scroll | 534352 | ETH | ✅ | -| Sophon | 50104 | SOPH | ✅ | -| Kaia | 8217 | KAIA | ✅ | -| BNB | 56 | BNB | ✅ | -| HyperEVM | 999 | HYPE | ✅ | - -### Testnet Chains - -| Network | Chain ID | Native Currency | Status | -| ---------------- | -------- | --------------- | ------ | -| Optimism Sepolia | 11155420 | ETH | ✅ | -| Polygon Amoy | 80002 | MATIC | ✅ | -| Arbitrum Sepolia | 421614 | ETH | ✅ | -| Base Sepolia | 84532 | ETH | ✅ | -| Sepolia | 11155111 | ETH | ✅ | -| Monad Testnet | 10143 | MON | ✅ | - -### Supported Tokens - -| Token | Name | Decimals | Networks | -| ----- | ---------- | -------- | -------------- | -| ETH | Ethereum | 18 | All EVM chains | -| USDC | USD Coin | 6 | All supported | -| USDT | Tether USD | 6 | All supported | - -## 🔗 Links - -- [GitHub Repository](https://github.com/availproject/nexus-sdk) -- [API Documentation](https://docs.availproject.org/api-reference/avail-nexus-sdk) diff --git a/packages/widgets/package.json b/packages/widgets/package.json deleted file mode 100644 index 57c20dec..00000000 --- a/packages/widgets/package.json +++ /dev/null @@ -1,85 +0,0 @@ -{ - "name": "@avail-project/nexus-widgets", - "version": "0.0.6", - "description": "Nexus React components for cross-chain transactions", - "main": "./dist/index.js", - "module": "./dist/index.esm.js", - "types": "./dist/index.d.ts", - "files": [ - "dist", - "README.md" - ], - "scripts": { - "build": "rollup -c && pnpm run copy:commons", - "copy:commons": "mkdir -p dist/commons && cp -R ../commons/dist/* dist/commons/ || true", - "dev": "rollup -c -w", - "typecheck": "tsc --noEmit" - }, - "sideEffects": [ - "**/*.css" - ], - "exports": { - ".": { - "types": "./dist/index.d.ts", - "import": "./dist/index.esm.js", - "require": "./dist/index.js" - } - }, - "keywords": [ - "nexus", - "react", - "components", - "widgets", - "blockchain", - "bridge", - "web3", - "ui" - ], - "author": "decocereus", - "license": "MIT", - "dependencies": { - "@lottiefiles/dotlottie-react": "0.14.2", - "@nexus/commons": "workspace:*", - "@avail-project/nexus-core": "workspace:*", - "class-variance-authority": "0.7.1", - "clsx": "2.1.1", - "decimal.js": "10.4.3", - "motion": "12.23.0", - "tailwind-merge": "3.3.1" - }, - "devDependencies": { - "@rollup/plugin-commonjs": "^25.0.8", - "@rollup/plugin-json": "6.1.0", - "@rollup/plugin-node-resolve": "^15.3.1", - "@rollup/plugin-typescript": "^11.1.6", - "@tailwindcss/postcss": "4.1.10", - "@types/react": "19.1.8", - "@types/react-dom": "19.1.6", - "autoprefixer": "10.4.21", - "postcss": "8.5.6", - "postcss-import": "16.1.1", - "postcss-nesting": "13.0.2", - "rollup": "^4.52.4", - "rollup-plugin-dts": "^6.2.3", - "rollup-plugin-postcss": "4.0.2", - "rollup-plugin-typescript2": "0.36.0", - "tailwindcss": "4.1.10", - "typescript": "^5.9.3" - }, - "peerDependencies": { - "react": ">=16.8.0", - "react-dom": ">=16.8.0", - "viem": "^2.0.0" - }, - "peerDependenciesMeta": { - "react": { - "optional": false - }, - "react-dom": { - "optional": false - } - }, - "publishConfig": { - "access": "public" - } -} diff --git a/packages/widgets/postcss.config.js b/packages/widgets/postcss.config.js deleted file mode 100644 index 52e338af..00000000 --- a/packages/widgets/postcss.config.js +++ /dev/null @@ -1,7 +0,0 @@ -module.exports = { - plugins: { - 'postcss-import': {}, - '@tailwindcss/postcss': {}, - 'autoprefixer': {}, - }, -} \ No newline at end of file diff --git a/packages/widgets/rollup.config.mjs b/packages/widgets/rollup.config.mjs deleted file mode 100644 index 6023d136..00000000 --- a/packages/widgets/rollup.config.mjs +++ /dev/null @@ -1,127 +0,0 @@ -import resolve from '@rollup/plugin-node-resolve'; -import commonjs from '@rollup/plugin-commonjs'; -import typescript from 'rollup-plugin-typescript2'; -import json from '@rollup/plugin-json'; -import alias from '@rollup/plugin-alias'; -import dts from 'rollup-plugin-dts'; -import postcss from 'rollup-plugin-postcss'; -import { defineConfig } from 'rollup'; -import { createRequire } from 'module'; - -const require = createRequire(import.meta.url); -const packageJson = require('./package.json'); - -const isProduction = process.env.NODE_ENV === 'production'; -const shouldGenerateSourceMaps = false; - -// Base configuration for widgets (includes React, CSS) -const baseConfig = { - input: 'src/index.ts', - plugins: [ - alias({ - entries: [{ find: '@nexus/commons', replacement: '../commons/dist/index.esm.js' }], - }), - json(), - resolve({ - browser: true, - preferBuiltins: false, - exportConditions: ['browser', 'module', 'import'], - dedupe: ['react', 'react-dom'], - }), - commonjs({ - include: /node_modules/, - transformMixedEsModules: true, - ignoreTryCatch: false, - }), - // PostCSS plugin for CSS processing - postcss({ - inject: true, - extract: false, - minimize: isProduction, - sourceMap: shouldGenerateSourceMaps, - modules: false, - config: { - path: './postcss.config.js', - }, - }), - typescript({ - tsconfig: './tsconfig.json', - useTsconfigDeclarationDir: true, - }), - ], - external: [ - // Peer dependencies that consumers should install - ...Object.keys(packageJson.peerDependencies || {}), - /^react/, - /^react-dom/, - /^viem/, - // External dependencies that consumers should install - '@lottiefiles/dotlottie-react', - /^motion/, - 'decimal.js', - '@avail-project/nexus-core', - ], - treeshake: { - moduleSideEffects: false, - propertyReadSideEffects: false, - unknownGlobalSideEffects: false, - }, -}; - -export default defineConfig([ - // Build configurations - { - ...baseConfig, - output: [ - { - file: 'dist/index.js', - format: 'cjs', - sourcemap: shouldGenerateSourceMaps, - exports: 'named', - interop: 'auto', - inlineDynamicImports: true, - // no path rewrite needed when source imports already use @avail-project/nexus-core - }, - { - file: 'dist/index.esm.js', - format: 'esm', - sourcemap: shouldGenerateSourceMaps, - exports: 'named', - inlineDynamicImports: true, - // no path rewrite needed when source imports already use @avail-project/nexus-core - }, - ], - }, - - // TypeScript declarations - { - input: 'src/index.ts', - output: [{ file: 'dist/index.d.ts', format: 'esm' }], - plugins: [ - resolve({ - browser: true, - preferBuiltins: false, - }), - dts({ exclude: ['**/*.css'] }), - // Rewrite import specifiers in generated d.ts - { - name: 'rewrite-commons-and-core-imports-dts', - renderChunk(code) { - return code - .replace(/@nexus\/commons\/constants/g, './commons/constants') - .replace(/@nexus\/commons/g, './commons'); - }, - }, - ], - external: [ - ...Object.keys(packageJson.peerDependencies || {}), - /^react/, - /^viem/, - '@lottiefiles/dotlottie-react', - /^motion/, - 'decimal.js', - '@avail-project/nexus-core', - /\.css$/, - ], - }, -]); diff --git a/packages/widgets/src/components/bridge-execute/bridge-execute-button.tsx b/packages/widgets/src/components/bridge-execute/bridge-execute-button.tsx deleted file mode 100644 index 9ef811bc..00000000 --- a/packages/widgets/src/components/bridge-execute/bridge-execute-button.tsx +++ /dev/null @@ -1,47 +0,0 @@ -'use client'; -import { useInternalNexus } from '../../providers/InternalNexusProvider'; -import { logger } from '@nexus/commons'; -import BridgeAndExecuteModal from './bridge-execute-modal'; -import { BridgeAndExecuteButtonProps } from '../../types'; - -export function BridgeAndExecuteButton({ - contractAddress, - contractAbi, - functionName, - buildFunctionParams, - prefill, - children, - className, - title, -}: BridgeAndExecuteButtonProps) { - const { startTransaction, activeTransaction } = useInternalNexus(); - - const isLoading = - activeTransaction?.status === 'processing' || activeTransaction?.reviewStatus === 'simulating'; - - if (!contractAddress || !contractAbi || !functionName || !buildFunctionParams) { - logger.warn('BridgeAndExecuteButton: Missing required contract props or builder'); - return null; - } - - const handleClick = () => { - const transactionData = { - ...(prefill || {}), - contractAddress, - contractAbi, - functionName, - buildFunctionParams, - }; - - startTransaction('bridgeAndExecute', transactionData); - }; - - return ( - <> -
- {children({ onClick: handleClick, isLoading, disabled: false })} -
- - - ); -} diff --git a/packages/widgets/src/components/bridge-execute/bridge-execute-modal.tsx b/packages/widgets/src/components/bridge-execute/bridge-execute-modal.tsx deleted file mode 100644 index b982fd3c..00000000 --- a/packages/widgets/src/components/bridge-execute/bridge-execute-modal.tsx +++ /dev/null @@ -1,129 +0,0 @@ -import { UnifiedTransactionModal } from '../shared/unified-transaction-modal'; -import { type BridgeAndExecuteParams, type BridgeAndExecuteSimulationResult } from '@nexus/commons'; -import { useInternalNexus } from '../../providers/InternalNexusProvider'; -import PrefilledInputs from '../shared/prefilled-inputs'; - -type InputData = { - toChainId?: number; - token?: string; - amount?: string | number; -}; - -function BridgeExecuteForm({ - inputData, - onUpdate, - disabled, - prefillFields = {}, -}: { - inputData: any; - onUpdate: (data: BridgeAndExecuteParams) => void; - disabled: boolean; - prefillFields?: { - toChainId?: boolean; - token?: boolean; - amount?: boolean; - }; -}) { - const { activeController } = useInternalNexus(); - - if (!activeController) return null; - - const requiredFields: (keyof InputData)[] = ['toChainId', 'token', 'amount']; - const hasEnoughInputs = requiredFields.every((field) => prefillFields[field] === true); - - if (hasEnoughInputs) { - return ; - } - - const handleUpdate = (data: any) => { - if (data.toChainId !== undefined) { - const updateData = { ...data, chainId: data.toChainId }; - onUpdate(updateData); - } else { - onUpdate(data); - } - }; - - return ( - - ); -} - -export default function BridgeAndExecuteModal({ title = 'Nexus Widget' }: { title?: string }) { - const getSimulationError = (simulationResult: BridgeAndExecuteSimulationResult) => { - if (!simulationResult) return true; - - // Check if the overall simulation failed - if (simulationResult.success === false || simulationResult.error) { - return true; - } - const isBridgeSkipped = simulationResult.metadata?.bridgeSkipped; - - if (!isBridgeSkipped) { - if (!simulationResult.bridgeSimulation || !simulationResult.bridgeSimulation.intent) { - return true; - } - } - if (simulationResult.executeSimulation && !simulationResult.executeSimulation.success) { - return true; - } - - return false; - }; - - const getMinimumAmount = (simulationResult: BridgeAndExecuteSimulationResult) => { - // If bridge was skipped, use the input amount instead of bridge simulation data - if (simulationResult?.metadata?.bridgeSkipped) { - return simulationResult.metadata.inputAmount || '0'; - } - - const bridgeSim = simulationResult?.bridgeSimulation; - return bridgeSim?.intent?.sourcesTotal || '0'; - }; - - const getSourceChains = ( - simulationResult: BridgeAndExecuteSimulationResult & { - allowance?: { - chainDetails?: Array<{ chainId: number; amount: string; needsApproval: boolean }>; - }; - }, - ) => { - // Use chainDetails from allowance if available (provides needsApproval info) - if (simulationResult?.allowance?.chainDetails) { - return simulationResult.allowance.chainDetails; - } - - // If bridge was skipped, return empty array since there's no bridge routing - if (simulationResult?.metadata?.bridgeSkipped) { - return []; - } - - const bridgeSim = simulationResult?.bridgeSimulation; - return bridgeSim?.intent?.sources?.map((s) => ({ chainId: s.chainID, amount: s.amount })) || []; - }; - - const transformInputData = (inputData: any) => { - if (!inputData) return {}; - return { - ...inputData, - toChainId: (inputData as BridgeAndExecuteParams).toChainId, - }; - }; - - return ( - - ); -} diff --git a/packages/widgets/src/components/bridge/bridge-button.tsx b/packages/widgets/src/components/bridge/bridge-button.tsx deleted file mode 100644 index 13f178bb..00000000 --- a/packages/widgets/src/components/bridge/bridge-button.tsx +++ /dev/null @@ -1,21 +0,0 @@ -'use client'; -import type { BridgeButtonProps } from '../../types'; -import { useInternalNexus } from '../../providers/InternalNexusProvider'; -import BridgeModal from './bridge-modal'; - -export function BridgeButton({ prefill, children, className, title }: BridgeButtonProps) { - const { startTransaction, activeTransaction } = useInternalNexus(); - const isLoading = - activeTransaction.status === 'processing' || activeTransaction.reviewStatus === 'simulating'; - - const handleClick = () => { - startTransaction('bridge', prefill); - }; - - return ( - <> -
{children({ onClick: handleClick, isLoading })}
- - - ); -} diff --git a/packages/widgets/src/components/bridge/bridge-modal.tsx b/packages/widgets/src/components/bridge/bridge-modal.tsx deleted file mode 100644 index 90273438..00000000 --- a/packages/widgets/src/components/bridge/bridge-modal.tsx +++ /dev/null @@ -1,99 +0,0 @@ -import { UnifiedTransactionModal } from '../shared/unified-transaction-modal'; -import { type SimulationResult } from '@nexus/commons'; -import { UnifiedTransactionForm, UnifiedInputData } from '../shared/unified-transaction-form'; -import PrefilledInputs from '../shared/prefilled-inputs'; -import { useInternalNexus } from '../../providers/InternalNexusProvider'; -// BridgeConfig removed - using type casting - -type InputData = { - chainId?: number; - token?: string; - amount?: string | number; -}; - -interface BridgeFormSectionProps { - inputData: InputData; - onUpdate: (data: UnifiedInputData) => void; - disabled?: boolean; - className?: string; - prefillFields?: { - chainId?: boolean; - token?: boolean; - amount?: boolean; - }; -} - -function BridgeFormSection({ - inputData, - onUpdate, - disabled = false, - className, - prefillFields = {}, -}: BridgeFormSectionProps) { - const { activeController } = useInternalNexus(); - - if (!activeController) return null; - const requiredFields: (keyof InputData)[] = ['chainId', 'token', 'amount']; - const hasEnoughInputs = requiredFields.every((field) => prefillFields[field] === true); - - if (hasEnoughInputs) { - return ; - } - - return ( - - ); -} - -export default function BridgeModal({ title = 'Nexus Widget' }: { title?: string }) { - const getSimulationError = (simulationResult: SimulationResult) => { - return ( - simulationResult && - 'bridgeSimulation' in simulationResult && - !simulationResult.bridgeSimulation - ); - }; - - const getMinimumAmount = (simulationResult: SimulationResult) => { - return simulationResult?.intent?.sourcesTotal || '0'; - }; - - const getSourceChains = ( - simulationResult: SimulationResult & { - allowance?: { - chainDetails?: Array<{ chainId: number; amount: string; needsApproval: boolean }>; - }; - }, - ) => { - // Use chainDetails from allowance if available (provides needsApproval info) - if (simulationResult?.allowance?.chainDetails) { - return simulationResult.allowance.chainDetails; - } - - // Fallback to original sources mapping - return ( - simulationResult?.intent?.sources?.map((source) => ({ - chainId: source.chainID, - amount: source.amount, - })) || [] - ); - }; - - return ( - - ); -} diff --git a/packages/widgets/src/components/icons/AvailLogo.tsx b/packages/widgets/src/components/icons/AvailLogo.tsx deleted file mode 100644 index d626626a..00000000 --- a/packages/widgets/src/components/icons/AvailLogo.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import React from 'react'; - -interface AvailLogoProps { - className?: string; -} - -export const AvailLogo: React.FC = ({ className = 'h-[88px] w-[191px]' }) => ( - - - - - -); diff --git a/packages/widgets/src/components/icons/CheckIcon.tsx b/packages/widgets/src/components/icons/CheckIcon.tsx deleted file mode 100644 index e7a49e34..00000000 --- a/packages/widgets/src/components/icons/CheckIcon.tsx +++ /dev/null @@ -1,22 +0,0 @@ -import React from 'react'; - -interface CheckIconProps { - className?: string; - size?: number; -} - -export const CheckIcon: React.FC = ({ className, size = 16 }) => ( - - - -); diff --git a/packages/widgets/src/components/icons/ChevronDownIcon.tsx b/packages/widgets/src/components/icons/ChevronDownIcon.tsx deleted file mode 100644 index d7d1115c..00000000 --- a/packages/widgets/src/components/icons/ChevronDownIcon.tsx +++ /dev/null @@ -1,22 +0,0 @@ -import React from 'react'; - -interface ChevronDownIconProps { - className?: string; - size?: number; -} - -export const ChevronDownIcon: React.FC = ({ className, size = 16 }) => ( - - - -); diff --git a/packages/widgets/src/components/icons/ChevronUpIcon.tsx b/packages/widgets/src/components/icons/ChevronUpIcon.tsx deleted file mode 100644 index 39e0dad7..00000000 --- a/packages/widgets/src/components/icons/ChevronUpIcon.tsx +++ /dev/null @@ -1,22 +0,0 @@ -import React from 'react'; - -interface ChevronUpIconProps { - className?: string; - size?: number; -} - -export const ChevronUpIcon: React.FC = ({ className, size = 16 }) => ( - - - -); diff --git a/packages/widgets/src/components/icons/CircleX.tsx b/packages/widgets/src/components/icons/CircleX.tsx deleted file mode 100644 index c3d75db3..00000000 --- a/packages/widgets/src/components/icons/CircleX.tsx +++ /dev/null @@ -1,24 +0,0 @@ -import React from 'react'; - -interface CircleXProps { - className?: string; - size?: number; -} - -export const CircleX: React.FC = ({ className, size = 16 }) => ( - - - - - -); diff --git a/packages/widgets/src/components/icons/Clock.tsx b/packages/widgets/src/components/icons/Clock.tsx deleted file mode 100644 index 48027667..00000000 --- a/packages/widgets/src/components/icons/Clock.tsx +++ /dev/null @@ -1,14 +0,0 @@ -const Clock = () => { - return ( - - - - ); -}; - -export default Clock; diff --git a/packages/widgets/src/components/icons/ExternalLink.tsx b/packages/widgets/src/components/icons/ExternalLink.tsx deleted file mode 100644 index 3e071465..00000000 --- a/packages/widgets/src/components/icons/ExternalLink.tsx +++ /dev/null @@ -1,24 +0,0 @@ -import React from 'react'; - -interface ExternalLinkProps { - className?: string; - size?: number; -} - -export const ExternalLink: React.FC = ({ className, size = 16 }) => ( - - - - - -); diff --git a/packages/widgets/src/components/icons/Maximize.tsx b/packages/widgets/src/components/icons/Maximize.tsx deleted file mode 100644 index d28e945f..00000000 --- a/packages/widgets/src/components/icons/Maximize.tsx +++ /dev/null @@ -1,39 +0,0 @@ -import React from 'react'; - -interface MaximizeProps { - className?: string; - size?: number; -} - -export const Maximize: React.FC = ({ className, size = 24 }) => ( - - - - - -); diff --git a/packages/widgets/src/components/icons/Minimize.tsx b/packages/widgets/src/components/icons/Minimize.tsx deleted file mode 100644 index 4d3ee50b..00000000 --- a/packages/widgets/src/components/icons/Minimize.tsx +++ /dev/null @@ -1,41 +0,0 @@ -import React from 'react'; - -interface MinimizeProps { - className?: string; - size?: number; -} - -export const Minimize: React.FC = ({ className, size = 16 }) => ( - -); diff --git a/packages/widgets/src/components/icons/MoneyCircles.tsx b/packages/widgets/src/components/icons/MoneyCircles.tsx deleted file mode 100644 index 3134a6df..00000000 --- a/packages/widgets/src/components/icons/MoneyCircles.tsx +++ /dev/null @@ -1,22 +0,0 @@ -const MoneyCircles = () => { - return ( - - - - - ); -}; - -export default MoneyCircles; diff --git a/packages/widgets/src/components/icons/Plus.tsx b/packages/widgets/src/components/icons/Plus.tsx deleted file mode 100644 index 2aeb6653..00000000 --- a/packages/widgets/src/components/icons/Plus.tsx +++ /dev/null @@ -1,23 +0,0 @@ -import React from 'react'; - -interface PlusProps { - className?: string; - size?: number; -} - -export const Plus: React.FC = ({ className, size = 16 }) => ( - - - - -); diff --git a/packages/widgets/src/components/icons/SmallAvailLogo.tsx b/packages/widgets/src/components/icons/SmallAvailLogo.tsx deleted file mode 100644 index 013fa332..00000000 --- a/packages/widgets/src/components/icons/SmallAvailLogo.tsx +++ /dev/null @@ -1,550 +0,0 @@ -import React from 'react'; - -interface SmallAvailLogoProps { - className?: string; -} - -export const SmallAvailLogo: React.FC = ({ - className = 'w-[58px] h-[16px]', -}) => ( - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -); diff --git a/packages/widgets/src/components/icons/SolarWallet.tsx b/packages/widgets/src/components/icons/SolarWallet.tsx deleted file mode 100644 index 37afdd26..00000000 --- a/packages/widgets/src/components/icons/SolarWallet.tsx +++ /dev/null @@ -1,18 +0,0 @@ -const SolarWallet = () => { - return ( - - - - - ); -}; - -export default SolarWallet; diff --git a/packages/widgets/src/components/icons/TwoCircles.tsx b/packages/widgets/src/components/icons/TwoCircles.tsx deleted file mode 100644 index b309794a..00000000 --- a/packages/widgets/src/components/icons/TwoCircles.tsx +++ /dev/null @@ -1,15 +0,0 @@ -const TwoCircles = () => { - return ( - - - - ); -}; - -export default TwoCircles; diff --git a/packages/widgets/src/components/icons/index.ts b/packages/widgets/src/components/icons/index.ts deleted file mode 100644 index 1dd4b4a2..00000000 --- a/packages/widgets/src/components/icons/index.ts +++ /dev/null @@ -1,10 +0,0 @@ -export { Minimize } from './Minimize'; -export { CircleX } from './CircleX'; -export { ExternalLink } from './ExternalLink'; -export { CheckIcon } from './CheckIcon'; -export { ChevronDownIcon } from './ChevronDownIcon'; -export { ChevronUpIcon } from './ChevronUpIcon'; -export { Maximize } from './Maximize'; -export { Plus } from './Plus'; -export { AvailLogo } from './AvailLogo'; -export { SmallAvailLogo } from './SmallAvailLogo'; diff --git a/packages/widgets/src/components/motion/base-modal.tsx b/packages/widgets/src/components/motion/base-modal.tsx deleted file mode 100644 index f478cd63..00000000 --- a/packages/widgets/src/components/motion/base-modal.tsx +++ /dev/null @@ -1,25 +0,0 @@ -import { cn } from '../../utils/utils'; -import type { ModalProps } from '../../types'; -import { Dialog, DialogContent } from './dialog-motion'; -import { motion } from 'motion/react'; - -export function BaseModal({ isOpen, onClose, children, className }: Readonly) { - return ( - - - - {children} - - - - ); -} diff --git a/packages/widgets/src/components/motion/button-motion.tsx b/packages/widgets/src/components/motion/button-motion.tsx deleted file mode 100644 index d183909e..00000000 --- a/packages/widgets/src/components/motion/button-motion.tsx +++ /dev/null @@ -1,63 +0,0 @@ -import * as React from 'react'; -import { motion } from 'motion/react'; -import { cn } from '../../utils/utils'; - -interface ButtonProps - extends Omit< - React.ButtonHTMLAttributes, - 'onDrag' | 'onDragEnd' | 'onDragStart' | 'onAnimationStart' | 'onAnimationEnd' - > { - variant?: 'default' | 'destructive' | 'outline' | 'secondary' | 'ghost' | 'link' | 'custom'; - size?: 'default' | 'sm' | 'lg' | 'icon' | 'custom'; - asChild?: boolean; - ref?: React.Ref; -} - -const buttonVariants = { - default: 'bg-nexus-primary-gray text-nexus-primary-foreground hover:bg-nexus-primary/90', - destructive: - 'bg-nexus-destructive text-nexus-destructive-foreground hover:bg-nexus-destructive/90', - outline: - 'border border-nexus-input bg-nexus-background hover:bg-nexus-accent hover:text-nexus-accent-foreground', - secondary: 'bg-nexus-secondary text-nexus-secondary-foreground hover:bg-nexus-secondary/80', - ghost: 'hover:bg-nexus-accent hover:text-nexus-accent-foreground', - link: 'text-nexus-primary underline-offset-4 hover:underline', - custom: '', -}; - -const buttonSizes = { - default: 'h-10 px-4 py-2', - sm: 'h-9 rounded-nexus-md px-3', - lg: 'h-11 rounded-nexus-md px-8', - icon: 'h-10 w-10', - custom: '', -}; - -const Button = React.forwardRef( - ({ className, variant = 'default', size = 'default', asChild = false, ...props }, ref) => { - return ( - - ); - }, -); - -Button.displayName = 'Button'; - -export { Button }; diff --git a/packages/widgets/src/components/motion/dialog-motion.tsx b/packages/widgets/src/components/motion/dialog-motion.tsx deleted file mode 100644 index 333bb4f6..00000000 --- a/packages/widgets/src/components/motion/dialog-motion.tsx +++ /dev/null @@ -1,246 +0,0 @@ -import * as React from 'react'; -import { motion, AnimatePresence } from 'motion/react'; -import { cn } from '../../utils/utils'; -import { createPortal } from 'react-dom'; - -interface DialogContextType { - open: boolean; - onOpenChange: (open: boolean) => void; -} - -const DialogContext = React.createContext(null); - -function useDialog() { - const context = React.useContext(DialogContext); - if (!context) { - throw new Error('Dialog components must be used within a Dialog'); - } - return context; -} - -interface DialogProps { - open?: boolean; - onOpenChange?: (open: boolean) => void; - children: React.ReactNode; -} - -function Dialog({ open = false, onOpenChange, children }: Readonly) { - const handleOpenChange = React.useCallback( - (newOpen: boolean) => { - onOpenChange?.(newOpen); - }, - [onOpenChange], - ); - - const value = React.useMemo( - () => ({ open, onOpenChange: handleOpenChange }), - [open, handleOpenChange], - ); - - return {children}; -} - -interface DialogTriggerProps extends React.ButtonHTMLAttributes { - asChild?: boolean; -} - -function DialogTrigger({ asChild = false, onClick, ...props }: Readonly) { - const { onOpenChange } = useDialog(); - - const handleClick = React.useCallback( - (e: React.MouseEvent) => { - onClick?.(e); - onOpenChange(true); - }, - [onClick, onOpenChange], - ); - - if (asChild) { - return React.cloneElement(React.Children.only(props.children as React.ReactElement), { - onClick: handleClick, - 'data-slot': 'dialog-trigger', - } as any); - } - - return - )} - {(executionResult as BridgeAndExecuteResult)?.executeExplorerUrl && ( - - )} - - ); - } - - if (transactionType === 'swap') { - return ( -
- {explorerURLs?.source && ( - - )} - {explorerURLs?.destination && ( - - )} -
- ); - } - - if (explorerURL) { - return ( - - ); - } - - return null; - }, [transactionType, explorerURL, explorerURLs, executionResult]); - - return ( - <> - - { - lottieRef.current?.resize(); - }} - className="absolute top-16 left-1/2 -translate-x-1/2 pointer-events-none" - > -
- { - lottieRef.current = instance; - }} - /> -
-
- -
-
- {/* Chains Row */} - - {/* Sources */} -
-
- {Array.isArray(sourceChainMeta) && - sourceChainMeta - .slice(0, 3) - .map((chain, index) => ( - {chain?.name 0 ? '-ml-5' : '', - chain?.id !== SUPPORTED_CHAINS.BASE && - chain?.id !== SUPPORTED_CHAINS.BASE_SEPOLIA - ? 'rounded-nexus-full' - : '', - )} - style={{ zIndex: (sourceChainMeta?.length || 0) - index }} - /> - ))} -
-
-

- {sourceAmount()} -

-

- From {sourceChainMeta?.length ?? 0} chain - {(sourceChainMeta?.length ?? 0) > 1 ? 's' : ''} -

-
-
- {/* Progress */} - -
-
- -
-
-
- {/* Destination */} -
- {destChainMeta ? ( - <> - - {destChainMeta?.name - -
-

- {destinationAmount()} -

-

- To {destChainMeta?.name ?? ''} -

-
- - ) : ( -
- )} -
- - {/* Text & timer */} - - {error ? ( - - ) : ( - <> -
- - {Math.floor(timer)} - - - . - - - {String(Math.floor((timer % 1) * 1000)).padStart(3, '0')}s - -
-
- -
-

- {description} -

- - )} - {/* Explorer links */} - {renderExplorerLinks()} -
-
-
- {/* Footer */} - -
- {status === 'success' && ( - - - - )} -
- Powered By - -
-
- - ); -}; diff --git a/packages/widgets/src/components/processing/processor-mini-card.tsx b/packages/widgets/src/components/processing/processor-mini-card.tsx deleted file mode 100644 index 61676d48..00000000 --- a/packages/widgets/src/components/processing/processor-mini-card.tsx +++ /dev/null @@ -1,268 +0,0 @@ -import React, { useCallback } from 'react'; -import { motion } from 'motion/react'; -import SuccessRipple from '../motion/success-ripple'; -import { Maximize, ExternalLink } from '../icons'; -import { type BridgeAndExecuteResult, SUPPORTED_CHAINS, TOKEN_METADATA } from '@nexus/commons'; -import { WordsPullUp } from '../motion/pull-up-words'; -import { cn } from '../../utils/utils'; -import { ThreeStageProgress } from '../motion/three-stage-progress'; -import { Button } from '../motion/button-motion'; -import { EnhancedInfoMessage } from '../shared/enhanced-info-message'; -import { ProcessorCardProps, SwapSimulationResult } from '../../types'; -import { TokenIcon } from '../shared/icons'; - -export const ProcessorMiniCard: React.FC = ({ - status, - toggleTransactionCollapse, - sourceChainMeta, - destChainMeta, - tokenMeta, - transactionType, - simulationResult, - processing, - explorerURL, - explorerURLs, - description, - error, - executionResult, -}: ProcessorCardProps) => { - const renderTokenIcon = useCallback(() => { - const progress = processing?.animationProgress ?? 0; - - if (transactionType !== 'swap') { - return ( - - ); - } - - const swapResult = simulationResult as SwapSimulationResult; - const destSymbol = swapResult?.intent?.destination?.token?.symbol?.toUpperCase(); - const destIcon = destSymbol ? TOKEN_METADATA[destSymbol]?.icon : undefined; - const sourceIcon = tokenMeta?.icon; - - return ( -
- - - - = 50 ? 1 : 0, scale: progress >= 50 ? 1 : 1.05 }} - transition={{ duration: 0.25 }} - > - - -
- ); - }, [ - processing?.animationProgress, - tokenMeta?.icon, - tokenMeta?.symbol, - transactionType, - simulationResult, - ]); - - return ( - - {/* Header */} -
-
- {/* Sources */} -
- {Array.isArray(sourceChainMeta) && - sourceChainMeta - .slice(0, 3) - .map((chain, index) => ( - {chain?.name 0 ? '-ml-3' : '', - chain?.id !== SUPPORTED_CHAINS.BASE && - chain?.id !== SUPPORTED_CHAINS.BASE_SEPOLIA - ? 'rounded-nexus-full' - : '', - )} - style={{ zIndex: (sourceChainMeta?.length || 0) - index }} - /> - ))} -
- - {/* Progress */} - - - - - {/* Destination */} - {destChainMeta ? ( - - {destChainMeta?.name} - - ) : ( -
- )} -
- -
- - {/* Body */} - {status === 'error' ? ( -
- -
- ) : ( -
- - - - {status === 'success' && - (() => { - if (transactionType === 'swap') { - if (explorerURLs?.destination) { - return ( - - ); - } - if (explorerURLs?.source) { - return ( - - ); - } - return null; - } - if (transactionType !== 'bridgeAndExecute') { - if (!explorerURL) return null; - return ( - - ); - } - const executeUrl = (executionResult as BridgeAndExecuteResult)?.executeExplorerUrl; - if (executeUrl) { - return ( - - ); - } - return null; - })()} - {status !== 'success' && ( -

- {description} -

- )} -
- )} - - ); -}; diff --git a/packages/widgets/src/components/processing/transaction-processor-shell.tsx b/packages/widgets/src/components/processing/transaction-processor-shell.tsx deleted file mode 100644 index 13ffa8fd..00000000 --- a/packages/widgets/src/components/processing/transaction-processor-shell.tsx +++ /dev/null @@ -1,234 +0,0 @@ -import { useEffect, useMemo, useState, useRef, memo } from 'react'; -import { motion, AnimatePresence } from 'motion/react'; -import { useInternalNexus } from '../../providers/InternalNexusProvider'; -import { ProcessorMiniCard } from './processor-mini-card'; -import { ProcessorFullCard } from './processor-full-card'; -import { - type BridgeAndExecuteSimulationResult, - type SimulationResult, - CHAIN_METADATA, - logger, - TOKEN_METADATA, -} from '@nexus/commons'; -import { getOperationText, getTokenFromInputData } from '../../utils/utils'; -import { useDragConstraints } from '../motion/drag-constraints'; -import { TransactionType, SwapSimulationResult } from '../../types'; - -const COLLAPSED = { width: 400, height: 120, radius: 16 } as const; -const EXPANDED = { width: 480, height: 500, radius: 16 } as const; - -const TransactionProcessorShell = ({ disableCollapse = false }: { disableCollapse?: boolean }) => { - const lastLoggedProcessingState = useRef(''); - const { - activeTransaction, - processing, - explorerURL, - explorerURLs, - timer, - toggleTransactionCollapse, - isTransactionCollapsed, - cancelTransaction, - } = useInternalNexus(); - - const { type: transactionType, simulationResult } = activeTransaction; - - const sources = useMemo(() => { - if (!simulationResult) return [] as number[]; - - if (transactionType === 'bridge' || transactionType === 'transfer') { - return (simulationResult as SimulationResult)?.intent?.sources?.map((s) => s.chainID) || []; - } - - if (transactionType === 'swap') { - const swapResult = simulationResult as SwapSimulationResult; - // For swap, extract chain IDs from sources - return swapResult?.intent?.sources?.map((source) => source?.chain?.id) || []; - } - - const bridgeExecuteResult = simulationResult as BridgeAndExecuteSimulationResult; - - // If bridge was skipped, use the target chain as the source since we're executing directly - if (bridgeExecuteResult?.metadata?.bridgeSkipped) { - return [bridgeExecuteResult.metadata.targetChain]; - } - - return bridgeExecuteResult.bridgeSimulation?.intent?.sources?.map((s) => s.chainID) || []; - }, [simulationResult, transactionType]); - - const destination = useMemo(() => { - if (!simulationResult) return 0; - - if (transactionType === 'bridge' || transactionType === 'transfer') { - return (simulationResult as SimulationResult)?.intent?.destination?.chainID || 0; - } - - if (transactionType === 'swap') { - const swapResult = simulationResult as SwapSimulationResult; - // For swap, extract destination chain ID - return swapResult?.intent?.destination?.chain?.id ?? 0; - } - - const bridgeExecuteResult = simulationResult as BridgeAndExecuteSimulationResult; - - // If bridge was skipped, use the target chain as the destination - if (bridgeExecuteResult?.metadata?.bridgeSkipped) { - return bridgeExecuteResult.metadata.targetChain; - } - - return bridgeExecuteResult.bridgeSimulation?.intent?.destination?.chainID || 0; - }, [simulationResult, transactionType]); - - const token = getTokenFromInputData(activeTransaction.inputData) || ''; - const sourceChainMeta = sources - .filter((s): s is number => s != null && !isNaN(s)) - .map((s) => CHAIN_METADATA[s]) - .filter(Boolean); - - const destChainMeta = destination ? CHAIN_METADATA[destination] : null; - const tokenMeta = token ? TOKEN_METADATA[token] : null; - - const getDescription = () => { - if (activeTransaction?.type === 'swap') { - if (processing?.statusText === 'Swap is completed') { - return 'Transaction Completed Successfully'; - } - const destinationToken = (activeTransaction?.simulationResult as SwapSimulationResult)?.intent - ?.destination?.token; - const destinationTokenSymbol = destinationToken - ? destinationToken.symbol.toUpperCase() - : 'token'; - - return `${getOperationText(transactionType as TransactionType)} ${tokenMeta?.symbol || 'token'} to ${destinationTokenSymbol} on ${destChainMeta?.name || 'destination chain'}`; - } - if (activeTransaction?.executionResult?.success) return 'Transaction Completed Successfully'; - return `${getOperationText(transactionType as TransactionType)} ${tokenMeta?.symbol || 'token'} from ${sourceChainMeta.length > 1 ? 'multiple chains' : sourceChainMeta[0]?.name} to ${destChainMeta?.name || 'destination chain'}`; - }; - - const shellActive = ['processing', 'success', 'error'].includes(activeTransaction.status); - - const dragConstraints = useDragConstraints(); - - const [windowSize, setWindowSize] = useState({ width: 0, height: 0 }); - - useEffect(() => { - const update = () => setWindowSize({ width: window.innerWidth, height: window.innerHeight }); - update(); - window.addEventListener('resize', update); - return () => window.removeEventListener('resize', update); - }, []); - - const collapsedPos = { - x: Math.max(16, windowSize.width - COLLAPSED.width - 16), - y: 16, - }; - - const expandedPos = { - x: Math.max(0, (windowSize.width - EXPANDED.width) / 2), - y: Math.max(0, (windowSize.height - EXPANDED.height) / 2), - }; - - if (!shellActive || !transactionType || !simulationResult) { - return null; - } - - // Only log processing changes when state actually changes to reduce noise - const processingStateKey = `${processing?.currentStep}-${processing?.totalSteps}-${processing?.statusText}-${processing?.animationProgress}`; - if (lastLoggedProcessingState.current !== processingStateKey && processing) { - logger.info('processing from hook', processing); - lastLoggedProcessingState.current = processingStateKey; - } - - return ( - - <> - {/* Backdrop */} - {!isTransactionCollapsed && ( - - )} - - {/* Processor Card */} - - {isTransactionCollapsed ? ( - - ) : ( - - )} - - - - ); -}; -TransactionProcessorShell.displayName = 'TransactionProcessorShell'; - -export default memo(TransactionProcessorShell); diff --git a/packages/widgets/src/components/processing/transaction-simulation.tsx b/packages/widgets/src/components/processing/transaction-simulation.tsx deleted file mode 100644 index 1351ff36..00000000 --- a/packages/widgets/src/components/processing/transaction-simulation.tsx +++ /dev/null @@ -1,77 +0,0 @@ -import { type SimulationResult, type BridgeAndExecuteSimulationResult } from '@nexus/commons'; -import { InfoMessage } from '../shared/info-message'; -import { TransactionDetailsDrawer } from '../shared/transaction-details-drawer'; -import TextLoader from '../motion/text-loader'; -import { - OrchestratorStatus, - ReviewStatus, - TransactionType, - SwapSimulationResult, -} from '../../types'; - -interface TransactionSimulationProps { - isLoading: boolean; - simulationResult?: ( - | SimulationResult - | BridgeAndExecuteSimulationResult - | SwapSimulationResult - ) & { - allowance?: { needsApproval: boolean }; - }; - inputData?: { - token?: string; - amount?: string | number; - chainId?: number; - toChainId?: number; - }; - type?: TransactionType; - callback: () => void; - status: OrchestratorStatus; - reviewStatus: ReviewStatus; -} - -export function TransactionSimulation({ - isLoading, - simulationResult, - inputData, - type, - callback, - status, - reviewStatus, -}: Readonly) { - if (isLoading) { - return ( -
- -
- ); - } - - if (!simulationResult) { - return null; - } - - return ( -
- {simulationResult?.allowance?.needsApproval && ( -
- - You need to set allowance in your wallet first to continue. - -
- )} - -
- -
-
- ); -} diff --git a/packages/widgets/src/components/shared/action-buttons.tsx b/packages/widgets/src/components/shared/action-buttons.tsx deleted file mode 100644 index 03998cc3..00000000 --- a/packages/widgets/src/components/shared/action-buttons.tsx +++ /dev/null @@ -1,67 +0,0 @@ -import { Button } from '../motion/button-motion'; -import { cn } from '../../utils/utils'; -import { SmallAvailLogo } from '../icons/SmallAvailLogo'; -import LoadingDots from '../motion/loading-dots'; - -interface ActionButtonsProps { - onCancel: () => void; - onPrimary: () => void; - primaryText?: string; - primaryLoading?: boolean; - primaryDisabled?: boolean; - className?: string; -} - -export function ActionButtons({ - onCancel, - onPrimary, - primaryText = 'Continue', - primaryLoading = false, - primaryDisabled = false, - className, -}: Readonly) { - return ( -
-
- - - -
-
- Powered By - -
-
- ); -} diff --git a/packages/widgets/src/components/shared/address-field.tsx b/packages/widgets/src/components/shared/address-field.tsx deleted file mode 100644 index e5217b88..00000000 --- a/packages/widgets/src/components/shared/address-field.tsx +++ /dev/null @@ -1,44 +0,0 @@ -import { Input } from '../motion/input'; -import { cn } from '../../utils/utils'; - -interface AddressFieldProps { - value?: string; - onChange?: (value: string) => void; - disabled?: boolean; - placeholder?: string; - className?: string; - hasValidationError?: boolean; -} - -export function AddressField({ - value, - onChange, - disabled = false, - placeholder = '0x...', - className, - hasValidationError = false, -}: Readonly) { - return ( -
-
- onChange?.(e.target.value)} - disabled={disabled} - className={cn( - 'px-0 placeholder:font-nexus-primary text-nexus-black font-semibold text-base', - hasValidationError ? 'border-red-500 focus:border-red-500' : '', - )} - /> -
-
- ); -} diff --git a/packages/widgets/src/components/shared/allowance-form.tsx b/packages/widgets/src/components/shared/allowance-form.tsx deleted file mode 100644 index ed456bc5..00000000 --- a/packages/widgets/src/components/shared/allowance-form.tsx +++ /dev/null @@ -1,265 +0,0 @@ -import { Fragment, useCallback, useEffect, useRef, useState } from 'react'; -import { cn, formatCost } from '../../utils/utils'; -import { EnhancedInfoMessage } from './enhanced-info-message'; -import { useInternalNexus } from '../../providers/InternalNexusProvider'; -import { CHAIN_METADATA, SUPPORTED_CHAINS, TOKEN_METADATA, formatUnits } from '@nexus/commons'; -import { FormField } from '../motion/form-field'; -import { Input } from '../motion/input'; - -export interface AllowanceFormProps { - token: string; - minimumAmount: string; - inputAmount: string; - sourceChains: { chainId: number; amount: string; needsApproval?: boolean }[]; - onApprove: (amount: string, isMinimum: boolean) => void; - onCancel: () => void; - isLoading?: boolean; - error?: string | null; - // Expose form state for external button handling - onFormStateChange?: (isValid: boolean, approveHandler: () => void) => void; -} - -export function AllowanceForm({ - token, - minimumAmount, - inputAmount, - sourceChains, - onApprove, - onCancel: _onCancel, - isLoading = false, - error = null, - onFormStateChange, -}: Readonly) { - const [currentAllowance, setCurrentAllowance] = useState(null); - const [selectedType, setSelectedType] = useState<'minimum' | 'custom'>('minimum'); - const [customAmount, setCustomAmount] = useState(''); - const { sdk } = useInternalNexus(); - - // Keep latest form values in refs to avoid stale closures when parent stores handler - const latestValuesRef = useRef({ selectedType, customAmount, minimumAmount }); - latestValuesRef.current.selectedType = selectedType; - latestValuesRef.current.customAmount = customAmount; - latestValuesRef.current.minimumAmount = minimumAmount; - - const tokenMetadata = TOKEN_METADATA[token]; - - // Stable handler that reads latest values from refs, so parent always has a fresh handler - const stableApproveHandler = useCallback(() => { - const { selectedType, customAmount, minimumAmount } = latestValuesRef.current; - if (selectedType === 'minimum') { - onApprove(minimumAmount, true); - } else { - onApprove(customAmount, false); - } - }, [onApprove]); - - const validateCustomAmount = (amount: string): boolean => { - if (!amount) return false; - const numAmount = parseFloat(amount); - const numInputAmount = parseFloat(inputAmount); - return !isNaN(numAmount) && numAmount > 0 && numAmount >= numInputAmount; - }; - - const getCurrentAllowance = async () => { - // Find the first chain that actually needs allowance - const chainThatNeedsAllowance = sourceChains.find((chain) => chain.needsApproval === true); - - if (!chainThatNeedsAllowance) { - // If no chain needs approval, show allowance from first chain or 0 - const firstChain = sourceChains[0]; - if (firstChain) { - const allowance = await sdk.getAllowance(firstChain.chainId, [token]); - const decimals = Number(TOKEN_METADATA[token].decimals); - const formattedAllowance = formatUnits(allowance[0]?.allowance ?? 0n, decimals); - setCurrentAllowance(formattedAllowance); - } else { - setCurrentAllowance('0'); - } - return; - } - - // Get allowance from the chain that needs approval - const allowance = await sdk.getAllowance(chainThatNeedsAllowance.chainId, [token]); - const decimals = Number(TOKEN_METADATA[token].decimals); - const formattedAllowance = formatUnits(allowance[0]?.allowance ?? 0n, decimals); - setCurrentAllowance(formattedAllowance); - }; - - useEffect(() => { - if (!currentAllowance) { - getCurrentAllowance(); - } - }, [sourceChains, token]); - - const isCustomValid = selectedType === 'custom' ? validateCustomAmount(customAmount) : true; - const isFormValid = selectedType === 'minimum' || isCustomValid; - - // Notify parent of form state changes; avoid depending on onFormStateChange to prevent loops - useEffect(() => { - if (onFormStateChange) { - onFormStateChange(isFormValid, stableApproveHandler); - } - }, [isFormValid]); - - return ( -
-
- {/* Header */} -
-

- Allow access to {formatCost(minimumAmount)} {token} to complete your transaction. -

-
- - {/* Token Information */} -
-
- Token -
- {tokenMetadata?.icon && ( - {token} - )} - - {token} on - -
- {sourceChains - .filter((chain) => chain.needsApproval !== false) // Show chains that need approval or are undefined - .map((source, index, filteredChains) => { - const chainMeta = CHAIN_METADATA[source?.chainId]; - return ( - - {chainMeta?.name} 0 ? '-ml-5' : '', - chainMeta?.id !== SUPPORTED_CHAINS.BASE && - chainMeta?.id !== SUPPORTED_CHAINS.BASE_SEPOLIA - ? 'rounded-nexus-full ' - : '', - )} - style={{ zIndex: filteredChains.length - index }} - title={chainMeta?.name} - /> - - ); - })} - {sourceChains.filter((chain) => chain.needsApproval !== false).length > 1 && ( - - +{sourceChains.filter((chain) => chain.needsApproval !== false).length} chains - - )} -
-
-
- {currentAllowance && ( -
-
- - Current Allowance - - - {currentAllowance} - -
-
- )} -
- - {error ? ( - - ) : ( -
-
- {/* Minimum Option */} -
setSelectedType('minimum')} - > -
-
- setSelectedType('minimum')} - className="text-blue-600" - /> -
- Min: - - {formatCost(minimumAmount)} - -
-
- - RECOMMENDED - -
-
- - {/* Custom Option */} -
-
setSelectedType('custom')} - > - setSelectedType('custom')} - className="text-blue-600" - /> - - Custom - -
-
-
- {selectedType === 'custom' && ( -
- - setCustomAmount(e.target.value)} - className={cn( - 'text-nexus-black text-base font-semibold font-nexus-primary leading-normal px-4 py-2 border border-nexus-input rounded-nexus-md', - customAmount && !isCustomValid ? 'border-red-500 focus:border-red-500' : '', - )} - /> - -
- )} -
- )} -
-
- ); -} diff --git a/packages/widgets/src/components/shared/amount-input.tsx b/packages/widgets/src/components/shared/amount-input.tsx deleted file mode 100644 index 757fc1de..00000000 --- a/packages/widgets/src/components/shared/amount-input.tsx +++ /dev/null @@ -1,136 +0,0 @@ -import * as React from 'react'; -import { cn } from '../../utils/utils'; -import { Input } from '../motion/input'; -import { useInternalNexus } from '../../providers/InternalNexusProvider'; -import { getFiatValue } from '../../utils/balance-utils'; - -interface AmountInputProps { - value?: string; - disabled?: boolean; - onChange?: (value: string) => void; - className?: string; - placeholder?: string; - debounceMs?: number; - token?: string; -} - -export function AmountInput({ - value, - disabled = false, - onChange, - className, - placeholder = '0.0', - debounceMs = 500, - token, -}: Readonly) { - const [localValue, setLocalValue] = React.useState(value || ''); - const timeoutRef = React.useRef(undefined); - const { exchangeRates } = useInternalNexus(); - - React.useEffect(() => { - setLocalValue(value || ''); - }, [value]); - - const validateNumberInput = (input: string): string => { - if (input === '') return ''; - if (input === '.') return '0.'; - // Remove non-numeric characters except dots - let cleaned = input.replace(/[^0-9.]/g, ''); - - // Handle case where input starts with decimal point - if (cleaned.startsWith('.')) { - cleaned = '0' + cleaned; - } - - // Handle multiple decimal points - keep only the first one - const decimalCount = (cleaned.match(/\./g) || []).length; - if (decimalCount > 1) { - const firstDecimalIndex = cleaned.indexOf('.'); - cleaned = - cleaned.substring(0, firstDecimalIndex + 1) + - cleaned.substring(firstDecimalIndex + 1).replace(/\./g, ''); - } - - if (cleaned.length > 1 && cleaned.startsWith('0')) { - const decimalIndex = cleaned.indexOf('.'); - if (decimalIndex === -1 || decimalIndex > 1) { - cleaned = cleaned.replace(/^0+/, ''); - if (cleaned === '' || cleaned.startsWith('.')) { - cleaned = '0' + cleaned; - } - } else if (decimalIndex === 1) { - if (cleaned.length > 2 && cleaned.substring(0, 2) === '00') { - cleaned = cleaned.replace(/^0+/, '0'); - } - } - } - - const decimalIndex = cleaned.indexOf('.'); - if (decimalIndex !== -1 && cleaned.length - decimalIndex > 19) { - cleaned = cleaned.substring(0, decimalIndex + 19); - } - - return cleaned; - }; - - const handleInputChange = (e: React.ChangeEvent) => { - const rawValue = e.target.value; - const validatedValue = validateNumberInput(rawValue); - - setLocalValue(validatedValue); - - if (!onChange) return; - - if (timeoutRef.current) { - clearTimeout(timeoutRef.current); - } - - timeoutRef.current = setTimeout(() => { - if (validatedValue !== value) { - onChange(validatedValue); - } - }, debounceMs); - }; - - React.useEffect(() => { - return () => { - if (timeoutRef.current) { - clearTimeout(timeoutRef.current); - } - }; - }, []); - - return ( -
-
- {onChange ? ( - - ) : ( -

- {value ?? 0} -

- )} -
- {token && value && ( -

- {getFiatValue(value, token, exchangeRates)} -

- )} -
- ); -} diff --git a/packages/widgets/src/components/shared/chain-select.tsx b/packages/widgets/src/components/shared/chain-select.tsx deleted file mode 100644 index 791e90d2..00000000 --- a/packages/widgets/src/components/shared/chain-select.tsx +++ /dev/null @@ -1,145 +0,0 @@ -import { useMemo } from 'react'; -import { ChainSelectProps } from '../../types'; -import { CHAIN_METADATA, DESTINATION_SWAP_TOKENS, NexusNetwork } from '@nexus/commons'; -import { ChainIcon } from './icons'; -import { cn } from '../../utils/utils'; -import { Button } from '../motion/button-motion'; -import { DrawerAutoClose } from '../motion/drawer'; -import { getFilteredChainsForToken } from '../../utils/token-utils'; -import { useInternalNexus } from '../../providers/InternalNexusProvider'; -import type { TransactionType } from '../../utils/balance-utils'; - -interface ChainSelectOption { - value: string; - label: string; - chainId: number; - logo: string; -} - -export function ChainSelect({ - value, - onValueChange, - disabled = false, - network = 'mainnet', - className, - hasValues, - isSource, - selectedToken, - transactionType, -}: ChainSelectProps & { - network?: NexusNetwork; - selectedToken?: string; - transactionType?: TransactionType; -}) { - const { sdk } = useInternalNexus(); - const availableChainIds = useMemo(() => { - if (!sdk) return [] as number[]; - let ids: number[] = []; - if (network === 'testnet' && transactionType !== 'swap') { - ids = sdk?.utils?.getSupportedChains(0)?.map((chain) => chain?.id) ?? []; - } else if (transactionType === 'swap' && network !== 'testnet') { - ids = isSource - ? (sdk?.utils?.getSwapSupportedChainsAndTokens()?.map((chain) => chain?.id) ?? []) - : Array.from(DESTINATION_SWAP_TOKENS.keys()); - } else { - ids = sdk?.utils?.getSupportedChains()?.map((chain) => chain?.id) ?? []; - } - // Exclude Fuel (9889) and any chains without known metadata to avoid runtime errors - return ids.filter((id) => id !== 9889 && !!CHAIN_METADATA[id]); - }, [sdk, network, transactionType, isSource]); - - const filteredChainIds = useMemo(() => { - if (!availableChainIds?.length) return [] as number[]; - if (selectedToken && transactionType) { - return getFilteredChainsForToken( - selectedToken, - availableChainIds, - transactionType, - sdk, - !isSource, - ); - } - return availableChainIds; - }, [availableChainIds, selectedToken, transactionType, sdk, isSource]); - - const chainOptions: ChainSelectOption[] = filteredChainIds - .filter((chainId) => !!CHAIN_METADATA[chainId]) - .map((chainId) => { - const metadata = CHAIN_METADATA[chainId]; - return { - value: chainId.toString(), - label: metadata?.name ?? `Chain ${chainId}`, - chainId, - logo: metadata?.logo ?? '', - }; - }); - const selectedOption = useMemo( - () => chainOptions.find((opt) => opt.value === (value ?? '')), - [value, chainOptions], - ); - - const handleSelect = (chainId: string) => { - if (disabled) return; - onValueChange(chainId); - }; - - // Check if current selection is still valid after filtering - const isCurrentSelectionValid = useMemo(() => { - if (!value) return true; - return chainOptions.some((option) => option.value === value); - }, [value, chainOptions]); - - if (network === 'testnet' && transactionType === 'swap') { - throw new Error('Swap not supported on testnet'); - } - - return ( -
-
-

- {isSource ? 'Source' : 'Destination'} Chain -

- {selectedToken && transactionType && !isCurrentSelectionValid && ( -

- Current chain doesn't support {selectedToken} -

- )} -
-
- {chainOptions.map((chain, index) => ( - - - - ))} - - {/* Empty state */} - {chainOptions.length === 0 && ( -
-

No chains available for selected token

-
- )} -
-
- ); -} diff --git a/packages/widgets/src/components/shared/destination-drawer.tsx b/packages/widgets/src/components/shared/destination-drawer.tsx deleted file mode 100644 index 440ca551..00000000 --- a/packages/widgets/src/components/shared/destination-drawer.tsx +++ /dev/null @@ -1,157 +0,0 @@ -import { ChainSelect } from './chain-select'; -import { TokenSelect } from './token-select'; -import { - Drawer, - DrawerClose, - DrawerContent, - DrawerHeader, - DrawerTitle, - DrawerTrigger, -} from '../motion/drawer'; -import { ChevronDownIcon, CircleX } from '../icons'; -import { FormField } from '../motion/form-field'; -import { CHAIN_METADATA, NexusNetwork, SUPPORTED_CHAINS } from '@nexus/commons'; -import { cn } from '../../utils/utils'; -import { TokenIcon } from './icons'; -import type { TransactionType as BalanceTransactionType } from '../../utils/balance-utils'; - -interface DestinationDrawerProps { - chainValue?: string; - tokenValue?: string; - isChainSelectDisabled?: boolean; - isTokenSelectDisabled?: boolean; - network?: NexusNetwork; - onChainValueChange: (chain: string) => void; - onTokenValueChange: (token: string, iconUrl?: string) => void; - fieldLabel?: string; - drawerTitle?: string; - type?: BalanceTransactionType; - isDestination?: boolean; - isSourceChain?: boolean; -} - -const DestinationTrigger = ({ - chainValue, - tokenValue, - fieldLabel = 'Destination', -}: { - chainValue?: string; - tokenValue?: string; - fieldLabel?: string; -}) => { - const chainId = chainValue ? parseInt(chainValue) : undefined; - - return ( - -
-
-
- {tokenValue ? ( - - ) : ( -
- )} - {chainId ? ( - {CHAIN_METADATA[chainId]?.name} - ) : ( -
- )} -
-
-

- {tokenValue ?? 'Token'} -

-

- {chainId ? CHAIN_METADATA[chainId]?.name : 'Chain'} -

-
-
- -
- - ); -}; - -const DestinationDrawer = ({ - chainValue, - tokenValue, - isChainSelectDisabled, - isTokenSelectDisabled, - network, - onChainValueChange, - onTokenValueChange, - fieldLabel, - drawerTitle = 'Select Destination Chain & Token', - type, - isDestination = false, - isSourceChain = false, -}: DestinationDrawerProps) => { - return ( - - - - - - -
- - {drawerTitle} - - - - -
-
- -
- - onTokenValueChange(token, iconUrl)} - disabled={isTokenSelectDisabled} - network={network} - className="w-full" - hasValues={!!chainValue} - type={type} - chainId={chainValue ? parseInt(chainValue) : undefined} - isDestination={isDestination} - /> -
-
-
- ); -}; - -export default DestinationDrawer; diff --git a/packages/widgets/src/components/shared/enhanced-info-message.tsx b/packages/widgets/src/components/shared/enhanced-info-message.tsx deleted file mode 100644 index 77a9f189..00000000 --- a/packages/widgets/src/components/shared/enhanced-info-message.tsx +++ /dev/null @@ -1,143 +0,0 @@ -import { useState } from 'react'; -import { InfoMessage } from './info-message'; -import { Button } from '../motion/button-motion'; -import { - isChainError, - extractChainIdFromError, - addChainToWallet, - formatErrorForUI, - cn, -} from '../../utils/utils'; -import { Plus } from '../icons'; -import { useInternalNexus } from '../../providers/InternalNexusProvider'; -import LoadingDots from '../motion/loading-dots'; -import { CHAIN_METADATA, SUPPORTED_CHAINS, logger } from '@nexus/commons'; - -interface EnhancedInfoMessageProps { - error: unknown; - context?: string; - className?: string; -} - -export function EnhancedInfoMessage({ - error, - context, - className, -}: Readonly) { - const [isAddingChain, setIsAddingChain] = useState(false); - const [chainAdded, setChainAdded] = useState(false); - const { sdk } = useInternalNexus(); - - const isChainRelatedError = isChainError(error); - const chainId = isChainRelatedError ? extractChainIdFromError(error) : null; - const chainMetadata = chainId ? CHAIN_METADATA[chainId] : null; - - const handleAddChain = async () => { - if (!chainId) return; - - setIsAddingChain(true); - try { - const provider = sdk.getEVMProviderWithCA(); - const success = await addChainToWallet(chainId, provider); - if (success) { - setChainAdded(true); - } - } catch (err) { - logger.error('Failed to add chain:', err as Error); - } finally { - setIsAddingChain(false); - } - }; - - const formattedError = formatErrorForUI(error, context); - - if (isChainRelatedError && chainMetadata && !chainAdded) { - return ( - -
-

{formattedError}

- -
- {chainMetadata.name} -
-

- {chainMetadata.name} -

-

- Chain ID: {chainId} -

-
- -
- -

- This will add {chainMetadata.name} network to your wallet so you can use it for - transactions. -

-
-
- ); - } - - if (chainAdded) { - return ( - -
-
- - - -
-
-

- {chainMetadata - ? `${chainMetadata.name} network added successfully!` - : 'Network added successfully!'} -

-

- You can now retry your transaction. -

-
-
-
- ); - } - - // Fallback to regular formatted error message - return ( - -

{formattedError}

-
- ); -} diff --git a/packages/widgets/src/components/shared/icons.tsx b/packages/widgets/src/components/shared/icons.tsx deleted file mode 100644 index b0233697..00000000 --- a/packages/widgets/src/components/shared/icons.tsx +++ /dev/null @@ -1,116 +0,0 @@ -import { - CHAIN_METADATA, - SUPPORTED_CHAINS, - TOKEN_METADATA, - DESTINATION_SWAP_TOKENS, - type ChainMetadata, -} from '@nexus/commons'; -import { cn } from '../../utils/utils'; - -// Additional token logos that might not be in TOKEN_METADATA -const ADDITIONAL_TOKEN_LOGOS: Record = { - WETH: 'https://assets.coingecko.com/coins/images/279/large/ethereum.png?1595348880', - USDS: 'https://assets.coingecko.com/coins/images/39926/standard/usds.webp?1726666683', - SOPH: 'https://assets.coingecko.com/coins/images/38680/large/sophon_logo_200.png', - KAIA: 'https://assets.coingecko.com/asset_platforms/images/9672/large/kaia.png', - BNB: 'https://assets.coingecko.com/coins/images/825/large/bnb-icon2_2x.png', - // Add ETH as fallback for any ETH-related tokens - ETH: 'https://coin-images.coingecko.com/coins/images/279/large/ethereum.png?1696501628', - // Add common token fallbacks - POL: 'https://coin-images.coingecko.com/coins/images/32440/standard/polygon.png', - AVAX: 'https://assets.coingecko.com/coins/images/12559/standard/Avalanche_Circle_RedWhite_Trans.png', - FUEL: 'https://coin-images.coingecko.com/coins/images/279/large/ethereum.png', - HYPE: 'https://assets.coingecko.com/asset_platforms/images/243/large/hyperliquid.png', - // Popular swap tokens - DAI: 'https://coin-images.coingecko.com/coins/images/9956/large/Badge_Dai.png?1696509996', - UNI: 'https://coin-images.coingecko.com/coins/images/12504/large/uni.jpg?1696512319', - AAVE: 'https://coin-images.coingecko.com/coins/images/12645/large/AAVE.png?1696512452', - LDO: 'https://coin-images.coingecko.com/coins/images/13573/large/Lido_DAO.png?1696513326', - PEPE: 'https://coin-images.coingecko.com/coins/images/29850/large/pepe-token.jpeg?1696528776', - OP: 'https://coin-images.coingecko.com/coins/images/25244/large/Optimism.png?1696524385', - ZRO: 'https://coin-images.coingecko.com/coins/images/28206/large/ftxG9_TJ_400x400.jpeg?1696527208', - OM: 'https://assets.coingecko.com/coins/images/12151/standard/OM_Token.png?1696511991', - KAITO: 'https://assets.coingecko.com/coins/images/54411/standard/Qm4DW488_400x400.jpg', -}; - -export const ChainIcon = ({ chainId }: { chainId: string }) => { - const chain = Object.values(CHAIN_METADATA).find( - (c: ChainMetadata) => c.id.toString() === chainId, - ); - const iconUrl = chain?.logo; - - if (!iconUrl) { - return
; - } - - return ( - {chainId} - ); -}; - -export const TokenIcon = ({ - tokenSymbol, - iconUrl, - className = 'w-6 h-6 rounded-nexus-full', -}: { - tokenSymbol: string; - iconUrl?: string; - className?: string; -}) => { - let finalIconUrl = iconUrl; - - // Comprehensive icon resolution logic - if (!finalIconUrl) { - // 1. First check additional token logos (prioritize over TOKEN_METADATA for better icons) - finalIconUrl = ADDITIONAL_TOKEN_LOGOS[tokenSymbol]; - - // 2. Then check standard TOKEN_METADATA - if (!finalIconUrl) { - const standardToken = TOKEN_METADATA[tokenSymbol]; - finalIconUrl = standardToken?.icon; - } - - // 3. Check destination swap tokens - if (!finalIconUrl) { - const allDestinationTokens = Array.from(DESTINATION_SWAP_TOKENS.values()).flat(); - const destinationToken = allDestinationTokens.find((token) => token.symbol === tokenSymbol); - finalIconUrl = destinationToken?.logo; - } - - // 4. Special handling for wrapped tokens - if (!finalIconUrl && tokenSymbol.startsWith('W') && tokenSymbol.length > 1) { - const baseSymbol = tokenSymbol.substring(1); // Remove 'W' prefix - finalIconUrl = ADDITIONAL_TOKEN_LOGOS[baseSymbol]; - } - - // 5. ETH fallback for any ethereum-related tokens - if (!finalIconUrl && (tokenSymbol.includes('ETH') || tokenSymbol === 'WETH')) { - finalIconUrl = ADDITIONAL_TOKEN_LOGOS['ETH']; - } - } - - // Fallback placeholder with first letter of token symbol - if (!finalIconUrl) { - return ( -
- {tokenSymbol.charAt(0).toUpperCase()} -
- ); - } - - return {tokenSymbol}; -}; diff --git a/packages/widgets/src/components/shared/info-message.tsx b/packages/widgets/src/components/shared/info-message.tsx deleted file mode 100644 index 9c86796a..00000000 --- a/packages/widgets/src/components/shared/info-message.tsx +++ /dev/null @@ -1,39 +0,0 @@ -import * as React from 'react'; -import { cn } from '../../utils/utils'; -import { cva, type VariantProps } from 'class-variance-authority'; - -const infoMessageVariants = cva( - 'px-2 py-3 rounded-nexus-md overflow-hidden font-nexus-primary font-semibold text-sm leading-[18px] backdrop-blur-[48px] border border-nexus-black/80', - { - variants: { - variant: { - success: 'bg-gradient-to-r from-[#86DF00]/16 to-[#73BF01]/16 text-nexus-black', - info: 'bg-blue-50 text-nexus-black', - warning: 'bg-gradient-to-r from-[#DFC200]/16 to-[#DFC200]/16 text-nexus-black', - error: 'bg-[#C03C541A] text-[#C03C54] border border-[#C03C541A]', - }, - }, - defaultVariants: { - variant: 'success', - }, - }, -); - -interface InfoMessageProps extends VariantProps { - children: React.ReactNode; - className?: string; -} - -export function InfoMessage({ variant, children, className }: Readonly) { - return ( -
-
-
-
- {children} -
-
-
-
- ); -} diff --git a/packages/widgets/src/components/shared/prefilled-inputs.tsx b/packages/widgets/src/components/shared/prefilled-inputs.tsx deleted file mode 100644 index 56539327..00000000 --- a/packages/widgets/src/components/shared/prefilled-inputs.tsx +++ /dev/null @@ -1,78 +0,0 @@ -import { CHAIN_METADATA, SUPPORTED_CHAINS, TOKEN_METADATA } from '@nexus/commons'; -import { cn, formatCost, truncateAddress } from '../../utils/utils'; -import { useInternalNexus } from '../../providers/InternalNexusProvider'; -import { getFiatValue } from '../../utils/balance-utils'; - -interface PrefilledInputsProps { - inputData: { - chainId?: number; - toChainId?: number; - token?: string; - amount?: string | number; - recipient?: string; - }; - className?: string; -} - -const PrefilledInputs = ({ inputData, className = '' }: PrefilledInputsProps) => { - const { exchangeRates } = useInternalNexus(); - const destinationChain = - CHAIN_METADATA[inputData?.chainId ?? inputData?.toChainId ?? SUPPORTED_CHAINS.ETHEREUM]; - const destinationToken = TOKEN_METADATA[inputData?.token ?? 'ETH']; - return ( -
-
-

Sending

-
-
- {destinationToken?.name} -
-

- {formatCost(inputData?.amount as string)} -

-

- {inputData?.token} -

-
-
-
-

To

- {destinationChain?.shortName} -

- {destinationChain?.name} -

-
-
-
- {inputData?.amount && inputData?.token && ( -

- {getFiatValue(inputData?.amount, inputData?.token, exchangeRates)} -

- )} - {inputData?.recipient && ( -
-

To

-

- {truncateAddress(inputData?.recipient, 4, 4)} -

-
- )} -
- ); -}; - -export default PrefilledInputs; diff --git a/packages/widgets/src/components/shared/swap-prefilled-inputs.tsx b/packages/widgets/src/components/shared/swap-prefilled-inputs.tsx deleted file mode 100644 index 40eb7b6d..00000000 --- a/packages/widgets/src/components/shared/swap-prefilled-inputs.tsx +++ /dev/null @@ -1,89 +0,0 @@ -import { CHAIN_METADATA, SUPPORTED_CHAINS, formatBalance } from '@nexus/commons'; -import { cn } from '../../utils/utils'; -import { useInternalNexus } from '../../providers/InternalNexusProvider'; -import { getFiatValue } from '../../utils/balance-utils'; -import { SwapInputData, SwapSimulationResult } from '../../types'; -import { TokenIcon } from './icons'; - -interface SwapPrefilledInputsProps { - inputData: Omit; - className?: string; -} - -const SwapPrefilledInputs = ({ inputData, className = '' }: SwapPrefilledInputsProps) => { - const { exchangeRates, activeTransaction } = useInternalNexus(); - const sourceChain = CHAIN_METADATA[inputData?.fromChainID ?? SUPPORTED_CHAINS.ETHEREUM]; - const destinationChain = CHAIN_METADATA[inputData?.toChainID ?? SUPPORTED_CHAINS.ETHEREUM]; - const transactionIntent = (activeTransaction?.simulationResult as SwapSimulationResult)?.intent; - - return ( -
-
-
-

- Swapping -

-
-
-
- -

- {inputData?.fromAmount} {inputData?.fromTokenAddress} -

- {sourceChain?.shortName} -
-
-

-
-
- -

- {transactionIntent - ? formatBalance( - transactionIntent?.destination?.amount, - transactionIntent?.destination?.token?.decimals, - 6, - ) - : '...'}{' '} - {inputData?.toTokenAddress} -

- {destinationChain?.shortName} -
-
-
- {inputData?.fromAmount && inputData?.fromTokenAddress && ( -

- {getFiatValue(inputData?.fromAmount, inputData?.fromTokenAddress, exchangeRates)} -

- )} -
- ); -}; - -export default SwapPrefilledInputs; diff --git a/packages/widgets/src/components/shared/token-select.tsx b/packages/widgets/src/components/shared/token-select.tsx deleted file mode 100644 index 8bfeeef4..00000000 --- a/packages/widgets/src/components/shared/token-select.tsx +++ /dev/null @@ -1,139 +0,0 @@ -import { useMemo } from 'react'; -import { TOKEN_METADATA, TESTNET_TOKEN_METADATA, NexusNetwork } from '@nexus/commons'; -import { TokenIcon } from './icons'; -import { cn } from '../../utils/utils'; -import { Button } from '../motion/button-motion'; -import { useInternalNexus } from '../../providers/InternalNexusProvider'; -import { DrawerAutoClose } from '../motion/drawer'; -import type { SwapInputData, TokenSelectProps } from '../../types'; -import { useAvailableTokens, type TokenSelectOption } from '../../utils/token-utils'; - -export function TokenSelect({ - value, - onValueChange, - disabled = false, - network = 'mainnet', - className, - hasValues, - type, - chainId, - isDestination = false, -}: TokenSelectProps & { - network?: NexusNetwork; - chainId?: number; - isDestination?: boolean; -}) { - const { unifiedBalance, sdk, isSdkInitialized, activeTransaction } = useInternalNexus(); - - const tokenOptions = useAvailableTokens({ - chainId, - type: type ?? 'bridge', - network, - isDestination, - sdk: isSdkInitialized ? sdk : undefined, - }); - - // Fallback to legacy logic if no type provided (backward compatibility) - const legacyTokenOptions: TokenSelectOption[] = useMemo(() => { - if (type) return []; // Use enhanced logic when type is available - - const tokenMetadata = network === 'testnet' ? TESTNET_TOKEN_METADATA : TOKEN_METADATA; - return Object.values(tokenMetadata).map((token) => ({ - value: token.symbol, - label: token.symbol, - icon: token.icon, - metadata: { - ...token, - contractAddress: undefined, - }, - })); - }, [network, type]); - - const finalTokenOptions = useMemo(() => { - const tokens = type ? tokenOptions : legacyTokenOptions; - const inputData = activeTransaction?.inputData as SwapInputData; - if (inputData && inputData?.fromTokenAddress) { - return tokens.filter((token) => token?.value !== inputData?.fromTokenAddress); - } - return tokens; - }, [type, tokenOptions, legacyTokenOptions]); - - const tokenBalanceBreakdown = useMemo(() => { - let breakdown: Record = {}; - unifiedBalance?.map((balance) => { - const key = balance?.symbol; - breakdown[key] = { - bal: parseFloat(balance?.balance) > 0 ? balance?.balance : '00', - chains: `${balance?.breakdown?.length > 1 ? balance?.breakdown?.length + ' chains' : balance?.breakdown?.length > 0 ? balance?.breakdown?.length + ' chain' : '-'}`, - }; - }); - return breakdown; - }, [unifiedBalance]); - - const selectedOption = useMemo( - () => finalTokenOptions.find((opt) => opt.value === (value ?? '')), - [finalTokenOptions, value], - ); - - const handleSelect = (token: string) => { - if (disabled) return; - onValueChange(token); - }; - - return ( -
-

- {type !== 'swap' - ? 'Destination Token' - : isDestination - ? 'Destination Token' - : 'Source Token'} -

-
- {finalTokenOptions.map((token, index) => ( - - - - ))} - - {/* Empty state */} - {finalTokenOptions.length === 0 && ( -
-

No tokens available

-
- )} -
-
- ); -} diff --git a/packages/widgets/src/components/shared/transaction-details-drawer.tsx b/packages/widgets/src/components/shared/transaction-details-drawer.tsx deleted file mode 100644 index 160a76cf..00000000 --- a/packages/widgets/src/components/shared/transaction-details-drawer.tsx +++ /dev/null @@ -1,390 +0,0 @@ -import { - type SimulationResult, - type BridgeAndExecuteSimulationResult, - type ReadableIntent as Intent, - CHAIN_METADATA, - SUPPORTED_CHAINS, -} from '@nexus/commons'; -import { SwapSimulationResult } from '../../types'; -import { cn, formatCost, getPrimaryButtonText, truncateAddress } from '../../utils/utils'; -import { - Drawer, - DrawerTrigger, - DrawerContent, - DrawerHeader, - DrawerTitle, - DrawerClose, - DrawerFooter, -} from '../motion/drawer'; -import { CircleX } from '../icons'; -import Clock from '../icons/Clock'; -import TwoCircles from '../icons/TwoCircles'; -import MoneyCircles from '../icons/MoneyCircles'; -import { Button } from '../motion/button-motion'; -import { useInternalNexus } from '../../providers/InternalNexusProvider'; -import { getFiatValue } from '../../utils/balance-utils'; -import type { OrchestratorStatus, ReviewStatus, TransactionType } from '../../types'; - -interface TransactionDetailsDrawerProps { - simulationResult?: ( - | SimulationResult - | BridgeAndExecuteSimulationResult - | SwapSimulationResult - ) & { - allowance?: { needsApproval: boolean }; - }; - inputData?: { - token?: string; - amount?: string | number; - chainId?: number; - toChainId?: number; - }; - callback: () => void; - triggerClassname?: string; - type?: TransactionType; - status: OrchestratorStatus; - reviewStatus: ReviewStatus; -} - -interface ChainInfo { - amount: string; - chainID: number; - chainLogo?: string; - chainName: string; - contractAddress?: string; -} - -interface FeesInfo { - caGas: string; - gasSupplied: string; - protocol: string; - solver: string; - total: string; -} - -interface TokenInfo { - decimals: number; - logo?: string; - name: string; - symbol: string; -} - -interface SimulationData { - contractAddress?: string; - functionName?: string; - destination: ChainInfo; - sources: ChainInfo[]; - fees: FeesInfo; - token: TokenInfo; - sourcesTotal: string; -} - -export function TransactionDetailsDrawer({ - simulationResult, - inputData, - callback, - triggerClassname = '', - type, - status, - reviewStatus, -}: Readonly) { - const { exchangeRates } = useInternalNexus(); - const getSimulationData = (): SimulationData | null => { - if (!simulationResult) return null; - console.log('Original simulationResult', simulationResult); - - // Handle swap simulation result - if ('swapMetadata' in simulationResult) { - const swapSim = simulationResult as SwapSimulationResult; - const intent = swapSim.intent; - if (!intent) return null; - const destinationChain = CHAIN_METADATA[intent?.destination?.chain.id]; - const sources = intent.sources.map((source) => { - const sourceChain = CHAIN_METADATA[source.chain.id]; - return { - chainID: sourceChain?.id, - chainName: sourceChain?.name || 'Unknown', - chainLogo: sourceChain?.logo, - amount: source.amount, - } as ChainInfo; - }); - - return { - destination: { - chainID: destinationChain?.id, - chainName: destinationChain?.name || 'Unknown', - chainLogo: destinationChain?.logo, - amount: swapSim?.intent?.destination?.amount, - } as ChainInfo, - sources, - fees: { - total: '0', // Swap fees are typically handled differently - caGas: '0', - gasSupplied: '0', - protocol: '0', - solver: '0', - } as FeesInfo, - token: { - symbol: intent?.sources?.[0]?.token?.symbol || 'Unknown', - name: intent?.sources?.[0]?.token?.symbol, - decimals: intent?.sources?.[0]?.token?.decimals, - } as TokenInfo, - sourcesTotal: intent.sources?.[0]?.amount || '0', - }; - } - - // Check if bridge was skipped in bridge & execute flow - if ( - 'metadata' in simulationResult && - (simulationResult as BridgeAndExecuteSimulationResult)?.metadata?.bridgeSkipped - ) { - const simulation = simulationResult as BridgeAndExecuteSimulationResult; - const metadata = simulation?.metadata; - - if (!metadata) return null; - - return { - contractAddress: metadata?.contractAddress ?? '', - functionName: metadata?.functionName ?? '', - destination: { - chainID: metadata?.targetChain, - chainName: CHAIN_METADATA[metadata?.targetChain]?.name || 'Unknown', - chainLogo: CHAIN_METADATA[metadata?.targetChain]?.logo, - amount: metadata?.inputAmount, - } as ChainInfo, - sources: [ - { - chainName: CHAIN_METADATA[metadata?.targetChain]?.name, - chainID: metadata?.targetChain, - chainLogo: CHAIN_METADATA[metadata?.targetChain]?.logo, - amount: metadata?.inputAmount, - }, - ], - fees: { - total: simulation?.executeSimulation?.gasUsed ?? '0', - bridge: '0', - caGas: '0', - gasSupplied: '0', - protocol: '0', - solver: '0', - } as FeesInfo, - token: { name: simulationResult?.metadata?.token || 'Unknown' } as TokenInfo, - sourcesTotal: metadata?.inputAmount || '0', - }; - } - - // Handle bridge & execute result where intent is nested - let intent: Intent | undefined = undefined; - if ('intent' in simulationResult) { - intent = (simulationResult as SimulationResult)?.intent; - } else if ('bridgeSimulation' in simulationResult && simulationResult?.bridgeSimulation) { - const simulation = simulationResult as BridgeAndExecuteSimulationResult; - intent = simulation?.bridgeSimulation?.intent; - const fees = { - total: simulation?.totalEstimatedCost?.total ?? '0', - ...simulation?.bridgeSimulation?.intent?.fees, - } as FeesInfo; - - return { - contractAddress: simulation?.executeSimulation?.contractAddress ?? '', - functionName: simulation?.executeSimulation?.functionName ?? '', - destination: intent?.destination as ChainInfo, - sources: (intent?.sources || []) as ChainInfo[], - fees: fees, - token: intent?.token as TokenInfo, - sourcesTotal: intent?.sourcesTotal as string, - }; - } - - if (!intent) return null; - - return { - destination: intent?.destination as ChainInfo, - sources: (intent?.sources || []) as ChainInfo[], - fees: intent?.fees as FeesInfo, - token: intent?.token as TokenInfo, - sourcesTotal: intent?.sourcesTotal ?? '0', - }; - }; - - const data = getSimulationData(); - - console.log('Simulation data', data); - - const getDestinationChain = () => { - if (inputData?.toChainId) return inputData.toChainId; - if (inputData?.chainId) return inputData.chainId; - return data?.destination?.chainID; - }; - - const destinationChainId = getDestinationChain(); - const destinationChain = destinationChainId ? CHAIN_METADATA[destinationChainId] : null; - - if (!data) return null; - - return ( - - - View Full Transaction Details - - - - - Transaction Details - - - - - -
- {/* Estimated Time */} -
-
- -

- Estimated Transaction time -

-
- - ~{type === 'bridgeAndExecute' ? '1.5 mins' : '30 seconds'} - -
- - {/* Total Fees */} -
-
- -

- Total Fees -

-
-
- - {formatCost(data.fees.total)} {inputData?.token || data.token.symbol} - - {inputData?.token && ( -

- {getFiatValue(data.fees.total, inputData?.token, exchangeRates)} -

- )} -
-
- - {/* Contract Address */} - {data?.contractAddress && data?.functionName && ( -
-
- -

- {data?.functionName} to -

-
- - {truncateAddress(data?.contractAddress, 4, 4)} - -
- )} - - {/* Sending */} -
-
- -

- Sending -

-
-
-
-

- {inputData?.amount || data.sourcesTotal} {inputData?.token || data.token.symbol} -

- {inputData?.token && ( -

- {getFiatValue(data.sourcesTotal, inputData?.token, exchangeRates)} -

- )} -
- {destinationChain && ( - <> -

on

- {destinationChain.name} - - {destinationChain.name} - - - )} -
-
- - {/* From Section */} - {Array.isArray(data.sources) && data.sources.length > 0 && ( -
-

From

-
- {data.sources.map((source) => { - const chainMeta = CHAIN_METADATA[source.chainID]; - return ( -
-
- {chainMeta?.name -
-
- {inputData?.token || data.token.symbol} -
-
- on {chainMeta?.name || 'Unknown Chain'} -
-
-
-
-
- {source.amount} -
-
- {inputData?.token && - getFiatValue(source.amount, inputData?.token, exchangeRates)} -
-
-
- ); - })} -
-
- )} -
- - - - - -
-
- ); -} diff --git a/packages/widgets/src/components/shared/unified-balance.tsx b/packages/widgets/src/components/shared/unified-balance.tsx deleted file mode 100644 index bcd83406..00000000 --- a/packages/widgets/src/components/shared/unified-balance.tsx +++ /dev/null @@ -1,287 +0,0 @@ -import { useMemo } from 'react'; -import { - Drawer, - DrawerContent, - DrawerTrigger, - DrawerHeader, - DrawerTitle, - DrawerClose, -} from '../motion/drawer'; -import { useInternalNexus } from '../../providers/InternalNexusProvider'; -import { - type SUPPORTED_TOKENS, - type UserAsset, - CHAIN_METADATA, - SUPPORTED_CHAINS, -} from '@nexus/commons'; -import SolarWallet from '../icons/SolarWallet'; -import { ChevronDownIcon, CircleX } from '../icons'; -import { cn, getTokenFromInputData } from '../../utils/utils'; -import { TokenIcon } from './icons'; - -const BalanceTrigger = ({ balance, token }: { balance?: UserAsset; token?: SUPPORTED_TOKENS }) => { - return ( -
-
- - {balance && token ? ( -
-

Total {token}

-

- accross {balance?.breakdown?.length} chains -

-
- ) : ( -

Select token to view cross chain balance

- )} -
- {balance && token && ( -
-
-

- {parseFloat(balance?.balance).toFixed(6)} {token} -

-

- ≈ ${balance?.balanceInFiat} -

-
- -
- )} -
- ); -}; - -const AllBalancesTrigger = ({ balances }: { balances: UserAsset[] }) => { - const totalFiat = useMemo(() => { - return balances?.reduce((sum, asset) => sum + (asset?.balanceInFiat || 0), 0) || 0; - }, [balances]); - - const { tokenCount, uniqueChainCount } = useMemo(() => { - const chains = new Set(); - balances?.forEach((asset) => { - asset?.breakdown?.forEach((b) => { - if (b?.chain?.id != null) chains.add(b.chain.id); - }); - }); - return { tokenCount: balances?.length || 0, uniqueChainCount: chains.size }; - }, [balances]); - - return ( -
-
- -
-

Unified Balance

-

- across {tokenCount} tokens • {uniqueChainCount} chains -

-
-
-
-
-

- ≈ ${totalFiat.toFixed(2)} -

-
- -
-
- ); -}; - -const ChainBalance = ({ - balance, - symbol, -}: { - balance: { - balance: string; - balanceInFiat: number; - chain: { - id: number; - logo: string; - name: string; - }; - contractAddress: `0x${string}`; - decimals: number; - isNative?: boolean; - }; - symbol: string; -}) => { - return ( -
-
- {CHAIN_METADATA[balance.chain.id]?.name} -
-

- {symbol} -

-

- on {balance.chain?.name || `Chain ${balance.chain?.id}`} -

-
-
-
-

- {parseFloat(balance.balance).toFixed(2)} -

-

- ${balance.balanceInFiat} -

-
-
- ); -}; - -const UnifiedBalance = () => { - const { unifiedBalance, activeTransaction } = useInternalNexus(); - const { inputData } = activeTransaction; - const tokenSymbol = getTokenFromInputData(inputData); - - const relevantBalance = useMemo(() => { - if (!unifiedBalance || !tokenSymbol) return [] as UserAsset[]; - return unifiedBalance.filter((balance) => balance?.symbol === tokenSymbol); - }, [tokenSymbol, unifiedBalance]); - - const tokenBalance = relevantBalance[0]; - - if (!unifiedBalance) return null; - - if (!tokenSymbol) - return ( - - - - - - -
- Balances Across Tokens - - - -
-
- -
- {unifiedBalance.map((asset) => { - return ( -
-
-
- {asset.symbol ? ( - - ) : null} -

- Total {asset.symbol} -

-
-
-

- {parseFloat(asset.balance) > 0 - ? parseFloat(asset.balance).toFixed(2) - : '0.00'}{' '} - {asset.symbol} -

-

- ≈ ${asset.balanceInFiat} -

-
-
- - {parseFloat(asset.balance) > 0 && ( -
- {asset.breakdown?.map((breakdownBalance, index: number) => ( - - ))} -
- )} -
- ); - })} -
-
-
- ); - - if (!tokenBalance) return null; - - return ( - - - - - - -
- Balance Across Chains - - - -
-
- -
- {/* Total Balance */} -
-
- -

- Total {tokenSymbol} -

-
-
-

- {parseFloat(tokenBalance.balance).toFixed(6)} {tokenSymbol} -

-

- ≈ ${tokenBalance.balanceInFiat} -

-
-
- - {/* Individual Chain Balances */} - {parseFloat(tokenBalance.balance) > 0 && ( -
- {tokenBalance.breakdown?.map((breakdownBalance, index: number) => ( - - ))} -
- )} -
-
-
- ); -}; - -export default UnifiedBalance; diff --git a/packages/widgets/src/components/shared/unified-transaction-form.tsx b/packages/widgets/src/components/shared/unified-transaction-form.tsx deleted file mode 100644 index abc68b54..00000000 --- a/packages/widgets/src/components/shared/unified-transaction-form.tsx +++ /dev/null @@ -1,378 +0,0 @@ -import { AmountInput } from './amount-input'; -import { AddressField } from './address-field'; -import { cn } from '../../utils/utils'; -import { useInternalNexus } from '../../providers/InternalNexusProvider'; -import { type TransactionType } from '../../utils/balance-utils'; -import { useMemo, useEffect } from 'react'; -import { CHAIN_METADATA, NexusNetwork } from '@nexus/commons'; -import { FormField } from '../motion/form-field'; -import DestinationDrawer from './destination-drawer'; -import { isAddress } from 'viem'; -import { SwapSimulationResult, SwapInputData } from 'src/types'; -import { isTokenChainCombinationValid } from '../../utils/token-utils'; - -export interface UnifiedInputData { - chainId?: number; - toChainId?: number; - token?: string; - inputToken?: string; - outputToken?: string; - amount?: string | number; - recipient?: string; -} - -interface UnifiedTransactionFormProps { - type: TransactionType; - inputData: UnifiedInputData; - onUpdate: (data: UnifiedInputData) => void; - disabled?: boolean; - className?: string; - prefillFields?: { - chainId?: boolean; - toChainId?: boolean; - token?: boolean; - inputToken?: boolean; - outputToken?: boolean; - amount?: boolean; - recipient?: boolean; - }; -} - -interface SwapTransactionFormProps { - inputData: SwapInputData; - onUpdate: (data: SwapInputData) => void; - disabled?: boolean; - className?: string; - prefillFields?: { - fromChainID?: boolean; - toChainID?: boolean; - fromTokenAddress?: boolean; - toTokenAddress?: boolean; - fromAmount?: boolean; - toAmount?: boolean; - }; -} - -interface SwapFormProps { - title: string; - inputData: SwapInputData; - isAmountDisabled?: boolean; - handleUpdate: (data: Partial) => void; - isChainSelectDisabled?: boolean; - isTokenSelectDisabled?: boolean; - isOutputTokenSelectDisabled?: boolean; - network?: NexusNetwork; - destinationAmount?: string; -} - -const FORM_CONFIG = { - bridge: { - chainLabel: 'Destination Network', - tokenLabel: 'Token to be transferred', - chainField: 'chainId', - showRecipient: false, - showOutputToken: false, - showDestinationAmount: false, - }, - bridgeAndExecute: { - chainLabel: 'Destination Network', - tokenLabel: 'Token to be deposited', - chainField: 'toChainId', - showRecipient: false, - showOutputToken: false, - showDestinationAmount: false, - }, - transfer: { - chainLabel: 'Source Network', - tokenLabel: 'Token to transfer', - chainField: 'chainId', - showRecipient: true, - showOutputToken: false, - showDestinationAmount: false, - }, - swap: { - chainLabel: 'Source Network', - tokenLabel: 'Input Token', - outputTokenLabel: 'Output Token', - chainField: 'fromChainID', - toChainField: 'toChainID', - showRecipient: false, - showDestinationAmount: true, - showOutputToken: true, - showDestinationChain: true, - }, -} as const; - -const SwapForm = ({ - title, - inputData, - isAmountDisabled, - handleUpdate, - isChainSelectDisabled, - isTokenSelectDisabled, - isOutputTokenSelectDisabled, - network = 'mainnet', - destinationAmount, -}: SwapFormProps) => { - return ( -
-
- - handleUpdate({ fromAmount: value, toAmount: value }) - } - token={inputData?.fromTokenAddress} - debounceMs={1000} - /> - - - { - if (isChainSelectDisabled) return; - handleUpdate({ fromChainID: parseInt(chainId, 10) as any }); - }} - onTokenValueChange={(token) => { - if (!isTokenSelectDisabled) { - handleUpdate({ fromTokenAddress: token as any }); - } - }} - isTokenSelectDisabled={isTokenSelectDisabled} - isChainSelectDisabled={isChainSelectDisabled} - network={network} - drawerTitle="Select Source Chain & Token" - fieldLabel="Source" - type="swap" - isSourceChain={true} - /> -
-
- - - - - { - if (isChainSelectDisabled) return; - handleUpdate({ toChainID: parseInt(chainId, 10) as any }); - }} - onTokenValueChange={(token) => { - if (!isOutputTokenSelectDisabled) { - handleUpdate({ toTokenAddress: token as any }); - } - }} - isTokenSelectDisabled={isOutputTokenSelectDisabled} - isChainSelectDisabled={isChainSelectDisabled} - network={network} - drawerTitle="Select Destination Chain & Token" - fieldLabel="Destination" - type="swap" - isDestination={true} - isSourceChain={false} - /> -
-
- ); -}; - -export function SwapTransactionForm({ - inputData, - onUpdate, - disabled = false, - className, - prefillFields = {}, -}: Readonly) { - const { config, isSimulating, activeTransaction } = useInternalNexus(); - - const isInputDisabled = disabled || isSimulating; - const isChainSelectDisabled = isInputDisabled || prefillFields.fromChainID; - const isTokenSelectDisabled = isInputDisabled || prefillFields.fromTokenAddress; - const isOutputTokenSelectDisabled = isInputDisabled || prefillFields.toTokenAddress; - const isAmountDisabled = isInputDisabled || prefillFields.fromAmount; - - const title = useMemo(() => { - const fromToken = inputData?.fromTokenAddress; - const toToken = inputData?.toTokenAddress; - if (fromToken && toToken) { - return `Swapping (${fromToken} → ${toToken})`; - } - return 'Swap'; - }, [inputData?.fromTokenAddress, inputData?.toTokenAddress]); - - const handleUpdate = (data: Partial) => { - onUpdate({ ...inputData, ...data }); - }; - - // Reset token when chain changes to invalid combination (disabled for swaps to prevent aggressive resets) - useEffect(() => { - // For swaps, we allow users to make selections and validate at execution time - // This prevents tokens from being reset when switching between valid chains - if (inputData.fromChainID && inputData.fromTokenAddress) { - // Skip validation for swaps to maintain user selections - const shouldReset = false; - if (shouldReset) { - handleUpdate({ fromTokenAddress: undefined }); - } - } - }, [inputData.fromChainID]); - - useEffect(() => { - // For swaps, we allow users to make selections and validate at execution time - if (inputData.toChainID && inputData.toTokenAddress) { - // Skip validation for swaps to maintain user selections - const shouldReset = false; - if (shouldReset) { - handleUpdate({ toTokenAddress: undefined }); - } - } - }, [inputData.toChainID]); - - const destinationAmount = useMemo(() => { - const intent = (activeTransaction?.simulationResult as SwapSimulationResult)?.intent; - if (intent?.destination?.amount) { - return parseFloat(intent.destination.amount).toFixed(6); - } - return '0'; - }, [activeTransaction?.simulationResult]); - - return ( -
- -
- ); -} - -export function UnifiedTransactionForm({ - type, - inputData, - onUpdate, - disabled = false, - className, - prefillFields = {}, -}: Readonly) { - const { config, isSimulating } = useInternalNexus(); - - const formConfig = FORM_CONFIG[type]; - const isInputDisabled = disabled || isSimulating; - const isChainSelectDisabled = - isInputDisabled || prefillFields[formConfig.chainField as keyof typeof prefillFields]; - const isTokenSelectDisabled = isInputDisabled || prefillFields.token || prefillFields.inputToken; - const isAmountDisabled = isInputDisabled || prefillFields.amount; - const isReceipientDisabled = isInputDisabled || prefillFields.recipient; - - const title = useMemo(() => { - const chainId = inputData?.chainId || inputData?.toChainId; - const token = inputData?.token || inputData?.inputToken; - - if (chainId && token) { - return `Sending (${token} to ${CHAIN_METADATA[chainId]?.name})`; - } - return 'Sending'; - }, [inputData, type]); - - const hasValidationError = useMemo( - () => inputData?.recipient && !isAddress(inputData?.recipient ?? ''), - [inputData?.recipient], - ); - - const handleUpdate = (data: UnifiedInputData) => { - onUpdate(data); - }; - - // Reset token when chain changes to invalid combination for bridge/bridgeAndExecute - useEffect(() => { - if (type === 'bridge' || type === 'bridgeAndExecute') { - const chainId = type === 'bridgeAndExecute' ? inputData.toChainId : inputData.chainId; - if (chainId && inputData.token) { - if (!isTokenChainCombinationValid(inputData.token, chainId, type)) { - handleUpdate({ token: undefined }); - } - } - } - }, [inputData.chainId, inputData.toChainId, type]); - - return ( -
-
-
- - handleUpdate({ amount: value })} - token={inputData?.token || inputData?.inputToken} - debounceMs={1000} - /> - - - { - if (isChainSelectDisabled) return; - const fieldName = formConfig.chainField; - handleUpdate({ [fieldName]: parseInt(chainId, 10) }); - }} - onTokenValueChange={(token) => { - if (!isTokenSelectDisabled) { - handleUpdate({ token }); - } - }} - isTokenSelectDisabled={isTokenSelectDisabled} - isChainSelectDisabled={isChainSelectDisabled} - network={config?.network ?? 'mainnet'} - /> -
- - {formConfig.showRecipient && ( - - { - if (!isReceipientDisabled) { - handleUpdate({ recipient: value }); - } - }} - disabled={isReceipientDisabled} - /> - - )} -
-
- ); -} diff --git a/packages/widgets/src/components/shared/unified-transaction-modal.tsx b/packages/widgets/src/components/shared/unified-transaction-modal.tsx deleted file mode 100644 index 00a0b2cf..00000000 --- a/packages/widgets/src/components/shared/unified-transaction-modal.tsx +++ /dev/null @@ -1,324 +0,0 @@ -import React, { useState, useCallback } from 'react'; -import { BaseModal } from '../motion/base-modal'; -import { useInternalNexus } from '../../providers/InternalNexusProvider'; -import { - cn, - getContentKey, - getModalTitle, - getPrimaryButtonText, - getTokenFromInputData, - getAmountFromInputData, -} from '../../utils/utils'; -import { type TransactionType } from '../../utils/balance-utils'; -import { TransactionSimulation } from '../processing/transaction-simulation'; -import { AvailLogo } from '../icons/AvailLogo'; -import UnifiedBalance from './unified-balance'; -import { InfoMessage } from './info-message'; -import { AllowanceForm } from './allowance-form'; -import { DialogFooter, DialogHeader, DialogTitle } from '../motion/dialog-motion'; -import { SlideTransition } from '../motion/slide-transition'; -import { EnhancedInfoMessage } from './enhanced-info-message'; -import { ActionButtons } from './action-buttons'; -import type { UnifiedInputData, SwapInputData } from '../../types'; - -interface UnifiedTransactionModalProps { - transactionType: TransactionType; - modalTitle: string; - FormComponent: React.ComponentType<{ - inputData: UnifiedInputData | SwapInputData; - onUpdate: (data: UnifiedInputData | SwapInputData) => void; - disabled: boolean; - prefillFields?: any; - }>; - getSimulationError?: (simulationResult: any) => boolean; - getMinimumAmount?: (simulationResult: any) => string; - getSourceChains?: ( - simulationResult: any, - ) => { chainId: number; amount: string; needsApproval?: boolean }[]; - transformInputData?: (inputData: any) => any; -} - -export function UnifiedTransactionModal({ - transactionType, - modalTitle, - FormComponent, - getSimulationError, - getMinimumAmount, - getSourceChains, - transformInputData, -}: Readonly) { - const { - activeTransaction, - activeController, - updateInput, - confirmAndProceed, - cancelTransaction, - initializeSdk, - triggerSimulation, - retrySimulation, - isSdkInitialized, - isSimulating, - insufficientBalance, - allowanceError, - isSettingAllowance, - approveAllowance, - denyAllowance, - startAllowanceFlow, - initiateSwap, - proceedWithSwap, - } = useInternalNexus(); - - const { status, reviewStatus, inputData, simulationResult, type, prefillFields } = - activeTransaction; - const [isInitializing, setIsInitializing] = useState(false); - const [allowanceFormValid, setAllowanceFormValid] = useState(false); - const [allowanceApproveHandler, setAllowanceApproveHandler] = useState<(() => void) | null>(null); - - const handleAllowanceFormStateChange = useCallback( - (isValid: boolean, handler: () => void) => { - setAllowanceFormValid(isValid); - setAllowanceApproveHandler(() => handler); - }, - [setAllowanceFormValid, setAllowanceApproveHandler], - ); - - // Helper function to check sufficient input for both regular transactions and swaps - const checkHasSufficientInput = useCallback( - (inputData: any) => { - if (!inputData) return false; - - if (transactionType === 'swap') { - // For swaps, check input directly (since activeController is null) - const data = inputData as Partial; - return !!( - data.fromChainID && - data.toChainID && - data.fromTokenAddress && - data.toTokenAddress && - data.fromAmount && - parseFloat(data.fromAmount?.toString() || '0') > 0 - ); - } else { - // For regular transactions, use activeController - return activeController?.hasSufficientInput(inputData || {}) || false; - } - }, - [transactionType, activeController], - ); - - // Type guard - return null if wrong transaction type - if (type !== transactionType) { - return null; - } - - const isOpen = - status !== 'idle' && status !== 'processing' && status !== 'success' && status !== 'error'; - const isBusy = status === 'processing' || reviewStatus === 'simulating'; - - const handleInitialize = async () => { - try { - setIsInitializing(true); - await initializeSdk(); - } finally { - setIsInitializing(false); - } - }; - - const handleReviewGatheringInput = async () => { - if (!checkHasSufficientInput(inputData)) return; - if (transactionType === 'swap') { - await initiateSwap(inputData as SwapInputData); - return; - } - triggerSimulation(); - }; - - const handleReviewReady = () => { - if (transactionType === 'swap') { - proceedWithSwap(); - return; - } - confirmAndProceed(); - }; - - const handleSetAllowance = () => { - if (allowanceApproveHandler) allowanceApproveHandler(); - }; - - const handleButtonClick = async () => { - // Early-return guards to keep complexity low - if (status === 'initializing') return handleInitialize(); - if (status === 'simulation_error') return retrySimulation(); - - if (status === 'review') { - if (reviewStatus === 'gathering_input') return handleReviewGatheringInput(); - if (reviewStatus === 'ready') return handleReviewReady(); - if (reviewStatus === 'needs_allowance') return startAllowanceFlow(); - } - - if (status === 'set_allowance') return handleSetAllowance(); - - return confirmAndProceed(); - }; - - const debouncedClick = () => { - setTimeout(handleButtonClick, 500); - }; - - const hasSufficientInput = checkHasSufficientInput(inputData); - const shouldShowSimulation = isSdkInitialized && hasSufficientInput; - const transformedInputData = transformInputData ? transformInputData(inputData) : inputData; - - const renderAllowanceContent = () => { - if (!simulationResult || !inputData) return null; - - // Get minimum amount and source chains using provided functions or defaults - const minimumAmount = getMinimumAmount ? getMinimumAmount(simulationResult) : '0'; - const sourceChains = getSourceChains ? getSourceChains(simulationResult) : []; - - return ( - - ); - }; - - const showFooterButtons = status !== 'processing' && status !== 'success' && status !== 'error'; - - const preventClose = status === 'processing' || reviewStatus === 'simulating'; - - const showHeader = - activeTransaction?.status !== 'processing' && - activeTransaction?.status !== 'success' && - activeTransaction?.status !== 'error'; - - const isPrimaryLoading = - isBusy || isInitializing || (status === 'set_allowance' && isSettingAllowance); - - return ( - {} : cancelTransaction} - hideCloseButton={true} - > - {/* Header - Fixed at top */} - {showHeader && ( - - - - {getModalTitle(status, modalTitle)} - - - )} - - {/* Content - Flexible middle area */} -
- - {(status === 'initializing' || status === 'review' || status === 'simulation_error') && ( - <> - - - -
- {!isSdkInitialized && ( - - Sign a quick message to turn on cross-chain transfers. Don't worry - it's gasless & no funds will move yet. - - )} - - {isSdkInitialized && insufficientBalance && ( - -
-

- Insufficient {getTokenFromInputData(inputData)} balance -

-

- You don't have enough {getTokenFromInputData(inputData)} to complete this - transaction. - {transactionType === 'bridgeAndExecute' - ? ' Consider using a smaller amount or add more funds to your wallet.' - : ' Please add more funds to your wallet or reduce the transaction amount.'} -

-
-
- )} - {(activeTransaction?.error && status === 'simulation_error') || - (simulationResult && getSimulationError && getSimulationError(simulationResult)) ? ( - - ) : ( - shouldShowSimulation && - !insufficientBalance && - status !== 'simulation_error' && - type !== 'swap' && ( - - ) - )} -
- - )} - {status === 'set_allowance' && <>{renderAllowanceContent()}} -
-
- - {/* Footer - Fixed at bottom */} - {showFooterButtons && ( - - - - )} -
- ); -} diff --git a/packages/widgets/src/components/swap/swap-button.tsx b/packages/widgets/src/components/swap/swap-button.tsx deleted file mode 100644 index d68e92d6..00000000 --- a/packages/widgets/src/components/swap/swap-button.tsx +++ /dev/null @@ -1,27 +0,0 @@ -'use client'; -import { FC } from 'react'; -import { useInternalNexus } from '../../providers/InternalNexusProvider'; -import { SwapButtonProps } from '../../types'; -import SwapModal from './swap-modal'; - -export const SwapButton: FC = ({ prefill, children, className, title }) => { - const { startTransaction, activeTransaction, config } = useInternalNexus(); - - if (config?.network === 'testnet') { - throw new Error('Testnet is not supported'); - } - - const isLoading = - activeTransaction.status === 'processing' || activeTransaction.reviewStatus === 'simulating'; - - const handleClick = () => { - startTransaction('swap', prefill); - }; - - return ( - <> -
{children({ onClick: handleClick, isLoading })}
- - - ); -}; diff --git a/packages/widgets/src/components/swap/swap-modal.tsx b/packages/widgets/src/components/swap/swap-modal.tsx deleted file mode 100644 index 27403568..00000000 --- a/packages/widgets/src/components/swap/swap-modal.tsx +++ /dev/null @@ -1,67 +0,0 @@ -import { UnifiedTransactionModal } from '../shared/unified-transaction-modal'; -import { SwapTransactionForm, UnifiedInputData } from '../shared/unified-transaction-form'; -import { SwapSimulationResult, SwapInputData } from '../../types'; -import SwapPrefilledInputs from '../shared/swap-prefilled-inputs'; - -interface SwapFormSectionProps { - inputData: SwapInputData | UnifiedInputData; - onUpdate: (data: SwapInputData | UnifiedInputData) => void; - disabled: boolean; - prefillFields?: any; -} - -function SwapFormSection({ - inputData, - onUpdate, - disabled = false, - prefillFields = {}, -}: Readonly) { - const swapInputData = inputData as SwapInputData; - const requiredFields = [ - 'fromChainID', - 'toChainID', - 'fromTokenAddress', - 'toTokenAddress', - 'fromAmount', - ]; - // Check if fields are actually prefilled (boolean values in prefillFields indicate prefilled fields) - const hasPrefilledInputs = requiredFields.every((field) => prefillFields[field] === true); - - if (hasPrefilledInputs) { - return ; - } - - return ( - void} - disabled={disabled} - prefillFields={prefillFields} - /> - ); -} - -export default function SwapModal({ title = 'Nexus Widget' }: Readonly<{ title?: string }>) { - const getSimulationError = (simulationResult: SwapSimulationResult): boolean => { - if (!simulationResult) return true; - return ( - simulationResult.success === false || - Boolean(simulationResult.error) || - !simulationResult.intent - ); - }; - const transformInputData = (inputData: SwapInputData | null | undefined) => { - if (!inputData) return {}; - return inputData; - }; - - return ( - - ); -} diff --git a/packages/widgets/src/components/transfer/transfer-button.tsx b/packages/widgets/src/components/transfer/transfer-button.tsx deleted file mode 100644 index 6841a458..00000000 --- a/packages/widgets/src/components/transfer/transfer-button.tsx +++ /dev/null @@ -1,26 +0,0 @@ -'use client'; -import type { TransferButtonProps } from '../../types'; -import { useInternalNexus } from '../../providers/InternalNexusProvider'; -import TransferModal from './transfer-modal'; - -export function TransferButton({ - prefill, - children, - className, - title, -}: Readonly) { - const { startTransaction, activeTransaction } = useInternalNexus(); - const isLoading = - activeTransaction.status === 'processing' || activeTransaction.reviewStatus === 'simulating'; - - const handleClick = () => { - startTransaction('transfer', prefill); - }; - - return ( - <> -
{children({ onClick: handleClick, isLoading })}
- - - ); -} diff --git a/packages/widgets/src/components/transfer/transfer-modal.tsx b/packages/widgets/src/components/transfer/transfer-modal.tsx deleted file mode 100644 index 5f66bc1d..00000000 --- a/packages/widgets/src/components/transfer/transfer-modal.tsx +++ /dev/null @@ -1,93 +0,0 @@ -import { UnifiedTransactionModal } from '../shared/unified-transaction-modal'; -import { SimulationResult } from '@nexus/commons'; -import { UnifiedInputData, UnifiedTransactionForm } from '../shared/unified-transaction-form'; -import { SwapInputData } from '../../types'; -import PrefilledInputs from '../shared/prefilled-inputs'; -import { useInternalNexus } from '../../providers/InternalNexusProvider'; - -interface TransferFormSectionProps { - inputData: UnifiedInputData | SwapInputData; - onUpdate: (data: UnifiedInputData | SwapInputData) => void; - disabled: boolean; - prefillFields?: any; -} - -type InputData = { - chainId?: number; - token?: string; - amount?: string | number; - recipient?: string; -}; - -function TransferFormSection({ - inputData, - onUpdate, - disabled = false, - prefillFields = {}, -}: Readonly) { - const { activeController } = useInternalNexus(); - - if (!activeController) return null; - - // Cast to UnifiedInputData since transfer operations only use this type - const transferInputData = inputData as UnifiedInputData; - - const requiredFields: (keyof InputData)[] = ['chainId', 'token', 'amount', 'recipient']; - const hasEnoughInputs = requiredFields.every((field) => prefillFields[field] === true); - - if (hasEnoughInputs) { - return ; - } - - return ( - void} - disabled={disabled} - prefillFields={prefillFields} - /> - ); -} - -export default function TransferModal({ title = 'Nexus Widget' }: Readonly<{ title?: string }>) { - const getSimulationError = (simulationResult: SimulationResult) => { - return simulationResult && !simulationResult.intent; - }; - - const getMinimumAmount = (simulationResult: SimulationResult) => { - return simulationResult?.intent?.sourcesTotal || '0'; - }; - - const getSourceChains = ( - simulationResult: SimulationResult & { - allowance?: { - chainDetails?: Array<{ chainId: number; amount: string; needsApproval: boolean }>; - }; - }, - ) => { - // Use chainDetails from allowance if available (provides needsApproval info) - if (simulationResult?.allowance?.chainDetails) { - return simulationResult.allowance.chainDetails; - } - - // Fallback to original sources mapping - return ( - simulationResult?.intent?.sources?.map((source) => ({ - chainId: source.chainID, - amount: source.amount, - })) || [] - ); - }; - - return ( - - ); -} diff --git a/packages/widgets/src/controllers/BridgeAndExecuteController.tsx b/packages/widgets/src/controllers/BridgeAndExecuteController.tsx deleted file mode 100644 index 42f9ac4e..00000000 --- a/packages/widgets/src/controllers/BridgeAndExecuteController.tsx +++ /dev/null @@ -1,198 +0,0 @@ -import React from 'react'; -import type { ITransactionController, ActiveTransaction } from '../types'; -import { NexusSDK } from '@avail-project/nexus-core'; -import { - UnifiedTransactionForm, - UnifiedInputData, -} from '../components/shared/unified-transaction-form'; - -import { - type DynamicParamBuilder, - type ExecuteParams, - type SUPPORTED_TOKENS, - type SUPPORTED_CHAINS_IDS, - type BridgeAndExecuteParams, - type BridgeAndExecuteResult, - type BridgeAndExecuteSimulationResult, - logger, -} from '@nexus/commons'; -import { Abi } from 'viem'; - -export interface BridgeAndExecuteConfig extends Partial {} - -const BridgeAndExecuteInputForm: React.FC<{ - prefill: Partial; - onUpdate: (data: Partial) => void; - isBusy: boolean; - prefillFields?: { - toChainId?: boolean; - token?: boolean; - amount?: boolean; - }; -}> = ({ prefill, onUpdate, isBusy, prefillFields = {} }) => { - // Transform BridgeAndExecuteConfig to UnifiedInputData - const unifiedInputData: UnifiedInputData = { - toChainId: prefill?.toChainId, - token: prefill?.token, - amount: prefill?.amount, - }; - - // Transform UnifiedInputData back to BridgeAndExecuteConfig - const handleUpdate = (data: UnifiedInputData) => { - // Only include defined values to avoid overwriting existing data - const transformedData: any = {}; - if (data.toChainId !== undefined) transformedData.toChainId = data.toChainId; - if (data.token !== undefined) transformedData.token = data.token; - if (data.amount !== undefined) transformedData.amount = data.amount; - - onUpdate(transformedData); - }; - - return ( - - ); -}; - -export class BridgeAndExecuteController implements ITransactionController { - InputForm = BridgeAndExecuteInputForm; - - hasSufficientInput(inputData: Partial): boolean { - const { - token, - amount, - toChainId, - contractAddress, - contractAbi, - functionName, - buildFunctionParams, - } = inputData as any; - - if (!token || !amount || !toChainId) return false; - if (!contractAddress || !contractAbi || !functionName || !buildFunctionParams) return false; - - const amt = parseFloat(amount.toString()); - return !isNaN(amt) && amt > 0; - } - - private buildExecute(inputData: { - token: SUPPORTED_TOKENS; - amount: string | number; - toChainId: SUPPORTED_CHAINS_IDS; - contractAddress: `0x${string}`; - contractAbi: Abi; - functionName: string; - buildFunctionParams: DynamicParamBuilder; - }): Omit { - // Return new callback-based execute params directly - return { - contractAddress: inputData.contractAddress, - contractAbi: inputData.contractAbi, - functionName: inputData.functionName, - buildFunctionParams: inputData.buildFunctionParams, - tokenApproval: - inputData.token !== 'ETH' - ? { - token: inputData.token, - amount: inputData.amount.toString(), - } - : undefined, - }; - } - - async runReview( - sdk: NexusSDK, - inputData: Partial, - ): Promise { - let params: BridgeAndExecuteParams = inputData as BridgeAndExecuteParams; - if (!params.execute) { - const execute = this.buildExecute(inputData as any); - params = { ...inputData, execute } as BridgeAndExecuteParams; - } - const simulationResult = await sdk.simulateBridgeAndExecute(params); - logger.info('bridgeAndExecute simulationResult', simulationResult); - - let needsApproval = false; - const chainDetails: Array<{ - chainId: number; - amount: string; - needsApproval: boolean; - }> = []; - - // Check if bridge part needs allowance (when bridge is NOT skipped) - if (simulationResult?.bridgeSimulation?.intent?.sources && inputData.token !== 'ETH') { - const sourcesData = simulationResult.bridgeSimulation.intent.sources; - - for (const source of sourcesData) { - const requiredAmount = sdk.utils.parseUnits( - source.amount, - sdk.utils.getTokenMetadata(inputData.token!)?.decimals ?? 18, - ); - - const allowances = await sdk.getAllowance(source.chainID, [inputData.token!]); - logger.info(`bridgeAndExecute bridge allowances for chain ${source.chainID}:`, allowances); - - const currentAllowance = allowances[0]?.allowance ?? 0n; - const chainNeedsApproval = currentAllowance < requiredAmount; - - if (chainNeedsApproval) { - needsApproval = true; - logger.info( - `BridgeAndExecute bridge allowance needed on chain ${source.chainID}: required=${requiredAmount.toString()}, current=${currentAllowance.toString()}`, - ); - } - - chainDetails.push({ - chainId: source.chainID, - amount: requiredAmount.toString(), - needsApproval: chainNeedsApproval, - }); - } - } - - // Also check if contract execution needs approval (when bridge is skipped) - // This is handled by the execute service internally, but we can inform the UI - const contractApprovalNeeded = !!simulationResult?.metadata?.approvalRequired; - if (contractApprovalNeeded) { - needsApproval = true; - } - - return { - ...simulationResult, - allowance: { - needsApproval, - chainDetails: chainDetails.length > 0 ? chainDetails : undefined, - }, - } as BridgeAndExecuteSimulationResult & { - allowance: { - needsApproval: boolean; - chainDetails?: Array<{ - chainId: number; - amount: string; - needsApproval: boolean; - }>; - }; - }; - } - - async confirmAndProceed( - sdk: NexusSDK, - inputData: Partial, - _simulationResult?: ActiveTransaction['simulationResult'], - ): Promise { - let params: BridgeAndExecuteParams = inputData as BridgeAndExecuteParams; - - if (!params.execute) { - const execute = this.buildExecute(inputData as any); - params = { ...inputData, execute } as BridgeAndExecuteParams; - } - - const result = await sdk.bridgeAndExecute(params); - return result; - } -} diff --git a/packages/widgets/src/controllers/BridgeController.tsx b/packages/widgets/src/controllers/BridgeController.tsx deleted file mode 100644 index 6b9e4e22..00000000 --- a/packages/widgets/src/controllers/BridgeController.tsx +++ /dev/null @@ -1,125 +0,0 @@ -import React from 'react'; -import type { ITransactionController, BridgeConfig, ActiveTransaction } from '../types'; -import { NexusSDK } from '@avail-project/nexus-core'; -import { type BridgeParams, type BridgeResult, logger } from '@nexus/commons'; -import { - UnifiedTransactionForm, - UnifiedInputData, -} from '../components/shared/unified-transaction-form'; - -const BridgeInputForm: React.FC<{ - prefill: Partial; - onUpdate: (data: Partial) => void; - isBusy: boolean; - prefillFields?: { - chainId?: boolean; - toChainId?: boolean; - token?: boolean; - amount?: boolean; - recipient?: boolean; - }; -}> = ({ prefill, onUpdate, isBusy, prefillFields = {} }) => { - // Transform BridgeConfig to UnifiedInputData - const unifiedInputData: UnifiedInputData = { - chainId: prefill?.chainId, - toChainId: prefill?.chainId, // Bridge uses same source chain - token: prefill?.token, - amount: prefill?.amount, - }; - - // Transform UnifiedInputData back to BridgeConfig - const handleUpdate = (data: UnifiedInputData) => { - onUpdate({ - chainId: data.chainId as any, - token: data.token as any, - amount: data.amount, - }); - }; - - return ( - - ); -}; - -export class BridgeController implements ITransactionController { - InputForm = BridgeInputForm; - - hasSufficientInput(inputData: Partial): boolean { - if (!inputData.amount || !inputData.chainId || !inputData.token) { - return false; - } - - const amount = parseFloat(inputData.amount.toString()); - return !isNaN(amount) && amount > 0; - } - - async runReview( - sdk: NexusSDK, - inputData: BridgeParams, - ): Promise { - const simulationResult = await sdk.simulateBridge(inputData); - logger.info('bridge simulationResult', simulationResult); - - const sourcesData = simulationResult?.intent?.sources || []; - let needsApproval = false; - const chainDetails: Array<{ - chainId: number; - amount: string; - needsApproval: boolean; - }> = []; - - for (const source of sourcesData) { - if (inputData?.token === 'ETH') { - chainDetails.push({ - chainId: source.chainID, - amount: source.amount, - needsApproval: false, - }); - continue; - } - - const requiredAmount = sdk.utils.parseUnits( - source.amount, - sdk.utils.getTokenMetadata(inputData.token)?.decimals ?? 18, - ); - - const allowances = await sdk.getAllowance(source.chainID, [inputData.token]); - logger.info(`allowances for chain ${source.chainID}:`, allowances); - - const currentAllowance = allowances[0]?.allowance ?? 0n; - const chainNeedsApproval = currentAllowance < requiredAmount; - - if (chainNeedsApproval) { - needsApproval = true; - logger.info( - `Allowance needed on chain ${source.chainID}: required=${requiredAmount}, current=${currentAllowance}`, - ); - } - - chainDetails.push({ - chainId: source.chainID, - amount: requiredAmount.toString(), - needsApproval: chainNeedsApproval, - }); - } - - return { - ...simulationResult, - allowance: { - needsApproval, - chainDetails, - }, - }; - } - - async confirmAndProceed(sdk: NexusSDK, inputData: BridgeParams): Promise { - const result = await sdk.bridge(inputData); - return result; - } -} diff --git a/packages/widgets/src/controllers/TransferController.tsx b/packages/widgets/src/controllers/TransferController.tsx deleted file mode 100644 index 28b73aaf..00000000 --- a/packages/widgets/src/controllers/TransferController.tsx +++ /dev/null @@ -1,135 +0,0 @@ -import React from 'react'; -import type { ITransactionController, ActiveTransaction } from '../types'; -import { NexusSDK } from '@avail-project/nexus-core'; -import { type TransferParams, type TransferResult, logger } from '@nexus/commons'; -import { - UnifiedTransactionForm, - UnifiedInputData, -} from '../components/shared/unified-transaction-form'; - -export interface TransferConfig extends Partial {} - -const TransferInputForm: React.FC<{ - prefill: Partial; - onUpdate: (data: Partial) => void; - isBusy: boolean; - prefillFields?: { - chainId?: boolean; - toChainId?: boolean; - token?: boolean; - amount?: boolean; - recipient?: boolean; - }; -}> = ({ prefill, onUpdate, isBusy, prefillFields = {} }) => { - // Transform TransferConfig to UnifiedInputData - const unifiedInputData: UnifiedInputData = { - chainId: prefill?.chainId, - toChainId: prefill?.chainId, // Transfer uses same chain - token: prefill?.token, - amount: prefill?.amount, - recipient: prefill?.recipient, - }; - - // Transform UnifiedInputData back to TransferConfig - const handleUpdate = (data: UnifiedInputData) => { - onUpdate({ - chainId: data.chainId as any, - token: data.token as any, - amount: data.amount, - recipient: data.recipient as any, // Cast to proper hex string type - }); - }; - - return ( - - ); -}; - -export class TransferController implements ITransactionController { - InputForm = TransferInputForm; - - hasSufficientInput(inputData: Partial): boolean { - if (!inputData.amount || !inputData.chainId || !inputData.token || !inputData.recipient) { - return false; - } - - const amount = parseFloat(inputData.amount.toString()); - if (isNaN(amount) || amount <= 0) { - return false; - } - - if (!/^0x[a-fA-F0-9]{40}$/.test(inputData.recipient)) { - return false; - } - - return true; - } - - async runReview( - sdk: NexusSDK, - inputData: TransferParams, - ): Promise { - const simulationResult = await sdk.simulateTransfer(inputData); - logger.info('transfer simulationResult', simulationResult); - const sourcesData = simulationResult?.intent?.sources || []; - let needsApproval = false; - const chainDetails: Array<{ - chainId: number; - amount: string; - needsApproval: boolean; - }> = []; - - for (const source of sourcesData) { - if (inputData?.token === 'ETH') { - chainDetails.push({ - chainId: source.chainID, - amount: source.amount, - needsApproval: false, - }); - continue; - } - - const requiredAmount = sdk.utils.parseUnits( - source.amount, - sdk.utils.getTokenMetadata(inputData.token)?.decimals ?? 18, - ); - const allowances = await sdk.getAllowance(source.chainID, [inputData.token]); - logger.info(`transfer allowances for chain ${source.chainID}:`, allowances); - - const currentAllowance = allowances[0]?.allowance ?? 0n; - const chainNeedsApproval = currentAllowance < requiredAmount; - - if (chainNeedsApproval) { - needsApproval = true; - logger.info( - `Transfer allowance needed on chain ${source.chainID}: required=${requiredAmount.toString()}, current=${currentAllowance.toString()}`, - ); - } - - chainDetails.push({ - chainId: source.chainID, - amount: requiredAmount.toString(), - needsApproval: chainNeedsApproval, - }); - } - - return { - ...simulationResult, - allowance: { - needsApproval, - chainDetails, - }, - }; - } - - async confirmAndProceed(sdk: NexusSDK, inputData: TransferParams): Promise { - const result = await sdk.transfer(inputData); - return result; - } -} diff --git a/packages/widgets/src/hooks/useListenTransaction.tsx b/packages/widgets/src/hooks/useListenTransaction.tsx deleted file mode 100644 index 67c943e9..00000000 --- a/packages/widgets/src/hooks/useListenTransaction.tsx +++ /dev/null @@ -1,363 +0,0 @@ -import { useEffect, useState, useCallback } from 'react'; -import { NEXUS_EVENTS } from '@nexus/commons'; -import { getStatusText } from '../utils/utils'; -import { NexusSDK } from '@avail-project/nexus-core'; -import { ActiveTransaction } from '../types'; -import { ProgressStep, ProgressSteps, SwapStep } from '@avail-project/nexus-core'; - -// Swap-specific step handling -export const getTextFromSwapStep = (step: SwapStep): string => { - switch (step.type) { - case 'CREATE_PERMIT_EOA_TO_EPHEMERAL': - return `Creating permit for eoa to ephemeral for ${step.symbol} on ${step.chain?.name || 'chain'}`; - case 'CREATE_PERMIT_FOR_SOURCE_SWAP': - return `Creating permit for source swap for ${step.symbol} on ${step.chain?.name || 'chain'}`; - case 'DESTINATION_SWAP_BATCH_TX': - return `Creating destination swap transaction`; - case 'DESTINATION_SWAP_HASH': - return `Hash for destination swap on ${step.chain?.name || 'chain'}`; - case 'DETERMINING_SWAP': - return `Generating routes for XCS`; - case 'RFF_ID': - return `Chain abstracted intent`; - case 'SOURCE_SWAP_BATCH_TX': - return 'Creating source swap batch transactions'; - case 'SOURCE_SWAP_HASH': - return `Hash for source swap on ${step.chain?.name || 'chain'}`; - case 'SWAP_COMPLETE': - return `Swap is completed`; - case 'SWAP_START': - return 'Swap starting'; - default: - return 'Processing swap'; - } -}; - -const swapSteps = [ - { id: 0, type: 'SWAP_START', typeID: 'SWAP_START', name: 'Starting Swap' }, - { id: 1, type: 'DETERMINING_SWAP', typeID: 'DETERMINING_SWAP', name: 'Finding Best Route' }, - { - id: 2, - type: 'SOURCE_SWAP_BATCH_TX', - typeID: 'SOURCE_SWAP_BATCH_TX', - name: 'Source Transaction', - }, - { id: 3, type: 'SOURCE_SWAP_HASH', typeID: 'SOURCE_SWAP_HASH', name: 'Source Transaction hash' }, - { id: 4, type: 'RFF_ID', typeID: 'RFF_ID', name: 'Source Transaction hash' }, - { - id: 5, - type: 'DESTINATION_SWAP_BATCH_TX', - typeID: 'DESTINATION_SWAP_BATCH_TX', - name: 'Destination Transaction', - }, - { - id: 6, - type: 'DESTINATION_SWAP_HASH', - typeID: 'DESTINATION_SWAP_HASH', - name: 'Destination Transaction hash', - }, - { - id: 7, - type: 'CREATE_PERMIT_FOR_SOURCE_SWAP', - typeID: 'CREATE_PERMIT_FOR_SOURCE_SWAP', - name: 'Permit', - }, - - { - id: 8, - type: 'CREATE_PERMIT_EOA_TO_EPHEMERAL', - typeID: 'CREATE_PERMIT_EOA_TO_EPHEMERAL', - name: 'Permit Ephemeral', - }, - { id: 9, type: 'SWAP_COMPLETE', typeID: 'SWAP_COMPLETE', name: 'Swap Complete' }, -]; - -interface ProcessingStep { - id: number; - completed: boolean; - progress: number; // 0-100 - stepData?: ProgressStep | ProgressSteps | SwapStep; -} - -interface ProcessingState { - currentStep: number; - totalSteps: number; - steps: ProcessingStep[]; - statusText: string; - animationProgress: number; -} - -const useListenTransaction = ({ - sdk, - activeTransaction, -}: { - sdk: NexusSDK; - activeTransaction: ActiveTransaction; -}) => { - const { type } = activeTransaction; - const DEFAULT_INITIAL_STEPS = 10; - - const [processing, setProcessing] = useState(() => ({ - currentStep: 0, - totalSteps: DEFAULT_INITIAL_STEPS, - steps: Array.from({ length: DEFAULT_INITIAL_STEPS }, (_, i) => ({ - id: i, - completed: false, - progress: 0, - })), - statusText: 'Verifying Request', - animationProgress: 0, - })); - const [explorerURL, setExplorerURL] = useState(null); - const [explorerURLs, setExplorerURLs] = useState<{ source?: string; destination?: string }>({}); - - const resetProcessingState = useCallback(() => { - setProcessing({ - currentStep: 0, - totalSteps: DEFAULT_INITIAL_STEPS, - steps: Array.from({ length: DEFAULT_INITIAL_STEPS }, (_, i) => ({ - id: i, - completed: false, - progress: 0, - })), - statusText: 'Verifying Request', - animationProgress: 0, - }); - setExplorerURL(null); - setExplorerURLs({}); - }, []); - - useEffect(() => { - if (!sdk) return; - - // Special handling for swap transactions - if (type === 'swap') { - // For swap, we create our own progress steps since no expected_steps are emitted - - const initialSteps = swapSteps.map((step, index) => ({ - id: index, - completed: false, - progress: 0, - stepData: step as any, // Step structure for swap mock data - })); - - setProcessing({ - currentStep: 0, - totalSteps: swapSteps.length, - steps: initialSteps, - statusText: 'Preparing Swap', - animationProgress: 0, - }); - - const handleSwapStepComplete = (stepData: SwapStep) => { - setProcessing((prev) => { - // Find matching step by type - const stepIndex = swapSteps.findIndex((s) => s.typeID === stepData.type); - - if (stepIndex === -1) { - // Unknown step, just advance progress - const nextStep = Math.min(prev.currentStep + 1, prev.totalSteps); - return { - ...prev, - currentStep: nextStep, - animationProgress: (nextStep / prev.totalSteps) * 100, - statusText: getTextFromSwapStep(stepData), - }; - } - - const newSteps = [...prev.steps]; - - // Mark all steps up to and including current as completed - for (let i = 0; i <= stepIndex && i < newSteps.length; i++) { - newSteps[i] = { - ...newSteps[i], - completed: true, - progress: 100, - stepData: i === stepIndex ? stepData : newSteps[i].stepData, - }; - } - - const nextStep = Math.min(stepIndex + 1, prev.totalSteps); - const animationProgress = ((stepIndex + 1) / prev.totalSteps) * 100; - - return { - ...prev, - currentStep: nextStep, - steps: newSteps, - animationProgress: Math.min(animationProgress, 100), - statusText: getTextFromSwapStep(stepData), - }; - }); - - // Handle explorer URL extraction for swap - if (stepData.type === 'SOURCE_SWAP_HASH' && 'explorerURL' in stepData) { - setExplorerURLs((prev) => ({ ...prev, source: stepData.explorerURL })); - setExplorerURL(stepData.explorerURL); // Keep for backward compatibility - } else if (stepData.type === 'DESTINATION_SWAP_HASH' && 'explorerURL' in stepData) { - setExplorerURLs((prev) => ({ ...prev, destination: stepData.explorerURL })); - setExplorerURL(stepData.explorerURL); // Update to show latest - } - }; - - sdk?.nexusEvents?.on(NEXUS_EVENTS.SWAP_STEPS, handleSwapStepComplete); - - return () => { - sdk.nexusEvents?.off(NEXUS_EVENTS.SWAP_STEPS, handleSwapStepComplete); - }; - } - - // Regular handling for non-swap transactions - // Flag to know when we have received the complete expected-steps list - let expectedReceived = false; - // Queue to store stepComplete events that arrive before expected steps - const pendingSteps: ProgressStep[] = []; - const expectedEventType = - type === 'bridgeAndExecute' - ? NEXUS_EVENTS.BRIDGE_EXECUTE_EXPECTED_STEPS - : NEXUS_EVENTS.EXPECTED_STEPS; - - const completedEventType = - type === 'bridgeAndExecute' - ? NEXUS_EVENTS.BRIDGE_EXECUTE_COMPLETED_STEPS - : NEXUS_EVENTS.STEP_COMPLETE; - - const handleExpectedSteps = (expectedSteps: ProgressSteps[]) => { - expectedReceived = true; - const stepCount = Array.isArray(expectedSteps) ? expectedSteps.length : expectedSteps; - const steps = Array.isArray(expectedSteps) ? expectedSteps : []; - - // Build initial step objects from expected steps array - const initialSteps = Array.from({ length: stepCount }, (_, i) => ({ - id: i, - completed: false, - progress: 0, - stepData: steps[i] || null, - })); - - // Preserve any steps that were already completed before this event arrived - setProcessing((prev: ProcessingState) => { - const completedTypeIDs = prev.steps - .filter((s) => s.completed) - .map((s) => (s.stepData as ProgressStep)?.typeID) as string[]; - - const mergedSteps = initialSteps.map((step) => { - const typeID = (step.stepData as any)?.typeID as string | undefined; - if (typeID && completedTypeIDs.includes(typeID)) { - return { ...step, completed: true, progress: 100 }; - } - return step; - }); - - const completedCount = mergedSteps.filter((s) => s.completed).length; - - let newState: ProcessingState = { - ...prev, - totalSteps: stepCount, - steps: mergedSteps, - currentStep: completedCount, - animationProgress: (completedCount / stepCount) * 100, - statusText: 'Verifying Request', - }; - - // Now process any queued steps that arrived before expected steps - if (pendingSteps.length > 0) { - pendingSteps.forEach((queuedStep) => { - newState = processStep(newState, queuedStep); - }); - pendingSteps.length = 0; // clear queue - } - - return newState; - }); - }; - - // Helper to process a single step and return updated state (pure function) - const processStep = (prev: ProcessingState, stepData: ProgressStep): ProcessingState => { - const { type: stepType, typeID, data } = stepData; - - let stepIndex = prev.steps.findIndex((s) => { - const id = (s.stepData as any)?.typeID as string | undefined; - return id === typeID; - }); - - if (stepIndex === -1) { - stepIndex = Math.min(prev.currentStep, prev.totalSteps - 1); - } - - const newSteps = [...prev.steps]; - - for (let i = 0; i <= stepIndex && i < newSteps.length; i++) { - newSteps[i] = { - ...newSteps[i], - completed: true, - progress: 100, - stepData: i === stepIndex ? stepData : newSteps[i].stepData, - }; - } - - const nextStep = Math.min(stepIndex + 1, prev.totalSteps); - const animationProgress = ((stepIndex + 1) / prev.totalSteps) * 100; - - let description = getStatusText(stepData, type || 'bridge'); - if (stepType === 'INTENT_COLLECTION' && data) { - description = 'Collecting Confirmations'; - } - - return { - ...prev, - currentStep: nextStep, - steps: newSteps, - animationProgress: Math.min(animationProgress, 100), - statusText: description, - }; - }; - - const handleStepComplete = (stepData: ProgressStep) => { - const { typeID, data } = stepData; - - // Always advance progress for better UX - setProcessing((prev) => processStep(prev, stepData)); - - // Queue until we have real mapping - if (!expectedReceived) { - pendingSteps.push(stepData); - } - - if (typeID === 'IS' && data && 'explorerURL' in data) { - setExplorerURL((data as any)?.explorerURL as string); - } - }; - - sdk?.nexusEvents?.on(expectedEventType, handleExpectedSteps); - sdk?.nexusEvents?.on(completedEventType, handleStepComplete); - - return () => { - sdk.nexusEvents?.off(expectedEventType, handleExpectedSteps); - sdk.nexusEvents?.off(completedEventType, handleStepComplete); - }; - }, [sdk, type]); - - useEffect(() => { - if (!sdk) return; - const handleBeforeUnload = (e: BeforeUnloadEvent) => { - if ( - activeTransaction.status === 'processing' || - activeTransaction.status === 'set_allowance' - ) { - e.preventDefault(); - e.returnValue = 'A transaction is currently in progress. Are you sure you want to leave?'; - } - return 'A transaction is currently in progress. Are you sure you want to leave?'; - }; - - window.addEventListener('beforeunload', handleBeforeUnload); - - return () => { - window.removeEventListener('beforeunload', handleBeforeUnload); - }; - }, [activeTransaction.status]); - - return { processing, explorerURL, explorerURLs, resetProcessingState }; -}; - -export default useListenTransaction; diff --git a/packages/widgets/src/hooks/useNexus.tsx b/packages/widgets/src/hooks/useNexus.tsx deleted file mode 100644 index d7ddb48d..00000000 --- a/packages/widgets/src/hooks/useNexus.tsx +++ /dev/null @@ -1,16 +0,0 @@ -import { useInternalNexus } from '../providers/InternalNexusProvider'; - -const useNexus = () => { - const { setProvider, sdk, isSdkInitialized, provider, initializeSdk, deinitializeSdk } = - useInternalNexus(); - return { - setProvider, - sdk, - isSdkInitialized, - provider, - initializeSdk, - deinitializeSdk, - }; -}; - -export default useNexus; diff --git a/packages/widgets/src/hooks/useOutsideClick.tsx b/packages/widgets/src/hooks/useOutsideClick.tsx deleted file mode 100644 index 0fe08606..00000000 --- a/packages/widgets/src/hooks/useOutsideClick.tsx +++ /dev/null @@ -1,25 +0,0 @@ -import React, { useEffect } from 'react'; - -const useOutsideClick = ( - ref: React.RefObject, - callback: (event: MouseEvent | TouchEvent) => void, -) => { - useEffect(() => { - const listener = (event: MouseEvent | TouchEvent) => { - if (!ref.current || !event.target || ref.current.contains(event.target as Node)) { - return; - } - callback(event); - }; - - document.addEventListener('mousedown', listener); - document.addEventListener('touchstart', listener); - - return () => { - document.removeEventListener('mousedown', listener); - document.removeEventListener('touchstart', listener); - }; - }, [ref]); -}; - -export default useOutsideClick; diff --git a/packages/widgets/src/index.ts b/packages/widgets/src/index.ts deleted file mode 100644 index 0f7553ee..00000000 --- a/packages/widgets/src/index.ts +++ /dev/null @@ -1,13 +0,0 @@ -// UI SDK entry point - React components and providers -import './styles/globals.css'; - -export { default as NexusProvider } from './providers/NexusProvider'; -export { default as useNexus } from './hooks/useNexus'; - -// Button components (named exports) -export { BridgeButton } from './components/bridge/bridge-button'; -export { TransferButton } from './components/transfer/transfer-button'; -export { BridgeAndExecuteButton } from './components/bridge-execute/bridge-execute-button'; -export { SwapButton } from './components/swap/swap-button'; - -export * from '@nexus/commons'; diff --git a/packages/widgets/src/providers/InternalNexusProvider.tsx b/packages/widgets/src/providers/InternalNexusProvider.tsx deleted file mode 100644 index db24aa52..00000000 --- a/packages/widgets/src/providers/InternalNexusProvider.tsx +++ /dev/null @@ -1,1073 +0,0 @@ -'use client'; -import { - createContext, - useContext, - useState, - ReactNode, - useCallback, - useMemo, - useEffect, - useRef, -} from 'react'; -import { - NexusSDK, - EthereumProvider, - UserAsset, - BridgeParams, - TransferParams, - BridgeAndExecuteParams, - SimulationResult, - NexusNetwork, - BridgeAndExecuteSimulationResult, -} from '@avail-project/nexus-core'; -import type { - ActiveTransaction, - BridgeConfig, - NexusContextValue, - TransactionType, - ITransactionController, - SwapInputData, -} from '../types'; -import type { TransferConfig } from '../controllers/TransferController'; -import { BridgeController } from '../controllers/BridgeController'; -import { TransferController } from '../controllers/TransferController'; -import { BridgeAndExecuteController } from '../controllers/BridgeAndExecuteController'; -import TransactionProcessorShell from '../components/processing/transaction-processor-shell'; -import { LayoutGroup } from 'motion/react'; -import useListenTransaction from '../hooks/useListenTransaction'; -import { - logger, - SwapIntentHook, - parseUnits, - TOKEN_METADATA, - ExactInSwapInput, -} from '@nexus/commons'; -import { DragConstraintsProvider } from '../components/motion/drag-constraints'; -import { getTokenFromInputData, getAmountFromInputData, formatSwapError } from '../utils/utils'; -import { getTokenAddress } from '../utils/token-utils'; - -const controllers: Record, ITransactionController> = { - bridge: new BridgeController(), - transfer: new TransferController(), - bridgeAndExecute: new BridgeAndExecuteController(), -}; - -// Type guards - -const NexusContext = createContext(null); - -const initialState: ActiveTransaction = { - type: null, - status: 'idle', - reviewStatus: 'gathering_input', - inputData: null, - prefillFields: {}, - simulationResult: null, - executionResult: null, - error: null, -}; - -// Utility: extract chain identifier regardless of transaction type -function getInputChainId( - data: - | Partial - | Partial - | Partial - | Partial - | null - | undefined, -): number | undefined { - if (!data) return undefined; - if ('chainId' in data && data.chainId !== undefined) return data.chainId as number; - if ('toChainId' in data && data.toChainId !== undefined) return data.toChainId; - return undefined; -} - -export function InternalNexusProvider({ - config, - children, - disableCollapse, -}: Readonly<{ - config?: { network?: NexusNetwork; debug?: boolean }; - children: ReactNode; - disableCollapse?: boolean; -}>) { - const [sdk] = useState( - () => new NexusSDK({ network: config?.network ?? 'mainnet', debug: config?.debug ?? false }), - ); - - const [provider, setProvider] = useState(undefined); - const [isSdkInitialized, setIsSdkInitialized] = useState(false); - const [activeTransaction, setActiveTransaction] = useState(initialState); - const [unifiedBalance, setUnifiedBalance] = useState([]); - const [exchangeRates, setExchangeRates] = useState>({}); - const [isSimulating, setIsSimulating] = useState(false); - const [insufficientBalance, setInsufficientBalance] = useState(false); - const [isTransactionCollapsed, setIsTransactionCollapsed] = useState(false); - const [timer, setTimer] = useState(0); - const [allowanceError, setAllowanceError] = useState(null); - const [isSettingAllowance, setIsSettingAllowance] = useState(false); - - // Swap-specific state - const swapAllowCallbackRef = useRef<(() => void) | null>(null); - const [isSwapExecuting, setIsSwapExecuting] = useState(false); - - const timerRef = useRef(null); - const debounceTimeoutRef = useRef(null); - - // Keep a live ref of SDK initialized state to avoid stale closures in callbacks - const isSdkInitializedRef = useRef(false); - useEffect(() => { - isSdkInitializedRef.current = isSdkInitialized; - }, [isSdkInitialized]); - - const activeController = useMemo(() => { - if (!activeTransaction.type) return null; - if (activeTransaction.type === 'swap') return null; // Swaps handled directly in provider - return controllers[activeTransaction.type]; - }, [activeTransaction.type]); - - const { processing, explorerURL, explorerURLs, resetProcessingState } = useListenTransaction({ - sdk, - activeTransaction, - }); - - const fetchExchangeRates = useCallback(async () => { - try { - const response = await fetch('https://api.coinbase.com/v2/exchange-rates?currency=USD'); - const bnbExchangeRate = await fetch( - 'https://api.coingecko.com/api/v3/simple/price?ids=binancecoin&vs_currencies=usd', - ); - const bnbData = await bnbExchangeRate.json(); - const data = await response.json(); - const rates = (data?.data?.rates ?? {}) as Record; - logger.info('all rates', rates); - // Convert from "units per USD" to "USD per unit" for easier UI multiplication - const usdPerUnit: Record = { BNB: bnbData.binancecoin.usd }; - for (const [symbol, value] of Object.entries(rates)) { - const unitsPerUsd = parseFloat(value); - if (Number.isFinite(unitsPerUsd) && unitsPerUsd > 0) { - usdPerUnit[symbol] = 1 / unitsPerUsd; - } - } - - // Ensure common stablecoins have a sane fallback - ['USD', 'USDC', 'USDT'].forEach((stable) => { - if (usdPerUnit[stable] === undefined) usdPerUnit[stable] = 1; - }); - setExchangeRates(usdPerUnit); - } catch (error) { - logger.error('Error fetching exchange rates:', error as Error); - } - }, []); - - const fetchBalances = async () => { - const unifiedBalance = await sdk.getUnifiedBalances(); - logger.debug('Unified balance', { unifiedBalance }); - setUnifiedBalance(unifiedBalance); - }; - - const initializeSdk = async (ethProvider?: EthereumProvider) => { - if (isSdkInitialized) return true; - const eipProvider = ethProvider ?? provider; - if (!eipProvider) { - setActiveTransaction((prev) => ({ - ...prev, - status: 'simulation_error', - error: new Error('Wallet provider not connected.'), - })); - return false; - } - - if (!provider && eipProvider) { - setProvider(ethProvider); - } - - try { - setActiveTransaction((prev) => ({ ...prev, status: 'initializing' })); - await sdk.initialize(eipProvider); - await fetchExchangeRates(); - await fetchBalances(); - setIsSdkInitialized(sdk.isInitialized()); - isSdkInitializedRef.current = sdk.isInitialized(); - setActiveTransaction((prev) => ({ ...prev, status: 'review' })); - return true; - } catch (err) { - logger.error('SDK initialization failed:', err as Error); - const error = err instanceof Error ? err : new Error('SDK Initialization failed.'); - setActiveTransaction((prev) => ({ ...prev, status: 'simulation_error', error })); - return false; - } - }; - - const deinitializeSdk = async () => { - if (!isSdkInitialized) return; - try { - await sdk?.deinit(); - reset(); - } catch (e) { - logger.error('Error deinitializing SDK', e as Error); - } - }; - - const reset = () => { - setProvider(undefined); - setIsSdkInitialized(false); - isSdkInitializedRef.current = false; - setActiveTransaction(initialState); - setUnifiedBalance([]); - setIsSimulating(false); - setInsufficientBalance(false); - setIsTransactionCollapsed(true); - setTimer(0); - setAllowanceError(null); - setIsSettingAllowance(false); - }; - - const startTransaction = useCallback( - ( - type: TransactionType, - prefillData: - | Partial - | Partial - | Partial - | Partial = {}, - ) => { - // Track which fields were prefilled - const prefillFields: { - chainId?: boolean; - toChainId?: boolean; - token?: boolean; - amount?: boolean; - recipient?: boolean; - fromChainID?: boolean; - toChainID?: boolean; - fromTokenAddress?: boolean; - toTokenAddress?: boolean; - fromAmount?: boolean; - toAmount?: boolean; - } = {}; - - if (prefillData) { - if ('chainId' in prefillData && prefillData.chainId !== undefined) { - prefillFields.chainId = true; - if (type === 'bridgeAndExecute') { - prefillFields.toChainId = true; - } - } - if ( - type === 'bridgeAndExecute' && - 'toChainId' in prefillData && - prefillData.toChainId !== undefined - ) { - prefillFields.toChainId = true; - } - if ('token' in prefillData && prefillData.token !== undefined) { - prefillFields.token = true; - } - if ('amount' in prefillData && prefillData.amount !== undefined) { - prefillFields.amount = true; - } - if ('recipient' in prefillData && prefillData.recipient !== undefined) { - prefillFields.recipient = true; - } - // Handle swap-specific fields - if ('fromChainID' in prefillData && prefillData.fromChainID !== undefined) { - prefillFields.fromChainID = true; - } - if ('toChainID' in prefillData && prefillData.toChainID !== undefined) { - prefillFields.toChainID = true; - } - if ('fromTokenAddress' in prefillData && prefillData.fromTokenAddress !== undefined) { - prefillFields.fromTokenAddress = true; - } - if ('toTokenAddress' in prefillData && prefillData.toTokenAddress !== undefined) { - prefillFields.toTokenAddress = true; - } - if ('fromAmount' in prefillData && prefillData.fromAmount !== undefined) { - prefillFields.fromAmount = true; - } - if ('toAmount' in prefillData && prefillData.toAmount !== undefined) { - prefillFields.toAmount = true; - } - } - const normalizedPrefillData = - type === 'bridgeAndExecute' && - 'toChainId' in prefillData && - prefillData.toChainId !== undefined - ? { ...prefillData, chainId: prefillData.toChainId } - : prefillData; - - setActiveTransaction({ - ...initialState, - type, - status: isSdkInitializedRef.current ? 'review' : 'initializing', - inputData: normalizedPrefillData as any, - prefillFields, - }); - }, - [isSdkInitialized], - ); - - const cancelTransaction = useCallback(async () => { - setIsSimulating(false); - setInsufficientBalance(false); - setIsTransactionCollapsed(true); - setTimer(0); - setActiveTransaction(initialState); - resetProcessingState(); - if (isSdkInitialized && sdk) { - try { - const updatedBalance = await sdk.getUnifiedBalances(); - setUnifiedBalance(updatedBalance); - } catch (err) { - logger.warn('Failed to refetch unified balance after transaction completion:', err); - } - } - }, [isSdkInitialized, sdk, resetProcessingState]); - - const toggleTransactionCollapse = useCallback(() => { - setIsTransactionCollapsed((prev) => !prev); - }, []); - - const updateInput = useCallback( - ( - data: - | Partial - | Partial - | Partial - | Partial, - ) => { - setActiveTransaction((prev) => ({ - ...prev, - inputData: { ...prev.inputData, ...data } as any, - reviewStatus: 'gathering_input', - status: prev.status === 'simulation_error' ? 'review' : prev.status, - error: prev.status === 'simulation_error' ? null : prev.error, - })); - - setIsSimulating(false); - setInsufficientBalance(false); - }, - [], - ); - - const checkInsufficientBalance = useCallback( - (inputData: Partial | Partial | Partial) => { - const token = getTokenFromInputData(inputData); - const amount = getAmountFromInputData(inputData); - - if (!token || !amount || !unifiedBalance.length) { - return false; - } - - const tokenBalance = unifiedBalance.find((asset) => asset.symbol === token); - if (!tokenBalance) { - logger.warn('Token not found in unified balance:', { - requestedToken: token, - availableTokens: unifiedBalance.map((asset) => asset.symbol), - }); - return true; // Consider it insufficient if token not found - } - - const requestedAmount = parseFloat(amount.toString()); - const availableBalance = parseFloat(tokenBalance.balance); - - const isInsufficient = requestedAmount > availableBalance; - - if (isInsufficient) { - logger.warn('Insufficient balance detected:', { - token: token, - requested: requestedAmount, - available: availableBalance, - deficit: requestedAmount - availableBalance, - }); - } - - return isInsufficient; - }, - [unifiedBalance], - ); - - const retrySimulation = useCallback(() => { - setIsSimulating(false); - setActiveTransaction((prev) => ({ - ...prev, - status: 'review', - error: null, - reviewStatus: 'gathering_input', - })); - }, []); - - const triggerSimulation = useCallback(async () => { - if (debounceTimeoutRef.current) { - clearTimeout(debounceTimeoutRef.current); - debounceTimeoutRef.current = null; - } - - const conditions = { - isSdkInitialized, - statusOk: - activeTransaction.status === 'review' || activeTransaction.status === 'simulation_error', - reviewStatusOk: activeTransaction.reviewStatus === 'gathering_input', - hasController: !!activeController, - - hasSufficientInput: activeTransaction.inputData - ? (() => { - if (activeTransaction.type === 'swap') { - // For swaps, check if we have sufficient input directly - const data = activeTransaction.inputData as Partial; - return !!( - data.fromChainID && - data.toChainID && - data.fromTokenAddress && - data.toTokenAddress && - data.fromAmount && - parseFloat(data.fromAmount?.toString() || '0') > 0 - ); - } else if (activeController) { - return activeController.hasSufficientInput(activeTransaction.inputData as any); - } - return false; - })() - : false, - notSimulating: !isSimulating, - }; - - if ( - activeTransaction.inputData && - conditions.isSdkInitialized && - conditions.statusOk && - conditions.reviewStatusOk && - (activeController || activeTransaction.type === 'swap') && // Swaps don't use controller - conditions.hasSufficientInput && - conditions.notSimulating - ) { - const { inputData } = activeTransaction; - - const hasInsufficientBalance = checkInsufficientBalance(inputData as any); - setInsufficientBalance(hasInsufficientBalance); - - if (hasInsufficientBalance) { - // Clear simulation result and ensure we stay in review mode for insufficient balance - setActiveTransaction((prev) => ({ - ...prev, - simulationResult: null, - reviewStatus: 'gathering_input', - status: 'review', // Explicitly ensure we stay in review mode - })); - setIsSimulating(false); // Ensure simulation state is cleared - return; - } - - setIsSimulating(true); - - debounceTimeoutRef.current = setTimeout(async () => { - // Check if input has changed since this timeout was set (simple cancellation) - const currentInputData = activeTransaction.inputData; - if ( - getAmountFromInputData(currentInputData as any) !== - getAmountFromInputData(inputData as any) || - getTokenFromInputData(currentInputData as any) !== - getTokenFromInputData(inputData as any) || - getInputChainId(currentInputData as any) !== getInputChainId(inputData as any) - ) { - setIsSimulating(false); // Reset simulation state - return; - } - - // Clear previous simulation result when starting new simulation - setActiveTransaction((prev) => ({ - ...prev, - simulationResult: null, - reviewStatus: 'simulating', - status: 'review', // Explicitly maintain review status - })); - - try { - let simulationResult: any; - - if (activeTransaction.type === 'swap') { - // For swaps, we skip simulation here since it's handled by initiateSwap - // This code path should not be reached for swaps anymore - await initiateSwap(inputData as SwapInputData); - return; - } else if (activeController) { - // Handle regular transaction controllers - simulationResult = await activeController.runReview(sdk, inputData); - } else { - throw new Error('No controller available for transaction type'); - } - - // Final check before applying results - ensure input hasn't changed - const finalInputData = activeTransaction.inputData; - if ( - getAmountFromInputData(finalInputData as any) !== - getAmountFromInputData(inputData as any) || - getTokenFromInputData(finalInputData as any) !== - getTokenFromInputData(inputData as any) || - getInputChainId(finalInputData as any) !== getInputChainId(inputData as any) - ) { - setIsSimulating(false); - return; - } - - // Check if simulation failed - if ( - simulationResult && - (('success' in simulationResult && !simulationResult.success) || - ('error' in simulationResult && simulationResult.error) || - // For bridge simulation within BridgeAndExecuteSimulationResult - // Only consider null bridgeSimulation a failure if bridge wasn't intentionally skipped - ('bridgeSimulation' in simulationResult && - simulationResult.bridgeSimulation === null && - !(simulationResult as BridgeAndExecuteSimulationResult)?.metadata?.bridgeSkipped)) - ) { - setActiveTransaction((prev) => ({ - ...prev, - simulationResult, - status: 'simulation_error', - error: new Error( - 'error' in simulationResult - ? simulationResult.error || 'Simulation failed' - : 'Simulation failed', - ), - reviewStatus: 'gathering_input', - })); - return; - } - - setActiveTransaction((prev) => ({ - ...prev, - simulationResult, - reviewStatus: simulationResult?.allowance?.needsApproval ? 'needs_allowance' : 'ready', - status: 'review', - })); - } catch (err) { - logger.error('Simulation failed:', err as Error); - const error = err instanceof Error ? err : new Error('Simulation failed.'); - setActiveTransaction((prev) => ({ - ...prev, - status: 'simulation_error', - error, - reviewStatus: 'gathering_input', - })); - } finally { - setIsSimulating(false); - } - }, 2000); - } - }, [ - activeTransaction.status, - activeTransaction.reviewStatus, - activeTransaction.inputData, - activeController, - sdk, - isSdkInitialized, - checkInsufficientBalance, - ]); - - const confirmAndProceed = useCallback(async () => { - if (!activeController || !activeTransaction.inputData || !activeTransaction.simulationResult) - return; - - if (insufficientBalance) { - logger.warn('Attempted to process transaction with insufficient balance'); - return; - } - - if (isSimulating) { - logger.warn('Attempted to process transaction while simulation is running'); - return; - } - - if (activeTransaction.status !== 'review') { - logger.warn( - 'Attempted to process transaction from invalid status:', - activeTransaction.status, - ); - return; - } - - if ( - activeTransaction.reviewStatus !== 'ready' && - activeTransaction.reviewStatus !== 'needs_allowance' - ) { - logger.warn( - 'Attempted to process transaction with invalid review status:', - activeTransaction.reviewStatus, - ); - return; - } - - if (activeTransaction.type === 'swap') { - // Swaps should not use confirmAndProceed - they use proceedWithSwap instead - logger.error( - 'confirmAndProceed should not be called for swaps - use proceedWithSwap instead', - ); - throw new Error( - 'confirmAndProceed should not be called for swaps - use proceedWithSwap instead', - ); - } - - if (!activeController) { - throw new Error('No controller available for transaction type'); - } - - setActiveTransaction((prev) => ({ ...prev, status: 'processing' })); - try { - // Handle regular transaction controllers - const executionResult = await activeController.confirmAndProceed( - sdk, - activeTransaction.inputData, - activeTransaction.simulationResult, - ); - - // For non-swap transactions, use the traditional success/error handling - setActiveTransaction((prev) => ({ - ...prev, - status: executionResult?.success ? 'success' : 'error', - error: executionResult?.error ? new Error(executionResult.error) : null, - executionResult, - })); - } catch (err) { - logger.error('Transaction failed.', err as Error); - const error = err instanceof Error ? err : new Error('Transaction failed.'); - setActiveTransaction((prev) => ({ ...prev, status: 'error', error })); - } - }, [ - activeController, - sdk, - activeTransaction.inputData, - activeTransaction.simulationResult, - insufficientBalance, - isSimulating, - activeTransaction.status, - activeTransaction.reviewStatus, - ]); - - // Single function to handle entire swap flow - const initiateSwap = useCallback( - async (inputData: SwapInputData) => { - try { - logger.info('Swap Provider: Starting swap process', inputData); - - // Validate required fields - if ( - !inputData?.fromChainID || - !inputData?.toChainID || - !inputData?.toTokenAddress || - !inputData?.fromAmount || - !inputData?.fromTokenAddress - ) { - throw new Error('Missing required fields for swap'); - } - - // Convert SwapInputData to SwapInput format for SDK - const fromAmountStr = inputData.fromAmount ?? '0'; - const fromAmountNumber = parseFloat(fromAmountStr.toString()); - - if (isNaN(fromAmountNumber) || fromAmountNumber <= 0) { - throw new Error('Invalid amount provided for swap'); - } - - const actualFromTokenAddress = getTokenAddress( - inputData.fromTokenAddress, - inputData.fromChainID, - 'swap', - ); - const actualToTokenAddress = getTokenAddress( - inputData.toTokenAddress, - inputData.toChainID, - 'swap', - ); - - const swapInput: ExactInSwapInput = { - from: [ - { - chainId: inputData.fromChainID, - amount: parseUnits( - fromAmountStr.toString(), - TOKEN_METADATA[inputData?.fromTokenAddress]?.decimals, - ), - tokenAddress: actualFromTokenAddress as `0x${string}`, - }, - ], - toChainId: inputData.toChainID, - toTokenAddress: actualToTokenAddress as `0x${string}`, - }; - - logger.info('Swap Provider: Prepared swap input', swapInput); - - // Start the swap process - sdk - .swapWithExactIn(swapInput, { - swapIntentHook: async (data: Parameters[0]) => { - swapAllowCallbackRef.current = data.allow; - // Update UI with captured intent (simulation result) - setActiveTransaction((prev) => ({ - ...prev, - simulationResult: { - success: true, - intent: data.intent, - swapMetadata: { - type: 'swap' as const, - inputToken: actualFromTokenAddress as `0x${string}`, - outputToken: swapInput.toTokenAddress, - fromChainId: inputData?.fromChainID, - toChainId: inputData.toChainID, - inputAmount: inputData?.fromAmount ?? '', - outputAmount: data.intent.destination?.amount?.toString() ?? '0', - }, - allowance: { - needsApproval: false, - chainDetails: [], - }, - }, - reviewStatus: 'ready', - status: 'review', - })); - }, - }) - .then((result) => { - if (result.success) { - // Swap succeeded - let useListenTransaction handle the success state - logger.info('Swap Provider: Swap execution succeeded'); - setActiveTransaction((prev) => ({ - ...prev, - status: 'success', - })); - } else { - // Swap failed - this captures your error! - logger.error('Swap Provider: Swap execution failed:', result.error); - - // Set a flag to prevent success callbacks from overriding this error - setActiveTransaction((prev) => ({ - ...prev, - status: 'simulation_error', - reviewStatus: 'gathering_input', // Reset reviewStatus to stop loading state - error: new Error(result?.error ?? 'Swap execution failed'), - executionResult: result, - })); - - // Clear the allow callback to prevent further execution - swapAllowCallbackRef.current = null; - } - }) - .catch((error) => { - // Network/SDK errors - logger.error('Swap Provider: Swap SDK error:', error); - const errorMessage = formatSwapError(error); - setActiveTransaction((prev) => ({ - ...prev, - status: 'simulation_error', - reviewStatus: 'gathering_input', // Reset reviewStatus to stop loading state - error: new Error(errorMessage), - })); - }) - .finally(() => { - setIsSwapExecuting(false); - swapAllowCallbackRef.current = null; - }); - } catch (error) { - logger.error('Swap Provider: Swap initiation failed:', error as Error); - const errorMessage = formatSwapError(error); - setActiveTransaction((prev) => ({ - ...prev, - status: 'simulation_error', - error: new Error(errorMessage), - })); - } - }, - [sdk], - ); - - // Function called when user clicks "Swap" button - const proceedWithSwap = useCallback(() => { - if (swapAllowCallbackRef.current && !isSwapExecuting) { - logger.info('Swap Provider: User confirmed swap - executing'); - setIsSwapExecuting(true); - setActiveTransaction((prev) => ({ ...prev, status: 'processing' })); - - // This triggers the .then() block above - swapAllowCallbackRef.current(); - } else { - logger.warn('Swap Provider: No allow callback available or already executing', { - hasCallback: !!swapAllowCallbackRef.current, - isExecuting: isSwapExecuting, - }); - } - }, [isSwapExecuting]); - - const approveAllowance = useCallback( - async (amount: string, isMinimum: boolean) => { - if ( - !activeController || - !activeTransaction.inputData || - !activeTransaction.simulationResult - ) { - return; - } - - if (activeTransaction.status !== 'set_allowance') { - logger.warn( - 'Attempted to approve allowance from invalid status:', - activeTransaction.status, - ); - return; - } - - setIsSettingAllowance(true); - setAllowanceError(null); - - try { - // For each source chain that needs allowance, set it - const { inputData, simulationResult } = activeTransaction; - - // Use chain-specific allowance details if available - const chainDetails = simulationResult?.allowance?.chainDetails; - if (chainDetails && chainDetails.length > 0) { - // Use the new chain-specific approach - for (const chainDetail of chainDetails) { - if (chainDetail.needsApproval) { - const token = getTokenFromInputData(inputData); - if (!token) continue; - - const tokenMeta = sdk.utils.getTokenMetadata(token as any); - const amountToApprove = isMinimum - ? sdk.utils.parseUnits(amount, tokenMeta?.decimals ?? 18) - : sdk.utils.parseUnits(amount, tokenMeta?.decimals ?? 18); - - await sdk.setAllowance(chainDetail.chainId, [token as any], amountToApprove); - } - } - } else { - // Fallback to original approach for backward compatibility - let sourcesData: Array<{ chainID: number; amount: string }> = - (simulationResult as SimulationResult)?.intent?.sources || []; - - // If bridge & execute simulation, sources are inside bridgeSimulation - if (sourcesData.length === 0 && 'bridgeSimulation' in (simulationResult as any)) { - const bridgeSim = (simulationResult as any).bridgeSimulation as SimulationResult; - sourcesData = bridgeSim?.intent?.sources || []; - } - - for (const source of sourcesData) { - const token = getTokenFromInputData(inputData); - if (!token) continue; - - const tokenMeta = sdk.utils.getTokenMetadata(token as any); - const amountToApprove = isMinimum - ? sdk.utils.parseUnits(amount, tokenMeta?.decimals ?? 18) - : sdk.utils.parseUnits(amount, tokenMeta?.decimals ?? 18); - - await sdk.setAllowance(source.chainID, [token as any], amountToApprove); - } - } - - // After successful allowance setting, proceed directly to transaction - setActiveTransaction((prev) => ({ ...prev, status: 'processing' })); - - try { - const executionResult = await activeController.confirmAndProceed( - sdk, - inputData, - simulationResult, - ); - setActiveTransaction((prev) => ({ - ...prev, - status: executionResult?.success ? 'success' : 'error', - error: executionResult?.error ? new Error(executionResult.error) : null, - executionResult, - })); - } catch (execErr) { - logger.error('Transaction failed after allowance approval.', execErr as Error); - const error = execErr instanceof Error ? execErr : new Error('Transaction failed.'); - setActiveTransaction((prev) => ({ ...prev, status: 'error', error })); - } - } catch (err) { - logger.error('Allowance setting failed:', err as Error); - const error = err instanceof Error ? err : new Error('Failed to set allowance.'); - setAllowanceError(error.message); - } finally { - setIsSettingAllowance(false); - } - }, - [ - activeController, - sdk, - activeTransaction.inputData, - activeTransaction.simulationResult, - activeTransaction.status, - ], - ); - - const denyAllowance = useCallback(() => { - setActiveTransaction((prev) => ({ - ...prev, - status: 'review', - reviewStatus: 'needs_allowance', - })); - setAllowanceError(null); - }, []); - - const startAllowanceFlow = useCallback(() => { - if ( - activeTransaction.status !== 'review' || - activeTransaction.reviewStatus !== 'needs_allowance' - ) { - logger.warn('Attempted to start allowance flow from invalid state:', { - status: activeTransaction.status, - reviewStatus: activeTransaction.reviewStatus, - }); - return; - } - - setActiveTransaction((prev) => ({ - ...prev, - status: 'set_allowance', - })); - setAllowanceError(null); - }, [activeTransaction.status, activeTransaction.reviewStatus]); - - useEffect(() => { - if ( - activeTransaction.status === 'review' && - activeTransaction.reviewStatus === 'gathering_input' && - activeTransaction.inputData - ) { - triggerSimulation(); - } - }, [ - getAmountFromInputData(activeTransaction.inputData), - getTokenFromInputData(activeTransaction.inputData), - getInputChainId(activeTransaction.inputData), - activeTransaction.status, - activeTransaction.reviewStatus, - activeTransaction.type, - triggerSimulation, - initiateSwap, - ]); - - useEffect(() => { - return () => { - if (debounceTimeoutRef.current) { - clearTimeout(debounceTimeoutRef.current); - debounceTimeoutRef.current = null; - } - }; - }, []); - - useEffect(() => { - if (activeTransaction.status === 'processing') { - timerRef.current = setInterval(() => { - setTimer((prev) => prev + 0.1); - }, 100); - } - - return () => { - if (timerRef.current) { - clearInterval(timerRef.current); - timerRef.current = null; - } - }; - }, [activeTransaction.status]); - - const value: NexusContextValue = useMemo( - () => ({ - // State - sdk, - activeTransaction, - isSdkInitialized, - activeController, - disableCollapse, - config, - provider, - unifiedBalance, - exchangeRates, - isSimulating, - insufficientBalance, - isTransactionCollapsed, - timer, - allowanceError, - isSettingAllowance, - - // Transaction processing state - processing, - explorerURL, - explorerURLs, - - // Actions - setProvider, - startTransaction, - updateInput, - confirmAndProceed, - cancelTransaction, - initializeSdk, - deinitializeSdk, - triggerSimulation, - retrySimulation, - toggleTransactionCollapse, - approveAllowance, - denyAllowance, - startAllowanceFlow, - - // Swap-specific functions - initiateSwap, - proceedWithSwap, - }), - [ - sdk, - activeTransaction, - isSdkInitialized, - activeController, - config, - provider, - setProvider, - startTransaction, - updateInput, - confirmAndProceed, - cancelTransaction, - initializeSdk, - deinitializeSdk, - triggerSimulation, - retrySimulation, - unifiedBalance, - exchangeRates, - isSimulating, - insufficientBalance, - isTransactionCollapsed, - toggleTransactionCollapse, - timer, - allowanceError, - isSettingAllowance, - processing, - explorerURL, - explorerURLs, - approveAllowance, - denyAllowance, - startAllowanceFlow, - initiateSwap, - proceedWithSwap, - ], - ); - - return ( - - - - {children} - - - - - ); -} - -export function useInternalNexus() { - const context = useContext(NexusContext); - if (!context) { - throw new Error('useInternalNexus must be used within a NexusProvider'); - } - return context; -} diff --git a/packages/widgets/src/providers/NexusProvider.tsx b/packages/widgets/src/providers/NexusProvider.tsx deleted file mode 100644 index 968f0810..00000000 --- a/packages/widgets/src/providers/NexusProvider.tsx +++ /dev/null @@ -1,21 +0,0 @@ -'use client'; -import React from 'react'; -import { InternalNexusProvider } from './InternalNexusProvider'; -import { type NexusNetwork, logger } from '@nexus/commons'; - -const NexusProvider = ({ - config, - children, -}: { - config?: { network?: NexusNetwork; debug?: boolean }; - children: React.ReactNode; -}) => { - logger.debug('NexusProvider', { config }); - return ( - - {children} - - ); -}; - -export default NexusProvider; diff --git a/packages/widgets/src/styles/globals.css b/packages/widgets/src/styles/globals.css deleted file mode 100644 index f88da7fe..00000000 --- a/packages/widgets/src/styles/globals.css +++ /dev/null @@ -1,248 +0,0 @@ -@import 'tailwindcss'; - -@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap'); - -@theme { - --color-nexus-backdrop: var(--nexus-backdrop); - --color-nexus-blue: var(--nexus-blue); - --color-nexus-gray: var(--nexus-color-gray); - --color-nexus-black: var(--nexus-color-black); - --color-nexus-primary-gray: var(--nexus-color-primary-hover); - --color-nexus-snow-white: var(--nexus-color-snow-white); - --color-nexus-success: var(--nexus-success); - --color-nexus-footer: var(--nexus-footer); - --color-nexus-footer-text: var(--nexus-footer-text); - - /* Core color system */ - --color-nexus-background: var(--nexus-color-background); - --color-nexus-foreground: var(--nexus-color-foreground); - --color-nexus-primary: var(--nexus-color-primary); - --color-nexus-primary-foreground: var(--nexus-color-primary-foreground); - --color-nexus-primary-hover: var(--nexus-color-primary-hover); - --color-nexus-secondary: var(--nexus-color-secondary); - --color-nexus-secondary-foreground: var(--nexus-color-secondary-foreground); - --color-nexus-secondary-background: var(--nexus-color-secondary-background); - --color-nexus-muted: var(--nexus-color-muted); - --color-nexus-muted-foreground: var(--nexus-color-muted-foreground); - --color-nexus-muted-secondary: var(--nexus-color-muted-secondary); - --color-nexus-accent: var(--nexus-color-accent); - --color-nexus-accent-green: var(--nexus-color-accent-green); - --color-nexus-accent-foreground: var(--nexus-color-accent-foreground); - --color-nexus-border: var(--nexus-color-border); - --color-nexus-border-secondary: var(--nexus-color-border-secondary); - --color-nexus-input: var(--nexus-color-input); - --color-nexus-ring: var(--nexus-color-ring); - --color-nexus-ring-offset: var(--nexus-color-background); - --color-nexus-destructive: var(--nexus-color-destructive); - --color-nexus-destructive-foreground: var(--nexus-color-destructive-foreground); - --color-nexus-destructive-secondary: var(--nexus-color-destructive-secondary); - --color-nexus-card: var(--nexus-color-card); - --color-nexus-card-foreground: var(--nexus-color-card-foreground); - - --font-nexus-primary: var(--nexus-font-primary); - --font-nexus-secondary: var(--nexus-font-secondary); - - /* Font Sizes */ - --font-size-xs: 12px; - --font-size-sm: 14px; - --font-size-base: 16px; - --font-size-lg: 20px; - --font-size-xl: 24px; - - /* Font Weights */ - --font-weight-base: 400; - --font-weight-medium: 500; - --font-weight-semibold: 600; - --font-weight-bold: 700; - - /* Border Radius */ - --radius-nexus-sm: var(--nexus-radius-sm); - --radius-nexus-md: var(--nexus-radius-md); - --radius-nexus-lg: var(--nexus-radius-lg); - --radius-nexus-xl: var(--nexus-radius-xl); - --radius-nexus-full: var(--nexus-radius-full); - - /* Shadows */ - --shadow-card: 0 4px 24px rgb(0 0 0 / 0.1); - --shadow-dropdown: 0 6px 6px rgb(0 0 0 / 0.25); - --shadow-xs: 0 1px 2px 0 rgb(0 0 0 / 0.05); - - /* Animation */ - --animate-fade-in: fade-in 0.2s ease-in-out; - --animate-slide-up: slide-up 0.3s ease-out; - --animate-slide-down: slide-down 0.3s ease-out; - --animate-in: in 0.2s ease-out; - --animate-out: out 0.2s ease-in; - --animate-fade-in-0: fade-in-0 0.2s ease-out; - --animate-fade-out-0: fade-out-0 0.2s ease-in; - --animate-zoom-in-95: zoom-in-95 0.2s ease-out; - --animate-zoom-out-95: zoom-out-95 0.2s ease-in; -} - -:root { - --nexus-color-white: #ffffff; - --nexus-color-gray: #eff0f2; - --nexus-color-snow-white: #fafafa; - --nexus-color-black: #000000; - --nexus-color-background: #f4f6f8; - --nexus-color-foreground: #1b1b1b; - --nexus-color-primary: #1b1b1b; - --nexus-color-primary-hover: #2b2b2b; - --nexus-color-primary-foreground: #ffffff; - --nexus-color-secondary: #565a60; - --nexus-color-secondary-foreground: #ffffff; - --nexus-color-secondary-background: #bed8ee66; - --nexus-color-muted: #808080; - --nexus-color-muted-secondary: #666666; - --nexus-color-muted-foreground: #565a60; - --nexus-color-accent: #0375d8; - --nexus-color-accent-green: #6b9826; - --nexus-color-accent-foreground: #ffffff; - --nexus-color-border: #e5e7e9; - --nexus-color-border-secondary: #425c72; - --nexus-color-input: #b3b3b3; - --nexus-color-ring: #2b80d7; - --nexus-color-destructive: #ef4444; - --nexus-color-destructive-secondary: #c03c54; - --nexus-color-destructive-foreground: #ffffff; - --nexus-color-card: #ffffff; - --nexus-color-card-foreground: #1b1b1b; - --nexus-color-success-base: #78c47b; - --nexus-color-neutral-50: #f4f6f8; - --nexus-color-neutral-100: #e8eaf0; - --nexus-color-neutral-200: #e5e7e9; - --nexus-color-brand-footer: #bed8ee; - --nexus-color-brand-footer-text: #4c4c4c; - --nexus-backdrop: #0e0e0e66; - --nexus-blue: #0375d8; - --nexus-success: #78c47b; - --nexus-footer: rgb(190 216 238 / 0.4); - --nexus-footer-text: rgb(76 76 76); - - --nexus-font-primary: - 'PP Mori', 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif; - --nexus-font-secondary: - 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif; - - /* Nexus SDK Border Radius */ - --nexus-radius-sm: 4px; - --nexus-radius-md: 8px; - --nexus-radius-lg: 12px; - --nexus-radius-xl: 16px; - --nexus-radius-full: 9999px; -} - -@keyframes fade-in { - from { - opacity: 0; - } - to { - opacity: 1; - } -} - -@keyframes slide-up { - from { - transform: translateY(10px); - opacity: 0; - } - to { - transform: translateY(0); - opacity: 1; - } -} - -@keyframes slide-down { - from { - transform: translateY(-10px); - opacity: 0; - } - to { - transform: translateY(0); - opacity: 1; - } -} - -@keyframes fade-out-scale { - 0% { - transform: scale(0.8); - opacity: 0.8; - } - 50% { - transform: scale(1.2); - opacity: 0.4; - } - 100% { - transform: scale(1.5); - opacity: 0; - } -} - -@keyframes in { - from { - opacity: 0; - transform: scale(0.95); - } - to { - opacity: 1; - transform: scale(1); - } -} - -@keyframes out { - from { - opacity: 1; - transform: scale(1); - } - to { - opacity: 0; - transform: scale(0.95); - } -} - -@keyframes fade-in-0 { - from { - opacity: 0; - } - to { - opacity: 1; - } -} - -@keyframes fade-out-0 { - from { - opacity: 1; - } - to { - opacity: 0; - } -} - -@keyframes zoom-in-95 { - from { - transform: scale(0.95); - } - to { - transform: scale(1); - } -} - -@keyframes zoom-out-95 { - from { - transform: scale(1); - } - to { - transform: scale(0.95); - } -} - -.no-scrollbar { - overflow-y: scroll; - scrollbar-width: none; /* Firefox */ - -ms-overflow-style: none; /* Internet Explorer 10+ */ -} -.no-scrollbar::-webkit-scrollbar { - /* WebKit */ - width: 0; - height: 0; -} diff --git a/packages/widgets/src/types/index.ts b/packages/widgets/src/types/index.ts deleted file mode 100644 index e1e906a3..00000000 --- a/packages/widgets/src/types/index.ts +++ /dev/null @@ -1,420 +0,0 @@ -import { ReactNode } from 'react'; -import { NexusSDK } from '@avail-project/nexus-core'; - -// Only import essential parameter types, not all from root types -import type { - BridgeParams, - TransferParams, - BridgeAndExecuteParams, - SUPPORTED_TOKENS, - SUPPORTED_CHAINS_IDS, - DynamicParamBuilder, - SimulationResult, - SwapInputOptionalParams, - SwapIntent, - UserAsset, - EthereumProvider, - ExactInSwapInput, - NexusNetwork, -} from '@nexus/commons'; - -import { Abi } from 'viem'; - -// Local result types for UI (to avoid importing all types) -interface BridgeResult { - success: boolean; - error?: string; - explorerUrl?: string; -} - -interface TransferResult { - success: boolean; - error?: string; - explorerUrl?: string; -} - -interface BridgeAndExecuteResult { - success: boolean; - error?: string; - executeTransactionHash?: string; - executeExplorerUrl?: string; - approvalTransactionHash?: string; - toChainId: number; -} - -interface BridgeAndExecuteSimulationResult { - success: boolean; - error?: string; - steps: any[]; - bridgeSimulation: SimulationResult | null; - executeSimulation?: any; -} - -export interface SwapInputData { - fromChainID?: 10 | 137 | 42161 | 534352 | 8453; - toChainID?: SUPPORTED_CHAINS_IDS; - fromTokenAddress?: 'USDC' | 'WETH' | 'DAI' | 'USDT' | 'USDS'; - toTokenAddress?: - | 'USDC' - | 'LDO' - | 'DAI' - | 'USDT' - | 'KAITO' - | 'ZRO' - | 'PEPE' - | 'ETH' - | 'OP' - | 'AAVE' - | 'UNI' - | 'OM'; - fromAmount?: string; - toAmount?: string; -} - -export interface UnifiedInputData { - chainId?: number; - toChainId?: number; - token?: string; - inputToken?: string; - outputToken?: string; - amount?: string | number; - recipient?: string; -} - -interface SwapResult { - success: boolean; - error?: string; - sourceExplorerUrl?: string; - destinationExplorerUrl?: string; -} - -export interface SwapSimulationResult { - success: boolean; - error?: string; - intent?: SwapIntent; - swapMetadata?: { - type: 'swap'; - inputToken: string; - outputToken: string; - fromChainId?: number; - toChainId?: number; - inputAmount: string; - outputAmount: string; - }; - allowance: { - needsApproval: false; - chainDetails: []; - }; -} - -// Local metadata types for UI -interface ChainMetadata { - id: number; - name: string; - shortName: string; - logo: string; - nativeCurrency: { - name: string; - symbol: string; - decimals: number; - }; - rpcUrls: string[]; - blockExplorerUrls: string[]; -} - -interface TokenMetadata { - symbol: string; - name: string; - decimals: number; - icon: string; - coingeckoId: string; - isNative?: boolean; -} - -// # 1. High-Level State Machines - -export type TransactionType = 'bridge' | 'transfer' | 'bridgeAndExecute' | 'swap'; - -export type OrchestratorStatus = - | 'idle' - | 'initializing' - | 'review' - | 'processing' - | 'success' - | 'error' - | 'simulation_error' - | 'set_allowance'; - -export type ReviewStatus = 'gathering_input' | 'simulating' | 'needs_allowance' | 'ready'; - -// # 2. Generic Data Structures for UI - -export interface ActiveTransaction { - type: TransactionType | null; - status: OrchestratorStatus; - reviewStatus: ReviewStatus; - inputData: - | Partial - | Partial - | Partial - | Partial - | null; - prefillFields?: { - chainId?: boolean; - toChainId?: boolean; - token?: boolean; - inputToken?: boolean; - outputToken?: boolean; - amount?: boolean; - recipient?: boolean; - fromChainID?: boolean; - toChainID?: boolean; - fromTokenAddress?: boolean; - toTokenAddress?: boolean; - fromAmount?: boolean; - toAmount?: boolean; - }; - simulationResult: - | ((SimulationResult | BridgeAndExecuteSimulationResult | SwapSimulationResult) & { - allowance?: { - needsApproval: boolean; - chainDetails?: Array<{ - chainId: number; - amount: string; - needsApproval: boolean; - }>; - }; - }) - | null; - executionResult: BridgeResult | BridgeAndExecuteResult | TransferResult | SwapResult | null; - error: Error | null; -} - -export interface ITransactionController { - // The UI component for gathering inputs for this transaction type - InputForm: React.FC<{ - prefill: any; - onUpdate: (data: any) => void; - isBusy: boolean; - tokenBalance?: string; - prefillFields?: { - chainId?: boolean; - toChainId?: boolean; - token?: boolean; - amount?: boolean; - recipient?: boolean; - }; - }>; - - // The main action function that drives the review, simulation, and execution - confirmAndProceed( - sdk: NexusSDK, - inputData: any, - simulationResult: ActiveTransaction['simulationResult'], - ): Promise; - - // A helper to start the simulation and allowance check - runReview(sdk: NexusSDK, inputData: any): Promise; - - // A method to check if the controller has enough data to proceed with a review - hasSufficientInput(inputData: any): boolean; -} - -// # 4. Provider and Hook Types - -// Processing state interface from useListenTransaction -export interface ProcessingStep { - id: number; - completed: boolean; - progress: number; // 0-100 - stepData?: any; // Can be ProgressStep, ProgressSteps, SwapStep, etc. -} - -export interface ProcessingState { - currentStep: number; - totalSteps: number; - steps: ProcessingStep[]; - statusText: string; - animationProgress: number; -} - -export interface NexusContextValue { - // State - sdk: NexusSDK; - activeTransaction: ActiveTransaction; - isSdkInitialized: boolean; - activeController: ITransactionController | null; - config?: { network?: NexusNetwork; debug?: boolean }; - provider: EthereumProvider | undefined; - unifiedBalance: UserAsset[]; - isSimulating: boolean; - insufficientBalance: boolean; - isTransactionCollapsed: boolean; - timer: number; - allowanceError: string | null; - isSettingAllowance: boolean; - exchangeRates: Record; - // Transaction processing state (from useListenTransaction) - processing: ProcessingState; - explorerURL: string | null; - explorerURLs?: { source?: string; destination?: string }; - - // Actions - setProvider: (provider: EthereumProvider) => void; - initializeSdk: (ethProvider?: EthereumProvider) => Promise; - deinitializeSdk: () => Promise; - startTransaction: ( - type: TransactionType, - prefillData?: - | Partial - | Partial - | Partial - | Partial, - ) => void; - updateInput: ( - data: - | Partial - | Partial - | Partial - | Partial, - ) => void; - confirmAndProceed: () => void; - cancelTransaction: () => void; - triggerSimulation: () => Promise; - retrySimulation: () => void; - toggleTransactionCollapse: () => void; - approveAllowance: (amount: string, isMinimum: boolean) => Promise; - denyAllowance: () => void; - startAllowanceFlow: () => void; - - // Swap-specific functions - initiateSwap: (inputData: SwapInputData) => Promise; - proceedWithSwap: () => void; -} - -// # 5. Existing Widget Configuration Types (with minor updates) - -export interface BaseComponentProps { - title?: string; - className?: string; - hasValues?: boolean; -} - -export interface BridgeConfig extends Partial {} - -export interface BridgeButtonProps extends BaseComponentProps { - prefill?: BridgeConfig; - children: (props: { onClick: () => void; isLoading: boolean }) => ReactNode; -} - -export interface SwapConfig { - inputs: ExactInSwapInput; - options?: SwapInputOptionalParams; -} - -export interface SwapButtonProps extends BaseComponentProps { - prefill?: Omit; - children: (props: { onClick: () => void; isLoading: boolean }) => ReactNode; -} - -// Transfer Widget Types -export interface TransferConfig extends Partial {} - -export interface TransferButtonProps extends BaseComponentProps { - prefill?: TransferConfig; - children: (props: { onClick: () => void; isLoading: boolean }) => ReactNode; -} - -// Balance Widget Types -export interface BalanceWidgetProps extends BaseComponentProps { - showChains?: boolean; - showValue?: boolean; - format?: 'short' | 'full'; -} - -// Modal Types -export interface ModalProps extends BaseComponentProps { - isOpen: boolean; - onClose: () => void; - description?: string; - size?: 'sm' | 'md' | 'lg'; - children: ReactNode; - hideCloseButton?: boolean; -} - -// Form Types -export interface TokenSelectProps extends BaseComponentProps { - value?: string; - onValueChange: (token: string, iconUrl?: string) => void; - disabled?: boolean; - network?: NexusNetwork; - type?: TransactionType; - chainId?: number; - isDestination?: boolean; -} - -export interface ChainSelectProps extends BaseComponentProps { - value?: string; - onValueChange: (chain: string) => void; - disabled?: boolean; - network?: NexusNetwork; - isSource?: boolean; -} - -export interface AmountInputProps extends BaseComponentProps { - value?: string; - onValueChange: (amount: string) => void; - token?: string; - balance?: string; - disabled?: boolean; - placeholder?: string; -} - -// Transaction Types -export interface TransactionStep { - id: string; - title: string; - description?: string; - status: 'pending' | 'active' | 'completed' | 'error'; -} - -export interface TransactionProgressProps extends BaseComponentProps { - steps: TransactionStep[]; - currentStep: string; - collapsible?: boolean; -} - -export interface BridgeAndExecuteButtonProps extends BaseComponentProps { - contractAddress: `0x${string}`; - contractAbi: Abi; - functionName: string; - buildFunctionParams: DynamicParamBuilder; - prefill?: { - toChainId?: SUPPORTED_CHAINS_IDS; - token?: SUPPORTED_TOKENS; - amount?: string; - }; - children: (props: { onClick: () => void; isLoading: boolean; disabled: boolean }) => ReactNode; -} - -// Re-export DynamicParamBuilder for convenience -export type { DynamicParamBuilder }; - -export interface ProcessorCardProps { - status: OrchestratorStatus; - cancelTransaction: () => void; - toggleTransactionCollapse: () => void; - sourceChainMeta: ChainMetadata[]; - destChainMeta: ChainMetadata | null; - tokenMeta: TokenMetadata | null; - transactionType: TransactionType; - simulationResult: SimulationResult | BridgeAndExecuteSimulationResult | SwapSimulationResult; - processing: ProcessingState; - explorerURL: string | null; - explorerURLs?: { source?: string; destination?: string }; - timer: number; - description: string; - error: Error | null; - executionResult: BridgeResult | TransferResult | BridgeAndExecuteResult | SwapResult | null; - disableCollapse?: boolean; -} diff --git a/packages/widgets/src/utils/balance-utils.ts b/packages/widgets/src/utils/balance-utils.ts deleted file mode 100644 index 70156af3..00000000 --- a/packages/widgets/src/utils/balance-utils.ts +++ /dev/null @@ -1,95 +0,0 @@ -import type { UserAsset } from '@avail-project/nexus-core'; -import { SUPPORTED_CHAINS_IDS, SUPPORTED_TOKENS } from '@nexus/commons'; - -export type TransactionType = 'bridge' | 'transfer' | 'bridgeAndExecute' | 'swap'; - -export interface EffectiveBalanceParams { - unifiedBalance: UserAsset[] | null; - token?: SUPPORTED_TOKENS; - destinationChainId?: SUPPORTED_CHAINS_IDS; - type: TransactionType; -} - -export interface EffectiveBalanceResult { - effectiveBalance: string; - totalBalance: string; - contextualMessage: string; -} - -/** - * Calculate effective balance based on transaction context - * - Bridge: Total balance minus destination chain balance - * - Transfer: Balance available on source chain only - * - BridgeAndExecute: Total balance minus destination chain balance - */ -export function calculateEffectiveBalance({ - unifiedBalance, - token, - destinationChainId, - type, -}: EffectiveBalanceParams): EffectiveBalanceResult { - if (!unifiedBalance || !token) { - return { - effectiveBalance: '0', - totalBalance: '0', - contextualMessage: `Balance: 0 ${token || ''}`, - }; - } - - const tokenAsset = unifiedBalance.find((asset) => asset.symbol === token); - - if (!tokenAsset) { - return { - effectiveBalance: '0', - totalBalance: '0', - contextualMessage: `Balance: 0 ${token}`, - }; - } - - const totalBalance = tokenAsset.balance; - let effectiveBalance = totalBalance; - let contextualMessage = `Balance: ${parseFloat(totalBalance).toFixed(6)} ${token}`; - - if (type === 'bridgeAndExecute' || type === 'swap') - return { - effectiveBalance, - totalBalance, - contextualMessage, - }; - - if (destinationChainId) { - const destinationBalance = - tokenAsset.breakdown?.find((item) => item.chain.id === destinationChainId)?.balance || '0'; - - const effectiveBalanceNum = Math.max( - 0, - parseFloat(totalBalance) - parseFloat(destinationBalance), - ); - effectiveBalance = effectiveBalanceNum.toString(); - contextualMessage = `Balance: ${effectiveBalanceNum.toFixed(6)} ${token}`; - } - - return { - effectiveBalance, - totalBalance, - contextualMessage, - }; -} - -export function getFiatValue( - amount: string | number | bigint, - token: string, - exchangeRates: Record, -) { - const key = (token || '').toUpperCase(); - const rate = exchangeRates?.[key]; - const amountNum = - typeof amount === 'number' - ? amount - : parseFloat((typeof amount === 'bigint' ? amount.toString() : amount) || '0'); - - const isValid = Number.isFinite(amountNum) && Number.isFinite(rate); - const approx = isValid ? rate * amountNum : 0; - - return `≈ $${approx.toFixed(2)}`; -} diff --git a/packages/widgets/src/utils/token-utils.ts b/packages/widgets/src/utils/token-utils.ts deleted file mode 100644 index 5d79cc93..00000000 --- a/packages/widgets/src/utils/token-utils.ts +++ /dev/null @@ -1,721 +0,0 @@ -import { useMemo } from 'react'; -import { - CHAIN_METADATA, - TOKEN_METADATA, - TESTNET_TOKEN_METADATA, - TOKEN_CONTRACT_ADDRESSES, - DESTINATION_SWAP_TOKENS, - type SupportedChainsResult, - type TokenMetadata, - NexusNetwork, -} from '@nexus/commons'; -import type { TransactionType } from './balance-utils'; -import type { NexusSDK } from '@avail-project/nexus-core'; - -/** - * Enhanced token metadata for UI components - */ -export interface EnhancedTokenMetadata extends TokenMetadata { - contractAddress?: `0x${string}`; -} - -/** - * Token selection options for UI components - */ -export interface TokenSelectOption { - value: string; - label: string; - icon: string; - metadata: EnhancedTokenMetadata; -} - -/** - * Parameters for token resolution - */ -export interface TokenResolutionParams { - chainId?: number; - type: TransactionType; - network?: NexusNetwork; - isDestination?: boolean; - sdk?: NexusSDK; -} - -/** - * SDK-provided swap support data structure (normalized from SupportedChainsResult) - */ -export interface TransactionSupportData { - chains: { id: number; name: string; logo: string }[]; - tokens: { - symbol: string; - address: string; - decimals: number; - name?: string; - logo?: string; - }[]; - chainTokenMap: Map; - tokenChainMap: Map; -} - -const LOGO_URLS: Record = { - WETH: 'https://assets.coingecko.com/coins/images/279/large/ethereum.png?1595348880', - USDS: 'https://assets.coingecko.com/coins/images/39926/standard/usds.webp?1726666683', - SOPH: 'https://assets.coingecko.com/coins/images/38680/large/sophon_logo_200.png', - KAIA: 'https://assets.coingecko.com/asset_platforms/images/9672/large/kaia.png', - BNB: 'https://assets.coingecko.com/coins/images/825/large/bnb-icon2_2x.png', - // Add ETH as fallback for any ETH-related tokens - ETH: 'https://coin-images.coingecko.com/coins/images/279/large/ethereum.png?1696501628', - // Add common token fallbacks - POL: 'https://coin-images.coingecko.com/coins/images/32440/standard/polygon.png', - AVAX: 'https://assets.coingecko.com/coins/images/12559/standard/Avalanche_Circle_RedWhite_Trans.png', - FUEL: 'https://coin-images.coingecko.com/coins/images/279/large/ethereum.png', - HYPE: 'https://assets.coingecko.com/asset_platforms/images/243/large/hyperliquid.png', - // Popular swap tokens - DAI: 'https://coin-images.coingecko.com/coins/images/9956/large/Badge_Dai.png?1696509996', - UNI: 'https://coin-images.coingecko.com/coins/images/12504/large/uni.jpg?1696512319', - AAVE: 'https://coin-images.coingecko.com/coins/images/12645/large/AAVE.png?1696512452', - LDO: 'https://coin-images.coingecko.com/coins/images/13573/large/Lido_DAO.png?1696513326', - PEPE: 'https://coin-images.coingecko.com/coins/images/29850/large/pepe-token.jpeg?1696528776', - OP: 'https://coin-images.coingecko.com/coins/images/25244/large/Optimism.png?1696524385', - ZRO: 'https://coin-images.coingecko.com/coins/images/28206/large/ftxG9_TJ_400x400.jpeg?1696527208', - OM: 'https://assets.coingecko.com/coins/images/12151/standard/OM_Token.png?1696511991', - KAITO: 'https://assets.coingecko.com/coins/images/54411/standard/Qm4DW488_400x400.jpg', -}; - -function _processSdkData(sdkData: SupportedChainsResult | null): TransactionSupportData | null { - if (!sdkData || !Array.isArray(sdkData)) return null; - - const chains = sdkData.map((chain) => ({ - id: chain.id, - name: chain.name, - logo: chain.logo, - })); - - const chainTokenMap = new Map(); - const tokenChainMap = new Map(); - const allTokens = new Map(); - - for (const chain of sdkData) { - const tokenSymbols: string[] = []; - // Guard against chains that might not have a tokens array - for (const token of chain.tokens || []) { - // Enhanced logo fallback logic - let finalLogo = token.logo; - if (!finalLogo) { - // First try direct lookup - finalLogo = LOGO_URLS[token.symbol]; - - // Handle wrapped tokens - if (!finalLogo && token.symbol.startsWith('W') && token.symbol.length > 1) { - const baseSymbol = token.symbol.substring(1); - finalLogo = LOGO_URLS[baseSymbol]; - } - - // ETH fallback for ethereum-related tokens - if (!finalLogo && (token.symbol.includes('ETH') || token.symbol === 'WETH')) { - finalLogo = LOGO_URLS['ETH']; - } - } - - // For native tokens (zero address), ensure they have proper logos - if (token.contractAddress === '0x0000000000000000000000000000000000000000') { - if (!finalLogo) { - // Use chain-specific native token logos - const nativeTokenLogos: Record = { - 137: 'https://coin-images.coingecko.com/coins/images/32440/standard/polygon.png', // POL - 43114: - 'https://assets.coingecko.com/coins/images/12559/standard/Avalanche_Circle_RedWhite_Trans.png', // AVAX - 56: 'https://assets.coingecko.com/coins/images/825/large/bnb-icon2_2x.png', // BNB - 8217: 'https://assets.coingecko.com/asset_platforms/images/9672/large/kaia.png', // KAIA - 50104: 'https://assets.coingecko.com/coins/images/38680/large/sophon_logo_200.png', // SOPH - }; - finalLogo = nativeTokenLogos[chain.id] || ''; - } - } - - tokenSymbols.push(token.symbol); - - if (!tokenChainMap.has(token.symbol)) { - tokenChainMap.set(token.symbol, []); - } - tokenChainMap.get(token.symbol)!.push(chain.id); - - if (!allTokens.has(token.symbol)) { - allTokens.set(token.symbol, { - symbol: token.symbol, - address: token.contractAddress, - decimals: token.decimals, - name: token.name || token.symbol, - logo: finalLogo, - }); - } - } - chainTokenMap.set(chain.id, tokenSymbols); - } - - return { - chains, - tokens: Array.from(allTokens.values()), - chainTokenMap, - tokenChainMap, - }; -} - -/** - * Get base token metadata based on network - */ -function getBaseTokenMetadata(_network: NexusNetwork = 'mainnet'): Record { - return _network === 'testnet' ? TESTNET_TOKEN_METADATA : TOKEN_METADATA; -} - -const transactionSupportDataCache = new Map(); - -/** - * Gets and processes support data for a given transaction type from the SDK. - * This function caches the processed data to avoid redundant calls and processing. - * @param sdk The NexusSDK instance. - * @param type The type of transaction. - * @returns Processed transaction support data or null. - */ -function getTransactionSupportData( - sdk: NexusSDK, - type: TransactionType, -): TransactionSupportData | null { - if (transactionSupportDataCache.has(type)) { - return transactionSupportDataCache.get(type)!; - } - - let rawData: SupportedChainsResult | null = null; - try { - if (type === 'swap') { - rawData = sdk?.utils?.getSwapSupportedChainsAndTokens?.(); - } else { - // getSupportedChains actually returns the same structure as getSwapSupportedChainsAndTokens - // despite what the TypeScript types say - rawData = sdk?.utils?.getSupportedChains?.() as SupportedChainsResult; - } - } catch (error) { - console.warn(`Failed to fetch support data for ${type} from SDK:`, error); - transactionSupportDataCache.set(type, null); - return null; - } - - const processedData = _processSdkData(rawData); - transactionSupportDataCache.set(type, processedData); - - return processedData; -} - -/** - * Convert destination swap token to standard token metadata format - */ -function convertDestinationTokenToMetadata( - destinationToken: NonNullable>[0], -): EnhancedTokenMetadata { - return { - symbol: destinationToken.symbol, - name: destinationToken.name, - decimals: destinationToken.decimals, - icon: destinationToken.logo, - coingeckoId: '', // Not provided in destination tokens - contractAddress: destinationToken.tokenAddress, - }; -} - -/** - * Get available tokens for a specific chain and transaction type. - * This function is the single source of truth for token resolution. - * It handles all transaction types and uses a caching mechanism for performance. - */ -export function getAvailableTokens(params: TokenResolutionParams): EnhancedTokenMetadata[] { - const { chainId, type, network = 'mainnet', isDestination = false, sdk } = params; - - // Handle swap destination tokens separately as they come from a different source (static list). - if (type === 'swap' && isDestination) { - const baseTokens = Object.values(getBaseTokenMetadata(network)); - let allDestinationTokens: ReturnType[] = []; - - if (chainId) { - const destinationTokens = DESTINATION_SWAP_TOKENS.get(chainId) || []; - allDestinationTokens = destinationTokens - .filter( - (destToken) => !baseTokens.some((baseToken) => baseToken.symbol === destToken.symbol), - ) - .map(convertDestinationTokenToMetadata); - } else { - const allChainTokens = Array.from(DESTINATION_SWAP_TOKENS.values()).flat(); - const uniqueTokens = new Map(); - allChainTokens.forEach((token) => { - if ( - !uniqueTokens.has(token.symbol) && - !baseTokens.some((baseToken) => baseToken.symbol === token.symbol) - ) { - uniqueTokens.set(token.symbol, token); - } - }); - allDestinationTokens = Array.from(uniqueTokens.values()).map( - convertDestinationTokenToMetadata, - ); - } - const enhancedBaseTokens = baseTokens.map((token) => ({ - ...token, - // @ts-expect-error - contractAddress: TOKEN_CONTRACT_ADDRESSES[token.symbol]?.[chainId || 0], - })); - const result = [...enhancedBaseTokens, ...allDestinationTokens]; - return result; - } - - // For swap source tokens, use only getSwapSupportedChainsAndTokens (ERC20 tokens only, no native tokens) - if (type === 'swap' && !isDestination && sdk) { - const supportData = getTransactionSupportData(sdk, type); - if (supportData) { - let tokensToDisplay = supportData.tokens; - - if (chainId) { - const supportedSymbols = supportData.chainTokenMap.get(chainId) || []; - tokensToDisplay = tokensToDisplay.filter((t) => supportedSymbols.includes(t.symbol)); - } - - const result = tokensToDisplay.map((token) => { - // Enhanced icon resolution for token options - let finalIcon = token.logo; - if (!finalIcon) { - finalIcon = LOGO_URLS[token.symbol]; - - // Handle wrapped tokens - if (!finalIcon && token.symbol.startsWith('W') && token.symbol.length > 1) { - const baseSymbol = token.symbol.substring(1); - finalIcon = LOGO_URLS[baseSymbol]; - } - - // ETH fallback for ethereum-related tokens - if (!finalIcon && (token.symbol.includes('ETH') || token.symbol === 'WETH')) { - finalIcon = LOGO_URLS['ETH']; - } - } - - return { - symbol: token.symbol, - name: token.name || token.symbol, - decimals: token.decimals, - icon: finalIcon || '', - coingeckoId: '', - contractAddress: token.address as `0x${string}`, - }; - }); - return result; - } - } - - // For all other cases (transfer, bridge, bridgeAndExecute), use the SDK data. - if (sdk) { - const supportData = getTransactionSupportData(sdk, type); - if (supportData) { - let tokensToDisplay = supportData.tokens; - - if (chainId) { - const supportedSymbols = supportData.chainTokenMap.get(chainId) || []; - tokensToDisplay = tokensToDisplay.filter((t) => supportedSymbols.includes(t.symbol)); - } - - const result = tokensToDisplay.map((token) => { - // Enhanced icon resolution for token options - let finalIcon = token.logo; - if (!finalIcon) { - finalIcon = LOGO_URLS[token.symbol]; - - // Handle wrapped tokens - if (!finalIcon && token.symbol.startsWith('W') && token.symbol.length > 1) { - const baseSymbol = token.symbol.substring(1); - finalIcon = LOGO_URLS[baseSymbol]; - } - - // ETH fallback for ethereum-related tokens - if (!finalIcon && (token.symbol.includes('ETH') || token.symbol === 'WETH')) { - finalIcon = LOGO_URLS['ETH']; - } - } - - return { - symbol: token.symbol, - name: token.name || token.symbol, - decimals: token.decimals, - icon: finalIcon || '', - coingeckoId: '', // Not provided by SDK - contractAddress: token.address as `0x${string}`, - }; - }); - return result; - } else { - } - } - - // Fallback for non-SDK or failed SDK calls. - const baseTokens = Object.values(getBaseTokenMetadata(network)); - // For non-swap transactions, include native tokens - if (type !== 'swap') { - const allNativeTokens: Array<{ - symbol: string; - name: string; - decimals: number; - icon: string; - coingeckoId: string; - }> = [ - { - symbol: 'ETH', - name: 'Ether', - decimals: 18, - icon: 'https://coin-images.coingecko.com/coins/images/279/large/ethereum.png', - coingeckoId: 'ethereum', - }, - { - symbol: 'POL', - name: 'POL', - decimals: 18, - icon: 'https://coin-images.coingecko.com/coins/images/32440/standard/polygon.png', - coingeckoId: 'polygon-ecosystem-token', - }, - { - symbol: 'AVAX', - name: 'Avalanche', - decimals: 18, - icon: 'https://assets.coingecko.com/coins/images/12559/standard/Avalanche_Circle_RedWhite_Trans.png', - coingeckoId: 'avalanche-2', - }, - { - symbol: 'BNB', - name: 'BNB', - decimals: 18, - icon: 'https://assets.coingecko.com/coins/images/825/large/bnb-icon2_2x.png', - coingeckoId: 'binancecoin', - }, - { - symbol: 'KAIA', - name: 'Kaia', - decimals: 18, - icon: 'https://assets.coingecko.com/asset_platforms/images/9672/large/kaia.png', - coingeckoId: 'kaia', - }, - { - symbol: 'SOPH', - name: 'Sophon', - decimals: 18, - icon: 'https://assets.coingecko.com/coins/images/38680/large/sophon_logo_200.png', - coingeckoId: 'sophon', - }, - { - symbol: 'FUEL', - name: 'Fuel', - decimals: 9, - icon: 'https://coin-images.coingecko.com/coins/images/279/large/ethereum.png', - coingeckoId: 'ethereum', - }, - ]; - - // If a specific chain is selected, only include native token for that chain - if (chainId) { - const chainNativeTokens: Record = { - 1: 'ETH', // Ethereum - 10: 'ETH', // Optimism - 137: 'POL', // Polygon - 8453: 'ETH', // Base - 42161: 'ETH', // Arbitrum - 534352: 'ETH', // Scroll - 43114: 'AVAX', // Avalanche - 56: 'BNB', // BNB Chain - 8217: 'KAIA', // Kaia - 50104: 'SOPH', // Sophon - 9889: 'FUEL', // Fuel - }; - - const nativeSymbol = chainNativeTokens[chainId]; - if (nativeSymbol) { - const nativeToken = allNativeTokens.find((t) => t.symbol === nativeSymbol); - if (nativeToken) { - baseTokens.push(nativeToken); - } - } - } else { - // No chain selected, include all native tokens - baseTokens.push(...allNativeTokens); - } - } - - const result = baseTokens.map((token) => { - // Enhanced icon resolution for base tokens - let finalIcon = token.icon; - if (!finalIcon) { - finalIcon = LOGO_URLS[token.symbol]; - - // Handle wrapped tokens - if (!finalIcon && token.symbol.startsWith('W') && token.symbol.length > 1) { - const baseSymbol = token.symbol.substring(1); - finalIcon = LOGO_URLS[baseSymbol]; - } - - // ETH fallback for ethereum-related tokens - if (!finalIcon && (token.symbol.includes('ETH') || token.symbol === 'WETH')) { - finalIcon = LOGO_URLS['ETH']; - } - } - - return { - ...token, - icon: finalIcon || token.icon, - // @ts-expect-error - contractAddress: TOKEN_CONTRACT_ADDRESSES[token.symbol]?.[chainId || 0], - }; - }); - return result; -} - -/** - * Convert enhanced token metadata to UI selection options - * Follows Interface Segregation Principle - provides only what UI needs - */ -export function convertTokensToSelectOptions(tokens: EnhancedTokenMetadata[]): TokenSelectOption[] { - return tokens.map((token) => ({ - value: token.symbol, - label: token.symbol, - icon: token.icon, - metadata: token, - })); -} - -/** - * React hook for token resolution with memoization. - * This is the single hook for fetching available tokens for all transaction types. - */ -export function useAvailableTokens(params: TokenResolutionParams): TokenSelectOption[] { - // The useMemo hook is crucial for performance, preventing re-computation on every render. - return useMemo(() => { - const tokens = getAvailableTokens(params); - return convertTokensToSelectOptions(tokens); - }, [params.chainId, params.type, params.network, params.isDestination, params.sdk]); -} - -/** - * Get token contract address with enhanced resolution - * Follows Open/Closed Principle - extensible for new token sources - */ -export function getTokenAddress( - tokenSymbol: string, - chainId: number, - type: TransactionType = 'transfer', -): `0x${string}` { - // Try standard TOKEN_CONTRACT_ADDRESSES first - // @ts-expect-error - const standardAddress = TOKEN_CONTRACT_ADDRESSES[tokenSymbol]?.[chainId]; - if (standardAddress) { - return standardAddress; - } - - // For swaps, check DESTINATION_SWAP_TOKENS - if (type === 'swap') { - const chainTokens = DESTINATION_SWAP_TOKENS.get(chainId); - const destinationToken = chainTokens?.find((t) => t.symbol === tokenSymbol); - if (destinationToken) { - return destinationToken.tokenAddress; - } - } - - throw new Error(`Token ${tokenSymbol} not supported on chain ${CHAIN_METADATA[chainId]?.name}`); -} - -/** - * Check if a token is available on a specific chain - * Follows Liskov Substitution Principle - can be used wherever boolean is expected - */ -export function isTokenAvailableOnChain( - tokenSymbol: string, - chainId: number, - type: TransactionType = 'transfer', -): boolean { - // For swaps, be more permissive to avoid aggressive token resets - if (type === 'swap') { - // Check if token exists in either base tokens or destination swap tokens - // @ts-expect-error - const baseTokens = TOKEN_CONTRACT_ADDRESSES[tokenSymbol]; - if (baseTokens && baseTokens[chainId]) { - return true; - } - - const chainTokens = DESTINATION_SWAP_TOKENS.get(chainId); - if (chainTokens?.some((t) => t.symbol === tokenSymbol)) { - return true; - } - - // For swap source tokens, be even more permissive since SDK data might be loading - return true; - } - - try { - getTokenAddress(tokenSymbol, chainId, type); - return true; - } catch { - return false; - } -} - -/** - * Get token metadata by symbol with enhanced resolution - * Follows Dependency Inversion Principle - depends on abstractions, not concretions - */ -export function getTokenMetadata( - tokenSymbol: string, - chainId?: number, - type: TransactionType = 'transfer', - network: NexusNetwork = 'mainnet', -): EnhancedTokenMetadata | null { - // Try base tokens first - const baseTokens = getBaseTokenMetadata(network); - const baseToken = baseTokens[tokenSymbol]; - - if (baseToken) { - return { - ...baseToken, - // @ts-expect-error - contractAddress: chainId ? TOKEN_CONTRACT_ADDRESSES[tokenSymbol]?.[chainId] : undefined, - }; - } - - // For swaps, check destination tokens - if (type === 'swap' && chainId) { - const chainTokens = DESTINATION_SWAP_TOKENS.get(chainId); - const destinationToken = chainTokens?.find((t) => t.symbol === tokenSymbol); - - if (destinationToken) { - return convertDestinationTokenToMetadata(destinationToken); - } - } - - return null; -} - -/** - * Filter tokens based on availability for a specific chain - * Utility function for component-level filtering - */ -export function filterTokensByChainAvailability( - tokens: EnhancedTokenMetadata[], - chainId: number, - type: TransactionType = 'transfer', -): EnhancedTokenMetadata[] { - return tokens.filter((token) => isTokenAvailableOnChain(token.symbol, chainId, type)); -} - -/** - * Get supported chain IDs for a specific token and transaction type. - * This is the single source of truth for chain resolution. - */ -export function getSupportedChainsForToken( - tokenSymbol: string, - type: TransactionType, - sdk?: NexusSDK, - isDestination?: boolean, -): number[] { - // For swap destination, use the static list + base tokens. - if (type === 'swap' && isDestination) { - const supportedChains = new Set(); - - // Check DESTINATION_SWAP_TOKENS - for (const [chainId, tokens] of DESTINATION_SWAP_TOKENS.entries()) { - if (tokens.some((token) => token.symbol === tokenSymbol)) { - supportedChains.add(chainId); - } - } - - // Check base tokens (TOKEN_CONTRACT_ADDRESSES) - // @ts-expect-error - const tokenContracts = TOKEN_CONTRACT_ADDRESSES[tokenSymbol]; - if (tokenContracts) { - Object.keys(tokenContracts).forEach((chainId) => supportedChains.add(Number(chainId))); - } - - return Array.from(supportedChains).sort((a, b) => a - b); - } - - // For swap source, use only getSwapSupportedChainsAndTokens - if (type === 'swap' && !isDestination && sdk) { - const supportData = getTransactionSupportData(sdk, type); - if (supportData) { - return (supportData.tokenChainMap.get(tokenSymbol) || []).sort((a, b) => a - b); - } - } - - // For all other cases (transfer, bridge, bridgeAndExecute), use the SDK data. - if (sdk) { - const supportData = getTransactionSupportData(sdk, type); - if (supportData) { - return (supportData.tokenChainMap.get(tokenSymbol) || []).sort((a, b) => a - b); - } - } - - // Fallback for non-SDK or failed SDK calls. - // For non-swap transactions, include both ERC20 contracts and native tokens on supported chains - const supportedChains = new Set(); - - // Add chains from TOKEN_CONTRACT_ADDRESSES (ERC20 tokens) - // @ts-expect-error - const tokenContracts = TOKEN_CONTRACT_ADDRESSES[tokenSymbol]; - if (tokenContracts) { - Object.keys(tokenContracts).forEach((chainId) => supportedChains.add(Number(chainId))); - } - - // Include native token chains if the token symbol matches a known native token - const nativeTokens: Record = { - ETH: [1, 10, 8453, 42161, 534352, 11155111, 84532, 421614, 11155420, 534351], // Ethereum networks - POL: [137, 80002], // Polygon - AVAX: [43114, 43113], // Avalanche - BNB: [56, 97], // BNB Chain - KAIA: [8217, 82170], // Kaia - SOPH: [50104], // Sophon - FUEL: [9889, 10143], // Fuel - }; - - const nativeChains = nativeTokens[tokenSymbol]; - if (nativeChains) { - nativeChains.forEach((chainId) => supportedChains.add(chainId)); - } - - return Array.from(supportedChains).sort((a, b) => a - b); -} - -/** - * Check if a token-chain combination is valid for swaps - * Used for validation and reset logic - */ -export function isTokenChainCombinationValid( - tokenSymbol?: string, - chainId?: number, - type: TransactionType = 'transfer', -): boolean { - if (!tokenSymbol || !chainId) return true; // Allow empty selections - - // For swaps, be more lenient with validation to avoid aggressive resets - // Let the user make selections and validate at execution time - if (type === 'swap') { - return true; - } - - return isTokenAvailableOnChain(tokenSymbol, chainId, type); -} - -/** - * Get chains that should be available based on a selected token. - * Filters a list of available chains against chains that support the token. - */ -export function getFilteredChainsForToken( - tokenSymbol: string | undefined, - availableChains: number[], - type: TransactionType, - sdk?: NexusSDK, - isDestination?: boolean, -): number[] { - if (!tokenSymbol) { - return availableChains; - } - - const supportedChains = getSupportedChainsForToken(tokenSymbol, type, sdk, isDestination); - return availableChains.filter((chainId) => supportedChains.includes(chainId)); -} diff --git a/packages/widgets/src/utils/utils.ts b/packages/widgets/src/utils/utils.ts deleted file mode 100644 index b341b4e7..00000000 --- a/packages/widgets/src/utils/utils.ts +++ /dev/null @@ -1,626 +0,0 @@ -import { clsx, type ClassValue } from 'clsx'; -import { twMerge } from 'tailwind-merge'; -import { OrchestratorStatus, ReviewStatus, SwapInputData } from '../types'; -import { Abi, isAddress } from 'viem'; -import { - type BridgeParams, - type TransferParams, - type BridgeAndExecuteParams, - CHAIN_METADATA, -} from '@nexus/commons'; - -export function cn(...inputs: ClassValue[]) { - return twMerge(clsx(inputs)); -} - -export const getButtonText = (status: OrchestratorStatus, reviewStatus: ReviewStatus) => { - if (status === 'initializing') return 'Sign'; - if (status === 'simulation_error') return 'Try Again'; - if (reviewStatus === 'gathering_input') return 'Start Transaction'; - if (reviewStatus === 'simulating') return 'Simulating...'; - if (reviewStatus === 'needs_allowance') return 'Approve and Continue'; - if (reviewStatus === 'ready') return 'Start Transaction'; - return 'Continue'; -}; - -export const getOperationText = (type: string) => { - switch (type) { - case 'bridge': - return 'Bridging'; - case 'transfer': - return 'Transferring'; - case 'bridgeAndExecute': - return 'Bridge & Execute'; - case 'swap': - return 'Swapping'; - default: - return 'Processing'; - } -}; - -export const getStatusText = (stepData: any, operationType: string) => { - if (!stepData) return 'Verifying Request'; - - const { type } = stepData; - const opText = getOperationText(operationType); - - switch (type) { - case 'INTENT_ACCEPTED': - return 'Intent Accepted'; - case 'INTENT_HASH_SIGNED': - return 'Signing Transaction'; - case 'INTENT_SUBMITTED': - return 'Submitting Transaction'; - case 'INTENT_COLLECTION': - return 'Collecting Confirmations'; - case 'INTENT_COLLECTION_COMPLETE': - return 'Confirmations Complete'; - case 'APPROVAL': - return 'Approving'; - case 'TRANSACTION_SENT': - return 'Sending Transaction'; - case 'RECEIPT_RECEIVED': - return 'Receipt Received'; - case 'TRANSACTION_CONFIRMED': - case 'INTENT_FULFILLED': - return `${opText} Complete`; - default: - return `Processing ${opText}`; - } -}; - -/** - * Common error patterns and their user-friendly messages - */ -const ERROR_PATTERNS = { - USER_REJECTED: [ - /user rejected/i, - /user denied/i, - /user cancelled/i, - /user refused/i, - /action_rejected/i, - /userRejectedRequest/i, - /transaction rejected by user/i, - /user rejected transaction/i, - /user canceled/i, - ], - NETWORK_ERROR: [ - /network error/i, - /connection failed/i, - /fetch failed/i, - /network request failed/i, - /rpc error/i, - /timeout/i, - /backend initialization failed/i, - /simulation client error/i, - ], - INSUFFICIENT_FUNDS: [ - /insufficient funds/i, - /insufficient balance/i, - /not enough/i, - /exceeds balance/i, - /balance too low/i, - /you don't have enough/i, - /sender doesn't have enough/i, - /transfer amount exceeds balance/i, - /erc20: transfer amount exceeds balance/i, - /erc20.*insufficient/i, - ], - GAS_ERROR: [ - /gas required exceeds allowance/i, - /out of gas/i, - /gas estimation failed/i, - /gas limit/i, - /intrinsic gas too low/i, - ], - TRANSACTION_FAILED: [ - /transaction failed/i, - /transaction reverted/i, - /execution reverted/i, - /transaction underpriced/i, - /nonce too low/i, - /call exception/i, - /transaction was reverted/i, - /replacement transaction underpriced/i, - /already known/i, - /reverted with reason/i, - /transaction rejected/i, - /transaction not mined within/i, - ], - ALLOWANCE_ERROR: [ - /allowance/i, - /approval/i, - /approve/i, - /token approval failed/i, - /insufficient allowance/i, - ], - CONTRACT_ERROR: [ - /contract/i, - /invalid address/i, - /abi/i, - /function not found/i, - /contract execution failed/i, - ], - CHAIN_ERROR: [ - /unrecognized chain id/i, - /unsupported chain/i, - /chain not found/i, - /invalid chain/i, - /try adding the chain using wallet_addEthereumChain/i, - /wrong network/i, - /switch to correct network/i, - ], - INIT_ERROR: [ - /initialization failed/i, - /sdk not initialized/i, - /provider not connected/i, - /wallet provider not connected/i, - /setup failed/i, - ], - BRIDGE_ERROR: [ - /bridge failed/i, - /bridging error/i, - /cross-chain error/i, - /bridge transaction failed/i, - ], - EXECUTE_ERROR: [ - /execute failed/i, - /execution error/i, - /execute phase failed/i, - /contract execution error/i, - ], - SWAP_ERROR: [ - /insufficient funds/i, - /insufficient balance/i, - /swap failed/i, - /swap error/i, - /vsc sbc tx/i, - /swap transaction failed/i, - /slippage/i, - /price impact/i, - /swap intent failed/i, - /swap execution failed/i, - /cot not present/i, - /chain of trust not present/i, - ], -} as const; - -/** - * User-friendly error messages - */ -const USER_FRIENDLY_MESSAGES = { - USER_REJECTED: "Transaction was cancelled. Please try again when you're ready to proceed.", - NETWORK_ERROR: 'Network connection issue. Please check your internet connection and try again.', - INSUFFICIENT_FUNDS: "You don't have enough balance to complete this transaction.", - GAS_ERROR: 'Transaction fee estimation failed. Please try again or adjust the gas settings.', - TRANSACTION_FAILED: 'Transaction failed to execute. This might be a temporary network issue.', - ALLOWANCE_ERROR: 'Token approval failed. Please try approving the token again.', - CONTRACT_ERROR: 'Smart contract interaction failed. Please try again.', - CHAIN_ERROR: 'This network is not added to your wallet. Please add it to continue.', - INIT_ERROR: 'Wallet connection issue. Please make sure your wallet is connected and try again.', - BRIDGE_ERROR: 'Cross-chain transfer failed. Please try again.', - EXECUTE_ERROR: 'Smart contract execution failed. Please try again.', - SWAP_ERROR: - 'Swap transaction failed. The destination chain may not support this token pair. Please try a different route.', - UNKNOWN: 'An unexpected error occurred. Please try again.', -} as const; - -/** - * Extract meaningful information from error messages while removing technical details - */ -function cleanErrorMessage(message: string): string { - // Remove version and package information - message = message.replace(/Version: [^\s]+/gi, ''); - message = message.replace(/viem@[^\s]+/gi, ''); - message = message.replace(/arcana@[^\s]+/gi, ''); - - // Remove common error prefixes that create noise - message = message.replace(/^Error: /gi, ''); - message = message.replace(/^RPC Error: /gi, ''); - - // Handle chained error messages - extract the most meaningful part - // Pattern: "Operation failed: Phase failed: Actual error" - const chainedErrorMatch = message.match( - /([^:]+operation failed|[^:]+phase failed|[^:]+error):\s*(.+)/i, - ); - if (chainedErrorMatch) { - const [, , actualError] = chainedErrorMatch; - // If the actual error is meaningful, use it; otherwise keep the chain - if (actualError && actualError.length > 10 && !actualError.includes('failed')) { - message = actualError.trim(); - } - } - - // Remove redundant "failed" phrases that pile up - message = message.replace(/\b(operation|phase|transaction|execution)\s+failed:\s*/gi, ''); - message = message.replace(/\bfailed:\s*/gi, ''); - - // Split by common delimiters and clean up - const lines = message.split(/[.\n]/).filter((line) => line.trim()); - const uniqueLines = [...new Set(lines.map((line) => line.trim()))]; - - // Take the first meaningful line if we have multiple - const meaningfulLine = - uniqueLines.find( - (line) => - line.length > 5 && - !line.toLowerCase().includes('operation failed') && - !line.toLowerCase().includes('phase failed'), - ) || uniqueLines[0]; - - return meaningfulLine?.trim() || message.trim(); -} - -/** - * Determine the error category based on the error message - */ -function categorizeError(errorMessage: string): keyof typeof USER_FRIENDLY_MESSAGES { - const message = errorMessage.toLowerCase(); - - for (const [category, patterns] of Object.entries(ERROR_PATTERNS)) { - if (patterns.some((pattern) => pattern.test(message))) { - return category as keyof typeof USER_FRIENDLY_MESSAGES; - } - } - - return 'UNKNOWN'; -} - -/** - * Format error messages to be user-friendly for display in UI components - * - * @param error - The error object or string from various sources (viem, Arcana SDK, etc.) - * @param context - Optional context about where the error occurred (e.g., 'simulation', 'bridge', 'execute') - * @returns A user-friendly error message - */ -function getRawErrorMessage(error: unknown): string { - if (error instanceof Error) return error.message; - if (typeof error === 'string') return error; - if (error && typeof error === 'object') { - const e = error as any; - return e.message || e.error || e.details || String(error); - } - return String(error); -} - -function handleUnknownCategory(cleanedMessage: string, context?: string): string | null { - if (cleanedMessage && cleanedMessage.length < 100 && cleanedMessage.length > 5) { - if ( - !cleanedMessage.includes('0x') && - !cleanedMessage.includes('viem@') && - !cleanedMessage.includes('Error:') - ) { - return cleanedMessage; - } - } - if (context === 'simulation') - return 'Unable to simulate this transaction. Please verify your inputs and try again.'; - if (context === 'transaction') - return 'Transaction could not be completed. Please check your wallet and try again.'; - if (context === 'bridge') - return 'Cross-chain transfer failed. Please check network connectivity and try again.'; - if (context === 'execute') - return 'Smart contract execution failed. Please verify the transaction details.'; - return null; -} - -export function formatErrorForUI(error: unknown, context?: string): string { - const errorMessage = getRawErrorMessage(error); - - console.error('Error being formatted for UI:', { error, errorMessage, context }); - - if (errorMessage.includes('COT not present') || errorMessage.includes('COT not available')) { - return 'This token pair is not supported on the selected destination chain. Please try a different token or destination chain.'; - } - - const cleanedMessage = cleanErrorMessage(errorMessage); - const category = categorizeError(cleanedMessage); - const userFriendlyMessage = USER_FRIENDLY_MESSAGES[category]; - - if (category === 'UNKNOWN') { - const alt = handleUnknownCategory(cleanedMessage, context); - if (alt) return alt; - - console.warn('Unknown error category detected:', { - cleanedMessage, - originalError: error, - context, - }); - } - - if (context && category !== 'USER_REJECTED') { - const contextual = getContextualErrorMessage(category, context); - if (contextual) return contextual; - } - - return userFriendlyMessage; -} - -/** - * Get context-specific error messages for better user experience - */ -function getContextualErrorMessage( - category: keyof typeof USER_FRIENDLY_MESSAGES, - context: string, -): string | null { - const contextMap: Record>> = { - simulation: { - NETWORK_ERROR: 'Unable to simulate transaction. Please check your connection and try again.', - INSUFFICIENT_FUNDS: 'Simulation shows insufficient balance for this transaction.', - GAS_ERROR: 'Unable to estimate transaction fees. Please try again.', - CONTRACT_ERROR: 'Contract simulation failed. Please verify the contract details.', - CHAIN_ERROR: 'Simulation failed due to network issues. Please add the required network.', - INIT_ERROR: 'Please connect your wallet to simulate transactions.', - }, - bridge: { - NETWORK_ERROR: 'Bridge service is temporarily unavailable. Please try again.', - INSUFFICIENT_FUNDS: 'Insufficient balance for cross-chain transfer.', - BRIDGE_ERROR: 'Cross-chain transfer failed. Please try again.', - CHAIN_ERROR: 'Source or destination network not supported in your wallet.', - }, - execute: { - CONTRACT_ERROR: 'Smart contract execution failed. Please verify the contract is correct.', - GAS_ERROR: 'Execution failed due to gas issues. Please try again.', - EXECUTE_ERROR: 'Contract interaction failed. Please try again.', - ALLOWANCE_ERROR: 'Token approval required before execution.', - }, - swap: { - NETWORK_ERROR: 'Swap service is temporarily unavailable. Please try again.', - INSUFFICIENT_FUNDS: 'Insufficient balance to complete the swap.', - SWAP_ERROR: 'Swap failed. Please verify your token selection and amount.', - GAS_ERROR: 'Swap failed due to gas issues. Please try again.', - CONTRACT_ERROR: 'Swap contract interaction failed. Please try again.', - ALLOWANCE_ERROR: 'Token approval required for swap.', - }, - allowance: { - ALLOWANCE_ERROR: 'Token approval transaction failed. Please try again.', - GAS_ERROR: 'Approval failed due to insufficient gas. Please try again.', - CONTRACT_ERROR: 'Token contract approval failed. Please verify the token.', - }, - initialization: { - INIT_ERROR: 'Wallet setup failed. Please reconnect your wallet and try again.', - NETWORK_ERROR: 'Unable to connect to Nexus services. Please try again.', - CHAIN_ERROR: 'Unsupported network. Please switch to a supported network.', - }, - }; - - const contextMessages = contextMap[context]; - return contextMessages?.[category] || null; -} - -/** - * Check if an error indicates user rejection/cancellation - */ -export function isUserRejectionError(error: unknown): boolean { - const errorMessage = error instanceof Error ? error.message : String(error); - return ERROR_PATTERNS.USER_REJECTED.some((pattern) => pattern.test(errorMessage)); -} - -/** - * Check if an error is related to an unrecognized chain - */ -export function isChainError(error: unknown): boolean { - const errorMessage = error instanceof Error ? error.message : String(error); - return ERROR_PATTERNS.CHAIN_ERROR.some((pattern) => pattern.test(errorMessage)); -} - -/** - * Format swap-specific error messages for better user experience - * - * @param error - The error object or string from swap operations - * @returns A user-friendly error message specific to swap operations - */ -export function formatSwapError(error: unknown): string { - // Use the general error formatter with swap context - return formatErrorForUI(error, 'swap'); -} - -/** - * Check if an error is swap-related - */ -export function isSwapError(error: unknown): boolean { - const errorMessage = error instanceof Error ? error.message : String(error); - return ERROR_PATTERNS.SWAP_ERROR.some((pattern) => pattern.test(errorMessage)); -} - -/** - * Extract chain ID from error message - * Supports both hex (0x...) and decimal formats - */ -export function extractChainIdFromError(error: unknown): number | null { - const errorMessage = error instanceof Error ? error.message : String(error); - const hexMatch = errorMessage.match(/(?:chain id|chainid)\s*["']?(0x[a-f0-9]+)["']?/i); - if (hexMatch) { - const chainId = parseInt(hexMatch[1], 16); - return isNaN(chainId) ? null : chainId; - } - const decimalMatch = errorMessage.match(/(?:chain id|chainid)\s*["']?(\d+)["']?/i); - if (decimalMatch) { - const chainId = parseInt(decimalMatch[1], 10); - return isNaN(chainId) ? null : chainId; - } - - return null; -} - -/** - * Add a chain to the user's wallet using wallet_addEthereumChain - */ -export async function addChainToWallet( - chainId: number, - provider: { request: (args: { method: string; params?: any[] }) => Promise }, -): Promise { - const chainMetadata = CHAIN_METADATA[chainId]; - if (!chainMetadata) { - console.error(`Chain metadata not found for chain ID: ${chainId}`); - return false; - } - - if (!provider) { - console.error('No provider available'); - return false; - } - - try { - await provider.request({ - method: 'wallet_addEthereumChain', - params: [ - { - chainId: `0x${chainId.toString(16)}`, - chainName: chainMetadata.name, - nativeCurrency: chainMetadata.nativeCurrency, - rpcUrls: chainMetadata.rpcUrls, - blockExplorerUrls: chainMetadata.blockExplorerUrls, - iconUrls: [chainMetadata.logo], - }, - ], - }); - return true; - } catch (error) { - console.error('Failed to add chain to wallet:', error); - return false; - } -} - -/** - * Find ABI fragment for given function name (optionally matching parameter count) - */ -export function findAbiFragment(abi: Abi, functionName: string, paramCount?: number) { - return (abi as any[]).find( - (item) => - item.type === 'function' && - item.name === functionName && - (paramCount === undefined || (item.inputs || []).length === paramCount), - ); -} - -export const getContentKey = (status: string, additionalStates?: string[]): string => { - if (['processing', 'success', 'error'].includes(status)) { - return 'processor'; - } - - if (status === 'set_allowance') { - return 'allowance'; - } - - if (additionalStates?.includes(status)) { - return status; - } - - return 'review'; -}; - -export const formatCost = (cost: string | number | bigint) => { - const costStr = typeof cost === 'bigint' ? cost.toString() : String(cost); - const numCost = parseFloat(costStr); - if (isNaN(numCost)) return 'Invalid'; - if (numCost < 0) return 'Invalid'; - if (numCost === 0) return 'Free'; - if (numCost < 0.001) return '< 0.001'; - return numCost.toFixed(6); -}; - -export function truncateAddress( - address: string, - startLength: number = 6, - endLength: number = 4, -): string { - if (!isAddress(address)) return address; - - if (address.length <= startLength + endLength + 2) return address; - - return `${address.slice(0, startLength)}...${address.slice(-endLength)}`; -} - -export const getModalTitle = (status: OrchestratorStatus, modalTitle: string) => { - if (status === 'set_allowance') return 'Approve Token Allowance'; - return modalTitle; -}; - -export const getPrimaryButtonText = (status: OrchestratorStatus, reviewStatus: ReviewStatus) => { - if (status === 'set_allowance') return 'Approve & Continue'; - return getButtonText(status, reviewStatus); -}; - -// Union type utility functions for handling different transaction input structures -type TransactionInputData = - | Partial - | Partial - | Partial - | Partial - | null - | undefined; - -/** - * Safely extract token field from union transaction input data - */ -export function getTokenFromInputData(data: TransactionInputData): string | undefined { - if (!data) return undefined; - - // For SwapInputData, check fromTokenAddress first, then other fields - if ('fromTokenAddress' in data && typeof data.fromTokenAddress === 'string') { - return data.fromTokenAddress; - } - - // For SwapConfig, check nested inputs structure - if ('inputs' in data && data.inputs) { - const inputs = data.inputs as any; - return inputs.inputToken || inputs.fromToken || inputs.token || inputs.fromTokenAddress; - } - - // For other transaction types, access directly - if ('token' in data && typeof data.token === 'string') { - return data.token; - } - - return undefined; -} - -/** - * Safely extract amount field from union transaction input data - */ -export function getAmountFromInputData(data: TransactionInputData): string | number | undefined { - if (!data) return undefined; - - // For SwapInputData, check fromAmount first, then amount - if ('fromAmount' in data && data.fromAmount !== undefined) { - return data.fromAmount; - } - - // For SwapConfig, check nested inputs structure - if ('inputs' in data && data.inputs) { - const inputs = data.inputs as any; - return inputs.amount || inputs.fromAmount; - } - - // For other transaction types, access directly - if ('amount' in data) { - return data.amount; - } - - return undefined; -} - -/** - * Safely extract chainId from union transaction input data - */ -export function getChainIdFromInputData(data: TransactionInputData): number | undefined { - if (!data) return undefined; - - // For SwapConfig, check nested inputs structure first - if ('inputs' in data && data.inputs) { - const inputs = data.inputs as any; - return inputs.chainId || inputs.toChainID; - } - - // For other transaction types, access directly - if ('chainId' in data && typeof data.chainId === 'number') { - return data.chainId; - } - - if ('toChainId' in data && typeof data.toChainId === 'number') { - return data.toChainId; - } - - return undefined; -} diff --git a/packages/widgets/tsconfig.json b/packages/widgets/tsconfig.json deleted file mode 100644 index 781bfb12..00000000 --- a/packages/widgets/tsconfig.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "extends": "../../tsconfig.json", - "compilerOptions": { - "outDir": "./dist", - "baseUrl": ".", - "jsx": "react-jsx", - "lib": ["dom", "dom.iterable", "esnext"], - "paths": { - "@nexus/commons": ["../commons/index.ts"], - "@nexus/commons/*": ["../commons/*"], - "@avail-project/nexus-core": ["../core/index.ts"], - "@avail-project/nexus-core/*": ["../core/*"], - "sdk": ["../core/sdk/index.ts"], - "sdk/*": ["../core/sdk/*"], - "adapters/*": ["../core/adapters/*"], - "integrations/*": ["../core/integrations/*"] - } - }, - "include": ["src/**/*.ts", "src/**/*.tsx", "src/**/*.d.ts"], - "exclude": ["dist", "node_modules"] -} diff --git a/scripts/README.md b/scripts/README.md index c8248675..16e63569 100644 --- a/scripts/README.md +++ b/scripts/README.md @@ -18,18 +18,6 @@ pnpm run release:core:dev pnpm run release:core:prod ``` -#### Widgets Package (`@avail-project/nexus-widgets`) - -```bash -# Development release (default) -./scripts/release-widgets.sh dev [patch|minor|major] -pnpm run release:widgets:dev - -# Production release -./scripts/release-widgets.sh prod [patch|minor|major] -pnpm run release:widgets:prod -``` - ### Local Tarballs (No Publish) ```bash @@ -37,8 +25,7 @@ pnpm run release:widgets:prod ./scripts/local-pack.sh # In another project -pnpm add /absolute/path/to/dist-tarballs/avail-project-nexus-core-*.tgz \ - /absolute/path/to/dist-tarballs/avail-project-nexus-widgets-*.tgz +pnpm add /absolute/path/to/dist-tarballs/avail-project-nexus-core-*.tgz ``` ## Release Types @@ -79,15 +66,6 @@ pnpm add /absolute/path/to/dist-tarballs/avail-project-nexus-core-*.tgz \ # Core – production release (patch) from current branch ./scripts/release-core.sh prod patch --yes - -# Widgets – interactive dev prerelease (requires matching core prerelease on npm) -./scripts/release-widgets.sh - -# Widgets – non-interactive dev prerelease (beta), resolves latest core beta by timestamp, dry-run -./scripts/release-widgets.sh dev patch beta --yes --dry-run - -# Widgets – production release (patch) -./scripts/release-widgets.sh prod patch --yes ``` ## Prerequisites diff --git a/scripts/release-widgets.sh b/scripts/release-widgets.sh deleted file mode 100755 index 3c9107eb..00000000 --- a/scripts/release-widgets.sh +++ /dev/null @@ -1,361 +0,0 @@ -#!/bin/bash - -# Nexus Widgets SDK Release Script -set -e - -# Colors for output -RED='\033[0;31m' -GREEN='\033[0;32m' -YELLOW='\033[1;33m' -BLUE='\033[0;34m' -PURPLE='\033[0;35m' -NC='\033[0m' # No Color - -# Function to print colored output -print_status() { - echo -e "${GREEN}[INFO]${NC} $1" -} - -print_warning() { - echo -e "${YELLOW}[WARNING]${NC} $1" -} - -print_error() { - echo -e "${RED}[ERROR]${NC} $1" -} - -print_header() { - echo -e "${PURPLE}[WIDGETS RELEASE]${NC} $1" -} - -# Flags -NON_INTERACTIVE=0 -for arg in "$@"; do - if [[ "$arg" == "--yes" || "$arg" == "-y" || "$arg" == "--ci" ]]; then - NON_INTERACTIVE=1 - fi -done -DRY_RUN=0 -for arg in "$@"; do - if [[ "$arg" == "--dry-run" || "$arg" == "-n" ]]; then - DRY_RUN=1 - fi -done - -# Check if we're in a git repository -if ! git rev-parse --git-dir > /dev/null 2>&1; then - print_error "Not in a git repository" - exit 1 -fi - -# Check if we're in the root directory -if [[ ! -f "package.json" ]] || [[ ! -d "packages/widgets" ]]; then - print_error "Please run this script from the monorepo root directory" - exit 1 -fi - -# Check for uncommitted changes -if ! git diff-index --quiet HEAD --; then - print_error "There are uncommitted changes. Please commit or stash them first." - exit 1 -fi - -# Get the release type from command line argument (positional defaults) -RELEASE_TYPE=${1:-"dev"} -VERSION_TYPE=${2:-"patch"} -PRERELEASE_ID=${3:-"dev"} - -# Interactive wizard (skipped with --yes) -if [[ $NON_INTERACTIVE -eq 0 ]]; then - echo "" - print_header "Interactive release wizard" - echo "This will publish @avail-project/nexus-widgets." - echo "" - echo "Examples:" - echo " dev prerelease: 0.0.2-beta.0 -> 0.0.2-beta.1 ... -> 0.0.2-beta.9 -> 0.0.3-beta.0" - echo " prod release: 0.0.2 -> 0.0.3 (patch), 0.1.0 (minor), 1.0.0 (major)" - echo "" - read -p "Release type [dev|prod] (default: $RELEASE_TYPE): " _rt - if [[ -n "$_rt" ]]; then RELEASE_TYPE="$_rt"; fi - if [[ "$RELEASE_TYPE" != "dev" && "$RELEASE_TYPE" != "prod" ]]; then - print_error "Invalid release type. Use 'dev' or 'prod'" - exit 1 - fi - if [[ "$RELEASE_TYPE" == "dev" ]]; then - read -p "Pre-release tag (e.g. beta, alpha, dev) (default: $PRERELEASE_ID): " _pre - if [[ -n "$_pre" ]]; then PRERELEASE_ID="$_pre"; fi - echo "" - echo "Dev prereleases are ANCHORED to the latest stable version." - echo "New series begin at -$PRERELEASE_ID.0 and increment 0..9, then roll to next patch." - else - read -p "Version bump [patch|minor|major] (default: $VERSION_TYPE): " _vtp - if [[ -n "$_vtp" ]]; then VERSION_TYPE="$_vtp"; fi - fi -fi - -if [[ "$RELEASE_TYPE" != "dev" && "$RELEASE_TYPE" != "prod" ]]; then - print_error "Invalid release type. Use 'dev' or 'prod'" - echo "Usage: $0 [dev|prod] [patch|minor|major] [prerelease-id]" - echo "Examples:" - echo " $0 dev patch alpha # Creates 0.1.1-alpha.0" - echo " $0 dev minor beta # Creates 0.2.0-beta.0" - echo " $0 dev patch # Creates 0.1.1-dev.0 (default)" - exit 1 -fi - -if [[ "$VERSION_TYPE" != "patch" && "$VERSION_TYPE" != "minor" && "$VERSION_TYPE" != "major" ]]; then - print_error "Invalid version type. Use 'patch', 'minor', or 'major'" - echo "Usage: $0 [dev|prod] [patch|minor|major] [prerelease-id]" - exit 1 -fi - -print_header "Starting @avail-project/nexus-widgets $RELEASE_TYPE release ($VERSION_TYPE)..." - -# Run type checking -print_status "Running type check..." -pnpm run typecheck:widgets - -# Clean previous builds -print_status "Cleaning previous builds..." -pnpm run clean - -# Build dependencies and widgets package -print_status "Building dependencies and @avail-project/nexus-widgets package..." -pnpm run build:widgets - -if [[ "$RELEASE_TYPE" == "prod" ]]; then - print_header "Creating production release..." - - # Ensure we're on main branch for production releases - CURRENT_BRANCH=$(git branch --show-current) - if [[ "$CURRENT_BRANCH" != "main" ]]; then - print_warning "Not on main branch. Current branch: $CURRENT_BRANCH" - if [[ $NON_INTERACTIVE -eq 0 ]]; then - read -p "Do you want to continue with production release from this branch? (y/N): " confirm - if [[ $confirm != [yY] ]]; then - print_error "Aborting production release. Switch to main branch first." - exit 1 - fi - else - print_status "--yes provided. Continuing from $CURRENT_BRANCH." - fi - fi - - # Check if @avail-project/nexus-core is published and available - print_status "Checking @avail-project/nexus-core dependency..." - if ! npm view @avail-project/nexus-core > /dev/null 2>&1; then - print_error "@avail-project/nexus-core is not published. Please release core package first." - print_status "Run: ./scripts/release-core.sh prod" - exit 1 - fi - - # Fetch latest version from npm to ensure proper increment - print_status "Fetching latest version from npm..." - LATEST_WIDGETS_VERSION=$(npm view @avail-project/nexus-widgets version 2>/dev/null || echo "0.0.0") - print_status "Latest widgets version: $LATEST_WIDGETS_VERSION" - - # Version bump - print_status "Bumping version ($VERSION_TYPE)..." - cd packages/widgets - - # Set current version to latest version to ensure proper increment - npm version "$LATEST_WIDGETS_VERSION" --no-git-tag-version --allow-same-version - npm version $VERSION_TYPE --no-git-tag-version - - WIDGETS_VERSION=$(node -p "require('./package.json').version") - cd ../.. - - # Commit version changes - git add packages/widgets/package.json - git commit -m "chore(widgets): release v$WIDGETS_VERSION" - - # Create tag (remove existing if present, then create new) - if git tag -l | grep -q "^widgets-v$WIDGETS_VERSION$"; then - print_warning "Tag widgets-v$WIDGETS_VERSION already exists, removing it..." - git tag -d "widgets-v$WIDGETS_VERSION" - fi - git tag "widgets-v$WIDGETS_VERSION" - - # Temporarily rewrite package for publishing - print_status "Preparing package for publishing as @avail-project/nexus-widgets..." - cd packages/widgets - - # Backup original package.json - cp package.json package.json.backup - - # Resolve published core version (prod) - CORE_PUBLISHED_VERSION=$(npm view @avail-project/nexus-core version 2>/dev/null || true) - export CORE_PUBLISHED_VERSION - if [[ -z "$CORE_PUBLISHED_VERSION" ]]; then - print_error "@avail-project/nexus-core is not published or version could not be resolved. Release core first." - exit 1 - fi - - # Ensure deps pin @avail-project/nexus-core to published version; remove internal commons from deps - node -e "const fs=require('fs');const p=JSON.parse(fs.readFileSync('package.json','utf8'));p.dependencies=p.dependencies||{};if(p.dependencies['@nexus/commons']){delete p.dependencies['@nexus/commons'];}p.dependencies['@avail-project/nexus-core']=process.env.CORE_PUBLISHED_VERSION;fs.writeFileSync('package.json',JSON.stringify(p,null,2)+'\n');" - - # Bundle internal commons into dist (imports already aliased by Rollup) - print_status "Bundling internal @nexus/commons into widgets dist..." - mkdir -p dist/commons - cp -R ../commons/dist/* dist/commons/ - - # Publish to npm (explicitly avoid marking as latest) - print_status "Publishing @avail-project/nexus-widgets@$WIDGETS_VERSION to npm (tag: legacy)..." - npm publish --access public --tag latest - - # Restore original package.json - mv package.json.backup package.json - cd ../.. - - # Push changes and tags - print_status "Pushing changes to git..." - git push origin $CURRENT_BRANCH - git push origin "widgets-v$WIDGETS_VERSION" - - print_header "✅ Production release completed!" - print_status "🚀 @avail-project/nexus-widgets@$WIDGETS_VERSION published successfully!" - print_status "📦 Install with: npm install @avail-project/nexus-widgets" - print_status "🎨 Includes React components for cross-chain transactions" - -else - print_header "Creating development release..." - - # Compute next prerelease version with 0-9 rollover by publication time - print_status "Computing next $PRERELEASE_ID version with rollover logic..." - cd packages/widgets - export PRERELEASE_ID - export PKG='@avail-project/nexus-widgets' - PRERELEASE_VERSION=$(node -e ' -const cp=require("child_process"); -const fs=require("fs"); -const pkg=process.env.PKG; -const pre=process.env.PRERELEASE_ID||"dev"; -const current=JSON.parse(fs.readFileSync("package.json","utf8")).version; -function exec(cmd){try{return cp.execSync(cmd,{stdio:["pipe","pipe","ignore"]}).toString().trim();}catch(e){return "";}} -function parse(v){const m=v&&v.match(/^(\d+)\.(\d+)\.(\d+)(?:-([0-9A-Za-z-]+)\.(\d+))?$/);if(!m) return null;return {M:+m[1],m:+m[2],p:+m[3],pre:m[4],n:m[5]?+m[5]:null};} -function toStr(b,preid,idx){return `${b.M}.${b.m}.${b.p}-${preid}.${idx}`} -let timesJSON = exec(`npm view ${pkg} time --json`); -let times={};try{times=JSON.parse(timesJSON||"{}");}catch(_){times={};} -// Determine base: prefer current prerelease channel if matching, otherwise use latest stable -let latestStable = exec(`npm view ${pkg} version 2>/dev/null`) || ""; -const parsedCurrent = parse(current); -let base = parse(latestStable) || (parsedCurrent ? {M:parsedCurrent.M,m:parsedCurrent.m,p:parsedCurrent.p} : {M:0,m:0,p:0}); -let next; -// Continue from current package version if already on requested prerelease channel -if(parsedCurrent && parsedCurrent.pre === pre){ - if(typeof parsedCurrent.n === "number" && parsedCurrent.n < 9){ - next = toStr({M:parsedCurrent.M,m:parsedCurrent.m,p:parsedCurrent.p}, pre, parsedCurrent.n + 1); - }else{ - // rollover to next patch from current base - next = toStr({M:parsedCurrent.M,m:parsedCurrent.m,p:parsedCurrent.p + 1}, pre, 0); - } -}else{ - // Find prereleases for THIS base only - let preEntries = Object.entries(times).filter(([v])=> new RegExp(`^${base.M}\\.${base.m}\\.${base.p}-${pre}\\.\\d+$`).test(v)); - preEntries.sort((a,b)=>new Date(a[1]) - new Date(b[1])); - if(preEntries.length){ - const lp = parse(preEntries[preEntries.length-1][0]); - if(lp && typeof lp.n === "number" && lp.n < 9){ - next = toStr({M:base.M,m:base.m,p:base.p}, pre, lp.n + 1); - }else{ - // rollover to next patch from base - next = toStr({M:base.M,m:base.m,p:base.p + 1}, pre, 0); - } - }else{ - next = toStr(base, pre, 0); - } -} -console.log(next); -') - export PRERELEASE_VERSION - npm version "$PRERELEASE_VERSION" --no-git-tag-version --allow-same-version - cd ../.. - - # Commit version changes - if [[ $DRY_RUN -eq 1 ]]; then - print_status "DRY RUN: would git add/commit dev bump to v$PRERELEASE_VERSION and tag widgets-v$PRERELEASE_VERSION" - else - git add packages/widgets/package.json - git commit -m "chore(widgets): $PRERELEASE_ID release v$PRERELEASE_VERSION" || print_status "No version changes to commit (dev)." - fi - - # Create tag (remove existing if present, then create new) - if git tag -l | grep -q "^widgets-v$PRERELEASE_VERSION$"; then - print_warning "Tag widgets-v$PRERELEASE_VERSION already exists, removing it..." - git tag -d "widgets-v$PRERELEASE_VERSION" - fi - if [[ $DRY_RUN -eq 1 ]]; then - print_status "DRY RUN: would create tag widgets-v$PRERELEASE_VERSION" - else - git tag "widgets-v$PRERELEASE_VERSION" - fi - - # Temporarily rewrite package for publishing - print_status "Preparing package for publishing as @avail-project/nexus-widgets..." - cd packages/widgets - - # Backup original package.json - cp package.json package.json.backup - - # Resolve latest published core version for the same prerelease tag by time (not semver) - export PRERELEASE_ID - CORE_PUBLISHED_VERSION=$(node -e ' -const cp=require("child_process"); -function exec(cmd){try{return cp.execSync(cmd,{stdio:["pipe","pipe","ignore"]}).toString().trim();}catch(e){return "";}} -const pre=process.env.PRERELEASE_ID||"dev"; -let times={}; -try{ times=JSON.parse(exec("npm view @avail-project/nexus-core time --json")||"{}"); }catch(_){ times={}; } -let entries=Object.entries(times).filter(([v])=>new RegExp(`^\\d+\\.\\d+\\.\\d+-${pre}\\.\\d+$`).test(v)); -entries.sort((a,b)=>new Date(a[1]) - new Date(b[1])); -let latest=entries.length? entries[entries.length-1][0] : ""; -process.stdout.write(latest); -') - export CORE_PUBLISHED_VERSION - if [[ -z "$CORE_PUBLISHED_VERSION" ]]; then - print_error "@avail-project/nexus-core@$PRERELEASE_ID is not published. Please release core $PRERELEASE_ID first (./scripts/release-core.sh dev patch $PRERELEASE_ID)." - exit 1 - fi - - # Ensure deps pin @avail-project/nexus-core to published dev version; remove internal commons from deps - node -e "const fs=require('fs');const p=JSON.parse(fs.readFileSync('package.json','utf8'));p.dependencies=p.dependencies||{};if(p.dependencies['@nexus/commons']){delete p.dependencies['@nexus/commons'];}p.dependencies['@avail-project/nexus-core']=process.env.CORE_PUBLISHED_VERSION;fs.writeFileSync('package.json',JSON.stringify(p,null,2)+'\n');" - - # Bundle internal commons into dist (imports already aliased by Rollup) - print_status "Bundling internal @nexus/commons into widgets dist..." - mkdir -p dist/commons - cp -R ../commons/dist/* dist/commons/ - - # Publish to npm with prerelease tag (or pack in dry-run) - if [[ $DRY_RUN -eq 1 ]]; then - print_status "DRY RUN: npm pack (skipping publish) for @avail-project/nexus-widgets@$PRERELEASE_VERSION" - npm pack >/dev/null 2>&1 || true - else - print_status "Publishing @avail-project/nexus-widgets@$PRERELEASE_VERSION to npm ($PRERELEASE_ID tag)..." - npm publish --access public --tag $PRERELEASE_ID - # Add incremental tag (e.g., alpha-1, beta-2) matching pre-release number - INCREMENTAL_TAG=$(node -e "const v=process.env.PRERELEASE_VERSION||'';const m=v.match(/$PRERELEASE_ID\\.(\\d+)/);console.log(m ? ('$PRERELEASE_ID-' + m[1]) : '$PRERELEASE_ID')") - if [ -n "$INCREMENTAL_TAG" ] && [ "$INCREMENTAL_TAG" != "$PRERELEASE_ID" ]; then - print_status "Adding dist-tag $INCREMENTAL_TAG for @avail-project/nexus-widgets@$PRERELEASE_VERSION..." - npm dist-tag add @avail-project/nexus-widgets@$PRERELEASE_VERSION $INCREMENTAL_TAG || true - fi - fi - - # Restore original package.json - mv package.json.backup package.json - cd ../.. - - # Push changes and tags - if [[ $DRY_RUN -eq 1 ]]; then - print_status "DRY RUN: skipping git push of branch and tag widgets-v$PRERELEASE_VERSION" - else - print_status "Pushing changes to git..." - git push origin $(git branch --show-current) - git push origin "widgets-v$PRERELEASE_VERSION" - fi - - print_header "✅ Development release completed!" - print_status "🚀 @avail-project/nexus-widgets@$PRERELEASE_VERSION published successfully!" - print_status "📦 Install with: npm install @avail-project/nexus-widgets@$PRERELEASE_ID" - print_status "🎨 Includes React components for cross-chain transactions" -fi - -print_header "🎉 @avail-project/nexus-widgets release process completed successfully!" From 9ec2d03be6420721c4349354f22022d95d61675d Mon Sep 17 00:00:00 2001 From: Abhishek Date: Wed, 12 Nov 2025 15:43:48 +0400 Subject: [PATCH 03/51] fix: updated remanant fn names and docs of transfer with bridgeAndTransfer (#64) --- packages/core/README.md | 4 ++-- packages/core/sdk/index.ts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/core/README.md b/packages/core/README.md index e389e721..fff555fe 100644 --- a/packages/core/README.md +++ b/packages/core/README.md @@ -257,13 +257,13 @@ const simulation = await sdk.simulateBridge({ token: 'USDC', amount: '83.50', ch ## 🔁 Transfer Operations ```typescript -const result = await sdk.transfer({ +const result = await sdk.bridgeAndTransfer({ token: 'USDC', amount: '1.53', chainId: 42161, recipient: '0x...', }); -const simulation = await sdk.simulateTransfer({ +const simulation = await sdk.simulateBridgeAndTransfer({ token: 'USDC', amount: '1.53', chainId: 42161, diff --git a/packages/core/sdk/index.ts b/packages/core/sdk/index.ts index 1fcc6b6e..968d4fdb 100644 --- a/packages/core/sdk/index.ts +++ b/packages/core/sdk/index.ts @@ -116,7 +116,7 @@ export class NexusSDK extends CA { /** * Simulate transfer transaction to get costs and fees */ - public async simulateTransfer(params: TransferParams): Promise { + public async simulateBridgeAndTransfer(params: TransferParams): Promise { return this._simulateBridgeAndTransfer(params); } From 02ceee989d499285724ac50b4bfffb9787ad96d0 Mon Sep 17 00:00:00 2001 From: Abhishek Date: Thu, 13 Nov 2025 07:05:43 +0400 Subject: [PATCH 04/51] fix: add buffer to gas, add L1Fee where applicable (#65) * fix: add buffer to gas, add L1Fee where applicable * fix: add value & data to 0x in serialize txn --- .../sdk/ca-base/query/bridgeAndExecute.ts | 31 ++++++++++++++++--- .../core/sdk/ca-base/utils/common.utils.ts | 5 +++ 2 files changed, 32 insertions(+), 4 deletions(-) diff --git a/packages/core/sdk/ca-base/query/bridgeAndExecute.ts b/packages/core/sdk/ca-base/query/bridgeAndExecute.ts index 90339133..9e348cc7 100644 --- a/packages/core/sdk/ca-base/query/bridgeAndExecute.ts +++ b/packages/core/sdk/ca-base/query/bridgeAndExecute.ts @@ -17,7 +17,15 @@ import { BRIDGE_STEPS, BridgeStepType, } from '@nexus/commons'; -import { createPublicClient, Hex, http, PublicClient, toHex, WalletClient } from 'viem'; +import { + createPublicClient, + Hex, + http, + PublicClient, + serializeTransaction, + toHex, + WalletClient, +} from 'viem'; import { createExplorerTxURL, divDecimals, @@ -27,6 +35,8 @@ import { generateStateOverride, switchChain, erc20GetAllowance, + percentageAdditionToBigInt, + getL1Fee, } from '../utils'; import { packERC20Approve } from '../swap/utils'; import { BackendSimulationClient } from 'integrations/tenderly'; @@ -83,7 +93,9 @@ class BridgeAndExecuteQuery { chainId: dstChain.id, tokenAddress: token.contractAddress, tokenSymbol: execute.tokenApproval?.token ?? 'ETH', - }); + }).then(({ gasUsed }) => ({ + gasUsed: percentageAdditionToBigInt(gasUsed, 0.1), + })); const determineGasFee = params.execute.gasPrice ? Promise.resolve({ @@ -93,10 +105,20 @@ class BridgeAndExecuteQuery { : dstPublicClient.estimateFeesPerGas(); // 5. simulate approval(?) and execution + fetch gasPrice + fetch unified balance - const [{ gasUsed }, gasFeeEstimate, balances] = await Promise.all([ + const [{ gasUsed }, gasFeeEstimate, balances, l1Fee] = await Promise.all([ determineGasUsed, determineGasFee, this.getUnifiedBalances(), + getL1Fee( + dstChain, + serializeTransaction({ + chainId: dstChain.id, + data: execute.data ?? '0x', + value: execute.value, + to: execute.to, + type: 'eip1559', + }), + ), ]); const gasPrice = gasFeeEstimate.maxFeePerGas ?? gasFeeEstimate.gasPrice ?? 0n; @@ -106,13 +128,14 @@ class BridgeAndExecuteQuery { }); } - const gasFee = gasUsed * gasPrice; + const gasFee = gasUsed * (gasPrice + l1Fee); logger.debug('BridgeAndExecute:3', { gasUsed, gasFeeEstimate, gasPrice, balances, + l1Fee, }); // 6. Determine gas or token needed via bridge diff --git a/packages/core/sdk/ca-base/utils/common.utils.ts b/packages/core/sdk/ca-base/utils/common.utils.ts index ccccd823..1bdc882b 100644 --- a/packages/core/sdk/ca-base/utils/common.utils.ts +++ b/packages/core/sdk/ca-base/utils/common.utils.ts @@ -817,6 +817,10 @@ async function waitForTronDepositTxConfirmation( throw new Error(`⏰ Timeout: Transaction not confirmed within ${timeout / 1000}s`); } +function percentageAdditionToBigInt(base: bigint, percentage: number) { + return base + BigInt(new Decimal(base).mul(percentage).toFixed(0)); +} + async function waitForTronApprovalTxConfirmation( amount: bigint, owner: Hex, @@ -912,6 +916,7 @@ const retrieveSIWESignatureFromLocalStorage = (address: Hex) => { }; export { + percentageAdditionToBigInt, retrieveSIWESignatureFromLocalStorage, storeSIWESignatureToLocalStorage, retrieveAddress, From aad91b885955eec11c1eecf4ec802cdfec4ee211 Mon Sep 17 00:00:00 2001 From: Abhishek Date: Thu, 13 Nov 2025 12:27:45 +0400 Subject: [PATCH 05/51] fix: added retries on rff collection, rebuild intent on fee issue (#62) * fix: added retries on rff collection, rebuild intent on fee issue * fix: breaking response loop in status:255 of create-rff * fix: added better error handling --- packages/core/sdk/ca-base/errors.ts | 8 +- packages/core/sdk/ca-base/nexusError.ts | 1 + .../sdk/ca-base/requestHandlers/bridge.ts | 91 +++++++---- packages/core/sdk/ca-base/utils/api.utils.ts | 141 +++++++++++------- 4 files changed, 160 insertions(+), 81 deletions(-) diff --git a/packages/core/sdk/ca-base/errors.ts b/packages/core/sdk/ca-base/errors.ts index da1af450..48a35566 100644 --- a/packages/core/sdk/ca-base/errors.ts +++ b/packages/core/sdk/ca-base/errors.ts @@ -75,7 +75,12 @@ export const Errors = { userRejectedSIWESignature: () => createError(ERROR_CODES.USER_DENIED_SIWE_SIGNATURE, `User rejected SIWE signature.`), - vscError: (msg: string) => createError(ERROR_CODES.INTERNAL_ERROR, `VSC: ${msg}`), + vscError: (msg: string, data?: unknown) => + createError(ERROR_CODES.INTERNAL_ERROR, `VSC: ${msg}`, { + details: { + data, + }, + }), cosmosError: (msg: string) => createError(ERROR_CODES.INTERNAL_ERROR, `COSMOS: ${msg}`), gasPriceError: (result: unknown) => @@ -93,4 +98,5 @@ export const Errors = { ), simulationError: (msg: string) => createError(ERROR_CODES.SIMULATION_FAILED, `tenderly simulation failed: ${msg}`), + rFFFeeExpired: () => createError(ERROR_CODES.RFF_FEE_EXPIRED, `fee is not adequate`), }; diff --git a/packages/core/sdk/ca-base/nexusError.ts b/packages/core/sdk/ca-base/nexusError.ts index 51d55411..ceefca9d 100644 --- a/packages/core/sdk/ca-base/nexusError.ts +++ b/packages/core/sdk/ca-base/nexusError.ts @@ -46,6 +46,7 @@ export const ERROR_CODES = { CONNECT_ACCOUNT_FAILED: 'CONNECT_ACCOUNT_FAILED', VAULT_CONTRACT_NOT_FOUND: 'VAULT_CONTRACT_NOT_FOUND', SLIPPAGE_EXCEEDED_ALLOWANCE: 'SLIPPAGE_EXCEEDED_ALLOWANCE', + RFF_FEE_EXPIRED: 'RFF_FEE_EXPIRED', } as const; export type ErrorCode = (typeof ERROR_CODES)[keyof typeof ERROR_CODES]; diff --git a/packages/core/sdk/ca-base/requestHandlers/bridge.ts b/packages/core/sdk/ca-base/requestHandlers/bridge.ts index 420f8089..662cdab2 100644 --- a/packages/core/sdk/ca-base/requestHandlers/bridge.ts +++ b/packages/core/sdk/ca-base/requestHandlers/bridge.ts @@ -73,6 +73,7 @@ import { } from '../utils'; import { TronWeb } from 'tronweb'; import { Errors } from '../errors'; +import { ERROR_CODES, NexusError } from '../nexusError'; type Params = { recipient?: Hex; @@ -250,7 +251,9 @@ class BridgeHandler { return sources; } - public execute = async () => { + public execute = async ( + shouldRetryOnFailure = true, + ): Promise<{ explorerURL: string; intentID: Long }> => { let intent = await this.buildIntent(this.params.sourceChains); const allowances = await getAllowances(intent.allSources, this.options.chainList); @@ -302,8 +305,35 @@ class BridgeHandler { await this.waitForOnAllowanceHook(insufficientAllowanceSources); console.timeEnd('process:AllowanceHook'); - // Step 6: process intent - return this.executeIntent(intent); + // Step 6: Process intent + logger.debug('intent', { intent }); + + const response = await this.processRFF(intent); + if (response.retry) { + logger.debug('rff fee expired, going to rebuild intent...'); + if (shouldRetryOnFailure) { + // If fee expired go back and rebuild intent if first time + return this.execute(false); + } else { + // Something else is wrong, retries probably wont fix it - so just throw + throw Errors.rFFFeeExpired(); + } + } + + const { explorerURL, intentID, requestHash, waitForDoubleCheckTx } = response; + + // Step 7: Wait for fill + storeIntentHashToStore(this.options.evm.address, intentID.toNumber()); + await this.waitForFill(requestHash, intentID, waitForDoubleCheckTx); + removeIntentHashFromStore(this.options.evm.address, intentID); + + this.markStepDone(BRIDGE_STEPS.INTENT_FULFILLED); + + if (this.params.dstChain.universe === Universe.ETHEREUM) { + await switchChain(this.options.evm.client, this.params.dstChain); + } + + return { explorerURL, intentID }; }; private async waitForFill( @@ -340,26 +370,16 @@ class BridgeHandler { await Promise.race(promisesToRace); } - private async executeIntent(intent: Intent) { - logger.debug('intent', { intent }); - - const { explorerURL, intentID, requestHash, waitForDoubleCheckTx } = - await this.processRFF(intent); - - storeIntentHashToStore(this.options.evm.address, intentID.toNumber()); - await this.waitForFill(requestHash, intentID, waitForDoubleCheckTx); - removeIntentHashFromStore(this.options.evm.address, intentID); - - this.markStepDone(BRIDGE_STEPS.INTENT_FULFILLED); - - if (this.params.dstChain.universe === Universe.ETHEREUM) { - await switchChain(this.options.evm.client, this.params.dstChain); - } - - return { explorerURL, intentID }; - } - - private async processRFF(intent: Intent) { + private async processRFF(intent: Intent): Promise< + | { retry: true } + | { + retry: false; + explorerURL: string; + intentID: Long; + requestHash: Hex; + waitForDoubleCheckTx: () => any; + } + > { const { msgBasicCosmos, omniversalRFF, signatureData, sources, universes } = await createRFFromIntent(intent, this.options, this.params.dstChain.universe); @@ -551,12 +571,24 @@ class BridgeHandler { message: 'going to create RFF', tokenCollections, }); - await vscCreateRFF( - this.options.networkConfig.VSC_DOMAIN, - intentID, - this.markStepDone, - tokenCollections, - ); + try { + await vscCreateRFF( + this.options.networkConfig.VSC_DOMAIN, + intentID, + this.markStepDone, + tokenCollections, + ); + } catch (e) { + logger.debug('vscCreateRFF', { + 'e instanceof NexusError?': e instanceof NexusError, + error: e, + }); + if (e instanceof NexusError && e.code === ERROR_CODES.RFF_FEE_EXPIRED) { + // Send back to process again + return { retry: true }; + } + throw e; + } } else { logger.debug('processRFF', { message: 'going to publish RFF', @@ -573,6 +605,7 @@ class BridgeHandler { } return { + retry: false, explorerURL, intentID, requestHash: destinationSigData.requestHash, diff --git a/packages/core/sdk/ca-base/utils/api.utils.ts b/packages/core/sdk/ca-base/utils/api.utils.ts index 791e10af..d6d836f5 100644 --- a/packages/core/sdk/ca-base/utils/api.utils.ts +++ b/packages/core/sdk/ca-base/utils/api.utils.ts @@ -30,6 +30,7 @@ import { minutesToMs, } from './common.utils'; import { Errors } from '../errors'; +import { remove, retry } from 'es-toolkit'; const logger = getLogger(); @@ -463,18 +464,29 @@ const vscCreateSponsoredApprovals = async ( }; type VSCCreateRFFResponse = + // Global | { - error: string; + error: true; errored: true; - idx: number; - status: 26; + code: 0x13; // Fee changed + } + | { + error: true; + errored: true; + code: 0x12; // Already deposited everything } + | { status: 0xff; idx: 0; errored: false } // transmission complete, if no global error + // Local | { errored: false; idx: number; - status: 16; + status: 0x10; // Success } - | { status: 255 }; + | { + errored: true; + idx: number; + status: 0x1a; // could not collect + }; const vscCreateRFF = async ( vscDomain: string, @@ -482,54 +494,81 @@ const vscCreateRFF = async ( msd: (s: BridgeStepType) => void, expectedCollectionIndexes: number[], ) => { - const receivedCollectionsACKs = []; - const connection = connect(new URL('/api/v1/create-rff', getVSCURL(vscDomain, 'wss')).toString()); - await connection.connected(); - - logger.debug('vscCreateRFF', { - expectedCollectionIndexes, - }); - - try { - connection.socket.send(pack({ id: id.toNumber() })); - - for await (const resp of connection.source) { - const data: VSCCreateRFFResponse = unpack(resp); - - logger.debug('vscCreateRFF:response', { data }); - - if (data.status === 255) { - if (expectedCollectionIndexes.length === receivedCollectionsACKs.length) { - msd(BRIDGE_STEPS.INTENT_COLLECTION_COMPLETE); - break; - } else { - logger.debug('(vsc)create-rff:collections failed', { - expectedCollectionIndexes, - receivedCollectionsACKs, - }); - throw Errors.vscError('create-rff: collections failed'); - } - } else if (data.status === 16) { - if (expectedCollectionIndexes.includes(data.idx)) { - receivedCollectionsACKs.push(data.idx); - } - msd( - BRIDGE_STEPS.INTENT_COLLECTION( - receivedCollectionsACKs.length, - expectedCollectionIndexes.length, - ), - ); - } else { - if (expectedCollectionIndexes.includes(data.idx)) { - throw Errors.vscError(`create-rff: ${data.error}`); - } else { - logger.debug('vscCreateRFF:ExpectedError:ignore', { data }); + const controller = new AbortController(); + const collectionIndexes = expectedCollectionIndexes.slice(); + const receivedCollectionsACKs: number[] = []; + await retry( + async () => { + const connection = connect( + new URL('/api/v1/create-rff', getVSCURL(vscDomain, 'wss')).toString(), + ); + try { + await connection.connected(); + connection.socket.send(pack({ id: id.toNumber() })); + responseLoop: for await (const resp of connection.source) { + const data: VSCCreateRFFResponse = unpack(resp); + + logger.debug('vscCreateRFF:response', { data }); + if ('idx' in data) { + // local msg + switch (data.status) { + // Will be called at the end of all calls, regardless of status + case 0xff: { + if (collectionIndexes.length === 0) { + msd(BRIDGE_STEPS.INTENT_COLLECTION_COMPLETE); + break responseLoop; + } else { + logger.debug('(vsc)create-rff:collections failed', { + expectedCollectionIndexes, + receivedCollectionsACKs, + }); + throw Errors.vscError('create-rff: some collections failed, retrying.'); + } + } + // Collection successful for a chain + case 0x1a: { + if (collectionIndexes.includes(data.idx)) { + receivedCollectionsACKs.push(data.idx); + remove(collectionIndexes, (d) => d === data.idx); + } + msd( + BRIDGE_STEPS.INTENT_COLLECTION( + receivedCollectionsACKs.length, + expectedCollectionIndexes.length, + ), + ); + break; + } + + // Collection failed or is not applicable(say for native) + default: { + if (collectionIndexes.includes(data.idx)) { + logger.debug(`vsc:create-rff:failed`, { data }); + } else { + logger.debug('vsc:create-rff:expectedError:ignore', { data }); + } + } + } + } else { + if (data.code === 0x13) { + controller.abort(Errors.rFFFeeExpired()); + throw Errors.rFFFeeExpired(); + } else if (data.code === 0x12) { + break; + } else { + throw Errors.vscError('create-rff: unhandled error', data); + } + } } + } finally { + connection.close(); } - } - } finally { - connection.close(); - } + }, + { + retries: 3, + signal: controller.signal, + }, + ); }; const checkIntentFilled = async (intentID: Long, grpcURL: string) => { From ed23e62a1782a91842e537747063f0289dc07619 Mon Sep 17 00:00:00 2001 From: Abhishek Date: Thu, 13 Nov 2025 15:19:57 +0400 Subject: [PATCH 06/51] fix: added waiting for sponsored approval hashes (#67) --- .../sdk/ca-base/requestHandlers/bridge.ts | 19 ++- packages/core/sdk/ca-base/utils/api.utils.ts | 25 ++-- .../core/sdk/ca-base/utils/contract.utils.ts | 115 +----------------- 3 files changed, 31 insertions(+), 128 deletions(-) diff --git a/packages/core/sdk/ca-base/requestHandlers/bridge.ts b/packages/core/sdk/ca-base/requestHandlers/bridge.ts index 662cdab2..499d5640 100644 --- a/packages/core/sdk/ca-base/requestHandlers/bridge.ts +++ b/packages/core/sdk/ca-base/requestHandlers/bridge.ts @@ -773,10 +773,25 @@ class BridgeHandler { logger.debug('setAllowances:sponsoredApprovals', { sponsoredApprovalParams, }); - await vscCreateSponsoredApprovals( + const approvalHashes = await vscCreateSponsoredApprovals( this.options.networkConfig.VSC_DOMAIN, sponsoredApprovalParams, - this.markStepDone, + ); + + await Promise.all( + approvalHashes.map(async (approval) => { + const chain = this.options.chainList.getChainByID(approval.chainId); + if (!chain) { + throw Errors.chainNotFound(approval.chainId); + } + + const publicClient = createPublicClientWithFallback(chain); + await waitForTxReceipt(approval.hash, publicClient); + BRIDGE_STEPS.ALLOWANCE_APPROVAL_MINED({ + id: approval.chainId, + }); + return; + }), ); } } catch (e) { diff --git a/packages/core/sdk/ca-base/utils/api.utils.ts b/packages/core/sdk/ca-base/utils/api.utils.ts index d6d836f5..248ea340 100644 --- a/packages/core/sdk/ca-base/utils/api.utils.ts +++ b/packages/core/sdk/ca-base/utils/api.utils.ts @@ -10,7 +10,7 @@ import Decimal from 'decimal.js'; import { connect } from 'it-ws/client'; import Long from 'long'; import { pack, unpack } from 'msgpackr'; -import { bytesToBigInt, bytesToNumber, toHex } from 'viem'; +import { bytesToBigInt, bytesToNumber, Hex, toHex } from 'viem'; import { BRIDGE_STEPS, BridgeStepType, @@ -419,7 +419,6 @@ type CreateSponsoredApprovalResponse = const vscCreateSponsoredApprovals = async ( vscDomain: string, input: SponsoredApprovalDataArray, - msd?: (s: BridgeStepType) => void, ) => { const connection = connect( new URL('/api/v1/create-sponsored-approvals', getVSCURL(vscDomain, 'wss')).toString(), @@ -427,10 +426,11 @@ const vscCreateSponsoredApprovals = async ( await connection.connected(); + const approvalHashes: { chainId: number; hash: Hex }[] = []; + try { connection.socket.send(pack(input)); - let count = 0; for await (const resp of connection.source) { const data: CreateSponsoredApprovalResponse = unpack(resp); @@ -444,20 +444,19 @@ const vscCreateSponsoredApprovals = async ( throw Errors.vscError(`create-sponsored-approvals: ${data.error}`); } - if (msd) { - msd( - BRIDGE_STEPS.ALLOWANCE_APPROVAL_MINED({ - id: bytesToNumber(input[data.part_idx].chain_id), - }), - ); - } + const inputData = input[data.part_idx]; - count += 1; - if (count == input.length) { + approvalHashes.push({ + chainId: bytesToNumber(inputData.chain_id), + hash: toHex(data.tx_hash), + }); + + if (approvalHashes.length == input.length) { break; } } - return 'ok'; + + return approvalHashes; } finally { connection.close(); } diff --git a/packages/core/sdk/ca-base/utils/contract.utils.ts b/packages/core/sdk/ca-base/utils/contract.utils.ts index f7d0c0f9..51f11394 100644 --- a/packages/core/sdk/ca-base/utils/contract.utils.ts +++ b/packages/core/sdk/ca-base/utils/contract.utils.ts @@ -1,11 +1,4 @@ -import { - ChaindataMap, - Currency, - OmniversalChainID, - PermitCreationError, - PermitVariant, - Universe, -} from '@avail-project/ca-common'; +import { Currency, PermitCreationError, PermitVariant } from '@avail-project/ca-common'; import { ERC20ABI as ERC20ABIC } from '@avail-project/ca-common'; import { CHAIN_IDS } from 'fuels'; import { @@ -19,12 +12,9 @@ import { getContract, Hex, hexToBigInt, - hexToBytes, http, - JsonRpcAccount, maxUint256, pad, - parseSignature, PublicClient, WalletClient, WebSocketTransport, @@ -39,13 +29,10 @@ import { ChainListType, Chain, EVMTransaction, - NetworkConfig, - SponsoredApprovalData, GetAllowanceParams, SetAllowanceParams, } from '@nexus/commons'; -import { vscCreateSponsoredApprovals } from './api.utils'; -import { convertTo32Bytes, equalFold, minutesToMs } from './common.utils'; +import { equalFold, minutesToMs } from './common.utils'; const logger = getLogger(); @@ -208,103 +195,6 @@ const getTokenTxFunction = (data: `0x${string}`) => { } }; -const setAllowances = async ( - tokenContractAddresses: Array<`0x${string}`>, - client: WalletClient, - networkConfig: NetworkConfig, - chainList: ChainListType, - chain: Chain, - amount: bigint, -) => { - const vaultAddr = chainList.getVaultContractAddress(chain.id); - const p = []; - const address = (await client.getAddresses())[0]; - - const chainId = new OmniversalChainID(Universe.ETHEREUM, chain.id); - const chainDatum = ChaindataMap.get(chainId); - if (!chainDatum) { - throw Errors.internal(`chain data not found for chain ${chainId}`); - } - - const account: JsonRpcAccount = { - address, - type: 'json-rpc', - }; - const publicClient = createPublicClientWithFallback(chain); - - const sponsoredApprovalParams: SponsoredApprovalData = { - address: hexToBytes( - pad(address, { - dir: 'left', - size: 32, - }), - ), - chain_id: chainDatum.ChainID32, - operations: [], - universe: chainDatum.Universe, - }; - - for (const addr of tokenContractAddresses) { - const currency = chainDatum.CurrencyMap.get(convertTo32Bytes(addr)); - if (!currency) { - throw Errors.internal(`currency not found for token ${addr}`); - } - - if (currency.permitVariant === PermitVariant.Unsupported) { - const hash = await erc20SetAllowance( - { - amount, - chain, - contractAddress: addr, - owner: address, - spender: vaultAddr, - }, - client, - ); - p.push( - (async function () { - const result = await publicClient.waitForTransactionReceipt({ - confirmations: 2, - hash, - }); - if (result.status === 'reverted') { - throw new Error('setAllowance failed with tx revert'); - } - })(), - ); - } else { - const signed = parseSignature( - await signPermitForAddressAndValue( - currency, - client, - publicClient, - account, - vaultAddr, - amount, - ), - ); - sponsoredApprovalParams.operations.push({ - sig_r: hexToBytes(signed.r), - sig_s: hexToBytes(signed.s), - sig_v: signed.yParity < 27 ? signed.yParity + 27 : signed.yParity, - token_address: currency.tokenAddress, - value: convertTo32Bytes(amount), - variant: currency.permitVariant === PermitVariant.PolygonEMT ? 2 : 1, - }); - } - } - - if (p.length) { - await Promise.all(p); - } - - if (sponsoredApprovalParams.operations.length) { - await vscCreateSponsoredApprovals(networkConfig.VSC_DOMAIN, [sponsoredApprovalParams]); - } - - return; -}; - const DEFAULT_GAS_ORACLE_ADDRESS = '0x420000000000000000000000000000000000000F'; const L1_GAS_ORACLES: Record = { @@ -578,7 +468,6 @@ export { getTokenTxFunction, isEVMTx, requestTimeout, - setAllowances, signPermitForAddressAndValue, switchChain, waitForIntentFulfilment, From 75fb464b1d10731cc917319fb33732f93db3bf86 Mon Sep 17 00:00:00 2001 From: Abhishek Date: Thu, 13 Nov 2025 16:07:08 +0400 Subject: [PATCH 07/51] fix: removed using pnpm workspaces (#68) * fix: removed using pnpm workspaces, changed all the references of @nexus/commons * fix: readded author --- README.md | 468 +- package-lock.json | 6323 +++++++++++++++++ package.json | 82 +- packages/commons/package.json | 34 - packages/commons/rollup.config.mjs | 62 - packages/commons/tsconfig.json | 16 - packages/core/README.md | 421 -- packages/core/package.json | 72 - packages/core/tsconfig.json | 13 - pnpm-lock.yaml | 6157 ---------------- pnpm-workspace.yaml | 2 - .../rollup.config.mjs => rollup.config.mjs | 34 +- scripts/README.md | 5 - {packages => src}/commons/constants/index.ts | 0 {packages => src}/commons/index.ts | 0 .../commons/types/bridge-steps.ts | 0 .../commons/types/contract-types.ts | 0 {packages => src}/commons/types/index.ts | 0 .../commons/types/integration-types.ts | 0 .../commons/types/service-types.ts | 0 {packages => src}/commons/types/swap-steps.ts | 0 {packages => src}/commons/types/swap-types.ts | 0 {packages => src}/commons/utils/format.ts | 0 {packages => src}/commons/utils/index.ts | 0 {packages => src}/commons/utils/logger.ts | 0 {packages/core => src}/index.ts | 6 +- .../core => src}/integrations/tenderly.ts | 4 +- {packages/core => src}/integrations/types.ts | 0 .../core => src}/sdk/ca-base/abi/erc20.ts | 0 .../core => src}/sdk/ca-base/abi/gasOracle.ts | 0 .../core => src}/sdk/ca-base/abi/misc.ts | 0 .../core => src}/sdk/ca-base/abi/vault.ts | 0 {packages/core => src}/sdk/ca-base/ca.ts | 9 +- {packages/core => src}/sdk/ca-base/chains.ts | 2 +- {packages/core => src}/sdk/ca-base/config.ts | 2 +- .../core => src}/sdk/ca-base/constants.ts | 0 {packages/core => src}/sdk/ca-base/errors.ts | 0 {packages/core => src}/sdk/ca-base/index.ts | 2 +- .../core => src}/sdk/ca-base/nexusError.ts | 0 .../sdk/ca-base/query/bridgeAndExecute.ts | 4 +- .../sdk/ca-base/query/bridgeAndTransfer.ts | 2 +- .../core => src}/sdk/ca-base/query/index.ts | 0 .../sdk/ca-base/requestHandlers/bridge.ts | 7 +- .../sdk/ca-base/requestHandlers/bridgeMax.ts | 2 +- .../sdk/ca-base/requestHandlers/helpers.ts | 2 +- {packages/core => src}/sdk/ca-base/steps.ts | 2 +- .../core => src}/sdk/ca-base/swap/abi.ts | 0 .../sdk/ca-base/swap/calibur.abi.ts | 0 .../sdk/ca-base/swap/constants.ts | 0 .../core => src}/sdk/ca-base/swap/data.ts | 2 +- .../core => src}/sdk/ca-base/swap/errors.ts | 0 {packages/core => src}/sdk/ca-base/swap/ob.ts | 9 +- .../core => src}/sdk/ca-base/swap/rff.ts | 4 +- .../core => src}/sdk/ca-base/swap/route.ts | 6 +- .../core => src}/sdk/ca-base/swap/sbc.ts | 2 +- .../core => src}/sdk/ca-base/swap/swap.ts | 4 +- .../core => src}/sdk/ca-base/swap/utils.ts | 11 +- .../sdk/ca-base/utils/api.utils.ts | 2 +- .../sdk/ca-base/utils/balance.utils.ts | 6 +- .../sdk/ca-base/utils/common.utils.ts | 4 +- .../sdk/ca-base/utils/contract.utils.ts | 4 +- .../sdk/ca-base/utils/cosmos.utils.ts | 2 +- .../core => src}/sdk/ca-base/utils/index.ts | 0 .../sdk/ca-base/utils/rff.utils.ts | 2 +- .../sdk/ca-base/utils/tron.utils.ts | 0 {packages/core => src}/sdk/index.ts | 8 +- {packages/core => src}/sdk/utils.ts | 2 +- tsconfig.json | 15 +- 68 files changed, 6798 insertions(+), 7018 deletions(-) create mode 100644 package-lock.json delete mode 100644 packages/commons/package.json delete mode 100644 packages/commons/rollup.config.mjs delete mode 100644 packages/commons/tsconfig.json delete mode 100644 packages/core/README.md delete mode 100644 packages/core/package.json delete mode 100644 packages/core/tsconfig.json delete mode 100644 pnpm-lock.yaml delete mode 100644 pnpm-workspace.yaml rename packages/core/rollup.config.mjs => rollup.config.mjs (74%) rename {packages => src}/commons/constants/index.ts (100%) rename {packages => src}/commons/index.ts (100%) rename {packages => src}/commons/types/bridge-steps.ts (100%) rename {packages => src}/commons/types/contract-types.ts (100%) rename {packages => src}/commons/types/index.ts (100%) rename {packages => src}/commons/types/integration-types.ts (100%) rename {packages => src}/commons/types/service-types.ts (100%) rename {packages => src}/commons/types/swap-steps.ts (100%) rename {packages => src}/commons/types/swap-types.ts (100%) rename {packages => src}/commons/utils/format.ts (100%) rename {packages => src}/commons/utils/index.ts (100%) rename {packages => src}/commons/utils/logger.ts (100%) rename {packages/core => src}/index.ts (93%) rename {packages/core => src}/integrations/tenderly.ts (98%) rename {packages/core => src}/integrations/types.ts (100%) rename {packages/core => src}/sdk/ca-base/abi/erc20.ts (100%) rename {packages/core => src}/sdk/ca-base/abi/gasOracle.ts (100%) rename {packages/core => src}/sdk/ca-base/abi/misc.ts (100%) rename {packages/core => src}/sdk/ca-base/abi/vault.ts (100%) rename {packages/core => src}/sdk/ca-base/ca.ts (99%) rename {packages/core => src}/sdk/ca-base/chains.ts (99%) rename {packages/core => src}/sdk/ca-base/config.ts (97%) rename {packages/core => src}/sdk/ca-base/constants.ts (100%) rename {packages/core => src}/sdk/ca-base/errors.ts (100%) rename {packages/core => src}/sdk/ca-base/index.ts (93%) rename {packages/core => src}/sdk/ca-base/nexusError.ts (100%) rename {packages/core => src}/sdk/ca-base/query/bridgeAndExecute.ts (99%) rename {packages/core => src}/sdk/ca-base/query/bridgeAndTransfer.ts (97%) rename {packages/core => src}/sdk/ca-base/query/index.ts (100%) rename {packages/core => src}/sdk/ca-base/requestHandlers/bridge.ts (99%) rename {packages/core => src}/sdk/ca-base/requestHandlers/bridgeMax.ts (95%) rename {packages/core => src}/sdk/ca-base/requestHandlers/helpers.ts (91%) rename {packages/core => src}/sdk/ca-base/steps.ts (98%) rename {packages/core => src}/sdk/ca-base/swap/abi.ts (100%) rename {packages/core => src}/sdk/ca-base/swap/calibur.abi.ts (100%) rename {packages/core => src}/sdk/ca-base/swap/constants.ts (100%) rename {packages/core => src}/sdk/ca-base/swap/data.ts (99%) rename {packages/core => src}/sdk/ca-base/swap/errors.ts (100%) rename {packages/core => src}/sdk/ca-base/swap/ob.ts (99%) rename {packages/core => src}/sdk/ca-base/swap/rff.ts (99%) rename {packages/core => src}/sdk/ca-base/swap/route.ts (99%) rename {packages/core => src}/sdk/ca-base/swap/sbc.ts (99%) rename {packages/core => src}/sdk/ca-base/swap/swap.ts (99%) rename {packages/core => src}/sdk/ca-base/swap/utils.ts (99%) rename {packages/core => src}/sdk/ca-base/utils/api.utils.ts (99%) rename {packages/core => src}/sdk/ca-base/utils/balance.utils.ts (98%) rename {packages/core => src}/sdk/ca-base/utils/common.utils.ts (99%) rename {packages/core => src}/sdk/ca-base/utils/contract.utils.ts (99%) rename {packages/core => src}/sdk/ca-base/utils/cosmos.utils.ts (99%) rename {packages/core => src}/sdk/ca-base/utils/index.ts (100%) rename {packages/core => src}/sdk/ca-base/utils/rff.utils.ts (99%) rename {packages/core => src}/sdk/ca-base/utils/tron.utils.ts (100%) rename {packages/core => src}/sdk/index.ts (97%) rename {packages/core => src}/sdk/utils.ts (98%) diff --git a/README.md b/README.md index 1ecd52c8..fff555fe 100644 --- a/README.md +++ b/README.md @@ -1,163 +1,421 @@ -# Nexus SDK +# @avail-project/nexus/core -A powerful TypeScript SDK for cross-chain operations, token bridging, and unified balance management across multiple EVM chains. +A **headless TypeScript SDK** for **cross-chain operations**, **token bridging**, **swapping**, and **unified balance management** — built for backends, CLIs, and custom UI integrations. -## Packages +> ⚡ Powering next-generation cross-chain apps with a single interface. -This monorepo contains two main packages: +--- -### [@avail-project/nexus-core](./packages/core/) - -**Headless SDK for cross-chain operations** - -- No React dependencies -- Direct chain abstraction integration +## 📦 Installation ```bash npm install @avail-project/nexus-core ``` -[📖 Core Documentation](./packages/core/README.md) +--- + +## 🚀 Quick Start + +```typescript +import { NexusSDK, NEXUS_EVENTS } from '@avail-project/nexus-core'; + +// Initialize SDK +const sdk = new NexusSDK({ network: 'mainnet' }); +await sdk.initialize(provider); // Your EVM-compatible wallet provider + +// (Optional) Add TRON support +const tronLinkAdapter = new TronLinkAdapter(); +sdk.addTron(tronLinkAdapter); + +// --------------------------- +// 1️⃣ Get unified balances +// --------------------------- +const balances = await sdk.getUnifiedBalances(false); // false = CA balances only +console.log('Balances:', balances); + +// --------------------------- +// 2️⃣ Bridge tokens +// --------------------------- +const bridgeResult = await sdk.bridge( + { + token: 'USDC', + amount: "1.5", + recipient: '0x...' // Optional + chainId: 137, // Polygon + }, + { + onEvent: (event) => { + if (event.name === NEXUS_EVENTS.STEPS_LIST) console.log('Bridge steps:', event.args); + if (event.name === NEXUS_EVENTS.STEP_COMPLETE) console.log('Step completed:', event.args); + }, + }, +); + +// --------------------------- +// 3️⃣ Transfer tokens +// --------------------------- +const transferResult = await sdk.bridgeAndTransfer( + { + token: 'ETH', + amount: "1.5", + chainId: 1, // Ethereum + recipient: '0x742d35Cc6634C0532925a3b8D4C9db96c4b4Db45', + }, + { + onEvent: (event) => { + if (event.name === NEXUS_EVENTS.STEPS_LIST) console.log('Transfer steps:', event.args); + if (event.name === NEXUS_EVENTS.STEP_COMPLETE) console.log('Step completed:', event.args); + }, + }, +); + +// --------------------------- +// 4️⃣ Execute a contract +// --------------------------- +const executeResult = await sdk.execute( + { + to: '0x...', + value: 0n, + data: '0x...', + tokenApproval: { token: 'USDC', amount: 10000n }, + }, + { + onEvent: (event) => { + if (event.name === NEXUS_EVENTS.STEPS_LIST) console.log('Execute steps:', event.args); + if (event.name === NEXUS_EVENTS.STEP_COMPLETE) console.log('Step completed:', event.args); + }, + }, +); + +// --------------------------- +// 5️⃣ Bridge and Execute +// --------------------------- +const bridgeAndExecuteResult = await sdk.bridgeAndExecute( + { + token: 'USDC', + amount: 100_000_000n, + toChainId: 1, + sourceChains: [8453], + execute: { + to: '0x...', + data: '0x...', + tokenApproval: { token: 'USDC', amount: 100_000_000n }, + }, + }, + { + onEvent: (event) => { + if (event.name === NEXUS_EVENTS.STEPS_LIST) console.log('Bridge+Execute steps:', event.args); + if (event.name === NEXUS_EVENTS.STEP_COMPLETE) console.log('Step completed:', event.args); + }, + }, +); + +// --------------------------- +// 6️⃣ Swap tokens +// --------------------------- +const swapResult = await sdk.swapWithExactIn( + { + from: [ + { chainId: 10, amount: 1_000_000n, tokenAddress: '0x...' }, + ], + toChainId: 8453, + toTokenAddress: '0x...', + }, + { + onEvent: (event) => console.log('Swap event:', event), + }, +); + +``` + +--- -## Supported Networks +## ✨ Core Features -### Mainnet Chains +- **Cross-chain bridging** — Move tokens seamlessly across 16+ chains. +- **Cross-chain swaps** — Execute EXACT_IN and EXACT_OUT swaps between any supported networks. +- **Unified balances** — Aggregate user assets and balances across all connected chains. +- **Optimized transfers** — Automatically choose the most efficient transfer route. +- **Contract execution** — Call smart contracts with automatic bridging and funding logic. +- **Transaction simulation** — Estimate gas, fees, and required approvals before sending. +- **Complete testnet coverage** — Full multi-chain test environment. +- **Comprehensive utilities** — Address, token, and chain helpers built in. -| Network | Chain ID | Native Currency | Status | -| --------- | -------- | --------------- | ------ | -| Ethereum | 1 | ETH | ✅ | -| Optimism | 10 | ETH | ✅ | -| Polygon | 137 | MATIC | ✅ | -| Arbitrum | 42161 | ETH | ✅ | -| Avalanche | 43114 | AVAX | ✅ | -| Base | 8453 | ETH | ✅ | -| Scroll | 534352 | ETH | ✅ | -| Sophon | 50104 | SOPH | ✅ | -| Kaia | 8217 | KAIA | ✅ | -| BNB | 56 | BNB | ✅ | -| HyperEVM | 999 | HYPE | ✅ | +--- -**Testnet Chains:** +## 🧠 Smart Optimizations -| Network | Chain ID | Native Currency | Status | -| ---------------- | -------- | --------------- | ------ | -| Optimism Sepolia | 11155420 | ETH | ✅ | -| Polygon Amoy | 80002 | MATIC | ✅ | -| Arbitrum Sepolia | 421614 | ETH | ✅ | -| Base Sepolia | 84532 | ETH | ✅ | -| Sepolia | 11155111 | ETH | ✅ | -| Monad Testnet | 10143 | MON | ✅ | +### 🔁 Bridge Skip Optimization -## Supported Tokens +During **bridge-and-execute** operations, the SDK checks whether sufficient funds already exist on the destination chain: -| Token | Networks | -| ----- | -------------- | -| ETH | All EVM chains | -| USDC | All supported | -| USDT | All supported | +- **Balance detection** — Verifies token and gas availability. +- **Integrated gas supply** — Provides gas alongside bridged tokens. +- **Adaptive bridging** — Skips unnecessary bridging or transfers only the shortfall. +- **Seamless fallback** — Uses chain abstraction if local funds are insufficient. -## 🚀 Quick Examples +### ⚡ Direct Transfer Optimization -### Headless SDK +For transfers, the SDK automatically chooses the most efficient execution path: + +- **Local balance checking** — Confirms token and gas availability on the target chain. +- **Direct EVM transfers** — Uses native transfers where possible (faster, cheaper). +- **Chain abstraction fallback** — Uses CA routing only when required. +- **Universal compatibility** — Works with both native tokens (ETH, MATIC) and ERC-20s (USDC, USDT). + +--- + +## 🏗️ Initialization ```typescript -import { NexusSDK } from '@avail-project/nexus-core'; +import { NexusSDK, type NexusNetwork } from '@avail-project/nexus-core'; +// Mainnet const sdk = new NexusSDK({ network: 'mainnet' }); -await sdk.initialize(provider); -// Bridge tokens -const result = await sdk.bridge({ - token: 'USDC', - amount: 100, - chainId: 137, +// Testnet +const sdkTest = new NexusSDK({ network: 'testnet' }); + +// Initialize with wallet provider +await sdk.initialize(window.ethereum); +``` + +--- + +## 📡 Event Handling + +**All main SDK functions support the `onEvent` hook**: + +- `bridge` +- `bridgeAndTransfer` +- `execute` +- `bridgeAndExecute` +- `swapWithExactIn` / `swapWithExactOut` + +Example usage for **progress steps**: + +```typescript +sdk.bridge({...}, { + onEvent: (event) => { + if(event.name === NEXUS_EVENTS.STEPS_LIST) { + // Store list of steps + } else if(event.name === NEXUS_EVENTS.STEP_COMPLETE) { + // Mark step as done + } + } }); ``` -## Documentation +Additional hooks for user interactions: -- [Core SDK Documentation](./packages/core/README.md) - Headless SDK API reference -- [API Documentation](https://docs.availproject.org/api-reference/avail-nexus-sdk) +```typescript +sdk.setOnIntentHook(({ intent, allow, deny, refresh }) => { + if (userApproves) allow(); + else deny(); +}); -## 🛠️ Development +sdk.setOnSwapIntentHook(({ intent, allow, deny, refresh }) => { + if (userApproves) allow(); + else deny(); +}); -```bash -# Install dependencies -pnpm install +sdk.setOnAllowanceHook(({ sources, allow, deny }) => { + allow(['min']); // 'max' or custom bigint[] supported +}); +``` + +### Consistent Event Pattern + +| Operation Type | Event Name | Description | +| ---------------- | -------------------- | --------------------------------------- | +| Bridge / Execute | `STEPS_LIST` | Full ordered list of steps emitted once | +| | `STEP_COMPLETE` | Fired per completed step with data | +| Swap | `SWAP_STEP_COMPLETE` | Fired per completed step with data | + +All events include `typeID`, `transactionHash`, `explorerURL`, and `error` (if any). + +--- -# Build all packages -pnpm build +## 💰 Balance Operations -# Run tests -pnpm test +```typescript +const balances = await sdk.getUnifiedBalances(); // CA balances +const allBalances = await sdk.getUnifiedBalances(true); // Includes swappable tokens ``` -## Monorepo & Workspace +--- -- Packages live under `packages/` and are linked via pnpm workspaces. -- Internal shared code stays in `@nexus/commons` (private). It is imported in source during development and bundled into `dist/commons` at build so consumers never install it directly. -- Published package names used everywhere (dev and build): - - `@avail-project/nexus-core` +## 🌉 Bridge Operations -### TS path mapping for local DX +```typescript +const result = await sdk.bridge({ token: 'USDC', amount: '83.50', chainId: 137 }); +const simulation = await sdk.simulateBridge({ token: 'USDC', amount: '83.50', chainId: 137 }); +``` -- Dev imports use published names while resolving locally: - - Root `tsconfig.json` maps `@avail-project/nexus-core` → `packages/core/*` - - Widgets `tsconfig.json` also maps `@avail-project/nexus-core` → `../core/*` -- Keep importing `@nexus/commons` in source; build rewrites it to `./commons` inside the dist. +--- -### Workspace versions and overrides +## 🔁 Transfer Operations -- Root `package.json` defines pnpm overrides to pin shared versions: - - `typescript`, `rollup`, `decimal.js`, `viem` -- Update once for all packages: +```typescript +const result = await sdk.bridgeAndTransfer({ + token: 'USDC', + amount: '1.53', + chainId: 42161, + recipient: '0x...', +}); +const simulation = await sdk.simulateBridgeAndTransfer({ + token: 'USDC', + amount: '1.53', + chainId: 42161, + recipient: '0x...', +}); +``` -```bash -pnpm -r up typescript rollup decimal.js viem +--- + +## ⚙️ Execute & Bridge+Execute + +```typescript +// Direct contract execution +const result = await sdk.execute({ + toChainId: 1, + to: '0xc3d688B66703497DAA19211EEdff47f25384cdc3', + data: '0x...', + tokenApproval: { token: 'USDC', amount: 1000000n }, +}); + +// Bridge and execute +const result2 = await sdk.bridgeAndExecute({ + token: 'USDC', + amount: 100_000_000n, + toChainId: 1, + sourceChains: [8453], + execute: { + to: '0xa354F35829Ae975e850e23e9615b11Da1B3dC4DE', + data: '0x...', + tokenApproval: { token: 'USDC', amount: 100_000_000n }, + }, +}); ``` -## Releases & Scripts +--- -- Scripts live in `scripts/`. Both core and widgets have an interactive wizard and CI-friendly flags. -- Commons is always bundled; it is removed from published dependencies. +## 🔄 Swap Operations -### Dev (pre-release) policy +```typescript +const swapResult = await sdk.swapWithExactIn( + { + from: [{ chainId: 10, amount: 1_000_000n, tokenAddress: '0x...' }], + toChainId: 8453, + toTokenAddress: '0x...', + }, + { onEvent: (event) => console.log(event) }, +); +``` -- Pre-release numbers progress `0..9` and roll over to the next patch: - - `0.0.2-beta.0 → 0.0.2-beta.1 … → 0.0.2-beta.9 → 0.0.3-beta.0` -- Widgets depends on the most recently published core prerelease by publish time (not by semver magnitude). +### Swap Types -### Flags +| Type | Description | Example | +| ------------- | ------------------------------------------------- | --------------------------- | +| **EXACT_IN** | Specify the amount you’re spending; output varies | “Swap 100 USDC for max ETH” | +| **EXACT_OUT** | Specify the amount you’ll receive; input varies | “Get exactly 1 ETH” | -- `--yes` or `--ci`: skip interactive prompts (useful in CI) -- `--dry-run` or `-n`: simulate publish (runs `npm pack`, skips git push/tag) +--- -### Core examples +## 🧩 Intent Management -```bash -# Interactive dev prerelease (choose tag like beta/alpha/dev) -./scripts/release-core.sh +```typescript +const intents = await sdk.getMyIntents(1); +console.log('Active intents:', intents); +``` -# Non-interactive dev prerelease (beta), dry-run -./scripts/release-core.sh dev patch beta --yes --dry-run +--- -# Non-interactive dev prerelease (beta), publish for real -./scripts/release-core.sh dev patch beta --yes +## 🛠️ Utilities -# Production release (patch) -./scripts/release-core.sh prod patch --yes +```typescript +const isValid = sdk.utils.isValidAddress('0x...'); +const chainMeta = sdk.utils.getChainMetadata(137); +const formatted = sdk.utils.formatTokenAmount('1000000', 'USDC'); // "1.0 USDC" ``` -### Local tarballs (no publish) +--- -```bash -# Build and create .tgz files for local install -./scripts/local-pack.sh +## 🧾 Error Handling -# In another project -pnpm add /absolute/path/to/dist-tarballs/avail-project-nexus-core-*.tgz +```typescript +try { + await sdk.bridge({ token: 'USDC', amount: 1.53, chainId: 137 }); +} catch (err) { + if (err instanceof NexusError) { + console.error(`[${err.code}] ${err.message}`); + } else { + console.error('Unexpected error:', err); + } +} ``` -## License +--- + +## 🧠 TypeScript Support + +```typescript +import type { + BridgeParams, + ExecuteParams, + TransferParams, + SwapResult, + NexusNetwork, + TokenMetadata, +} from '@avail-project/nexus-core'; +``` + +--- + +## 🌐 Supported Networks + +### Mainnets + +| Network | Chain ID | Native | Status | +| --------- | --------- | ------ | ------ | +| Ethereum | 1 | ETH | ✅ | +| Optimism | 10 | ETH | ✅ | +| Polygon | 137 | MATIC | ✅ | +| Arbitrum | 42161 | ETH | ✅ | +| Avalanche | 43114 | AVAX | ✅ | +| Base | 8453 | ETH | ✅ | +| Scroll | 534352 | ETH | ✅ | +| Sophon | 50104 | SOPH | ✅ | +| Kaia | 8217 | KAIA | ✅ | +| BNB | 56 | BNB | ✅ | +| HyperEVM | 999 | HYPE | ✅ | +| TRON | 728126428 | TRX | ✅ | + +### Testnets + +| Network | Chain ID | Native | Status | +| ---------------- | -------- | ------ | ------ | +| Optimism Sepolia | 11155420 | ETH | ✅ | +| Polygon Amoy | 80002 | MATIC | ✅ | +| Arbitrum Sepolia | 421614 | ETH | ✅ | +| Base Sepolia | 84532 | ETH | ✅ | +| Sepolia | 11155111 | ETH | ✅ | +| Monad Testnet | 10143 | MON | ✅ | +| Validium | 567 | VLDM | ✅ | + +--- + +## 💎 Supported Tokens + +| Token | Name | Decimals | Availability | +| ----- | ---------- | -------- | -------------- | +| ETH | Ethereum | 18 | All EVM chains | +| USDC | USD Coin | 6 | All supported | +| USDT | Tether USD | 6 | All supported | + +--- + +## 🔗 Resources -MIT +- **GitHub:** [availproject/nexus-sdk](https://github.com/availproject/nexus-sdk) +- **Docs:** [docs.availproject.org](https://docs.availproject.org/nexus/avail-nexus-sdk) diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 00000000..45eb58d4 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,6323 @@ +{ + "name": "@avail-project/nexus-core", + "version": "1.0.0-beta.26", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "@avail-project/nexus-core", + "version": "1.0.0-beta.26", + "license": "MIT", + "dependencies": { + "@avail-project/ca-common": "1.0.0-beta.7", + "@cosmjs/proto-signing": "^0.34.0", + "@cosmjs/stargate": "^0.34.0", + "@metamask/safe-event-emitter": "3.1.2", + "@starkware-industries/starkware-crypto-utils": "^0.2.1", + "@tronweb3/tronwallet-abstract-adapter": "^1.1.9", + "axios": "^1.12.2", + "decimal.js": "^10.6.0", + "es-toolkit": "^1.40.0", + "fuels": "0.101.1", + "it-ws": "^6.1.5", + "long": "^5.3.2", + "msgpackr": "^1.11.5", + "tronweb": "^6.0.4", + "tslib": "2.8.1" + }, + "devDependencies": { + "@rollup/plugin-commonjs": "^25.0.8", + "@rollup/plugin-json": "6.1.0", + "@rollup/plugin-node-resolve": "^15.3.1", + "@rollup/plugin-typescript": "^11.1.6", + "rollup": "^4.52.4", + "rollup-plugin-dts": "^6.2.3", + "rollup-plugin-typescript2": "0.36.0", + "typescript": "^5.9.3" + }, + "peerDependencies": { + "viem": "^2.31.7" + } + }, + "node_modules/@adraffy/ens-normalize": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/@adraffy/ens-normalize/-/ens-normalize-1.10.1.tgz", + "integrity": "sha512-96Z2IP3mYmF1Xg2cDm8f1gWGf/HUVedQ3FMifV4kG/PQ4yEP51xDtRAEfhVNt5f/uzpNkZHwWQuUcu6D6K+Ekw==", + "license": "MIT" + }, + "node_modules/@avail-project/ca-common": { + "version": "1.0.0-beta.7", + "resolved": "https://registry.npmjs.org/@avail-project/ca-common/-/ca-common-1.0.0-beta.7.tgz", + "integrity": "sha512-TCRrAM5aW0A+DoQiqmY0UJcZn6R3Mtpbt7V57V6LG4Tu52j4CC8Eye2a8Uo37YoFDXilB+AKyK6Ia+U9Kjximw==", + "license": "MIT", + "dependencies": { + "@bufbuild/protobuf": "^2.6.0", + "@improbable-eng/grpc-web": "^0.15.0", + "browser-headers": "^0.4.1", + "es-toolkit": "^1.39.7", + "tslib": "^2.8.1" + }, + "peerDependencies": { + "@cosmjs/proto-signing": "^0.34.0", + "@cosmjs/stargate": "^0.34.0", + "axios": "^1.10.0", + "decimal.js": "^10.6.0", + "fuels": "^0.101.1", + "long": "^5.3.2", + "msgpackr": "^1.11.4", + "viem": "^2.31.7" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz", + "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.27.1", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", + "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/runtime": { + "version": "7.26.10", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.26.10.tgz", + "integrity": "sha512-2WJMeRQPHKSPemqk/awGrAiuFfzBmOIPXKizAsVhWH9YJqLZ0H+HS4c8loHGgW6utJ3E/ejXQUsiGaQy2NZ9Fw==", + "license": "MIT", + "dependencies": { + "regenerator-runtime": "^0.14.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@bufbuild/protobuf": { + "version": "2.10.1", + "resolved": "https://registry.npmjs.org/@bufbuild/protobuf/-/protobuf-2.10.1.tgz", + "integrity": "sha512-ckS3+vyJb5qGpEYv/s1OebUHDi/xSNtfgw1wqKZo7MR9F2z+qXr0q5XagafAG/9O0QPVIUfST0smluYSTpYFkg==", + "license": "(Apache-2.0 AND BSD-3-Clause)" + }, + "node_modules/@cosmjs/amino": { + "version": "0.34.1", + "resolved": "https://registry.npmjs.org/@cosmjs/amino/-/amino-0.34.1.tgz", + "integrity": "sha512-9kfGtJf/skhS5O/xKkCtSJgLHcFK1VoEEzCFJsMV4YLvlMIZznVmzwqlOwMtI/dYaVQpyzfHedLwxph2bfIIQA==", + "license": "Apache-2.0", + "dependencies": { + "@cosmjs/crypto": "^0.34.1", + "@cosmjs/encoding": "^0.34.1", + "@cosmjs/math": "^0.34.1", + "@cosmjs/utils": "^0.34.1" + } + }, + "node_modules/@cosmjs/crypto": { + "version": "0.34.1", + "resolved": "https://registry.npmjs.org/@cosmjs/crypto/-/crypto-0.34.1.tgz", + "integrity": "sha512-fouXCXB4vNKLi9hyhdLL1elJ12reZH1UxJK4JPEkMOSaLAPClIHEu8NZ8cXYNlu2yTi86NX+I0TE4cEPsvSpWA==", + "license": "Apache-2.0", + "dependencies": { + "@cosmjs/encoding": "^0.34.1", + "@cosmjs/math": "^0.34.1", + "@cosmjs/utils": "^0.34.1", + "@noble/curves": "^1.9.2", + "@noble/hashes": "^1", + "bn.js": "^5.2.0", + "libsodium-wrappers-sumo": "^0.7.11" + } + }, + "node_modules/@cosmjs/encoding": { + "version": "0.34.1", + "resolved": "https://registry.npmjs.org/@cosmjs/encoding/-/encoding-0.34.1.tgz", + "integrity": "sha512-5+Ta7v05UxAqicKgk16c4rg0vsHPbzJOp5rfOxbiiJOfu3fVJkmmQgz5VuTrsvl5AZf9pulen7b8SK/rQYzKDg==", + "license": "Apache-2.0", + "dependencies": { + "base64-js": "^1.3.0", + "bech32": "^1.1.4", + "readonly-date": "^1.0.0" + } + }, + "node_modules/@cosmjs/json-rpc": { + "version": "0.34.1", + "resolved": "https://registry.npmjs.org/@cosmjs/json-rpc/-/json-rpc-0.34.1.tgz", + "integrity": "sha512-hSq4eEQ2cc7YVvvJER0Fr+Y02ZzKNz02+wHTetVh0JcniEP71ZDQC00E+/je817V+vt7mN1dxoeeC5IY9kKtRw==", + "license": "Apache-2.0", + "dependencies": { + "@cosmjs/stream": "^0.34.1", + "xstream": "^11.14.0" + } + }, + "node_modules/@cosmjs/math": { + "version": "0.34.1", + "resolved": "https://registry.npmjs.org/@cosmjs/math/-/math-0.34.1.tgz", + "integrity": "sha512-QRFMcxCZ5JMQr6ANU7+5mrPdx3XTT0/6jGHY1wP4q4T3IfgHJItu5HqOi22VbSNb/IWpDWwTS46eqvbXyRMeqg==", + "license": "Apache-2.0", + "dependencies": { + "bn.js": "^5.2.0" + } + }, + "node_modules/@cosmjs/proto-signing": { + "version": "0.34.1", + "resolved": "https://registry.npmjs.org/@cosmjs/proto-signing/-/proto-signing-0.34.1.tgz", + "integrity": "sha512-7oeU2QyVwAWoeGXtsrQ8e6eCjWR4essYDegFA4a/1eXFnIvAb8oPMxoVshZfUmDhhhtmyHQvuqxFm3zMO0R6aA==", + "license": "Apache-2.0", + "dependencies": { + "@cosmjs/amino": "^0.34.1", + "@cosmjs/crypto": "^0.34.1", + "@cosmjs/encoding": "^0.34.1", + "@cosmjs/math": "^0.34.1", + "@cosmjs/utils": "^0.34.1", + "cosmjs-types": "^0.9.0" + } + }, + "node_modules/@cosmjs/socket": { + "version": "0.34.1", + "resolved": "https://registry.npmjs.org/@cosmjs/socket/-/socket-0.34.1.tgz", + "integrity": "sha512-+MiuC+WDzaA8cU635JEK8tY/ImrRRcPzE+0ExoL4ZzqgzIcXf1hbgmqgKF85yyhGnk/nMTLsEteyoJIaWxsTtA==", + "license": "Apache-2.0", + "dependencies": { + "@cosmjs/stream": "^0.34.1", + "isomorphic-ws": "^4.0.1", + "ws": "^7", + "xstream": "^11.14.0" + } + }, + "node_modules/@cosmjs/stargate": { + "version": "0.34.1", + "resolved": "https://registry.npmjs.org/@cosmjs/stargate/-/stargate-0.34.1.tgz", + "integrity": "sha512-BOaSEmHnThtpKft7jFwFKOKptRoVNq01vmaDKoTISgmS5qi9JgVwiogjL679Aclmmy/xO+GoRfQvWsFrR7f1KA==", + "license": "Apache-2.0", + "dependencies": { + "@cosmjs/amino": "^0.34.1", + "@cosmjs/encoding": "^0.34.1", + "@cosmjs/math": "^0.34.1", + "@cosmjs/proto-signing": "^0.34.1", + "@cosmjs/stream": "^0.34.1", + "@cosmjs/tendermint-rpc": "^0.34.1", + "@cosmjs/utils": "^0.34.1", + "cosmjs-types": "^0.9.0" + } + }, + "node_modules/@cosmjs/stream": { + "version": "0.34.1", + "resolved": "https://registry.npmjs.org/@cosmjs/stream/-/stream-0.34.1.tgz", + "integrity": "sha512-EVbSFUnBMHkRX7Oy+JrGe3i8TjxnRs5BKJa8CZnn4ZHSWf6Krw+nWlaJ7FixFttd+PX8c+Agzw+Qhv3pm9HPVg==", + "license": "Apache-2.0", + "dependencies": { + "xstream": "^11.14.0" + } + }, + "node_modules/@cosmjs/tendermint-rpc": { + "version": "0.34.1", + "resolved": "https://registry.npmjs.org/@cosmjs/tendermint-rpc/-/tendermint-rpc-0.34.1.tgz", + "integrity": "sha512-cYiyln2wmYvY4/n4ehfAjoFf3SoO8P8mgioqdDb6QItTeQmwX4lDU+YOv3b2KzoA6ufH6SX1nJyPJ3X0YJhfwA==", + "license": "Apache-2.0", + "dependencies": { + "@cosmjs/crypto": "^0.34.1", + "@cosmjs/encoding": "^0.34.1", + "@cosmjs/json-rpc": "^0.34.1", + "@cosmjs/math": "^0.34.1", + "@cosmjs/socket": "^0.34.1", + "@cosmjs/stream": "^0.34.1", + "@cosmjs/utils": "^0.34.1", + "cross-fetch": "^4.1.0", + "readonly-date": "^1.0.0", + "xstream": "^11.14.0" + } + }, + "node_modules/@cosmjs/utils": { + "version": "0.34.1", + "resolved": "https://registry.npmjs.org/@cosmjs/utils/-/utils-0.34.1.tgz", + "integrity": "sha512-OjevgFwbVN7t8afmFF8A3rj80jQnOXqwdGEzfv7jbYxTvhUGPa8SvpeaulhWQYQ49K3zlIuB9a2PJWdf1H9Udw==", + "license": "Apache-2.0" + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.1.tgz", + "integrity": "sha512-kfYGy8IdzTGy+z0vFGvExZtxkFlA4zAxgKEahG9KE1ScBjpQnFsNOX8KTU5ojNru5ed5CVoJYXFtoxaq5nFbjQ==", + "cpu": [ + "ppc64" + ], + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.1.tgz", + "integrity": "sha512-dp+MshLYux6j/JjdqVLnMglQlFu+MuVeNrmT5nk6q07wNhCdSnB7QZj+7G8VMUGh1q+vj2Bq8kRsuyA00I/k+Q==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.1.tgz", + "integrity": "sha512-50tM0zCJW5kGqgG7fQ7IHvQOcAn9TKiVRuQ/lN0xR+T2lzEFvAi1ZcS8DiksFcEpf1t/GYOeOfCAgDHFpkiSmA==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.1.tgz", + "integrity": "sha512-GCj6WfUtNldqUzYkN/ITtlhwQqGWu9S45vUXs7EIYf+7rCiiqH9bCloatO9VhxsL0Pji+PF4Lz2XXCES+Q8hDw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.1.tgz", + "integrity": "sha512-5hEZKPf+nQjYoSr/elb62U19/l1mZDdqidGfmFutVUjjUZrOazAtwK+Kr+3y0C/oeJfLlxo9fXb1w7L+P7E4FQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.1.tgz", + "integrity": "sha512-hxVnwL2Dqs3fM1IWq8Iezh0cX7ZGdVhbTfnOy5uURtao5OIVCEyj9xIzemDi7sRvKsuSdtCAhMKarxqtlyVyfA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.1.tgz", + "integrity": "sha512-1MrCZs0fZa2g8E+FUo2ipw6jw5qqQiH+tERoS5fAfKnRx6NXH31tXBKI3VpmLijLH6yriMZsxJtaXUyFt/8Y4A==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.1.tgz", + "integrity": "sha512-0IZWLiTyz7nm0xuIs0q1Y3QWJC52R8aSXxe40VUxm6BB1RNmkODtW6LHvWRrGiICulcX7ZvyH6h5fqdLu4gkww==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.1.tgz", + "integrity": "sha512-NdKOhS4u7JhDKw9G3cY6sWqFcnLITn6SqivVArbzIaf3cemShqfLGHYMx8Xlm/lBit3/5d7kXvriTUGa5YViuQ==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.1.tgz", + "integrity": "sha512-jaN3dHi0/DDPelk0nLcXRm1q7DNJpjXy7yWaWvbfkPvI+7XNSc/lDOnCLN7gzsyzgu6qSAmgSvP9oXAhP973uQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.1.tgz", + "integrity": "sha512-OJykPaF4v8JidKNGz8c/q1lBO44sQNUQtq1KktJXdBLn1hPod5rE/Hko5ugKKZd+D2+o1a9MFGUEIUwO2YfgkQ==", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.1.tgz", + "integrity": "sha512-nGfornQj4dzcq5Vp835oM/o21UMlXzn79KobKlcs3Wz9smwiifknLy4xDCLUU0BWp7b/houtdrgUz7nOGnfIYg==", + "cpu": [ + "loong64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.1.tgz", + "integrity": "sha512-1osBbPEFYwIE5IVB/0g2X6i1qInZa1aIoj1TdL4AaAb55xIIgbg8Doq6a5BzYWgr+tEcDzYH67XVnTmUzL+nXg==", + "cpu": [ + "mips64el" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.1.tgz", + "integrity": "sha512-/6VBJOwUf3TdTvJZ82qF3tbLuWsscd7/1w+D9LH0W/SqUgM5/JJD0lrJ1fVIfZsqB6RFmLCe0Xz3fmZc3WtyVg==", + "cpu": [ + "ppc64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.1.tgz", + "integrity": "sha512-nSut/Mx5gnilhcq2yIMLMe3Wl4FK5wx/o0QuuCLMtmJn+WeWYoEGDN1ipcN72g1WHsnIbxGXd4i/MF0gTcuAjQ==", + "cpu": [ + "riscv64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.1.tgz", + "integrity": "sha512-cEECeLlJNfT8kZHqLarDBQso9a27o2Zd2AQ8USAEoGtejOrCYHNtKP8XQhMDJMtthdF4GBmjR2au3x1udADQQQ==", + "cpu": [ + "s390x" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.1.tgz", + "integrity": "sha512-xbfUhu/gnvSEg+EGovRc+kjBAkrvtk38RlerAzQxvMzlB4fXpCFCeUAYzJvrnhFtdeyVCDANSjJvOvGYoeKzFA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.1.tgz", + "integrity": "sha512-O96poM2XGhLtpTh+s4+nP7YCCAfb4tJNRVZHfIE7dgmax+yMP2WgMd2OecBuaATHKTHsLWHQeuaxMRnCsH8+5g==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.1.tgz", + "integrity": "sha512-X53z6uXip6KFXBQ+Krbx25XHV/NCbzryM6ehOAeAil7X7oa4XIq+394PWGnwaSQ2WRA0KI6PUO6hTO5zeF5ijA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.1.tgz", + "integrity": "sha512-Na9T3szbXezdzM/Kfs3GcRQNjHzM6GzFBeU1/6IV/npKP5ORtp9zbQjvkDJ47s6BCgaAZnnnu/cY1x342+MvZg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.1.tgz", + "integrity": "sha512-T3H78X2h1tszfRSf+txbt5aOp/e7TAz3ptVKu9Oyir3IAOFPGV6O9c2naym5TOriy1l0nNf6a4X5UXRZSGX/dw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.1.tgz", + "integrity": "sha512-2H3RUvcmULO7dIE5EWJH8eubZAI4xw54H1ilJnRNZdeo8dTADEZ21w6J22XBkXqGJbe0+wnNJtw3UXRoLJnFEg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.1.tgz", + "integrity": "sha512-GE7XvrdOzrb+yVKB9KsRMq+7a2U/K5Cf/8grVFRAGJmfADr/e/ODQ134RK2/eeHqYV5eQRFxb1hY7Nr15fv1NQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.1.tgz", + "integrity": "sha512-uOxSJCIcavSiT6UnBhBzE8wy3n0hOkJsBOzy7HDAuTDE++1DJMRRVCPGisULScHL+a/ZwdXPpXD3IyFKjA7K8A==", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.1.tgz", + "integrity": "sha512-Y1EQdcfwMSeQN/ujR5VayLOJ1BHaK+ssyk0AEzPjC+t1lITgsnccPqFjb6V+LsTp/9Iov4ysfjxLaGJ9RPtkVg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@fuel-ts/abi-coder": { + "version": "0.101.1", + "resolved": "https://registry.npmjs.org/@fuel-ts/abi-coder/-/abi-coder-0.101.1.tgz", + "integrity": "sha512-PgKO4BLo8dzwdJqHIMmOtoOiV/a8OIqPju9h3maOLXMDwgVXxL/NLku33iLP8CDuFu91AssAOg5XURTHDfQ1aQ==", + "license": "Apache-2.0", + "dependencies": { + "@fuel-ts/crypto": "0.101.1", + "@fuel-ts/errors": "0.101.1", + "@fuel-ts/hasher": "0.101.1", + "@fuel-ts/math": "0.101.1", + "@fuel-ts/utils": "0.101.1", + "type-fest": "4.34.1" + }, + "engines": { + "node": "^18.20.3 || ^20.0.0 || ^22.0.0" + } + }, + "node_modules/@fuel-ts/abi-typegen": { + "version": "0.101.1", + "resolved": "https://registry.npmjs.org/@fuel-ts/abi-typegen/-/abi-typegen-0.101.1.tgz", + "integrity": "sha512-4s4Zf+5Ohdym9bl/Cebl7kwufaKJ9C2nJNt5EB+0bXmVArl8zOpP67U+cQSVXawMUVryBVM3mY7Ay2p/WD9wDg==", + "license": "Apache-2.0", + "dependencies": { + "@fuel-ts/errors": "0.101.1", + "@fuel-ts/utils": "0.101.1", + "@fuel-ts/versions": "0.101.1", + "commander": "13.1.0", + "glob": "10.4.5", + "handlebars": "4.7.8", + "mkdirp": "3.0.1", + "ramda": "0.30.1", + "rimraf": "5.0.10" + }, + "bin": { + "fuels-typegen": "typegen.js" + }, + "engines": { + "node": "^18.20.3 || ^20.0.0 || ^22.0.0" + } + }, + "node_modules/@fuel-ts/abi-typegen/node_modules/glob": { + "version": "10.4.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", + "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "license": "ISC", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@fuel-ts/abi-typegen/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@fuel-ts/account": { + "version": "0.101.1", + "resolved": "https://registry.npmjs.org/@fuel-ts/account/-/account-0.101.1.tgz", + "integrity": "sha512-x+UfuBaCvb9KYT+wIJba3RL21nR4JH0qZevDs/jzw9cLMsLl8AYLKMg2wS9rhR5OCoa9PbsOe9DDrDI+y3BpVA==", + "license": "Apache-2.0", + "dependencies": { + "@fuel-ts/abi-coder": "0.101.1", + "@fuel-ts/address": "0.101.1", + "@fuel-ts/crypto": "0.101.1", + "@fuel-ts/errors": "0.101.1", + "@fuel-ts/hasher": "0.101.1", + "@fuel-ts/math": "0.101.1", + "@fuel-ts/merkle": "0.101.1", + "@fuel-ts/transactions": "0.101.1", + "@fuel-ts/utils": "0.101.1", + "@fuel-ts/versions": "0.101.1", + "@fuels/vm-asm": "0.60.2", + "@noble/curves": "1.8.1", + "events": "3.3.0", + "graphql": "16.10.0", + "graphql-request": "6.1.0", + "graphql-tag": "2.12.6", + "ramda": "0.30.1" + }, + "engines": { + "node": "^18.20.3 || ^20.0.0 || ^22.0.0" + } + }, + "node_modules/@fuel-ts/account/node_modules/@noble/curves": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.8.1.tgz", + "integrity": "sha512-warwspo+UYUPep0Q+vtdVB4Ugn8GGQj8iyB3gnRWsztmUHTI3S1nhdiWNsPUGL0vud7JlRRk1XEu7Lq1KGTnMQ==", + "license": "MIT", + "dependencies": { + "@noble/hashes": "1.7.1" + }, + "engines": { + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@fuel-ts/account/node_modules/@noble/hashes": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.7.1.tgz", + "integrity": "sha512-B8XBPsn4vT/KJAGqDzbwztd+6Yte3P4V7iafm24bxgDe/mlRuK6xmWPuCNrKt2vDafZ8MfJLlchDG/vYafQEjQ==", + "license": "MIT", + "engines": { + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@fuel-ts/address": { + "version": "0.101.1", + "resolved": "https://registry.npmjs.org/@fuel-ts/address/-/address-0.101.1.tgz", + "integrity": "sha512-l+PvQ2kB/zS/TW7S3/UjjaJ95UNflWizmKr97M13gkOdP99UuI2InYu9zjH72Azbt3LR/RMilHMTyZeWRSV42w==", + "license": "Apache-2.0", + "dependencies": { + "@fuel-ts/crypto": "0.101.1", + "@fuel-ts/errors": "0.101.1", + "@fuel-ts/utils": "0.101.1", + "@noble/hashes": "1.7.1" + }, + "engines": { + "node": "^18.20.3 || ^20.0.0 || ^22.0.0" + } + }, + "node_modules/@fuel-ts/address/node_modules/@noble/hashes": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.7.1.tgz", + "integrity": "sha512-B8XBPsn4vT/KJAGqDzbwztd+6Yte3P4V7iafm24bxgDe/mlRuK6xmWPuCNrKt2vDafZ8MfJLlchDG/vYafQEjQ==", + "license": "MIT", + "engines": { + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@fuel-ts/contract": { + "version": "0.101.1", + "resolved": "https://registry.npmjs.org/@fuel-ts/contract/-/contract-0.101.1.tgz", + "integrity": "sha512-UBOjDIYqO1EY8qirjxpEUsW0K2+fR8mC0xDI8k0c1Aes3YVAZyMmpf6ZWvjF5BVElu4kO8pFXr6xcQoDn6TuMw==", + "license": "Apache-2.0", + "dependencies": { + "@fuel-ts/abi-coder": "0.101.1", + "@fuel-ts/account": "0.101.1", + "@fuel-ts/crypto": "0.101.1", + "@fuel-ts/errors": "0.101.1", + "@fuel-ts/hasher": "0.101.1", + "@fuel-ts/math": "0.101.1", + "@fuel-ts/merkle": "0.101.1", + "@fuel-ts/program": "0.101.1", + "@fuel-ts/transactions": "0.101.1", + "@fuel-ts/utils": "0.101.1", + "@fuels/vm-asm": "0.60.2", + "ramda": "0.30.1" + }, + "engines": { + "node": "^18.20.3 || ^20.0.0 || ^22.0.0" + } + }, + "node_modules/@fuel-ts/crypto": { + "version": "0.101.1", + "resolved": "https://registry.npmjs.org/@fuel-ts/crypto/-/crypto-0.101.1.tgz", + "integrity": "sha512-Dy6Q1NbdGojyT0q3mrZu72hSTlXfNprKA6A6vJHKkwRcwFphnrZHAubVfjzus4ZeQf9fdcqZrfWLUG76/F6r9g==", + "license": "Apache-2.0", + "dependencies": { + "@fuel-ts/errors": "0.101.1", + "@fuel-ts/utils": "0.101.1", + "@noble/hashes": "1.7.1" + }, + "engines": { + "node": "^18.20.3 || ^20.0.0 || ^22.0.0" + } + }, + "node_modules/@fuel-ts/crypto/node_modules/@noble/hashes": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.7.1.tgz", + "integrity": "sha512-B8XBPsn4vT/KJAGqDzbwztd+6Yte3P4V7iafm24bxgDe/mlRuK6xmWPuCNrKt2vDafZ8MfJLlchDG/vYafQEjQ==", + "license": "MIT", + "engines": { + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@fuel-ts/errors": { + "version": "0.101.1", + "resolved": "https://registry.npmjs.org/@fuel-ts/errors/-/errors-0.101.1.tgz", + "integrity": "sha512-BPp3/tD3YyxbV/qGujwrUOluyB4abEHOD1GIgvUGKiLy9S3TNjBzIPLYG0ARVcswvYTEh8r7/hoZcRKtpNpcEQ==", + "license": "Apache-2.0", + "dependencies": { + "@fuel-ts/versions": "0.101.1" + }, + "engines": { + "node": "^18.20.3 || ^20.0.0 || ^22.0.0" + } + }, + "node_modules/@fuel-ts/hasher": { + "version": "0.101.1", + "resolved": "https://registry.npmjs.org/@fuel-ts/hasher/-/hasher-0.101.1.tgz", + "integrity": "sha512-diLLZbMvwy6ivkZEBDzh6HXkqPzxCVJov29A4A+ILwvKcXHultJ/36bxj3S415cj5DtgVj8KBoqeo1Sw7cg+rg==", + "license": "Apache-2.0", + "dependencies": { + "@fuel-ts/crypto": "0.101.1", + "@fuel-ts/utils": "0.101.1", + "@noble/hashes": "1.7.1" + }, + "engines": { + "node": "^18.20.3 || ^20.0.0 || ^22.0.0" + } + }, + "node_modules/@fuel-ts/hasher/node_modules/@noble/hashes": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.7.1.tgz", + "integrity": "sha512-B8XBPsn4vT/KJAGqDzbwztd+6Yte3P4V7iafm24bxgDe/mlRuK6xmWPuCNrKt2vDafZ8MfJLlchDG/vYafQEjQ==", + "license": "MIT", + "engines": { + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@fuel-ts/math": { + "version": "0.101.1", + "resolved": "https://registry.npmjs.org/@fuel-ts/math/-/math-0.101.1.tgz", + "integrity": "sha512-F1bGLZN71DmL5h1/znlXgWahL8A28RMur4B2MscTp/sFyqQ9tHlpEDjdF2ajr3lSxlMWohDJbElCNramLqE/Tg==", + "license": "Apache-2.0", + "dependencies": { + "@fuel-ts/errors": "0.101.1", + "@types/bn.js": "5.1.6", + "bn.js": "5.2.1" + }, + "engines": { + "node": "^18.20.3 || ^20.0.0 || ^22.0.0" + } + }, + "node_modules/@fuel-ts/math/node_modules/@types/bn.js": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-5.1.6.tgz", + "integrity": "sha512-Xh8vSwUeMKeYYrj3cX4lGQgFSF/N03r+tv4AiLl1SucqV+uTQpxRcnM8AkXKHwYP9ZPXOYXRr2KPXpVlIvqh9w==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@fuel-ts/math/node_modules/bn.js": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.1.tgz", + "integrity": "sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ==", + "license": "MIT" + }, + "node_modules/@fuel-ts/merkle": { + "version": "0.101.1", + "resolved": "https://registry.npmjs.org/@fuel-ts/merkle/-/merkle-0.101.1.tgz", + "integrity": "sha512-JJEdTQ2BxWHjX09caf42Ebfc32J0dHx/dv9pXfvpxc3BUgdRE8gM0Wvrqq/cu6S2XD/Y6vQp/qhOq9PXWJUuKg==", + "license": "Apache-2.0", + "dependencies": { + "@fuel-ts/hasher": "0.101.1", + "@fuel-ts/math": "0.101.1" + }, + "engines": { + "node": "^18.20.3 || ^20.0.0 || ^22.0.0" + } + }, + "node_modules/@fuel-ts/program": { + "version": "0.101.1", + "resolved": "https://registry.npmjs.org/@fuel-ts/program/-/program-0.101.1.tgz", + "integrity": "sha512-6ManClwCW7NI4jE3BoaNWStHyGEWcrD7hkK+9T5+hESY0ckGiBGMuKvR3VhVaTsTRVfqMx/m1kPSu2O5BY/vrA==", + "license": "Apache-2.0", + "dependencies": { + "@fuel-ts/abi-coder": "0.101.1", + "@fuel-ts/account": "0.101.1", + "@fuel-ts/address": "0.101.1", + "@fuel-ts/errors": "0.101.1", + "@fuel-ts/math": "0.101.1", + "@fuel-ts/transactions": "0.101.1", + "@fuel-ts/utils": "0.101.1", + "@fuels/vm-asm": "0.60.2", + "ramda": "0.30.1" + }, + "engines": { + "node": "^18.20.3 || ^20.0.0 || ^22.0.0" + } + }, + "node_modules/@fuel-ts/recipes": { + "version": "0.101.1", + "resolved": "https://registry.npmjs.org/@fuel-ts/recipes/-/recipes-0.101.1.tgz", + "integrity": "sha512-DVQfE7pnoFBmTNwBPrL2qN5jlp8w9rCD9aQKwvBaPwvi4UYiTg1elcWlX5/mEhUAnGlDIYOQ4XFuxLZAgmDUww==", + "license": "Apache-2.0", + "dependencies": { + "@fuel-ts/abi-coder": "0.101.1", + "@fuel-ts/abi-typegen": "0.101.1", + "@fuel-ts/account": "0.101.1", + "@fuel-ts/address": "0.101.1", + "@fuel-ts/contract": "0.101.1", + "@fuel-ts/program": "0.101.1", + "@fuel-ts/transactions": "0.101.1", + "@fuel-ts/utils": "0.101.1" + }, + "engines": { + "node": "^18.20.3 || ^20.0.0 || ^22.0.0" + } + }, + "node_modules/@fuel-ts/script": { + "version": "0.101.1", + "resolved": "https://registry.npmjs.org/@fuel-ts/script/-/script-0.101.1.tgz", + "integrity": "sha512-6s6SKciwOYM/MK1DAE7Cd19hTL5FOG+FtPP9IvZ+UwmNz7zydD2LXHdTcOjTPZnhmzvhBrlfH2CUAsOqhMHGpg==", + "license": "Apache-2.0", + "dependencies": { + "@fuel-ts/abi-coder": "0.101.1", + "@fuel-ts/account": "0.101.1", + "@fuel-ts/errors": "0.101.1", + "@fuel-ts/math": "0.101.1", + "@fuel-ts/program": "0.101.1", + "@fuel-ts/transactions": "0.101.1", + "@fuel-ts/utils": "0.101.1" + }, + "engines": { + "node": "^18.20.3 || ^20.0.0 || ^22.0.0" + } + }, + "node_modules/@fuel-ts/transactions": { + "version": "0.101.1", + "resolved": "https://registry.npmjs.org/@fuel-ts/transactions/-/transactions-0.101.1.tgz", + "integrity": "sha512-VLCtwOO5PD31rxSnGbBaJuQO8AwvqUwwRfXrE3fLzrreJKyUM5K2XZHsfQq9dtd/RWaaOUPNMp7ztVQzKebfUQ==", + "license": "Apache-2.0", + "dependencies": { + "@fuel-ts/abi-coder": "0.101.1", + "@fuel-ts/address": "0.101.1", + "@fuel-ts/errors": "0.101.1", + "@fuel-ts/hasher": "0.101.1", + "@fuel-ts/math": "0.101.1", + "@fuel-ts/utils": "0.101.1" + }, + "engines": { + "node": "^18.20.3 || ^20.0.0 || ^22.0.0" + } + }, + "node_modules/@fuel-ts/utils": { + "version": "0.101.1", + "resolved": "https://registry.npmjs.org/@fuel-ts/utils/-/utils-0.101.1.tgz", + "integrity": "sha512-H7j38/quroMccPrjFrnn+Cuui6iPpyH15NKdBT2XVv96rk9XX2DG5aBIGn+nYqPTA8+W+a7sp3U65sgckyZ4Rg==", + "license": "Apache-2.0", + "dependencies": { + "@fuel-ts/errors": "0.101.1", + "@fuel-ts/math": "0.101.1", + "@fuel-ts/versions": "0.101.1", + "fflate": "0.8.2" + }, + "engines": { + "node": "^18.20.3 || ^20.0.0 || ^22.0.0" + }, + "peerDependencies": { + "vitest": "3.0.9" + } + }, + "node_modules/@fuel-ts/versions": { + "version": "0.101.1", + "resolved": "https://registry.npmjs.org/@fuel-ts/versions/-/versions-0.101.1.tgz", + "integrity": "sha512-3/tYZBbCaShkzfrVEBulm83f3MJaUpOCK4q3BpAxvbhWHsKS9AxbLhHWQ0RZUXII5OJmGnSpWfy0Bhe7FYo93A==", + "license": "Apache-2.0", + "dependencies": { + "chalk": "4", + "cli-table": "0.3.11" + }, + "bin": { + "fuels-versions": "versions.js" + }, + "engines": { + "node": "^18.20.3 || ^20.0.0 || ^22.0.0" + } + }, + "node_modules/@fuels/vm-asm": { + "version": "0.60.2", + "resolved": "https://registry.npmjs.org/@fuels/vm-asm/-/vm-asm-0.60.2.tgz", + "integrity": "sha512-wkCu63jTGJWpRZQirTaB8S4/gyoebEJLk3AKfnykt/lgWp1U9iHOcCICVHQP547i+y8jEVKwk18+huINFyYVFQ==", + "license": "Apache-2.0" + }, + "node_modules/@graphql-typed-document-node/core": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@graphql-typed-document-node/core/-/core-3.2.0.tgz", + "integrity": "sha512-mB9oAsNCm9aM3/SOv4YtBMqZbYj10R7dkq8byBqxGY/ncFwhf2oQzMV+LCRlWoDSEBJ3COiR1yeDvMtsoOsuFQ==", + "license": "MIT", + "peerDependencies": { + "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" + } + }, + "node_modules/@improbable-eng/grpc-web": { + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/@improbable-eng/grpc-web/-/grpc-web-0.15.0.tgz", + "integrity": "sha512-ERft9/0/8CmYalqOVnJnpdDry28q+j+nAlFFARdjyxXDJ+Mhgv9+F600QC8BR9ygOfrXRlAk6CvST2j+JCpQPg==", + "license": "Apache-2.0", + "dependencies": { + "browser-headers": "^0.4.1" + }, + "peerDependencies": { + "google-protobuf": "^3.14.0" + } + }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "license": "ISC", + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "license": "MIT" + }, + "node_modules/@metamask/safe-event-emitter": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@metamask/safe-event-emitter/-/safe-event-emitter-3.1.2.tgz", + "integrity": "sha512-5yb2gMI1BDm0JybZezeoX/3XhPDOtTbcFvpTXM9kxsoZjPZFh4XciqRbpD6N86HYZqWDhEaKUDuOyR0sQHEjMA==", + "license": "ISC", + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/@msgpackr-extract/msgpackr-extract-darwin-arm64": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-darwin-arm64/-/msgpackr-extract-darwin-arm64-3.0.3.tgz", + "integrity": "sha512-QZHtlVgbAdy2zAqNA9Gu1UpIuI8Xvsd1v8ic6B2pZmeFnFcMWiPLfWXh7TVw4eGEZ/C9TH281KwhVoeQUKbyjw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@msgpackr-extract/msgpackr-extract-darwin-x64": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-darwin-x64/-/msgpackr-extract-darwin-x64-3.0.3.tgz", + "integrity": "sha512-mdzd3AVzYKuUmiWOQ8GNhl64/IoFGol569zNRdkLReh6LRLHOXxU4U8eq0JwaD8iFHdVGqSy4IjFL4reoWCDFw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@msgpackr-extract/msgpackr-extract-linux-arm": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-arm/-/msgpackr-extract-linux-arm-3.0.3.tgz", + "integrity": "sha512-fg0uy/dG/nZEXfYilKoRe7yALaNmHoYeIoJuJ7KJ+YyU2bvY8vPv27f7UKhGRpY6euFYqEVhxCFZgAUNQBM3nw==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@msgpackr-extract/msgpackr-extract-linux-arm64": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-arm64/-/msgpackr-extract-linux-arm64-3.0.3.tgz", + "integrity": "sha512-YxQL+ax0XqBJDZiKimS2XQaf+2wDGVa1enVRGzEvLLVFeqa5kx2bWbtcSXgsxjQB7nRqqIGFIcLteF/sHeVtQg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@msgpackr-extract/msgpackr-extract-linux-x64": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-x64/-/msgpackr-extract-linux-x64-3.0.3.tgz", + "integrity": "sha512-cvwNfbP07pKUfq1uH+S6KJ7dT9K8WOE4ZiAcsrSes+UY55E/0jLYc+vq+DO7jlmqRb5zAggExKm0H7O/CBaesg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@msgpackr-extract/msgpackr-extract-win32-x64": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-win32-x64/-/msgpackr-extract-win32-x64-3.0.3.tgz", + "integrity": "sha512-x0fWaQtYp4E6sktbsdAqnehxDgEc/VwM7uLsRCYWaiGu0ykYdZPiS8zCWdnjHwyiumousxfBm4SO31eXqwEZhQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@noble/ciphers": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@noble/ciphers/-/ciphers-1.3.0.tgz", + "integrity": "sha512-2I0gnIVPtfnMw9ee9h1dJG7tp81+8Ob3OJb3Mv37rx5L40/b0i7djjCVvGOVqc9AEIQyvyu1i6ypKdFw8R8gQw==", + "license": "MIT", + "peer": true, + "engines": { + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@noble/curves": { + "version": "1.9.7", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.9.7.tgz", + "integrity": "sha512-gbKGcRUYIjA3/zCCNaWDciTMFI0dCkvou3TL8Zmy5Nc7sJ47a0jtOeZoTaMxkuqRo9cRhjOdZJXegxYE5FN/xw==", + "license": "MIT", + "dependencies": { + "@noble/hashes": "1.8.0" + }, + "engines": { + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@noble/hashes": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.8.0.tgz", + "integrity": "sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==", + "license": "MIT", + "engines": { + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/@rollup/plugin-commonjs": { + "version": "25.0.8", + "resolved": "https://registry.npmjs.org/@rollup/plugin-commonjs/-/plugin-commonjs-25.0.8.tgz", + "integrity": "sha512-ZEZWTK5n6Qde0to4vS9Mr5x/0UZoqCxPVR9KRUjU4kA2sO7GEUn1fop0DAwpO6z0Nw/kJON9bDmSxdWxO/TT1A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@rollup/pluginutils": "^5.0.1", + "commondir": "^1.0.1", + "estree-walker": "^2.0.2", + "glob": "^8.0.3", + "is-reference": "1.2.1", + "magic-string": "^0.30.3" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "rollup": "^2.68.0||^3.0.0||^4.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } + } + }, + "node_modules/@rollup/plugin-json": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@rollup/plugin-json/-/plugin-json-6.1.0.tgz", + "integrity": "sha512-EGI2te5ENk1coGeADSIwZ7G2Q8CJS2sF120T7jLw4xFw9n7wIOXHo+kIYRAoVpJAN+kmqZSoO3Fp4JtoNF4ReA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@rollup/pluginutils": "^5.1.0" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } + } + }, + "node_modules/@rollup/plugin-node-resolve": { + "version": "15.3.1", + "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-15.3.1.tgz", + "integrity": "sha512-tgg6b91pAybXHJQMAAwW9VuWBO6Thi+q7BCNARLwSqlmsHz0XYURtGvh/AuwSADXSI4h/2uHbs7s4FzlZDGSGA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@rollup/pluginutils": "^5.0.1", + "@types/resolve": "1.20.2", + "deepmerge": "^4.2.2", + "is-module": "^1.0.0", + "resolve": "^1.22.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "rollup": "^2.78.0||^3.0.0||^4.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } + } + }, + "node_modules/@rollup/plugin-typescript": { + "version": "11.1.6", + "resolved": "https://registry.npmjs.org/@rollup/plugin-typescript/-/plugin-typescript-11.1.6.tgz", + "integrity": "sha512-R92yOmIACgYdJ7dJ97p4K69I8gg6IEHt8M7dUBxN3W6nrO8uUxX5ixl0yU/N3aZTi8WhPuICvOHXQvF6FaykAA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@rollup/pluginutils": "^5.1.0", + "resolve": "^1.22.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "rollup": "^2.14.0||^3.0.0||^4.0.0", + "tslib": "*", + "typescript": ">=3.7.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + }, + "tslib": { + "optional": true + } + } + }, + "node_modules/@rollup/pluginutils": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.3.0.tgz", + "integrity": "sha512-5EdhGZtnu3V88ces7s53hhfK5KSASnJZv8Lulpc04cWO3REESroJXg73DFsOmgbU2BhwV0E20bu2IDZb3VKW4Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "estree-walker": "^2.0.2", + "picomatch": "^4.0.2" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } + } + }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.53.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.53.2.tgz", + "integrity": "sha512-yDPzwsgiFO26RJA4nZo8I+xqzh7sJTZIWQOxn+/XOdPE31lAvLIYCKqjV+lNH/vxE2L2iH3plKxDCRK6i+CwhA==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.53.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.53.2.tgz", + "integrity": "sha512-k8FontTxIE7b0/OGKeSN5B6j25EuppBcWM33Z19JoVT7UTXFSo3D9CdU39wGTeb29NO3XxpMNauh09B+Ibw+9g==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.53.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.53.2.tgz", + "integrity": "sha512-A6s4gJpomNBtJ2yioj8bflM2oogDwzUiMl2yNJ2v9E7++sHrSrsQ29fOfn5DM/iCzpWcebNYEdXpaK4tr2RhfQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.53.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.53.2.tgz", + "integrity": "sha512-e6XqVmXlHrBlG56obu9gDRPW3O3hLxpwHpLsBJvuI8qqnsrtSZ9ERoWUXtPOkY8c78WghyPHZdmPhHLWNdAGEw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.53.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.53.2.tgz", + "integrity": "sha512-v0E9lJW8VsrwPux5Qe5CwmH/CF/2mQs6xU1MF3nmUxmZUCHazCjLgYvToOk+YuuUqLQBio1qkkREhxhc656ViA==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.53.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.53.2.tgz", + "integrity": "sha512-ClAmAPx3ZCHtp6ysl4XEhWU69GUB1D+s7G9YjHGhIGCSrsg00nEGRRZHmINYxkdoJehde8VIsDC5t9C0gb6yqA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.53.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.53.2.tgz", + "integrity": "sha512-EPlb95nUsz6Dd9Qy13fI5kUPXNSljaG9FiJ4YUGU1O/Q77i5DYFW5KR8g1OzTcdZUqQQ1KdDqsTohdFVwCwjqg==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.53.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.53.2.tgz", + "integrity": "sha512-BOmnVW+khAUX+YZvNfa0tGTEMVVEerOxN0pDk2E6N6DsEIa2Ctj48FOMfNDdrwinocKaC7YXUZ1pHlKpnkja/Q==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.53.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.53.2.tgz", + "integrity": "sha512-Xt2byDZ+6OVNuREgBXr4+CZDJtrVso5woFtpKdGPhpTPHcNG7D8YXeQzpNbFRxzTVqJf7kvPMCub/pcGUWgBjA==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.53.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.53.2.tgz", + "integrity": "sha512-+LdZSldy/I9N8+klim/Y1HsKbJ3BbInHav5qE9Iy77dtHC/pibw1SR/fXlWyAk0ThnpRKoODwnAuSjqxFRDHUQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-gnu": { + "version": "4.53.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.53.2.tgz", + "integrity": "sha512-8ms8sjmyc1jWJS6WdNSA23rEfdjWB30LH8Wqj0Cqvv7qSHnvw6kgMMXRdop6hkmGPlyYBdRPkjJnj3KCUHV/uQ==", + "cpu": [ + "loong64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-gnu": { + "version": "4.53.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.53.2.tgz", + "integrity": "sha512-3HRQLUQbpBDMmzoxPJYd3W6vrVHOo2cVW8RUo87Xz0JPJcBLBr5kZ1pGcQAhdZgX9VV7NbGNipah1omKKe23/g==", + "cpu": [ + "ppc64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.53.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.53.2.tgz", + "integrity": "sha512-fMjKi+ojnmIvhk34gZP94vjogXNNUKMEYs+EDaB/5TG/wUkoeua7p7VCHnE6T2Tx+iaghAqQX8teQzcvrYpaQA==", + "cpu": [ + "riscv64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-musl": { + "version": "4.53.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.53.2.tgz", + "integrity": "sha512-XuGFGU+VwUUV5kLvoAdi0Wz5Xbh2SrjIxCtZj6Wq8MDp4bflb/+ThZsVxokM7n0pcbkEr2h5/pzqzDYI7cCgLQ==", + "cpu": [ + "riscv64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.53.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.53.2.tgz", + "integrity": "sha512-w6yjZF0P+NGzWR3AXWX9zc0DNEGdtvykB03uhonSHMRa+oWA6novflo2WaJr6JZakG2ucsyb+rvhrKac6NIy+w==", + "cpu": [ + "s390x" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.53.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.53.2.tgz", + "integrity": "sha512-yo8d6tdfdeBArzC7T/PnHd7OypfI9cbuZzPnzLJIyKYFhAQ8SvlkKtKBMbXDxe1h03Rcr7u++nFS7tqXz87Gtw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.53.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.53.2.tgz", + "integrity": "sha512-ah59c1YkCxKExPP8O9PwOvs+XRLKwh/mV+3YdKqQ5AMQ0r4M4ZDuOrpWkUaqO7fzAHdINzV9tEVu8vNw48z0lA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-openharmony-arm64": { + "version": "4.53.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.53.2.tgz", + "integrity": "sha512-4VEd19Wmhr+Zy7hbUsFZ6YXEiP48hE//KPLCSVNY5RMGX2/7HZ+QkN55a3atM1C/BZCGIgqN+xrVgtdak2S9+A==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.53.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.53.2.tgz", + "integrity": "sha512-IlbHFYc/pQCgew/d5fslcy1KEaYVCJ44G8pajugd8VoOEI8ODhtb/j8XMhLpwHCMB3yk2J07ctup10gpw2nyMA==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.53.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.53.2.tgz", + "integrity": "sha512-lNlPEGgdUfSzdCWU176ku/dQRnA7W+Gp8d+cWv73jYrb8uT7HTVVxq62DUYxjbaByuf1Yk0RIIAbDzp+CnOTFg==", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-gnu": { + "version": "4.53.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.53.2.tgz", + "integrity": "sha512-S6YojNVrHybQis2lYov1sd+uj7K0Q05NxHcGktuMMdIQ2VixGwAfbJ23NnlvvVV1bdpR2m5MsNBViHJKcA4ADw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.53.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.53.2.tgz", + "integrity": "sha512-k+/Rkcyx//P6fetPoLMb8pBeqJBNGx81uuf7iljX9++yNBVRDQgD04L+SVXmXmh5ZP4/WOp4mWF0kmi06PW2tA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@scure/base": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.2.6.tgz", + "integrity": "sha512-g/nm5FgUa//MCj1gV09zTJTaM6KBAHqLN907YVQqf7zC49+DcO4B1so4ZX07Ef10Twr6nuqYEH9GEggFXA4Fmg==", + "license": "MIT", + "peer": true, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@scure/bip32": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@scure/bip32/-/bip32-1.7.0.tgz", + "integrity": "sha512-E4FFX/N3f4B80AKWp5dP6ow+flD1LQZo/w8UnLGYZO674jS6YnYeepycOOksv+vLPSpgN35wgKgy+ybfTb2SMw==", + "license": "MIT", + "peer": true, + "dependencies": { + "@noble/curves": "~1.9.0", + "@noble/hashes": "~1.8.0", + "@scure/base": "~1.2.5" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@scure/bip39": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.6.0.tgz", + "integrity": "sha512-+lF0BbLiJNwVlev4eKelw1WWLaiKXw7sSl8T6FvBlWkdX+94aGJ4o8XjUdlyhTCjd8c+B3KT3JfS8P0bLRNU6A==", + "license": "MIT", + "peer": true, + "dependencies": { + "@noble/hashes": "~1.8.0", + "@scure/base": "~1.2.5" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@starkware-industries/starkware-crypto-utils": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/@starkware-industries/starkware-crypto-utils/-/starkware-crypto-utils-0.2.1.tgz", + "integrity": "sha512-rA5O9b53zaoBOQwQxBd0cbumFbQoBm9NH/vfu+o0Cq3oouEbNPALneLlLjOmFEId2/WOJ5ecC64rFLI/PwuIPQ==", + "license": "Apache-2.0", + "dependencies": { + "assert": "^2.0.0", + "bip39": "^3.0.4", + "bn.js": "^4.12.0", + "brorand": "^1.1.0", + "buffer": "^6.0.3", + "crypto-browserify": "^3.12.0", + "elliptic": "^6.5.4", + "enc-utils": "^3.0.0", + "ethereumjs-wallet": "^1.0.2", + "hash.js": "^1.1.7", + "hmac-drbg": "^1.0.1", + "inherits": "^2.0.4", + "js-sha3": "^0.8.0", + "minimalistic-assert": "^1.0.1", + "minimalistic-crypto-utils": "^1.0.1", + "stream-browserify": "^3.0.0" + } + }, + "node_modules/@starkware-industries/starkware-crypto-utils/node_modules/bn.js": { + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.2.tgz", + "integrity": "sha512-n4DSx829VRTRByMRGdjQ9iqsN0Bh4OolPsFnaZBLcbi8iXcB+kJ9s7EnRt4wILZNV3kPLHkRVfOc/HvhC3ovDw==", + "license": "MIT" + }, + "node_modules/@tronweb3/tronwallet-abstract-adapter": { + "version": "1.1.10", + "resolved": "https://registry.npmjs.org/@tronweb3/tronwallet-abstract-adapter/-/tronwallet-abstract-adapter-1.1.10.tgz", + "integrity": "sha512-gZExaEZwPfI9oI7qSi56p/5Zl/DEzo1JlcD3lQzz1cuz0rZmEFpIqDS2mhY4r/IwEPwilIU7lg7T8/RQDVk9gA==", + "license": "MIT", + "dependencies": { + "eventemitter3": "^4.0.0", + "tronweb": "6" + }, + "engines": { + "node": ">=16", + "pnpm": ">=7" + } + }, + "node_modules/@types/bn.js": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-5.2.0.tgz", + "integrity": "sha512-DLbJ1BPqxvQhIGbeu8VbUC1DiAiahHtAYvA0ZEAa4P31F7IaArc8z3C3BRQdWX4mtLQuABG4yzp76ZrS02Ui1Q==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/estree": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "24.10.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-24.10.1.tgz", + "integrity": "sha512-GNWcUTRBgIRJD5zj+Tq0fKOJ5XZajIiBroOF0yvj2bSU1WvNdYS/dn9UxwsujGW4JX06dnHyjV2y9rRaybH0iQ==", + "license": "MIT", + "dependencies": { + "undici-types": "~7.16.0" + } + }, + "node_modules/@types/pbkdf2": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@types/pbkdf2/-/pbkdf2-3.1.2.tgz", + "integrity": "sha512-uRwJqmiXmh9++aSu1VNEn3iIxWOhd8AHXNSdlaLfdAAdSTY9jYVeGWnzejM3dvrkbqE3/hyQkQQ29IFATEGlew==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/resolve": { + "version": "1.20.2", + "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.20.2.tgz", + "integrity": "sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/secp256k1": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/@types/secp256k1/-/secp256k1-4.0.7.tgz", + "integrity": "sha512-Rcvjl6vARGAKRO6jHeKMatGrvOMGrR/AR11N1x2LqintPCyDZ7NBhrh238Z2VZc7aM7KIwnFpFQ7fnfK4H/9Qw==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/ws": { + "version": "8.18.1", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.18.1.tgz", + "integrity": "sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@vitest/expect": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-3.0.9.tgz", + "integrity": "sha512-5eCqRItYgIML7NNVgJj6TVCmdzE7ZVgJhruW0ziSQV4V7PvLkDL1bBkBdcTs/VuIz0IxPb5da1IDSqc1TR9eig==", + "license": "MIT", + "peer": true, + "dependencies": { + "@vitest/spy": "3.0.9", + "@vitest/utils": "3.0.9", + "chai": "^5.2.0", + "tinyrainbow": "^2.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/mocker": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-3.0.9.tgz", + "integrity": "sha512-ryERPIBOnvevAkTq+L1lD+DTFBRcjueL9lOUfXsLfwP92h4e+Heb+PjiqS3/OURWPtywfafK0kj++yDFjWUmrA==", + "license": "MIT", + "peer": true, + "dependencies": { + "@vitest/spy": "3.0.9", + "estree-walker": "^3.0.3", + "magic-string": "^0.30.17" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "msw": "^2.4.9", + "vite": "^5.0.0 || ^6.0.0" + }, + "peerDependenciesMeta": { + "msw": { + "optional": true + }, + "vite": { + "optional": true + } + } + }, + "node_modules/@vitest/mocker/node_modules/estree-walker": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", + "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", + "license": "MIT", + "peer": true, + "dependencies": { + "@types/estree": "^1.0.0" + } + }, + "node_modules/@vitest/pretty-format": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-3.2.4.tgz", + "integrity": "sha512-IVNZik8IVRJRTr9fxlitMKeJeXFFFN0JaB9PHPGQ8NKQbGpfjlTx9zO4RefN8gp7eqjNy8nyK3NZmBzOPeIxtA==", + "license": "MIT", + "peer": true, + "dependencies": { + "tinyrainbow": "^2.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/runner": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-3.0.9.tgz", + "integrity": "sha512-NX9oUXgF9HPfJSwl8tUZCMP1oGx2+Sf+ru6d05QjzQz4OwWg0psEzwY6VexP2tTHWdOkhKHUIZH+fS6nA7jfOw==", + "license": "MIT", + "peer": true, + "dependencies": { + "@vitest/utils": "3.0.9", + "pathe": "^2.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/snapshot": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-3.0.9.tgz", + "integrity": "sha512-AiLUiuZ0FuA+/8i19mTYd+re5jqjEc2jZbgJ2up0VY0Ddyyxg/uUtBDpIFAy4uzKaQxOW8gMgBdAJJ2ydhu39A==", + "license": "MIT", + "peer": true, + "dependencies": { + "@vitest/pretty-format": "3.0.9", + "magic-string": "^0.30.17", + "pathe": "^2.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/snapshot/node_modules/@vitest/pretty-format": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-3.0.9.tgz", + "integrity": "sha512-OW9F8t2J3AwFEwENg3yMyKWweF7oRJlMyHOMIhO5F3n0+cgQAJZBjNgrF8dLwFTEXl5jUqBLXd9QyyKv8zEcmA==", + "license": "MIT", + "peer": true, + "dependencies": { + "tinyrainbow": "^2.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/spy": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-3.0.9.tgz", + "integrity": "sha512-/CcK2UDl0aQ2wtkp3YVWldrpLRNCfVcIOFGlVGKO4R5eajsH393Z1yiXLVQ7vWsj26JOEjeZI0x5sm5P4OGUNQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "tinyspy": "^3.0.2" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/utils": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-3.0.9.tgz", + "integrity": "sha512-ilHM5fHhZ89MCp5aAaM9uhfl1c2JdxVxl3McqsdVyVNN6JffnEen8UMCdRTzOhGXNQGo5GNL9QugHrz727Wnng==", + "license": "MIT", + "peer": true, + "dependencies": { + "@vitest/pretty-format": "3.0.9", + "loupe": "^3.1.3", + "tinyrainbow": "^2.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/utils/node_modules/@vitest/pretty-format": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-3.0.9.tgz", + "integrity": "sha512-OW9F8t2J3AwFEwENg3yMyKWweF7oRJlMyHOMIhO5F3n0+cgQAJZBjNgrF8dLwFTEXl5jUqBLXd9QyyKv8zEcmA==", + "license": "MIT", + "peer": true, + "dependencies": { + "tinyrainbow": "^2.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/abitype": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/abitype/-/abitype-1.1.0.tgz", + "integrity": "sha512-6Vh4HcRxNMLA0puzPjM5GBgT4aAcFGKZzSgAXvuZ27shJP6NEpielTuqbBmZILR5/xd0PizkBGy5hReKz9jl5A==", + "license": "MIT", + "peer": true, + "funding": { + "url": "https://github.com/sponsors/wevm" + }, + "peerDependencies": { + "typescript": ">=5.0.4", + "zod": "^3.22.0 || ^4.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + }, + "zod": { + "optional": true + } + } + }, + "node_modules/aes-js": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/aes-js/-/aes-js-3.1.2.tgz", + "integrity": "sha512-e5pEa2kBnBOgR4Y/p20pskXI74UEz7de8ZGVo58asOtvSVG5YAbJeELPZxOmt+Bnz3rX753YKhfIn4X4l1PPRQ==", + "license": "MIT" + }, + "node_modules/ansi-regex": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "license": "ISC", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/anymatch/node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/asn1.js": { + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.10.1.tgz", + "integrity": "sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==", + "license": "MIT", + "dependencies": { + "bn.js": "^4.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0" + } + }, + "node_modules/asn1.js/node_modules/bn.js": { + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.2.tgz", + "integrity": "sha512-n4DSx829VRTRByMRGdjQ9iqsN0Bh4OolPsFnaZBLcbi8iXcB+kJ9s7EnRt4wILZNV3kPLHkRVfOc/HvhC3ovDw==", + "license": "MIT" + }, + "node_modules/assert": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/assert/-/assert-2.1.0.tgz", + "integrity": "sha512-eLHpSK/Y4nhMJ07gDaAzoX/XAKS8PSaojml3M0DM4JpV1LAi5JOJ/p6H/XWrl8L+DzVEvVCW1z3vWAaB9oTsQw==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2", + "is-nan": "^1.3.2", + "object-is": "^1.1.5", + "object.assign": "^4.1.4", + "util": "^0.12.5" + } + }, + "node_modules/assertion-error": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz", + "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/async": { + "version": "2.6.4", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz", + "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==", + "license": "MIT", + "dependencies": { + "lodash": "^4.17.14" + } + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "license": "MIT" + }, + "node_modules/available-typed-arrays": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", + "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", + "license": "MIT", + "dependencies": { + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/axios": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.13.2.tgz", + "integrity": "sha512-VPk9ebNqPcy5lRGuSlKx752IlDatOjT9paPlm8A7yOuW2Fbvp4X3JznJtT4f0GzGLLiWE9W8onz51SqLYwzGaA==", + "license": "MIT", + "dependencies": { + "follow-redirects": "^1.15.6", + "form-data": "^4.0.4", + "proxy-from-env": "^1.1.0" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "license": "MIT" + }, + "node_modules/base-x": { + "version": "3.0.11", + "resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.11.tgz", + "integrity": "sha512-xz7wQ8xDhdyP7tQxwdteLYeFfS68tSMNCZ/Y37WJ4bhGfKPpqEIlmIyueQHqOyoPhE6xNUqjzRr8ra0eF9VRvA==", + "license": "MIT", + "dependencies": { + "safe-buffer": "^5.0.1" + } + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/bech32": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/bech32/-/bech32-1.1.4.tgz", + "integrity": "sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ==", + "license": "MIT" + }, + "node_modules/bignumber.js": { + "version": "9.1.2", + "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.1.2.tgz", + "integrity": "sha512-2/mKyZH9K85bzOEfhXDBFZTGd1CTs+5IHpeFQo9luiBG7hghdC851Pj2WAhb6E3R6b9tZj/XKhbg4fum+Kepug==", + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/binary-extensions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/bip39": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/bip39/-/bip39-3.1.0.tgz", + "integrity": "sha512-c9kiwdk45Do5GL0vJMe7tS95VjCii65mYAH7DfWl3uW8AVzXKQVUm64i3hzVybBDMp9r7j9iNxR85+ul8MdN/A==", + "license": "ISC", + "dependencies": { + "@noble/hashes": "^1.2.0" + } + }, + "node_modules/blakejs": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/blakejs/-/blakejs-1.2.1.tgz", + "integrity": "sha512-QXUSXI3QVc/gJME0dBpXrag1kbzOqCjCX8/b54ntNyW6sjtoqxqRk3LTmXzaJoh71zMsDCjM+47jS7XiwN/+fQ==", + "license": "MIT" + }, + "node_modules/bn.js": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.2.tgz", + "integrity": "sha512-v2YAxEmKaBLahNwE1mjp4WON6huMNeuDvagFZW+ASCuA/ku0bXR9hSMw0XpiqMoA3+rmnyck/tPRSFQkoC9Cuw==", + "license": "MIT" + }, + "node_modules/brace-expansion": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "license": "MIT", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/brorand": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", + "integrity": "sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==", + "license": "MIT" + }, + "node_modules/browser-headers": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/browser-headers/-/browser-headers-0.4.1.tgz", + "integrity": "sha512-CA9hsySZVo9371qEHjHZtYxV2cFtVj5Wj/ZHi8ooEsrtm4vOnl9Y9HmyYWk9q+05d7K3rdoAE0j3MVEFVvtQtg==", + "license": "Apache-2.0" + }, + "node_modules/browserify-aes": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", + "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", + "license": "MIT", + "dependencies": { + "buffer-xor": "^1.0.3", + "cipher-base": "^1.0.0", + "create-hash": "^1.1.0", + "evp_bytestokey": "^1.0.3", + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/browserify-cipher": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz", + "integrity": "sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==", + "license": "MIT", + "dependencies": { + "browserify-aes": "^1.0.4", + "browserify-des": "^1.0.0", + "evp_bytestokey": "^1.0.0" + } + }, + "node_modules/browserify-des": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.2.tgz", + "integrity": "sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==", + "license": "MIT", + "dependencies": { + "cipher-base": "^1.0.1", + "des.js": "^1.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "node_modules/browserify-rsa": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.1.1.tgz", + "integrity": "sha512-YBjSAiTqM04ZVei6sXighu679a3SqWORA3qZTEqZImnlkDIFtKc6pNutpjyZ8RJTjQtuYfeetkxM11GwoYXMIQ==", + "license": "MIT", + "dependencies": { + "bn.js": "^5.2.1", + "randombytes": "^2.1.0", + "safe-buffer": "^5.2.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/browserify-sign": { + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.5.tgz", + "integrity": "sha512-C2AUdAJg6rlM2W5QMp2Q4KGQMVBwR1lIimTsUnutJ8bMpW5B52pGpR2gEnNBNwijumDo5FojQ0L9JrXA8m4YEw==", + "license": "ISC", + "dependencies": { + "bn.js": "^5.2.2", + "browserify-rsa": "^4.1.1", + "create-hash": "^1.2.0", + "create-hmac": "^1.1.7", + "elliptic": "^6.6.1", + "inherits": "^2.0.4", + "parse-asn1": "^5.1.9", + "readable-stream": "^2.3.8", + "safe-buffer": "^5.2.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/bs58": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/bs58/-/bs58-4.0.1.tgz", + "integrity": "sha512-Ok3Wdf5vOIlBrgCvTq96gBkJw+JUEzdBgyaza5HLtPm7yTHkjRy8+JzNyHF7BHa0bNWOQIp3m5YF0nnFcOIKLw==", + "license": "MIT", + "dependencies": { + "base-x": "^3.0.2" + } + }, + "node_modules/bs58check": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/bs58check/-/bs58check-2.1.2.tgz", + "integrity": "sha512-0TS1jicxdU09dwJMNZtVAfzPi6Q6QeN0pM1Fkzrjn+XYHvzMKPU3pHVpva+769iNVSfIYWf7LJ6WR+BuuMf8cA==", + "license": "MIT", + "dependencies": { + "bs58": "^4.0.0", + "create-hash": "^1.1.0", + "safe-buffer": "^5.1.2" + } + }, + "node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, + "node_modules/buffer-xor": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", + "integrity": "sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ==", + "license": "MIT" + }, + "node_modules/bundle-require": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/bundle-require/-/bundle-require-5.1.0.tgz", + "integrity": "sha512-3WrrOuZiyaaZPWiEt4G3+IffISVC9HYlWueJEBWED4ZH4aIAC2PnkdnuRrR94M+w6yGWn4AglWtJtBI8YqvgoA==", + "license": "MIT", + "dependencies": { + "load-tsconfig": "^0.2.3" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "peerDependencies": { + "esbuild": ">=0.18" + } + }, + "node_modules/cac": { + "version": "6.7.14", + "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz", + "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/call-bind": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz", + "integrity": "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.0", + "es-define-property": "^1.0.0", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/chai": { + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/chai/-/chai-5.3.3.tgz", + "integrity": "sha512-4zNhdJD/iOjSH0A05ea+Ke6MU5mmpQcbQsSOkgdaUMJ9zTlDTD/GYlwohmIE2u0gaxHYiVHEn1Fw9mZ/ktJWgw==", + "license": "MIT", + "peer": true, + "dependencies": { + "assertion-error": "^2.0.1", + "check-error": "^2.1.1", + "deep-eql": "^5.0.1", + "loupe": "^3.1.0", + "pathval": "^2.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/check-error": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-2.1.1.tgz", + "integrity": "sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 16" + } + }, + "node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "license": "MIT", + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/cipher-base": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.7.tgz", + "integrity": "sha512-Mz9QMT5fJe7bKI7MH31UilT5cEK5EHHRCccw/YRFsRY47AuNgaV6HY3rscp0/I4Q+tTW/5zoqpSeRRI54TkDWA==", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.4", + "safe-buffer": "^5.2.1", + "to-buffer": "^1.2.2" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/cli-table": { + "version": "0.3.11", + "resolved": "https://registry.npmjs.org/cli-table/-/cli-table-0.3.11.tgz", + "integrity": "sha512-IqLQi4lO0nIB4tcdTpN4LCB9FI3uqrJZK7RC515EnhZ6qBaglkIgICb1wjeAqpdoOabm1+SuQtkXIPdYC93jhQ==", + "dependencies": { + "colors": "1.0.3" + }, + "engines": { + "node": ">= 0.2.0" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "license": "MIT" + }, + "node_modules/colors": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.0.3.tgz", + "integrity": "sha512-pFGrxThWcWQ2MsAz6RtgeWe4NK2kUE1WfsrvvlctdII745EW9I0yflqhe7++M5LEc7bV2c/9/5zc8sFcpL0Drw==", + "license": "MIT", + "engines": { + "node": ">=0.1.90" + } + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "license": "MIT", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/commander": { + "version": "13.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-13.1.0.tgz", + "integrity": "sha512-/rFeCpNJQbhSZjGVwO9RFV3xPqbnERS8MmIQzCtD/zl6gpJuV/bMLuN92oG3F7d8oDEHHRrujSXNUr8fpjntKw==", + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/commondir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", + "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==", + "dev": true, + "license": "MIT" + }, + "node_modules/core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", + "license": "MIT" + }, + "node_modules/cosmjs-types": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/cosmjs-types/-/cosmjs-types-0.9.0.tgz", + "integrity": "sha512-MN/yUe6mkJwHnCFfsNPeCfXVhyxHYW6c/xDUzrSbBycYzw++XvWDMJArXp2pLdgD6FQ8DW79vkPjeNKVrXaHeQ==", + "license": "Apache-2.0" + }, + "node_modules/create-ecdh": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.4.tgz", + "integrity": "sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A==", + "license": "MIT", + "dependencies": { + "bn.js": "^4.1.0", + "elliptic": "^6.5.3" + } + }, + "node_modules/create-ecdh/node_modules/bn.js": { + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.2.tgz", + "integrity": "sha512-n4DSx829VRTRByMRGdjQ9iqsN0Bh4OolPsFnaZBLcbi8iXcB+kJ9s7EnRt4wILZNV3kPLHkRVfOc/HvhC3ovDw==", + "license": "MIT" + }, + "node_modules/create-hash": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", + "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", + "license": "MIT", + "dependencies": { + "cipher-base": "^1.0.1", + "inherits": "^2.0.1", + "md5.js": "^1.3.4", + "ripemd160": "^2.0.1", + "sha.js": "^2.4.0" + } + }, + "node_modules/create-hmac": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", + "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", + "license": "MIT", + "dependencies": { + "cipher-base": "^1.0.3", + "create-hash": "^1.1.0", + "inherits": "^2.0.1", + "ripemd160": "^2.0.0", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + } + }, + "node_modules/cross-fetch": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-4.1.0.tgz", + "integrity": "sha512-uKm5PU+MHTootlWEY+mZ4vvXoCn4fLQxT9dSc1sXVMSFkINTJVN8cAQROpwcKm8bJ/c7rgZVIBWzH5T78sNZZw==", + "license": "MIT", + "dependencies": { + "node-fetch": "^2.7.0" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/crypto-browserify": { + "version": "3.12.1", + "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.1.tgz", + "integrity": "sha512-r4ESw/IlusD17lgQi1O20Fa3qNnsckR126TdUuBgAu7GBYSIPvdNyONd3Zrxh0xCwA4+6w/TDArBPsMvhur+KQ==", + "license": "MIT", + "dependencies": { + "browserify-cipher": "^1.0.1", + "browserify-sign": "^4.2.3", + "create-ecdh": "^4.0.4", + "create-hash": "^1.2.0", + "create-hmac": "^1.1.7", + "diffie-hellman": "^5.0.3", + "hash-base": "~3.0.4", + "inherits": "^2.0.4", + "pbkdf2": "^3.1.2", + "public-encrypt": "^4.0.3", + "randombytes": "^2.1.0", + "randomfill": "^1.0.4" + }, + "engines": { + "node": ">= 0.10" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/decimal.js": { + "version": "10.6.0", + "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.6.0.tgz", + "integrity": "sha512-YpgQiITW3JXGntzdUmyUR1V812Hn8T1YVXhCu+wO3OpS4eU9l4YdD3qjyiKdV6mvV29zapkMeD390UVEf2lkUg==", + "license": "MIT" + }, + "node_modules/deep-eql": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-5.0.2.tgz", + "integrity": "sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/deepmerge": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/define-properties": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", + "license": "MIT", + "dependencies": { + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/des.js": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.1.0.tgz", + "integrity": "sha512-r17GxjhUCjSRy8aiJpr8/UadFIzMzJGexI3Nmz4ADi9LYSFx4gTBp80+NaX/YsXWWLhpZ7v/v/ubEc/bCNfKwg==", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0" + } + }, + "node_modules/detect-libc": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", + "license": "Apache-2.0", + "optional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/diffie-hellman": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", + "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==", + "license": "MIT", + "dependencies": { + "bn.js": "^4.1.0", + "miller-rabin": "^4.0.0", + "randombytes": "^2.0.0" + } + }, + "node_modules/diffie-hellman/node_modules/bn.js": { + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.2.tgz", + "integrity": "sha512-n4DSx829VRTRByMRGdjQ9iqsN0Bh4OolPsFnaZBLcbi8iXcB+kJ9s7EnRt4wILZNV3kPLHkRVfOc/HvhC3ovDw==", + "license": "MIT" + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "license": "MIT" + }, + "node_modules/elliptic": { + "version": "6.6.1", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.6.1.tgz", + "integrity": "sha512-RaddvvMatK2LJHqFJ+YA4WysVN5Ita9E35botqIYspQ4TkRAlCicdzKOjlyv/1Za5RyTNn7di//eEV0uTAfe3g==", + "license": "MIT", + "dependencies": { + "bn.js": "^4.11.9", + "brorand": "^1.1.0", + "hash.js": "^1.0.0", + "hmac-drbg": "^1.0.1", + "inherits": "^2.0.4", + "minimalistic-assert": "^1.0.1", + "minimalistic-crypto-utils": "^1.0.1" + } + }, + "node_modules/elliptic/node_modules/bn.js": { + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.2.tgz", + "integrity": "sha512-n4DSx829VRTRByMRGdjQ9iqsN0Bh4OolPsFnaZBLcbi8iXcB+kJ9s7EnRt4wILZNV3kPLHkRVfOc/HvhC3ovDw==", + "license": "MIT" + }, + "node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "license": "MIT" + }, + "node_modules/enc-utils": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/enc-utils/-/enc-utils-3.0.0.tgz", + "integrity": "sha512-e57t/Z2HzWOLwOp7DZcV0VMEY8t7ptWwsxyp6kM2b2zrk6JqIpXxzkruHAMiBsy5wg9jp/183GdiRXCvBtzsYg==", + "license": "MIT", + "dependencies": { + "is-typedarray": "1.0.0", + "typedarray-to-buffer": "3.1.5" + } + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-module-lexer": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.7.0.tgz", + "integrity": "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==", + "license": "MIT", + "peer": true + }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-toolkit": { + "version": "1.41.0", + "resolved": "https://registry.npmjs.org/es-toolkit/-/es-toolkit-1.41.0.tgz", + "integrity": "sha512-bDd3oRmbVgqZCJS6WmeQieOrzpl3URcWBUVDXxOELlUW2FuW+0glPOz1n0KnRie+PdyvUZcXz2sOn00c6pPRIA==", + "license": "MIT", + "workspaces": [ + "docs", + "benchmarks" + ] + }, + "node_modules/esbuild": { + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.1.tgz", + "integrity": "sha512-BGO5LtrGC7vxnqucAe/rmvKdJllfGaYWdyABvyMoXQlfYMb2bbRuReWR5tEGE//4LcNJj9XrkovTqNYRFZHAMQ==", + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.25.1", + "@esbuild/android-arm": "0.25.1", + "@esbuild/android-arm64": "0.25.1", + "@esbuild/android-x64": "0.25.1", + "@esbuild/darwin-arm64": "0.25.1", + "@esbuild/darwin-x64": "0.25.1", + "@esbuild/freebsd-arm64": "0.25.1", + "@esbuild/freebsd-x64": "0.25.1", + "@esbuild/linux-arm": "0.25.1", + "@esbuild/linux-arm64": "0.25.1", + "@esbuild/linux-ia32": "0.25.1", + "@esbuild/linux-loong64": "0.25.1", + "@esbuild/linux-mips64el": "0.25.1", + "@esbuild/linux-ppc64": "0.25.1", + "@esbuild/linux-riscv64": "0.25.1", + "@esbuild/linux-s390x": "0.25.1", + "@esbuild/linux-x64": "0.25.1", + "@esbuild/netbsd-arm64": "0.25.1", + "@esbuild/netbsd-x64": "0.25.1", + "@esbuild/openbsd-arm64": "0.25.1", + "@esbuild/openbsd-x64": "0.25.1", + "@esbuild/sunos-x64": "0.25.1", + "@esbuild/win32-arm64": "0.25.1", + "@esbuild/win32-ia32": "0.25.1", + "@esbuild/win32-x64": "0.25.1" + } + }, + "node_modules/estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", + "dev": true, + "license": "MIT" + }, + "node_modules/ethereum-cryptography": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz", + "integrity": "sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ==", + "license": "MIT", + "dependencies": { + "@types/pbkdf2": "^3.0.0", + "@types/secp256k1": "^4.0.1", + "blakejs": "^1.1.0", + "browserify-aes": "^1.2.0", + "bs58check": "^2.1.2", + "create-hash": "^1.2.0", + "create-hmac": "^1.1.7", + "hash.js": "^1.1.7", + "keccak": "^3.0.0", + "pbkdf2": "^3.0.17", + "randombytes": "^2.1.0", + "safe-buffer": "^5.1.2", + "scrypt-js": "^3.0.0", + "secp256k1": "^4.0.1", + "setimmediate": "^1.0.5" + } + }, + "node_modules/ethereumjs-util": { + "version": "7.1.5", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-7.1.5.tgz", + "integrity": "sha512-SDl5kKrQAudFBUe5OJM9Ac6WmMyYmXX/6sTmLZ3ffG2eY6ZIGBes3pEDxNN6V72WyOw4CPD5RomKdsa8DAAwLg==", + "license": "MPL-2.0", + "dependencies": { + "@types/bn.js": "^5.1.0", + "bn.js": "^5.1.2", + "create-hash": "^1.1.2", + "ethereum-cryptography": "^0.1.3", + "rlp": "^2.2.4" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/ethereumjs-wallet": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/ethereumjs-wallet/-/ethereumjs-wallet-1.0.2.tgz", + "integrity": "sha512-CCWV4RESJgRdHIvFciVQFnCHfqyhXWchTPlkfp28Qc53ufs+doi5I/cV2+xeK9+qEo25XCWfP9MiL+WEPAZfdA==", + "deprecated": "New package name format for new versions: @ethereumjs/wallet. Please update.", + "license": "MIT", + "dependencies": { + "aes-js": "^3.1.2", + "bs58check": "^2.1.2", + "ethereum-cryptography": "^0.1.3", + "ethereumjs-util": "^7.1.2", + "randombytes": "^2.1.0", + "scrypt-js": "^3.0.1", + "utf8": "^3.0.0", + "uuid": "^8.3.2" + } + }, + "node_modules/ethers": { + "version": "6.13.5", + "resolved": "https://registry.npmjs.org/ethers/-/ethers-6.13.5.tgz", + "integrity": "sha512-+knKNieu5EKRThQJWwqaJ10a6HE9sSehGeqWN65//wE7j47ZpFhKAnHB/JJFibwwg61I/koxaPsXbXpD/skNOQ==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/ethers-io/" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { + "@adraffy/ens-normalize": "1.10.1", + "@noble/curves": "1.2.0", + "@noble/hashes": "1.3.2", + "@types/node": "22.7.5", + "aes-js": "4.0.0-beta.5", + "tslib": "2.7.0", + "ws": "8.17.1" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/ethers/node_modules/@noble/curves": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.2.0.tgz", + "integrity": "sha512-oYclrNgRaM9SsBUBVbb8M6DTV7ZHRTKugureoYEncY5c65HOmRzvSiTE3y5CYaPYJA/GVkrhXEoF0M3Ya9PMnw==", + "license": "MIT", + "dependencies": { + "@noble/hashes": "1.3.2" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/ethers/node_modules/@noble/hashes": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.2.tgz", + "integrity": "sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ==", + "license": "MIT", + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/ethers/node_modules/@types/node": { + "version": "22.7.5", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.7.5.tgz", + "integrity": "sha512-jML7s2NAzMWc//QSJ1a3prpk78cOPchGvXJsC3C6R6PSMoooztvRVQEz89gmBTBY1SPMaqo5teB4uNHPdetShQ==", + "license": "MIT", + "dependencies": { + "undici-types": "~6.19.2" + } + }, + "node_modules/ethers/node_modules/aes-js": { + "version": "4.0.0-beta.5", + "resolved": "https://registry.npmjs.org/aes-js/-/aes-js-4.0.0-beta.5.tgz", + "integrity": "sha512-G965FqalsNyrPqgEGON7nIx1e/OVENSgiEIzyC63haUMuvNnwIgIjMs52hlTCKhkBny7A2ORNlfY9Zu+jmGk1Q==", + "license": "MIT" + }, + "node_modules/ethers/node_modules/tslib": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", + "license": "0BSD" + }, + "node_modules/ethers/node_modules/undici-types": { + "version": "6.19.8", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", + "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", + "license": "MIT" + }, + "node_modules/ethers/node_modules/ws": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz", + "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==", + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/event-iterator": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/event-iterator/-/event-iterator-2.0.0.tgz", + "integrity": "sha512-KGft0ldl31BZVV//jj+IAIGCxkvvUkkON+ScH6zfoX+l+omX6001ggyRSpI0Io2Hlro0ThXotswCtfzS8UkIiQ==", + "license": "MIT" + }, + "node_modules/eventemitter3": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", + "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", + "license": "MIT" + }, + "node_modules/events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "license": "MIT", + "engines": { + "node": ">=0.8.x" + } + }, + "node_modules/evp_bytestokey": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", + "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", + "license": "MIT", + "dependencies": { + "md5.js": "^1.3.4", + "safe-buffer": "^5.1.1" + } + }, + "node_modules/expect-type": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.2.2.tgz", + "integrity": "sha512-JhFGDVJ7tmDJItKhYgJCGLOWjuK9vPxiXoUFLwLDc99NlmklilbiQJwoctZtt13+xMw91MCk/REan6MWHqDjyA==", + "license": "Apache-2.0", + "peer": true, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/fflate": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/fflate/-/fflate-0.8.2.tgz", + "integrity": "sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A==", + "license": "MIT" + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-cache-dir": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.2.tgz", + "integrity": "sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==", + "dev": true, + "license": "MIT", + "dependencies": { + "commondir": "^1.0.1", + "make-dir": "^3.0.2", + "pkg-dir": "^4.1.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/avajs/find-cache-dir?sponsor=1" + } + }, + "node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/follow-redirects": { + "version": "1.15.11", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.11.tgz", + "integrity": "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "license": "MIT", + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/for-each": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz", + "integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==", + "license": "MIT", + "dependencies": { + "is-callable": "^1.2.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/foreground-child": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", + "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", + "license": "ISC", + "dependencies": { + "cross-spawn": "^7.0.6", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/form-data": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.4.tgz", + "integrity": "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==", + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.2", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true, + "license": "ISC" + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/fuels": { + "version": "0.101.1", + "resolved": "https://registry.npmjs.org/fuels/-/fuels-0.101.1.tgz", + "integrity": "sha512-/0LwAynHrKZZn4aw7QkyVc+Af+MIwlg82eCVSdAUVDJ+/pQ6Oma+aZyqjynmsKEuOlvkzw+jhUReGoWqexF4tg==", + "license": "Apache-2.0", + "dependencies": { + "@fuel-ts/abi-coder": "0.101.1", + "@fuel-ts/abi-typegen": "0.101.1", + "@fuel-ts/account": "0.101.1", + "@fuel-ts/address": "0.101.1", + "@fuel-ts/contract": "0.101.1", + "@fuel-ts/crypto": "0.101.1", + "@fuel-ts/errors": "0.101.1", + "@fuel-ts/hasher": "0.101.1", + "@fuel-ts/math": "0.101.1", + "@fuel-ts/program": "0.101.1", + "@fuel-ts/recipes": "0.101.1", + "@fuel-ts/script": "0.101.1", + "@fuel-ts/transactions": "0.101.1", + "@fuel-ts/utils": "0.101.1", + "@fuel-ts/versions": "0.101.1", + "@fuels/vm-asm": "0.60.2", + "bundle-require": "5.1.0", + "chalk": "4", + "chokidar": "3.6.0", + "commander": "13.1.0", + "esbuild": "0.25.1", + "glob": "10.4.5", + "handlebars": "4.7.8", + "joycon": "3.1.1", + "lodash.camelcase": "4.3.0", + "portfinder": "1.0.32", + "toml": "3.0.0", + "uglify-js": "3.19.3", + "yup": "1.6.1" + }, + "bin": { + "fuels": "fuels.js" + }, + "engines": { + "node": "^18.20.3 || ^20.0.0 || ^22.0.0" + } + }, + "node_modules/fuels/node_modules/glob": { + "version": "10.4.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", + "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "license": "ISC", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/fuels/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/generator-function": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/generator-function/-/generator-function-2.0.1.tgz", + "integrity": "sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/glob": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", + "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^5.0.1", + "once": "^1.3.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/globalthis": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", + "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", + "license": "MIT", + "dependencies": { + "define-properties": "^1.2.1", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/google-protobuf": { + "version": "3.21.4", + "resolved": "https://registry.npmjs.org/google-protobuf/-/google-protobuf-3.21.4.tgz", + "integrity": "sha512-MnG7N936zcKTco4Jd2PX2U96Kf9PxygAPKBug+74LHzmHXmceN16MmRcdgZv+DGef/S9YvQAfRsNCn4cjf9yyQ==", + "license": "(BSD-3-Clause AND Apache-2.0)" + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/graphql": { + "version": "16.10.0", + "resolved": "https://registry.npmjs.org/graphql/-/graphql-16.10.0.tgz", + "integrity": "sha512-AjqGKbDGUFRKIRCP9tCKiIGHyriz2oHEbPIbEtcSLSs4YjReZOIPQQWek4+6hjw62H9QShXHyaGivGiYVLeYFQ==", + "license": "MIT", + "engines": { + "node": "^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0" + } + }, + "node_modules/graphql-request": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/graphql-request/-/graphql-request-6.1.0.tgz", + "integrity": "sha512-p+XPfS4q7aIpKVcgmnZKhMNqhltk20hfXtkaIkTfjjmiKMJ5xrt5c743cL03y/K7y1rg3WrIC49xGiEQ4mxdNw==", + "license": "MIT", + "dependencies": { + "@graphql-typed-document-node/core": "^3.2.0", + "cross-fetch": "^3.1.5" + }, + "peerDependencies": { + "graphql": "14 - 16" + } + }, + "node_modules/graphql-request/node_modules/cross-fetch": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.2.0.tgz", + "integrity": "sha512-Q+xVJLoGOeIMXZmbUK4HYk+69cQH6LudR0Vu/pRm2YlU/hDV9CiS0gKUMaWY5f2NeUH9C1nV3bsTlCo0FsTV1Q==", + "license": "MIT", + "dependencies": { + "node-fetch": "^2.7.0" + } + }, + "node_modules/graphql-tag": { + "version": "2.12.6", + "resolved": "https://registry.npmjs.org/graphql-tag/-/graphql-tag-2.12.6.tgz", + "integrity": "sha512-FdSNcu2QQcWnM2VNvSCCDCVS5PpPqpzgFT8+GXzqJuoDd0CBncxCY278u4mhRO7tMgo2JjgJA5aZ+nWSQ/Z+xg==", + "license": "MIT", + "dependencies": { + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "graphql": "^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0" + } + }, + "node_modules/handlebars": { + "version": "4.7.8", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.8.tgz", + "integrity": "sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==", + "license": "MIT", + "dependencies": { + "minimist": "^1.2.5", + "neo-async": "^2.6.2", + "source-map": "^0.6.1", + "wordwrap": "^1.0.0" + }, + "bin": { + "handlebars": "bin/handlebars" + }, + "engines": { + "node": ">=0.4.7" + }, + "optionalDependencies": { + "uglify-js": "^3.1.4" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hash-base": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.5.tgz", + "integrity": "sha512-vXm0l45VbcHEVlTCzs8M+s0VeYsB2lnlAaThoLKGXr3bE/VWDOelNUnycUPEhKEaXARL2TEFjBOyUiM6+55KBg==", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.4", + "safe-buffer": "^5.2.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/hash.js": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", + "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "minimalistic-assert": "^1.0.1" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/hmac-drbg": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", + "integrity": "sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg==", + "license": "MIT", + "dependencies": { + "hash.js": "^1.0.3", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.1" + } + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "BSD-3-Clause" + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "dev": true, + "license": "ISC", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "license": "ISC" + }, + "node_modules/is-arguments": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.2.0.tgz", + "integrity": "sha512-7bVbi0huj/wrIAOzb8U1aszg9kdi3KN/CyU19CTI7tAoZYEZoL9yCDXpbXN+uPsuWnP02cyug1gleqq+TU+YCA==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "license": "MIT", + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-callable": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-core-module": { + "version": "2.16.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", + "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", + "dev": true, + "license": "MIT", + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-generator-function": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.2.tgz", + "integrity": "sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.4", + "generator-function": "^2.0.0", + "get-proto": "^1.0.1", + "has-tostringtag": "^1.0.2", + "safe-regex-test": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz", + "integrity": "sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==", + "dev": true, + "license": "MIT" + }, + "node_modules/is-nan": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/is-nan/-/is-nan-1.3.2.tgz", + "integrity": "sha512-E+zBKpQ2t6MEo1VsonYmluk9NxGrbzpeeLC2xIViuO2EjU2xsXsBPwTr3Ykv9l08UYEVEdWeRZNouaZqF6RN0w==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-reference": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/is-reference/-/is-reference-1.2.1.tgz", + "integrity": "sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "*" + } + }, + "node_modules/is-regex": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz", + "integrity": "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-typed-array": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz", + "integrity": "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==", + "license": "MIT", + "dependencies": { + "which-typed-array": "^1.1.16" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==", + "license": "MIT" + }, + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "license": "MIT" + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "license": "ISC" + }, + "node_modules/isomorphic-ws": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/isomorphic-ws/-/isomorphic-ws-4.0.1.tgz", + "integrity": "sha512-BhBvN2MBpWTaSHdWRb/bwdZJ1WaehQ2L1KngkCkfLUGF0mAWAT1sQUQacEmQ0jXkFw/czDXPNQSL5u2/Krsz1w==", + "license": "MIT", + "peerDependencies": { + "ws": "*" + } + }, + "node_modules/isows": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/isows/-/isows-1.0.7.tgz", + "integrity": "sha512-I1fSfDCZL5P0v33sVqeTDSpcstAg/N+wF5HS033mogOVIp4B+oHC7oOCsA3axAbBSGTJ8QubbNmnIRN/h8U7hg==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/wevm" + } + ], + "license": "MIT", + "peer": true, + "peerDependencies": { + "ws": "*" + } + }, + "node_modules/it-stream-types": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/it-stream-types/-/it-stream-types-2.0.2.tgz", + "integrity": "sha512-Rz/DEZ6Byn/r9+/SBCuJhpPATDF9D+dz5pbgSUyBsCDtza6wtNATrz/jz1gDyNanC3XdLboriHnOC925bZRBww==", + "license": "Apache-2.0 OR MIT" + }, + "node_modules/it-ws": { + "version": "6.1.5", + "resolved": "https://registry.npmjs.org/it-ws/-/it-ws-6.1.5.tgz", + "integrity": "sha512-uWjMtpy5HqhSd/LlrlP3fhYrr7rUfJFFMABv0F5d6n13Q+0glhZthwUKpEAVhDrXY95Tb1RB5lLqqef+QbVNaw==", + "license": "Apache-2.0 OR MIT", + "dependencies": { + "@types/ws": "^8.2.2", + "event-iterator": "^2.0.0", + "it-stream-types": "^2.0.1", + "uint8arrays": "^5.0.0", + "ws": "^8.4.0" + }, + "engines": { + "node": ">=16.0.0", + "npm": ">=7.0.0" + } + }, + "node_modules/it-ws/node_modules/ws": { + "version": "8.18.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.3.tgz", + "integrity": "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==", + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/jackspeak": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, + "node_modules/joycon": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/joycon/-/joycon-3.1.1.tgz", + "integrity": "sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==", + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/js-sha3": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.8.0.tgz", + "integrity": "sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==", + "license": "MIT" + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/jsonfile": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", + "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", + "dev": true, + "license": "MIT", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/keccak": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/keccak/-/keccak-3.0.4.tgz", + "integrity": "sha512-3vKuW0jV8J3XNTzvfyicFR5qvxrSAGl7KIhvgOu5cmWwM7tZRj3fMbj/pfIf4be7aznbc+prBWGjywox/g2Y6Q==", + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "node-addon-api": "^2.0.0", + "node-gyp-build": "^4.2.0", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/keccak/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/libsodium-sumo": { + "version": "0.7.15", + "resolved": "https://registry.npmjs.org/libsodium-sumo/-/libsodium-sumo-0.7.15.tgz", + "integrity": "sha512-5tPmqPmq8T8Nikpm1Nqj0hBHvsLFCXvdhBFV7SGOitQPZAA6jso8XoL0r4L7vmfKXr486fiQInvErHtEvizFMw==", + "license": "ISC" + }, + "node_modules/libsodium-wrappers-sumo": { + "version": "0.7.15", + "resolved": "https://registry.npmjs.org/libsodium-wrappers-sumo/-/libsodium-wrappers-sumo-0.7.15.tgz", + "integrity": "sha512-aSWY8wKDZh5TC7rMvEdTHoyppVq/1dTSAeAR7H6pzd6QRT3vQWcT5pGwCotLcpPEOLXX6VvqihSPkpEhYAjANA==", + "license": "ISC", + "dependencies": { + "libsodium-sumo": "^0.7.15" + } + }, + "node_modules/load-tsconfig": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/load-tsconfig/-/load-tsconfig-0.2.5.tgz", + "integrity": "sha512-IXO6OCs9yg8tMKzfPZ1YmheJbZCiEsnBdcB03l0OcfK9prKnJb96siuHCr5Fl37/yo9DnKU+TLpxzTUspw9shg==", + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + } + }, + "node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "license": "MIT" + }, + "node_modules/lodash.camelcase": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", + "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==", + "license": "MIT" + }, + "node_modules/long": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/long/-/long-5.3.2.tgz", + "integrity": "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==", + "license": "Apache-2.0" + }, + "node_modules/loupe": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/loupe/-/loupe-3.2.1.tgz", + "integrity": "sha512-CdzqowRJCeLU72bHvWqwRBBlLcMEtIvGrlvef74kMnV2AolS9Y8xUv1I0U/MNAWMhBlKIoyuEgoJ0t/bbwHbLQ==", + "license": "MIT", + "peer": true + }, + "node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "license": "ISC" + }, + "node_modules/magic-string": { + "version": "0.30.21", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", + "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.5" + } + }, + "node_modules/make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "dev": true, + "license": "MIT", + "dependencies": { + "semver": "^6.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/make-dir/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/md5.js": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", + "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", + "license": "MIT", + "dependencies": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "node_modules/miller-rabin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", + "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", + "license": "MIT", + "dependencies": { + "bn.js": "^4.0.0", + "brorand": "^1.0.1" + }, + "bin": { + "miller-rabin": "bin/miller-rabin" + } + }, + "node_modules/miller-rabin/node_modules/bn.js": { + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.2.tgz", + "integrity": "sha512-n4DSx829VRTRByMRGdjQ9iqsN0Bh4OolPsFnaZBLcbi8iXcB+kJ9s7EnRt4wILZNV3kPLHkRVfOc/HvhC3ovDw==", + "license": "MIT" + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", + "license": "ISC" + }, + "node_modules/minimalistic-crypto-utils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", + "integrity": "sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==", + "license": "MIT" + }, + "node_modules/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "license": "ISC", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/mkdirp": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-3.0.1.tgz", + "integrity": "sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==", + "license": "MIT", + "bin": { + "mkdirp": "dist/cjs/src/bin.js" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/msgpackr": { + "version": "1.11.5", + "resolved": "https://registry.npmjs.org/msgpackr/-/msgpackr-1.11.5.tgz", + "integrity": "sha512-UjkUHN0yqp9RWKy0Lplhh+wlpdt9oQBYgULZOiFhV3VclSF1JnSQWZ5r9gORQlNYaUKQoR8itv7g7z1xDDuACA==", + "license": "MIT", + "optionalDependencies": { + "msgpackr-extract": "^3.0.2" + } + }, + "node_modules/msgpackr-extract": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/msgpackr-extract/-/msgpackr-extract-3.0.3.tgz", + "integrity": "sha512-P0efT1C9jIdVRefqjzOQ9Xml57zpOXnIuS+csaB4MdZbTdmGDLo8XhzBG1N7aO11gKDDkJvBLULeFTo46wwreA==", + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "dependencies": { + "node-gyp-build-optional-packages": "5.2.2" + }, + "bin": { + "download-msgpackr-prebuilds": "bin/download-prebuilds.js" + }, + "optionalDependencies": { + "@msgpackr-extract/msgpackr-extract-darwin-arm64": "3.0.3", + "@msgpackr-extract/msgpackr-extract-darwin-x64": "3.0.3", + "@msgpackr-extract/msgpackr-extract-linux-arm": "3.0.3", + "@msgpackr-extract/msgpackr-extract-linux-arm64": "3.0.3", + "@msgpackr-extract/msgpackr-extract-linux-x64": "3.0.3", + "@msgpackr-extract/msgpackr-extract-win32-x64": "3.0.3" + } + }, + "node_modules/multiformats": { + "version": "13.4.1", + "resolved": "https://registry.npmjs.org/multiformats/-/multiformats-13.4.1.tgz", + "integrity": "sha512-VqO6OSvLrFVAYYjgsr8tyv62/rCQhPgsZUXLTqoFLSgdkgiUYKYeArbt1uWLlEpkjxQe+P0+sHlbPEte1Bi06Q==", + "license": "Apache-2.0 OR MIT" + }, + "node_modules/nanoid": { + "version": "3.3.11", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", + "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "peer": true, + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "license": "MIT" + }, + "node_modules/node-addon-api": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-2.0.2.tgz", + "integrity": "sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA==", + "license": "MIT" + }, + "node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "license": "MIT", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/node-gyp-build": { + "version": "4.8.4", + "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.4.tgz", + "integrity": "sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ==", + "license": "MIT", + "bin": { + "node-gyp-build": "bin.js", + "node-gyp-build-optional": "optional.js", + "node-gyp-build-test": "build-test.js" + } + }, + "node_modules/node-gyp-build-optional-packages": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/node-gyp-build-optional-packages/-/node-gyp-build-optional-packages-5.2.2.tgz", + "integrity": "sha512-s+w+rBWnpTMwSFbaE0UXsRlg7hU4FjekKU4eyAih5T8nJuNZT1nNsskXpxmeqSK9UzkBl6UgRlnKc8hz8IEqOw==", + "license": "MIT", + "optional": true, + "dependencies": { + "detect-libc": "^2.0.1" + }, + "bin": { + "node-gyp-build-optional-packages": "bin.js", + "node-gyp-build-optional-packages-optional": "optional.js", + "node-gyp-build-optional-packages-test": "build-test.js" + } + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-is": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.6.tgz", + "integrity": "sha512-F8cZ+KfGlSGi09lJT7/Nd6KJZ9ygtvYC0/UYYLI9nmQKLMnydpB9yvbv9K1uSkEu7FU9vYPmVwLg328tX+ot3Q==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.assign": { + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.7.tgz", + "integrity": "sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0", + "has-symbols": "^1.1.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/ox": { + "version": "0.9.6", + "resolved": "https://registry.npmjs.org/ox/-/ox-0.9.6.tgz", + "integrity": "sha512-8SuCbHPvv2eZLYXrNmC0EC12rdzXQLdhnOMlHDW2wiCPLxBrOOJwX5L5E61by+UjTPOryqQiRSnjIKCI+GykKg==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/wevm" + } + ], + "license": "MIT", + "peer": true, + "dependencies": { + "@adraffy/ens-normalize": "^1.11.0", + "@noble/ciphers": "^1.3.0", + "@noble/curves": "1.9.1", + "@noble/hashes": "^1.8.0", + "@scure/bip32": "^1.7.0", + "@scure/bip39": "^1.6.0", + "abitype": "^1.0.9", + "eventemitter3": "5.0.1" + }, + "peerDependencies": { + "typescript": ">=5.4.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/ox/node_modules/@adraffy/ens-normalize": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@adraffy/ens-normalize/-/ens-normalize-1.11.1.tgz", + "integrity": "sha512-nhCBV3quEgesuf7c7KYfperqSS14T8bYuvJ8PcLJp6znkZpFc0AuW4qBtr8eKVyPPe/8RSr7sglCWPU5eaxwKQ==", + "license": "MIT", + "peer": true + }, + "node_modules/ox/node_modules/@noble/curves": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.9.1.tgz", + "integrity": "sha512-k11yZxZg+t+gWvBbIswW0yoJlu8cHOC7dhunwOzoWH/mXGBiYyR4YY6hAEK/3EUs4UpB8la1RfdRpeGsFHkWsA==", + "license": "MIT", + "peer": true, + "dependencies": { + "@noble/hashes": "1.8.0" + }, + "engines": { + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/ox/node_modules/eventemitter3": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", + "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==", + "license": "MIT", + "peer": true + }, + "node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/package-json-from-dist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", + "license": "BlueOak-1.0.0" + }, + "node_modules/parse-asn1": { + "version": "5.1.9", + "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.9.tgz", + "integrity": "sha512-fIYNuZ/HastSb80baGOuPRo1O9cf4baWw5WsAp7dBuUzeTD/BoaG8sVTdlPFksBE2lF21dN+A1AnrpIjSWqHHg==", + "license": "ISC", + "dependencies": { + "asn1.js": "^4.10.1", + "browserify-aes": "^1.2.0", + "evp_bytestokey": "^1.0.3", + "pbkdf2": "^3.1.5", + "safe-buffer": "^5.2.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true, + "license": "MIT" + }, + "node_modules/path-scurry": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", + "license": "BlueOak-1.0.0", + "dependencies": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/pathe": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", + "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", + "license": "MIT", + "peer": true + }, + "node_modules/pathval": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-2.0.1.tgz", + "integrity": "sha512-//nshmD55c46FuFw26xV/xFAaB5HF9Xdap7HJBBnrKdAd6/GxDBaNA1870O79+9ueg61cZLSVc+OaFlfmObYVQ==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 14.16" + } + }, + "node_modules/pbkdf2": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.5.tgz", + "integrity": "sha512-Q3CG/cYvCO1ye4QKkuH7EXxs3VC/rI1/trd+qX2+PolbaKG0H+bgcZzrTt96mMyRtejk+JMCiLUn3y29W8qmFQ==", + "license": "MIT", + "dependencies": { + "create-hash": "^1.2.0", + "create-hmac": "^1.1.7", + "ripemd160": "^2.0.3", + "safe-buffer": "^5.2.1", + "sha.js": "^2.4.12", + "to-buffer": "^1.2.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "find-up": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/portfinder": { + "version": "1.0.32", + "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.32.tgz", + "integrity": "sha512-on2ZJVVDXRADWE6jnQaX0ioEylzgBpQk8r55NE4wjXW1ZxO+BgDlY6DXwj20i0V8eB4SenDQ00WEaxfiIQPcxg==", + "license": "MIT", + "dependencies": { + "async": "^2.6.4", + "debug": "^3.2.7", + "mkdirp": "^0.5.6" + }, + "engines": { + "node": ">= 0.12.0" + } + }, + "node_modules/portfinder/node_modules/mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "license": "MIT", + "dependencies": { + "minimist": "^1.2.6" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/possible-typed-array-names": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz", + "integrity": "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/postcss": { + "version": "8.5.6", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", + "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "peer": true, + "dependencies": { + "nanoid": "^3.3.11", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "license": "MIT" + }, + "node_modules/property-expr": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/property-expr/-/property-expr-2.0.6.tgz", + "integrity": "sha512-SVtmxhRE/CGkn3eZY1T6pC8Nln6Fr/lu1mKSgRud0eC73whjGfoAogbn78LkD8aFL0zz3bAFerKSnOl7NlErBA==", + "license": "MIT" + }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", + "license": "MIT" + }, + "node_modules/public-encrypt": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz", + "integrity": "sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==", + "license": "MIT", + "dependencies": { + "bn.js": "^4.1.0", + "browserify-rsa": "^4.0.0", + "create-hash": "^1.1.0", + "parse-asn1": "^5.0.0", + "randombytes": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "node_modules/public-encrypt/node_modules/bn.js": { + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.2.tgz", + "integrity": "sha512-n4DSx829VRTRByMRGdjQ9iqsN0Bh4OolPsFnaZBLcbi8iXcB+kJ9s7EnRt4wILZNV3kPLHkRVfOc/HvhC3ovDw==", + "license": "MIT" + }, + "node_modules/ramda": { + "version": "0.30.1", + "resolved": "https://registry.npmjs.org/ramda/-/ramda-0.30.1.tgz", + "integrity": "sha512-tEF5I22zJnuclswcZMc8bDIrwRHRzf+NqVEmqg50ShAZMP7MWeR/RGDthfM/p+BlqvF2fXAzpn8i+SJcYD3alw==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/ramda" + } + }, + "node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "license": "MIT", + "dependencies": { + "safe-buffer": "^5.1.0" + } + }, + "node_modules/randomfill": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz", + "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==", + "license": "MIT", + "dependencies": { + "randombytes": "^2.0.5", + "safe-buffer": "^5.1.0" + } + }, + "node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "license": "MIT", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/readable-stream/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "license": "MIT" + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "license": "MIT", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/readdirp/node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/readonly-date": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/readonly-date/-/readonly-date-1.0.0.tgz", + "integrity": "sha512-tMKIV7hlk0h4mO3JTmmVuIlJVXjKk3Sep9Bf5OH0O+758ruuVkUy2J9SttDLm91IEX/WHlXPSpxMGjPj4beMIQ==", + "license": "Apache-2.0" + }, + "node_modules/regenerator-runtime": { + "version": "0.14.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", + "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==", + "license": "MIT" + }, + "node_modules/resolve": { + "version": "1.22.11", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.11.tgz", + "integrity": "sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-core-module": "^2.16.1", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/rimraf": { + "version": "5.0.10", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.10.tgz", + "integrity": "sha512-l0OE8wL34P4nJH/H2ffoaniAokM2qSmrtXHmlpvYr5AVVX8msAyW0l8NVJFDxlSK4u3Uh/f41cQheDVdnYijwQ==", + "license": "ISC", + "dependencies": { + "glob": "^10.3.7" + }, + "bin": { + "rimraf": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rimraf/node_modules/glob": { + "version": "10.4.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", + "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "license": "ISC", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rimraf/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/ripemd160": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.3.tgz", + "integrity": "sha512-5Di9UC0+8h1L6ZD2d7awM7E/T4uA1fJRlx6zk/NvdCCVEoAnFqvHmCuNeIKoCeIixBX/q8uM+6ycDvF8woqosA==", + "license": "MIT", + "dependencies": { + "hash-base": "^3.1.2", + "inherits": "^2.0.4" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/ripemd160/node_modules/hash-base": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.2.tgz", + "integrity": "sha512-Bb33KbowVTIj5s7Ked1OsqHUeCpz//tPwR+E2zJgJKo9Z5XolZ9b6bdUgjmYlwnWhoOQKoTd1TYToZGn5mAYOg==", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.4", + "readable-stream": "^2.3.8", + "safe-buffer": "^5.2.1", + "to-buffer": "^1.2.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/rlp": { + "version": "2.2.7", + "resolved": "https://registry.npmjs.org/rlp/-/rlp-2.2.7.tgz", + "integrity": "sha512-d5gdPmgQ0Z+AklL2NVXr/IoSjNZFfTVvQWzL/AM2AOcSzYP2xjlb0AC8YyCLc41MSNf6P6QVtjgPdmVtzb+4lQ==", + "license": "MPL-2.0", + "dependencies": { + "bn.js": "^5.2.0" + }, + "bin": { + "rlp": "bin/rlp" + } + }, + "node_modules/rollup": { + "version": "4.53.2", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.53.2.tgz", + "integrity": "sha512-MHngMYwGJVi6Fmnk6ISmnk7JAHRNF0UkuucA0CUW3N3a4KnONPEZz+vUanQP/ZC/iY1Qkf3bwPWzyY84wEks1g==", + "license": "MIT", + "dependencies": { + "@types/estree": "1.0.8" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.53.2", + "@rollup/rollup-android-arm64": "4.53.2", + "@rollup/rollup-darwin-arm64": "4.53.2", + "@rollup/rollup-darwin-x64": "4.53.2", + "@rollup/rollup-freebsd-arm64": "4.53.2", + "@rollup/rollup-freebsd-x64": "4.53.2", + "@rollup/rollup-linux-arm-gnueabihf": "4.53.2", + "@rollup/rollup-linux-arm-musleabihf": "4.53.2", + "@rollup/rollup-linux-arm64-gnu": "4.53.2", + "@rollup/rollup-linux-arm64-musl": "4.53.2", + "@rollup/rollup-linux-loong64-gnu": "4.53.2", + "@rollup/rollup-linux-ppc64-gnu": "4.53.2", + "@rollup/rollup-linux-riscv64-gnu": "4.53.2", + "@rollup/rollup-linux-riscv64-musl": "4.53.2", + "@rollup/rollup-linux-s390x-gnu": "4.53.2", + "@rollup/rollup-linux-x64-gnu": "4.53.2", + "@rollup/rollup-linux-x64-musl": "4.53.2", + "@rollup/rollup-openharmony-arm64": "4.53.2", + "@rollup/rollup-win32-arm64-msvc": "4.53.2", + "@rollup/rollup-win32-ia32-msvc": "4.53.2", + "@rollup/rollup-win32-x64-gnu": "4.53.2", + "@rollup/rollup-win32-x64-msvc": "4.53.2", + "fsevents": "~2.3.2" + } + }, + "node_modules/rollup-plugin-dts": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/rollup-plugin-dts/-/rollup-plugin-dts-6.2.3.tgz", + "integrity": "sha512-UgnEsfciXSPpASuOelix7m4DrmyQgiaWBnvI0TM4GxuDh5FkqW8E5hu57bCxXB90VvR1WNfLV80yEDN18UogSA==", + "dev": true, + "license": "LGPL-3.0-only", + "dependencies": { + "magic-string": "^0.30.17" + }, + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/Swatinem" + }, + "optionalDependencies": { + "@babel/code-frame": "^7.27.1" + }, + "peerDependencies": { + "rollup": "^3.29.4 || ^4", + "typescript": "^4.5 || ^5.0" + } + }, + "node_modules/rollup-plugin-typescript2": { + "version": "0.36.0", + "resolved": "https://registry.npmjs.org/rollup-plugin-typescript2/-/rollup-plugin-typescript2-0.36.0.tgz", + "integrity": "sha512-NB2CSQDxSe9+Oe2ahZbf+B4bh7pHwjV5L+RSYpCu7Q5ROuN94F9b6ioWwKfz3ueL3KTtmX4o2MUH2cgHDIEUsw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@rollup/pluginutils": "^4.1.2", + "find-cache-dir": "^3.3.2", + "fs-extra": "^10.0.0", + "semver": "^7.5.4", + "tslib": "^2.6.2" + }, + "peerDependencies": { + "rollup": ">=1.26.3", + "typescript": ">=2.4.0" + } + }, + "node_modules/rollup-plugin-typescript2/node_modules/@rollup/pluginutils": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-4.2.1.tgz", + "integrity": "sha512-iKnFXr7NkdZAIHiIWE+BX5ULi/ucVFYWD6TbAV+rZctiRTY2PL6tsIKhoIOaoskiWAkgu+VsbXgUVDNLHf+InQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "estree-walker": "^2.0.1", + "picomatch": "^2.2.2" + }, + "engines": { + "node": ">= 8.0.0" + } + }, + "node_modules/rollup-plugin-typescript2/node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/safe-regex-test": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.1.0.tgz", + "integrity": "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "is-regex": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/scrypt-js": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/scrypt-js/-/scrypt-js-3.0.1.tgz", + "integrity": "sha512-cdwTTnqPu0Hyvf5in5asVdZocVDTNRmR7XEcJuIzMjJeSHybHl7vpB66AzwTaIg6CLSbtjcxc8fqcySfnTkccA==", + "license": "MIT" + }, + "node_modules/secp256k1": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/secp256k1/-/secp256k1-4.0.4.tgz", + "integrity": "sha512-6JfvwvjUOn8F/jUoBY2Q1v5WY5XS+rj8qSe0v8Y4ezH4InLgTEeOOPQsRll9OV429Pvo6BCHGavIyJfr3TAhsw==", + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "elliptic": "^6.5.7", + "node-addon-api": "^5.0.0", + "node-gyp-build": "^4.2.0" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/secp256k1/node_modules/node-addon-api": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-5.1.0.tgz", + "integrity": "sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA==", + "license": "MIT" + }, + "node_modules/semver": { + "version": "7.7.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", + "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/setimmediate": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==", + "license": "MIT" + }, + "node_modules/sha.js": { + "version": "2.4.12", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.12.tgz", + "integrity": "sha512-8LzC5+bvI45BjpfXU8V5fdU2mfeKiQe1D1gIMn7XUlF3OTUrpdJpPPH4EMAnF0DsHHdSZqCdSss5qCmJKuiO3w==", + "license": "(MIT AND BSD-3-Clause)", + "dependencies": { + "inherits": "^2.0.4", + "safe-buffer": "^5.2.1", + "to-buffer": "^1.2.0" + }, + "bin": { + "sha.js": "bin.js" + }, + "engines": { + "node": ">= 0.10" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/siginfo": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz", + "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==", + "license": "ISC", + "peer": true + }, + "node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "license": "BSD-3-Clause", + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/stackback": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", + "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==", + "license": "MIT", + "peer": true + }, + "node_modules/std-env": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.10.0.tgz", + "integrity": "sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==", + "license": "MIT", + "peer": true + }, + "node_modules/stream-browserify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-3.0.0.tgz", + "integrity": "sha512-H73RAHsVBapbim0tU2JwwOiXUj+fikfiaoYAKHF3VJfA0pe2BCzkhAHBlLG6REzE+2WNZcxOXjK7lkso+9euLA==", + "license": "MIT", + "dependencies": { + "inherits": "~2.0.4", + "readable-stream": "^3.5.0" + } + }, + "node_modules/stream-browserify/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/string_decoder/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "license": "MIT" + }, + "node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "license": "MIT", + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "license": "MIT" + }, + "node_modules/string-width-cjs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz", + "integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/symbol-observable": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-2.0.3.tgz", + "integrity": "sha512-sQV7phh2WCYAn81oAkakC5qjq2Ml0g8ozqz03wOGnx9dDlG1de6yrF+0RAzSJD8fPUow3PTSMf2SAbOGxb93BA==", + "license": "MIT", + "engines": { + "node": ">=0.10" + } + }, + "node_modules/tiny-case": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/tiny-case/-/tiny-case-1.0.3.tgz", + "integrity": "sha512-Eet/eeMhkO6TX8mnUteS9zgPbUMQa4I6Kkp5ORiBD5476/m+PIRiumP5tmh5ioJpH7k51Kehawy2UDfsnxxY8Q==", + "license": "MIT" + }, + "node_modules/tinybench": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz", + "integrity": "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==", + "license": "MIT", + "peer": true + }, + "node_modules/tinyexec": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-0.3.2.tgz", + "integrity": "sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==", + "license": "MIT", + "peer": true + }, + "node_modules/tinyglobby": { + "version": "0.2.15", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", + "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "fdir": "^6.5.0", + "picomatch": "^4.0.3" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/tinypool": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-1.1.1.tgz", + "integrity": "sha512-Zba82s87IFq9A9XmjiX5uZA/ARWDrB03OHlq+Vw1fSdt0I+4/Kutwy8BP4Y/y/aORMo61FQ0vIb5j44vSo5Pkg==", + "license": "MIT", + "peer": true, + "engines": { + "node": "^18.0.0 || >=20.0.0" + } + }, + "node_modules/tinyrainbow": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-2.0.0.tgz", + "integrity": "sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/tinyspy": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-3.0.2.tgz", + "integrity": "sha512-n1cw8k1k0x4pgA2+9XrOkFydTerNcJ1zWCO5Nn9scWHTD+5tp8dghT2x1uduQePZTZgd3Tupf+x9BxJjeJi77Q==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/to-buffer": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.2.2.tgz", + "integrity": "sha512-db0E3UJjcFhpDhAF4tLo03oli3pwl3dbnzXOUIlRKrp+ldk/VUxzpWYZENsw2SZiuBjHAk7DfB0VU7NKdpb6sw==", + "license": "MIT", + "dependencies": { + "isarray": "^2.0.5", + "safe-buffer": "^5.2.1", + "typed-array-buffer": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/to-buffer/node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "license": "MIT" + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "license": "MIT", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/toml": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/toml/-/toml-3.0.0.tgz", + "integrity": "sha512-y/mWCZinnvxjTKYhJ+pYxwD0mRLVvOtdS2Awbgxln6iEnt4rk0yBxeSBHkGJcPucRiG0e55mwWp+g/05rsrd6w==", + "license": "MIT" + }, + "node_modules/toposort": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/toposort/-/toposort-2.0.2.tgz", + "integrity": "sha512-0a5EOkAUp8D4moMi2W8ZF8jcga7BgZd91O/yabJCFY8az+XSzeGyTKs0Aoo897iV1Nj6guFq8orWDS96z91oGg==", + "license": "MIT" + }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "license": "MIT" + }, + "node_modules/tronweb": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/tronweb/-/tronweb-6.1.0.tgz", + "integrity": "sha512-ANEr2YneA2frXTpsxDR21yk2cJLIvOdPe7dg7gu96TyqfVbS9eCrguNuN+qCUZOC/zW3n6R880bBDbEWKZiWzA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "7.26.10", + "axios": "1.12.2", + "bignumber.js": "9.1.2", + "ethereum-cryptography": "2.2.1", + "ethers": "6.13.5", + "eventemitter3": "5.0.1", + "google-protobuf": "3.21.4", + "semver": "7.7.1", + "validator": "13.15.20" + } + }, + "node_modules/tronweb/node_modules/@noble/curves": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.4.2.tgz", + "integrity": "sha512-TavHr8qycMChk8UwMld0ZDRvatedkzWfH8IiaeGCfymOP5i0hSCozz9vHOL0nkwk7HRMlFnAiKpS2jrUmSybcw==", + "license": "MIT", + "dependencies": { + "@noble/hashes": "1.4.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/tronweb/node_modules/@noble/hashes": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.4.0.tgz", + "integrity": "sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==", + "license": "MIT", + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/tronweb/node_modules/@scure/base": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.1.9.tgz", + "integrity": "sha512-8YKhl8GHiNI/pU2VMaofa2Tor7PJRAjwQLBBuilkJ9L5+13yVbC7JO/wS7piioAvPSwR3JKM1IJ/u4xQzbcXKg==", + "license": "MIT", + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/tronweb/node_modules/@scure/bip32": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@scure/bip32/-/bip32-1.4.0.tgz", + "integrity": "sha512-sVUpc0Vq3tXCkDGYVWGIZTRfnvu8LoTDaev7vbwh0omSvVORONr960MQWdKqJDCReIEmTj3PAr73O3aoxz7OPg==", + "license": "MIT", + "dependencies": { + "@noble/curves": "~1.4.0", + "@noble/hashes": "~1.4.0", + "@scure/base": "~1.1.6" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/tronweb/node_modules/@scure/bip39": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.3.0.tgz", + "integrity": "sha512-disdg7gHuTDZtY+ZdkmLpPCk7fxZSu3gBiEGuoC1XYxv9cGx3Z6cpTggCgW6odSOOIXCiDjuGejW+aJKCY/pIQ==", + "license": "MIT", + "dependencies": { + "@noble/hashes": "~1.4.0", + "@scure/base": "~1.1.6" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/tronweb/node_modules/axios": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.12.2.tgz", + "integrity": "sha512-vMJzPewAlRyOgxV2dU0Cuz2O8zzzx9VYtbJOaBgXFeLc4IV/Eg50n4LowmehOOR61S8ZMpc2K5Sa7g6A4jfkUw==", + "license": "MIT", + "dependencies": { + "follow-redirects": "^1.15.6", + "form-data": "^4.0.4", + "proxy-from-env": "^1.1.0" + } + }, + "node_modules/tronweb/node_modules/ethereum-cryptography": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-2.2.1.tgz", + "integrity": "sha512-r/W8lkHSiTLxUxW8Rf3u4HGB0xQweG2RyETjywylKZSzLWoWAijRz8WCuOtJ6wah+avllXBqZuk29HCCvhEIRg==", + "license": "MIT", + "dependencies": { + "@noble/curves": "1.4.2", + "@noble/hashes": "1.4.0", + "@scure/bip32": "1.4.0", + "@scure/bip39": "1.3.0" + } + }, + "node_modules/tronweb/node_modules/eventemitter3": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", + "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==", + "license": "MIT" + }, + "node_modules/tronweb/node_modules/semver": { + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", + "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" + }, + "node_modules/type-fest": { + "version": "4.34.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.34.1.tgz", + "integrity": "sha512-6kSc32kT0rbwxD6QL1CYe8IqdzN/J/ILMrNK+HMQCKH3insCDRY/3ITb0vcBss0a3t72fzh2YSzj8ko1HgwT3g==", + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/typed-array-buffer": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz", + "integrity": "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-typed-array": "^1.1.14" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/typedarray-to-buffer": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", + "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", + "license": "MIT", + "dependencies": { + "is-typedarray": "^1.0.0" + } + }, + "node_modules/typescript": { + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "devOptional": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/uglify-js": { + "version": "3.19.3", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.19.3.tgz", + "integrity": "sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ==", + "license": "BSD-2-Clause", + "bin": { + "uglifyjs": "bin/uglifyjs" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/uint8arrays": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/uint8arrays/-/uint8arrays-5.1.0.tgz", + "integrity": "sha512-vA6nFepEmlSKkMBnLBaUMVvAC4G3CTmO58C12y4sq6WPDOR7mOFYOi7GlrQ4djeSbP6JG9Pv9tJDM97PedRSww==", + "license": "Apache-2.0 OR MIT", + "dependencies": { + "multiformats": "^13.0.0" + } + }, + "node_modules/undici-types": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz", + "integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==", + "license": "MIT" + }, + "node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/utf8": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/utf8/-/utf8-3.0.0.tgz", + "integrity": "sha512-E8VjFIQ/TyQgp+TZfS6l8yp/xWppSAHzidGiRrqe4bK4XP9pTRyKFgGJpO3SN7zdX4DeomTrwaseCHovfpFcqQ==", + "license": "MIT" + }, + "node_modules/util": { + "version": "0.12.5", + "resolved": "https://registry.npmjs.org/util/-/util-0.12.5.tgz", + "integrity": "sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "is-arguments": "^1.0.4", + "is-generator-function": "^1.0.7", + "is-typed-array": "^1.1.3", + "which-typed-array": "^1.1.2" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "license": "MIT" + }, + "node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "license": "MIT", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/validator": { + "version": "13.15.20", + "resolved": "https://registry.npmjs.org/validator/-/validator-13.15.20.tgz", + "integrity": "sha512-KxPOq3V2LmfQPP4eqf3Mq/zrT0Dqp2Vmx2Bn285LwVahLc+CsxOM0crBHczm8ijlcjZ0Q5Xd6LW3z3odTPnlrw==", + "license": "MIT", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/viem": { + "version": "2.39.0", + "resolved": "https://registry.npmjs.org/viem/-/viem-2.39.0.tgz", + "integrity": "sha512-rCN+IfnMESlrg/iPyyVL+M9NS/BHzyyNy72470tFmbTuscY3iPaZGMtJDcHKKV8TC6HV9DjWk0zWX6cpu0juyA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/wevm" + } + ], + "license": "MIT", + "peer": true, + "dependencies": { + "@noble/curves": "1.9.1", + "@noble/hashes": "1.8.0", + "@scure/bip32": "1.7.0", + "@scure/bip39": "1.6.0", + "abitype": "1.1.0", + "isows": "1.0.7", + "ox": "0.9.6", + "ws": "8.18.3" + }, + "peerDependencies": { + "typescript": ">=5.0.4" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/viem/node_modules/@noble/curves": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.9.1.tgz", + "integrity": "sha512-k11yZxZg+t+gWvBbIswW0yoJlu8cHOC7dhunwOzoWH/mXGBiYyR4YY6hAEK/3EUs4UpB8la1RfdRpeGsFHkWsA==", + "license": "MIT", + "peer": true, + "dependencies": { + "@noble/hashes": "1.8.0" + }, + "engines": { + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/viem/node_modules/ws": { + "version": "8.18.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.3.tgz", + "integrity": "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/vite": { + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/vite/-/vite-6.4.1.tgz", + "integrity": "sha512-+Oxm7q9hDoLMyJOYfUYBuHQo+dkAloi33apOPP56pzj+vsdJDzr+j1NISE5pyaAuKL4A3UD34qd0lx5+kfKp2g==", + "license": "MIT", + "peer": true, + "dependencies": { + "esbuild": "^0.25.0", + "fdir": "^6.4.4", + "picomatch": "^4.0.2", + "postcss": "^8.5.3", + "rollup": "^4.34.9", + "tinyglobby": "^0.2.13" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^18.0.0 || ^20.0.0 || >=22.0.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", + "jiti": ">=1.21.0", + "less": "*", + "lightningcss": "^1.21.0", + "sass": "*", + "sass-embedded": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.16.0", + "tsx": "^4.8.1", + "yaml": "^2.4.2" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "jiti": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true + } + } + }, + "node_modules/vite-node": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-3.0.9.tgz", + "integrity": "sha512-w3Gdx7jDcuT9cNn9jExXgOyKmf5UOTb6WMHz8LGAm54eS1Elf5OuBhCxl6zJxGhEeIkgsE1WbHuoL0mj/UXqXg==", + "license": "MIT", + "peer": true, + "dependencies": { + "cac": "^6.7.14", + "debug": "^4.4.0", + "es-module-lexer": "^1.6.0", + "pathe": "^2.0.3", + "vite": "^5.0.0 || ^6.0.0" + }, + "bin": { + "vite-node": "vite-node.mjs" + }, + "engines": { + "node": "^18.0.0 || ^20.0.0 || >=22.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/vite-node/node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", + "peer": true, + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/vitest": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-3.0.9.tgz", + "integrity": "sha512-BbcFDqNyBlfSpATmTtXOAOj71RNKDDvjBM/uPfnxxVGrG+FSH2RQIwgeEngTaTkuU/h0ScFvf+tRcKfYXzBybQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "@vitest/expect": "3.0.9", + "@vitest/mocker": "3.0.9", + "@vitest/pretty-format": "^3.0.9", + "@vitest/runner": "3.0.9", + "@vitest/snapshot": "3.0.9", + "@vitest/spy": "3.0.9", + "@vitest/utils": "3.0.9", + "chai": "^5.2.0", + "debug": "^4.4.0", + "expect-type": "^1.1.0", + "magic-string": "^0.30.17", + "pathe": "^2.0.3", + "std-env": "^3.8.0", + "tinybench": "^2.9.0", + "tinyexec": "^0.3.2", + "tinypool": "^1.0.2", + "tinyrainbow": "^2.0.0", + "vite": "^5.0.0 || ^6.0.0", + "vite-node": "3.0.9", + "why-is-node-running": "^2.3.0" + }, + "bin": { + "vitest": "vitest.mjs" + }, + "engines": { + "node": "^18.0.0 || ^20.0.0 || >=22.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "@edge-runtime/vm": "*", + "@types/debug": "^4.1.12", + "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", + "@vitest/browser": "3.0.9", + "@vitest/ui": "3.0.9", + "happy-dom": "*", + "jsdom": "*" + }, + "peerDependenciesMeta": { + "@edge-runtime/vm": { + "optional": true + }, + "@types/debug": { + "optional": true + }, + "@types/node": { + "optional": true + }, + "@vitest/browser": { + "optional": true + }, + "@vitest/ui": { + "optional": true + }, + "happy-dom": { + "optional": true + }, + "jsdom": { + "optional": true + } + } + }, + "node_modules/vitest/node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", + "peer": true, + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "license": "BSD-2-Clause" + }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "license": "MIT", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/which-typed-array": { + "version": "1.1.19", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.19.tgz", + "integrity": "sha512-rEvr90Bck4WZt9HHFC4DJMsjvu7x+r6bImz0/BrbWb7A2djJ8hnZMrWnHo9F8ssv0OMErasDhftrfROTyqSDrw==", + "license": "MIT", + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "for-each": "^0.3.5", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/why-is-node-running": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.3.0.tgz", + "integrity": "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==", + "license": "MIT", + "peer": true, + "dependencies": { + "siginfo": "^2.0.0", + "stackback": "0.0.2" + }, + "bin": { + "why-is-node-running": "cli.js" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==", + "license": "MIT" + }, + "node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "license": "MIT" + }, + "node_modules/wrap-ansi-cjs/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/ws": { + "version": "7.5.10", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz", + "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==", + "license": "MIT", + "engines": { + "node": ">=8.3.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/xstream": { + "version": "11.14.0", + "resolved": "https://registry.npmjs.org/xstream/-/xstream-11.14.0.tgz", + "integrity": "sha512-1bLb+kKKtKPbgTK6i/BaoAn03g47PpFstlbe1BA+y3pNS/LfvcaghS5BFf9+EE1J+KwSQsEpfJvFN5GqFtiNmw==", + "license": "MIT", + "dependencies": { + "globalthis": "^1.0.1", + "symbol-observable": "^2.0.3" + } + }, + "node_modules/yup": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/yup/-/yup-1.6.1.tgz", + "integrity": "sha512-JED8pB50qbA4FOkDol0bYF/p60qSEDQqBD0/qeIrUCG1KbPBIQ776fCUNb9ldbPcSTxA69g/47XTo4TqWiuXOA==", + "license": "MIT", + "dependencies": { + "property-expr": "^2.0.5", + "tiny-case": "^1.0.3", + "toposort": "^2.0.2", + "type-fest": "^2.19.0" + } + }, + "node_modules/yup/node_modules/type-fest": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", + "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + } + } +} diff --git a/package.json b/package.json index a8a718d5..9288204f 100644 --- a/package.json +++ b/package.json @@ -1,22 +1,26 @@ { - "name": "nexus-sdk-monorepo", + "name": "@avail-project/nexus-core", "version": "1.0.0-beta.26", - "private": true, - "description": "Nexus SDK monorepo - cross-chain transactions with minimal friction", + "description": "Nexus headless SDK for cross-chain transactions", + "main": "./dist/index.js", + "module": "./dist/index.esm.js", + "types": "./dist/index.d.ts", + "files": [ + "dist", + "README.md" + ], "scripts": { - "build:commons": "pnpm -F @nexus/commons build", - "build:core": "pnpm -F @nexus/commons build && pnpm -F @avail-project/nexus-core build", - "build": "pnpm run build:core", - "dev:core": "pnpm -F @avail-project/nexus-core dev", - "dev": "pnpm run dev:core", - "format": "prettier --write \"packages/**/*.{ts,tsx}\"", - "prepare": "husky install", - "typecheck:core": "pnpm -F @avail-project/nexus-core typecheck", - "typecheck": "pnpm -r typecheck", - "clean": "rimraf packages/core/dist packages/commons/dist", - "clean:modules": "rimraf node_modules packages/core/node_modules packages/commons/node_modules", - "release:core:dev": "./scripts/release-core.sh dev", - "release:core:prod": "./scripts/release-core.sh prod" + "build": "rollup -c", + "dev": "rollup -c -w", + "typecheck": "tsc --noEmit" + }, + "sideEffects": false, + "exports": { + ".": { + "types": "./dist/index.d.ts", + "import": "./dist/index.esm.js", + "require": "./dist/index.js" + } }, "keywords": [ "nexus", @@ -27,27 +31,41 @@ "web3", "chain", "abstraction", - "intent", - "unified", - "balance", - "sdk" + "headless" ], "author": "decocereus, makyl", "license": "MIT", - "pnpm": { - "overrides": { - "typescript": "^5.0.0", - "rollup": "^4.0.0", - "decimal.js": "10.6.0", - "viem": "^2.0.0" - } + "dependencies": { + "@avail-project/ca-common": "1.0.0-beta.7", + "@cosmjs/proto-signing": "^0.34.0", + "@cosmjs/stargate": "^0.34.0", + "@metamask/safe-event-emitter": "3.1.2", + "@starkware-industries/starkware-crypto-utils": "^0.2.1", + "@tronweb3/tronwallet-abstract-adapter": "^1.1.9", + "axios": "^1.12.2", + "decimal.js": "^10.6.0", + "es-toolkit": "^1.40.0", + "fuels": "0.101.1", + "it-ws": "^6.1.5", + "long": "^5.3.2", + "msgpackr": "^1.11.5", + "tronweb": "^6.0.4", + "tslib": "2.8.1" }, "devDependencies": { - "@rollup/plugin-alias": "^5.1.1", - "@types/node": "^20.19.22", - "husky": "^8.0.3", - "prettier": "^3.6.2", - "rimraf": "^5.0.10", + "@rollup/plugin-commonjs": "^25.0.8", + "@rollup/plugin-json": "6.1.0", + "@rollup/plugin-node-resolve": "^15.3.1", + "@rollup/plugin-typescript": "^11.1.6", + "rollup": "^4.52.4", + "rollup-plugin-dts": "^6.2.3", + "rollup-plugin-typescript2": "0.36.0", "typescript": "^5.9.3" + }, + "peerDependencies": { + "viem": "^2.31.7" + }, + "publishConfig": { + "access": "public" } } diff --git a/packages/commons/package.json b/packages/commons/package.json deleted file mode 100644 index 383d098f..00000000 --- a/packages/commons/package.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "name": "@nexus/commons", - "version": "0.0.1", - "description": "Shared types, constants, and utilities for Nexus SDK", - "main": "./dist/index.js", - "module": "./dist/index.esm.js", - "types": "./dist/index.d.ts", - "author": "decocereus", - "private": true, - "sideEffects": false, - "scripts": { - "build": "rollup -c", - "dev": "rollup -c -w", - "typecheck": "tsc --noEmit" - }, - "dependencies": { - "@avail-project/ca-common": "1.0.0-beta.7", - "@cosmjs/proto-signing": "^0.34.0", - "@tronweb3/tronwallet-abstract-adapter": "^1.1.9", - "decimal.js": "^10.6.0", - "fuels": "0.101.1", - "tronweb": "^6.0.4", - "viem": "^2.38.3" - }, - "devDependencies": { - "@rollup/plugin-commonjs": "^25.0.8", - "@rollup/plugin-json": "6.1.0", - "@rollup/plugin-node-resolve": "^15.3.1", - "@rollup/plugin-typescript": "^11.1.6", - "rollup": "^4.52.4", - "rollup-plugin-dts": "^6.2.3", - "typescript": "^5.9.3" - } -} diff --git a/packages/commons/rollup.config.mjs b/packages/commons/rollup.config.mjs deleted file mode 100644 index 229c5a40..00000000 --- a/packages/commons/rollup.config.mjs +++ /dev/null @@ -1,62 +0,0 @@ -import resolve from '@rollup/plugin-node-resolve'; -import commonjs from '@rollup/plugin-commonjs'; -import typescript from '@rollup/plugin-typescript'; -import json from '@rollup/plugin-json'; -import dts from 'rollup-plugin-dts'; -import { defineConfig } from 'rollup'; -import { createRequire } from 'module'; - -const require = createRequire(import.meta.url); -const packageJson = require('./package.json'); - -const isProduction = process.env.NODE_ENV === 'production'; -const shouldGenerateSourceMaps = false; - -// Base configuration -const baseConfig = { - input: 'index.ts', - plugins: [ - json(), - resolve({ - browser: true, - preferBuiltins: false, - }), - commonjs({ - include: /node_modules/, - }), - typescript({ - tsconfig: './tsconfig.json', - sourceMap: shouldGenerateSourceMaps, - }), - ], - external: [...Object.keys(packageJson.dependencies || {}), /^viem/], -}; - -export default defineConfig([ - // Build configurations - { - ...baseConfig, - output: [ - { - file: 'dist/index.js', - format: 'cjs', - sourcemap: shouldGenerateSourceMaps, - exports: 'named', - }, - { - file: 'dist/index.esm.js', - format: 'esm', - sourcemap: shouldGenerateSourceMaps, - exports: 'named', - }, - ], - }, - - // TypeScript declarations - { - input: 'index.ts', - output: [{ file: 'dist/index.d.ts', format: 'esm' }], - plugins: [dts()], - external: [...Object.keys(packageJson.dependencies || {}), /^viem/], - }, -]); diff --git a/packages/commons/tsconfig.json b/packages/commons/tsconfig.json deleted file mode 100644 index 1545e341..00000000 --- a/packages/commons/tsconfig.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "extends": "../../tsconfig.json", - "compilerOptions": { - "outDir": "./dist", - "rootDir": ".", - "baseUrl": "." - }, - "include": [ - "**/*.ts", - "**/*.d.ts" - ], - "exclude": [ - "dist", - "node_modules" - ] -} \ No newline at end of file diff --git a/packages/core/README.md b/packages/core/README.md deleted file mode 100644 index fff555fe..00000000 --- a/packages/core/README.md +++ /dev/null @@ -1,421 +0,0 @@ -# @avail-project/nexus/core - -A **headless TypeScript SDK** for **cross-chain operations**, **token bridging**, **swapping**, and **unified balance management** — built for backends, CLIs, and custom UI integrations. - -> ⚡ Powering next-generation cross-chain apps with a single interface. - ---- - -## 📦 Installation - -```bash -npm install @avail-project/nexus-core -``` - ---- - -## 🚀 Quick Start - -```typescript -import { NexusSDK, NEXUS_EVENTS } from '@avail-project/nexus-core'; - -// Initialize SDK -const sdk = new NexusSDK({ network: 'mainnet' }); -await sdk.initialize(provider); // Your EVM-compatible wallet provider - -// (Optional) Add TRON support -const tronLinkAdapter = new TronLinkAdapter(); -sdk.addTron(tronLinkAdapter); - -// --------------------------- -// 1️⃣ Get unified balances -// --------------------------- -const balances = await sdk.getUnifiedBalances(false); // false = CA balances only -console.log('Balances:', balances); - -// --------------------------- -// 2️⃣ Bridge tokens -// --------------------------- -const bridgeResult = await sdk.bridge( - { - token: 'USDC', - amount: "1.5", - recipient: '0x...' // Optional - chainId: 137, // Polygon - }, - { - onEvent: (event) => { - if (event.name === NEXUS_EVENTS.STEPS_LIST) console.log('Bridge steps:', event.args); - if (event.name === NEXUS_EVENTS.STEP_COMPLETE) console.log('Step completed:', event.args); - }, - }, -); - -// --------------------------- -// 3️⃣ Transfer tokens -// --------------------------- -const transferResult = await sdk.bridgeAndTransfer( - { - token: 'ETH', - amount: "1.5", - chainId: 1, // Ethereum - recipient: '0x742d35Cc6634C0532925a3b8D4C9db96c4b4Db45', - }, - { - onEvent: (event) => { - if (event.name === NEXUS_EVENTS.STEPS_LIST) console.log('Transfer steps:', event.args); - if (event.name === NEXUS_EVENTS.STEP_COMPLETE) console.log('Step completed:', event.args); - }, - }, -); - -// --------------------------- -// 4️⃣ Execute a contract -// --------------------------- -const executeResult = await sdk.execute( - { - to: '0x...', - value: 0n, - data: '0x...', - tokenApproval: { token: 'USDC', amount: 10000n }, - }, - { - onEvent: (event) => { - if (event.name === NEXUS_EVENTS.STEPS_LIST) console.log('Execute steps:', event.args); - if (event.name === NEXUS_EVENTS.STEP_COMPLETE) console.log('Step completed:', event.args); - }, - }, -); - -// --------------------------- -// 5️⃣ Bridge and Execute -// --------------------------- -const bridgeAndExecuteResult = await sdk.bridgeAndExecute( - { - token: 'USDC', - amount: 100_000_000n, - toChainId: 1, - sourceChains: [8453], - execute: { - to: '0x...', - data: '0x...', - tokenApproval: { token: 'USDC', amount: 100_000_000n }, - }, - }, - { - onEvent: (event) => { - if (event.name === NEXUS_EVENTS.STEPS_LIST) console.log('Bridge+Execute steps:', event.args); - if (event.name === NEXUS_EVENTS.STEP_COMPLETE) console.log('Step completed:', event.args); - }, - }, -); - -// --------------------------- -// 6️⃣ Swap tokens -// --------------------------- -const swapResult = await sdk.swapWithExactIn( - { - from: [ - { chainId: 10, amount: 1_000_000n, tokenAddress: '0x...' }, - ], - toChainId: 8453, - toTokenAddress: '0x...', - }, - { - onEvent: (event) => console.log('Swap event:', event), - }, -); - -``` - ---- - -## ✨ Core Features - -- **Cross-chain bridging** — Move tokens seamlessly across 16+ chains. -- **Cross-chain swaps** — Execute EXACT_IN and EXACT_OUT swaps between any supported networks. -- **Unified balances** — Aggregate user assets and balances across all connected chains. -- **Optimized transfers** — Automatically choose the most efficient transfer route. -- **Contract execution** — Call smart contracts with automatic bridging and funding logic. -- **Transaction simulation** — Estimate gas, fees, and required approvals before sending. -- **Complete testnet coverage** — Full multi-chain test environment. -- **Comprehensive utilities** — Address, token, and chain helpers built in. - ---- - -## 🧠 Smart Optimizations - -### 🔁 Bridge Skip Optimization - -During **bridge-and-execute** operations, the SDK checks whether sufficient funds already exist on the destination chain: - -- **Balance detection** — Verifies token and gas availability. -- **Integrated gas supply** — Provides gas alongside bridged tokens. -- **Adaptive bridging** — Skips unnecessary bridging or transfers only the shortfall. -- **Seamless fallback** — Uses chain abstraction if local funds are insufficient. - -### ⚡ Direct Transfer Optimization - -For transfers, the SDK automatically chooses the most efficient execution path: - -- **Local balance checking** — Confirms token and gas availability on the target chain. -- **Direct EVM transfers** — Uses native transfers where possible (faster, cheaper). -- **Chain abstraction fallback** — Uses CA routing only when required. -- **Universal compatibility** — Works with both native tokens (ETH, MATIC) and ERC-20s (USDC, USDT). - ---- - -## 🏗️ Initialization - -```typescript -import { NexusSDK, type NexusNetwork } from '@avail-project/nexus-core'; - -// Mainnet -const sdk = new NexusSDK({ network: 'mainnet' }); - -// Testnet -const sdkTest = new NexusSDK({ network: 'testnet' }); - -// Initialize with wallet provider -await sdk.initialize(window.ethereum); -``` - ---- - -## 📡 Event Handling - -**All main SDK functions support the `onEvent` hook**: - -- `bridge` -- `bridgeAndTransfer` -- `execute` -- `bridgeAndExecute` -- `swapWithExactIn` / `swapWithExactOut` - -Example usage for **progress steps**: - -```typescript -sdk.bridge({...}, { - onEvent: (event) => { - if(event.name === NEXUS_EVENTS.STEPS_LIST) { - // Store list of steps - } else if(event.name === NEXUS_EVENTS.STEP_COMPLETE) { - // Mark step as done - } - } -}); -``` - -Additional hooks for user interactions: - -```typescript -sdk.setOnIntentHook(({ intent, allow, deny, refresh }) => { - if (userApproves) allow(); - else deny(); -}); - -sdk.setOnSwapIntentHook(({ intent, allow, deny, refresh }) => { - if (userApproves) allow(); - else deny(); -}); - -sdk.setOnAllowanceHook(({ sources, allow, deny }) => { - allow(['min']); // 'max' or custom bigint[] supported -}); -``` - -### Consistent Event Pattern - -| Operation Type | Event Name | Description | -| ---------------- | -------------------- | --------------------------------------- | -| Bridge / Execute | `STEPS_LIST` | Full ordered list of steps emitted once | -| | `STEP_COMPLETE` | Fired per completed step with data | -| Swap | `SWAP_STEP_COMPLETE` | Fired per completed step with data | - -All events include `typeID`, `transactionHash`, `explorerURL`, and `error` (if any). - ---- - -## 💰 Balance Operations - -```typescript -const balances = await sdk.getUnifiedBalances(); // CA balances -const allBalances = await sdk.getUnifiedBalances(true); // Includes swappable tokens -``` - ---- - -## 🌉 Bridge Operations - -```typescript -const result = await sdk.bridge({ token: 'USDC', amount: '83.50', chainId: 137 }); -const simulation = await sdk.simulateBridge({ token: 'USDC', amount: '83.50', chainId: 137 }); -``` - ---- - -## 🔁 Transfer Operations - -```typescript -const result = await sdk.bridgeAndTransfer({ - token: 'USDC', - amount: '1.53', - chainId: 42161, - recipient: '0x...', -}); -const simulation = await sdk.simulateBridgeAndTransfer({ - token: 'USDC', - amount: '1.53', - chainId: 42161, - recipient: '0x...', -}); -``` - ---- - -## ⚙️ Execute & Bridge+Execute - -```typescript -// Direct contract execution -const result = await sdk.execute({ - toChainId: 1, - to: '0xc3d688B66703497DAA19211EEdff47f25384cdc3', - data: '0x...', - tokenApproval: { token: 'USDC', amount: 1000000n }, -}); - -// Bridge and execute -const result2 = await sdk.bridgeAndExecute({ - token: 'USDC', - amount: 100_000_000n, - toChainId: 1, - sourceChains: [8453], - execute: { - to: '0xa354F35829Ae975e850e23e9615b11Da1B3dC4DE', - data: '0x...', - tokenApproval: { token: 'USDC', amount: 100_000_000n }, - }, -}); -``` - ---- - -## 🔄 Swap Operations - -```typescript -const swapResult = await sdk.swapWithExactIn( - { - from: [{ chainId: 10, amount: 1_000_000n, tokenAddress: '0x...' }], - toChainId: 8453, - toTokenAddress: '0x...', - }, - { onEvent: (event) => console.log(event) }, -); -``` - -### Swap Types - -| Type | Description | Example | -| ------------- | ------------------------------------------------- | --------------------------- | -| **EXACT_IN** | Specify the amount you’re spending; output varies | “Swap 100 USDC for max ETH” | -| **EXACT_OUT** | Specify the amount you’ll receive; input varies | “Get exactly 1 ETH” | - ---- - -## 🧩 Intent Management - -```typescript -const intents = await sdk.getMyIntents(1); -console.log('Active intents:', intents); -``` - ---- - -## 🛠️ Utilities - -```typescript -const isValid = sdk.utils.isValidAddress('0x...'); -const chainMeta = sdk.utils.getChainMetadata(137); -const formatted = sdk.utils.formatTokenAmount('1000000', 'USDC'); // "1.0 USDC" -``` - ---- - -## 🧾 Error Handling - -```typescript -try { - await sdk.bridge({ token: 'USDC', amount: 1.53, chainId: 137 }); -} catch (err) { - if (err instanceof NexusError) { - console.error(`[${err.code}] ${err.message}`); - } else { - console.error('Unexpected error:', err); - } -} -``` - ---- - -## 🧠 TypeScript Support - -```typescript -import type { - BridgeParams, - ExecuteParams, - TransferParams, - SwapResult, - NexusNetwork, - TokenMetadata, -} from '@avail-project/nexus-core'; -``` - ---- - -## 🌐 Supported Networks - -### Mainnets - -| Network | Chain ID | Native | Status | -| --------- | --------- | ------ | ------ | -| Ethereum | 1 | ETH | ✅ | -| Optimism | 10 | ETH | ✅ | -| Polygon | 137 | MATIC | ✅ | -| Arbitrum | 42161 | ETH | ✅ | -| Avalanche | 43114 | AVAX | ✅ | -| Base | 8453 | ETH | ✅ | -| Scroll | 534352 | ETH | ✅ | -| Sophon | 50104 | SOPH | ✅ | -| Kaia | 8217 | KAIA | ✅ | -| BNB | 56 | BNB | ✅ | -| HyperEVM | 999 | HYPE | ✅ | -| TRON | 728126428 | TRX | ✅ | - -### Testnets - -| Network | Chain ID | Native | Status | -| ---------------- | -------- | ------ | ------ | -| Optimism Sepolia | 11155420 | ETH | ✅ | -| Polygon Amoy | 80002 | MATIC | ✅ | -| Arbitrum Sepolia | 421614 | ETH | ✅ | -| Base Sepolia | 84532 | ETH | ✅ | -| Sepolia | 11155111 | ETH | ✅ | -| Monad Testnet | 10143 | MON | ✅ | -| Validium | 567 | VLDM | ✅ | - ---- - -## 💎 Supported Tokens - -| Token | Name | Decimals | Availability | -| ----- | ---------- | -------- | -------------- | -| ETH | Ethereum | 18 | All EVM chains | -| USDC | USD Coin | 6 | All supported | -| USDT | Tether USD | 6 | All supported | - ---- - -## 🔗 Resources - -- **GitHub:** [availproject/nexus-sdk](https://github.com/availproject/nexus-sdk) -- **Docs:** [docs.availproject.org](https://docs.availproject.org/nexus/avail-nexus-sdk) diff --git a/packages/core/package.json b/packages/core/package.json deleted file mode 100644 index c04bdb80..00000000 --- a/packages/core/package.json +++ /dev/null @@ -1,72 +0,0 @@ -{ - "name": "@avail-project/nexus-core", - "version": "1.0.0-beta.26", - "description": "Nexus headless SDK for cross-chain transactions", - "main": "./dist/index.js", - "module": "./dist/index.esm.js", - "types": "./dist/index.d.ts", - "files": [ - "dist", - "README.md" - ], - "scripts": { - "build": "rollup -c && pnpm run copy:commons", - "copy:commons": "mkdir -p dist/commons && cp -R ../commons/dist/* dist/commons/ || true", - "dev": "rollup -c -w", - "typecheck": "tsc --noEmit" - }, - "sideEffects": false, - "exports": { - ".": { - "types": "./dist/index.d.ts", - "import": "./dist/index.esm.js", - "require": "./dist/index.js" - } - }, - "keywords": [ - "nexus", - "sdk", - "blockchain", - "bridge", - "swap", - "web3", - "chain", - "abstraction", - "headless" - ], - "author": "decocereus", - "license": "MIT", - "dependencies": { - "@avail-project/ca-common": "1.0.0-beta.7", - "@cosmjs/proto-signing": "^0.34.0", - "@cosmjs/stargate": "^0.34.0", - "@metamask/safe-event-emitter": "3.1.2", - "@starkware-industries/starkware-crypto-utils": "^0.2.1", - "@tronweb3/tronwallet-abstract-adapter": "^1.1.9", - "axios": "^1.12.2", - "decimal.js": "^10.6.0", - "es-toolkit": "^1.40.0", - "fuels": "0.101.1", - "it-ws": "^6.1.5", - "long": "^5.3.2", - "msgpackr": "^1.11.5", - "tronweb": "^6.0.4", - "tslib": "2.8.1" - }, - "devDependencies": { - "@rollup/plugin-commonjs": "^25.0.8", - "@rollup/plugin-json": "6.1.0", - "@rollup/plugin-node-resolve": "^15.3.1", - "@rollup/plugin-typescript": "^11.1.6", - "rollup": "^4.52.4", - "rollup-plugin-dts": "^6.2.3", - "rollup-plugin-typescript2": "0.36.0", - "typescript": "^5.9.3" - }, - "peerDependencies": { - "viem": "^2.31.7" - }, - "publishConfig": { - "access": "public" - } -} diff --git a/packages/core/tsconfig.json b/packages/core/tsconfig.json deleted file mode 100644 index a4e45bda..00000000 --- a/packages/core/tsconfig.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "extends": "../../tsconfig.json", - "compilerOptions": { - "outDir": "./dist", - "baseUrl": ".", - "paths": { - "@nexus/commons": ["../commons/index.ts"], - "@nexus/commons/*": ["../commons/*"] - } - }, - "include": ["**/*.ts", "**/*.d.ts"], - "exclude": ["dist", "node_modules"] -} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml deleted file mode 100644 index 3c65f5b2..00000000 --- a/pnpm-lock.yaml +++ /dev/null @@ -1,6157 +0,0 @@ -lockfileVersion: '9.0' - -settings: - autoInstallPeers: true - excludeLinksFromLockfile: false - -overrides: - typescript: ^5.0.0 - rollup: ^4.0.0 - decimal.js: 10.6.0 - viem: ^2.0.0 - -importers: - - .: - devDependencies: - '@rollup/plugin-alias': - specifier: ^5.1.1 - version: 5.1.1(rollup@4.52.4) - '@types/node': - specifier: ^20.19.22 - version: 20.19.22 - husky: - specifier: ^8.0.3 - version: 8.0.3 - prettier: - specifier: ^3.6.2 - version: 3.6.2 - rimraf: - specifier: ^5.0.10 - version: 5.0.10 - typescript: - specifier: ^5.0.0 - version: 5.9.3 - - packages/commons: - dependencies: - '@avail-project/ca-common': - specifier: 1.0.0-beta.7 - version: 1.0.0-beta.7(@cosmjs/proto-signing@0.34.0)(@cosmjs/stargate@0.34.0)(axios@1.12.2)(decimal.js@10.6.0)(fuels@0.101.1(vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2)))(google-protobuf@3.21.4)(long@5.3.2)(msgpackr@1.11.5)(viem@2.38.3(typescript@5.9.3)) - '@cosmjs/proto-signing': - specifier: ^0.34.0 - version: 0.34.0 - '@tronweb3/tronwallet-abstract-adapter': - specifier: ^1.1.9 - version: 1.1.9 - decimal.js: - specifier: 10.6.0 - version: 10.6.0 - fuels: - specifier: 0.101.1 - version: 0.101.1(vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2)) - tronweb: - specifier: ^6.0.4 - version: 6.0.4 - viem: - specifier: ^2.0.0 - version: 2.38.3(typescript@5.9.3) - devDependencies: - '@rollup/plugin-commonjs': - specifier: ^25.0.8 - version: 25.0.8(rollup@4.52.4) - '@rollup/plugin-json': - specifier: 6.1.0 - version: 6.1.0(rollup@4.52.4) - '@rollup/plugin-node-resolve': - specifier: ^15.3.1 - version: 15.3.1(rollup@4.52.4) - '@rollup/plugin-typescript': - specifier: ^11.1.6 - version: 11.1.6(rollup@4.52.4)(tslib@2.8.1)(typescript@5.9.3) - rollup: - specifier: ^4.0.0 - version: 4.52.4 - rollup-plugin-dts: - specifier: ^6.2.3 - version: 6.2.3(rollup@4.52.4)(typescript@5.9.3) - typescript: - specifier: ^5.0.0 - version: 5.9.3 - - packages/core: - dependencies: - '@avail-project/ca-common': - specifier: 1.0.0-beta.7 - version: 1.0.0-beta.7(@cosmjs/proto-signing@0.34.0)(@cosmjs/stargate@0.34.0)(axios@1.12.2)(decimal.js@10.6.0)(fuels@0.101.1(vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2)))(google-protobuf@3.21.4)(long@5.3.2)(msgpackr@1.11.5)(viem@2.38.3(typescript@5.9.3)) - '@cosmjs/proto-signing': - specifier: ^0.34.0 - version: 0.34.0 - '@cosmjs/stargate': - specifier: ^0.34.0 - version: 0.34.0 - '@metamask/safe-event-emitter': - specifier: 3.1.2 - version: 3.1.2 - '@starkware-industries/starkware-crypto-utils': - specifier: ^0.2.1 - version: 0.2.1 - '@tronweb3/tronwallet-abstract-adapter': - specifier: ^1.1.9 - version: 1.1.9 - axios: - specifier: ^1.12.2 - version: 1.12.2 - decimal.js: - specifier: 10.6.0 - version: 10.6.0 - es-toolkit: - specifier: ^1.40.0 - version: 1.40.0 - fuels: - specifier: 0.101.1 - version: 0.101.1(vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2)) - it-ws: - specifier: ^6.1.5 - version: 6.1.5 - long: - specifier: ^5.3.2 - version: 5.3.2 - msgpackr: - specifier: ^1.11.5 - version: 1.11.5 - tronweb: - specifier: ^6.0.4 - version: 6.0.4 - tslib: - specifier: 2.8.1 - version: 2.8.1 - viem: - specifier: ^2.0.0 - version: 2.38.3(typescript@5.9.3) - devDependencies: - '@rollup/plugin-commonjs': - specifier: ^25.0.8 - version: 25.0.8(rollup@4.52.4) - '@rollup/plugin-json': - specifier: 6.1.0 - version: 6.1.0(rollup@4.52.4) - '@rollup/plugin-node-resolve': - specifier: ^15.3.1 - version: 15.3.1(rollup@4.52.4) - '@rollup/plugin-typescript': - specifier: ^11.1.6 - version: 11.1.6(rollup@4.52.4)(tslib@2.8.1)(typescript@5.9.3) - rollup: - specifier: ^4.0.0 - version: 4.52.4 - rollup-plugin-dts: - specifier: ^6.2.3 - version: 6.2.3(rollup@4.52.4)(typescript@5.9.3) - rollup-plugin-typescript2: - specifier: 0.36.0 - version: 0.36.0(rollup@4.52.4)(typescript@5.9.3) - typescript: - specifier: ^5.0.0 - version: 5.9.3 - - packages/widgets: - dependencies: - '@avail-project/nexus-core': - specifier: workspace:* - version: link:../core - '@lottiefiles/dotlottie-react': - specifier: 0.14.2 - version: 0.14.2(react@19.2.0) - '@nexus/commons': - specifier: workspace:* - version: link:../commons - class-variance-authority: - specifier: 0.7.1 - version: 0.7.1 - clsx: - specifier: 2.1.1 - version: 2.1.1 - decimal.js: - specifier: 10.6.0 - version: 10.6.0 - motion: - specifier: 12.23.0 - version: 12.23.0(react-dom@19.2.0(react@19.2.0))(react@19.2.0) - react: - specifier: '>=16.8.0' - version: 19.2.0 - react-dom: - specifier: '>=16.8.0' - version: 19.2.0(react@19.2.0) - tailwind-merge: - specifier: 3.3.1 - version: 3.3.1 - viem: - specifier: ^2.0.0 - version: 2.38.3(typescript@5.9.3) - devDependencies: - '@rollup/plugin-commonjs': - specifier: ^25.0.8 - version: 25.0.8(rollup@4.52.4) - '@rollup/plugin-json': - specifier: 6.1.0 - version: 6.1.0(rollup@4.52.4) - '@rollup/plugin-node-resolve': - specifier: ^15.3.1 - version: 15.3.1(rollup@4.52.4) - '@rollup/plugin-typescript': - specifier: ^11.1.6 - version: 11.1.6(rollup@4.52.4)(tslib@2.8.1)(typescript@5.9.3) - '@tailwindcss/postcss': - specifier: 4.1.10 - version: 4.1.10 - '@types/react': - specifier: 19.1.8 - version: 19.1.8 - '@types/react-dom': - specifier: 19.1.6 - version: 19.1.6(@types/react@19.1.8) - autoprefixer: - specifier: 10.4.21 - version: 10.4.21(postcss@8.5.6) - postcss: - specifier: 8.5.6 - version: 8.5.6 - postcss-import: - specifier: 16.1.1 - version: 16.1.1(postcss@8.5.6) - postcss-nesting: - specifier: 13.0.2 - version: 13.0.2(postcss@8.5.6) - rollup: - specifier: ^4.0.0 - version: 4.52.4 - rollup-plugin-dts: - specifier: ^6.2.3 - version: 6.2.3(rollup@4.52.4)(typescript@5.9.3) - rollup-plugin-postcss: - specifier: 4.0.2 - version: 4.0.2(postcss@8.5.6) - rollup-plugin-typescript2: - specifier: 0.36.0 - version: 0.36.0(rollup@4.52.4)(typescript@5.9.3) - tailwindcss: - specifier: 4.1.10 - version: 4.1.10 - typescript: - specifier: ^5.0.0 - version: 5.9.3 - -packages: - - '@adraffy/ens-normalize@1.10.1': - resolution: {integrity: sha512-96Z2IP3mYmF1Xg2cDm8f1gWGf/HUVedQ3FMifV4kG/PQ4yEP51xDtRAEfhVNt5f/uzpNkZHwWQuUcu6D6K+Ekw==} - - '@adraffy/ens-normalize@1.11.1': - resolution: {integrity: sha512-nhCBV3quEgesuf7c7KYfperqSS14T8bYuvJ8PcLJp6znkZpFc0AuW4qBtr8eKVyPPe/8RSr7sglCWPU5eaxwKQ==} - - '@alloc/quick-lru@5.2.0': - resolution: {integrity: sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==} - engines: {node: '>=10'} - - '@ampproject/remapping@2.3.0': - resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==} - engines: {node: '>=6.0.0'} - - '@avail-project/ca-common@1.0.0-beta.7': - resolution: {integrity: sha512-TCRrAM5aW0A+DoQiqmY0UJcZn6R3Mtpbt7V57V6LG4Tu52j4CC8Eye2a8Uo37YoFDXilB+AKyK6Ia+U9Kjximw==} - peerDependencies: - '@cosmjs/proto-signing': ^0.34.0 - '@cosmjs/stargate': ^0.34.0 - axios: ^1.10.0 - decimal.js: 10.6.0 - fuels: ^0.101.1 - long: ^5.3.2 - msgpackr: ^1.11.4 - viem: ^2.0.0 - - '@babel/code-frame@7.27.1': - resolution: {integrity: sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==} - engines: {node: '>=6.9.0'} - - '@babel/helper-validator-identifier@7.27.1': - resolution: {integrity: sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==} - engines: {node: '>=6.9.0'} - - '@babel/runtime@7.26.10': - resolution: {integrity: sha512-2WJMeRQPHKSPemqk/awGrAiuFfzBmOIPXKizAsVhWH9YJqLZ0H+HS4c8loHGgW6utJ3E/ejXQUsiGaQy2NZ9Fw==} - engines: {node: '>=6.9.0'} - - '@bufbuild/protobuf@2.9.0': - resolution: {integrity: sha512-rnJenoStJ8nvmt9Gzye8nkYd6V22xUAnu4086ER7h1zJ508vStko4pMvDeQ446ilDTFpV5wnoc5YS7XvMwwMqA==} - - '@cosmjs/amino@0.34.0': - resolution: {integrity: sha512-wvVMmsr5cM7BSY1Z6QkOuJOjWaC4u5xjvfEO9tSpFhxjXeYlkZapU+Zp88pK6hG/UJUkGD301MN+STFbfWW2xA==} - - '@cosmjs/crypto@0.34.0': - resolution: {integrity: sha512-hn8Z1RYS9bhT5mbitGhPYF5CMcln9r2BVZ7nXIpfpI7TdhUEmNnHVI2ddodxFun0uOg8kokOM6X/etD/MZ6NFA==} - - '@cosmjs/encoding@0.34.0': - resolution: {integrity: sha512-oWUA9VTnr74GHMdMCvaaCfP0g66Y9iT7TA8vkWB1sfd+fO5FznAcMACEiF+sBE0TBoKGr02tYCJDCe9XNp2gOg==} - - '@cosmjs/json-rpc@0.34.0': - resolution: {integrity: sha512-2j0kmz1l3ftVkSRjt1d3H0iHlP5s02ULGz4CBF+Da/2u93ghudxfC38i0QiWKIjIGtqUv5w9ryd0YqIgnmuEew==} - - '@cosmjs/math@0.34.0': - resolution: {integrity: sha512-E/7dxu/hhbVEz1NNGJi+gPAadEtlk4N1ONm4CRgTnVWmPSLHNFgATF+UANAVUVAOfy6OpB0t94gAHRLYnEZYeA==} - - '@cosmjs/proto-signing@0.34.0': - resolution: {integrity: sha512-1/f4JNSAhsP5lr7fdCJxT+qkWqeDq8vViwCilqMIkqvxLAcf6FxEkvmTOpYBAdOT5fVe3+5nZ5GX5FYMq1tdfA==} - - '@cosmjs/socket@0.34.0': - resolution: {integrity: sha512-smIYDsRVLkP/q/Rkxq7Lutrxly3uJOisKvcdpNGkG9PVENwYdF5imHwNy/pLhOIRfk8AGE2s03ag0b2HYwxSzQ==} - - '@cosmjs/stargate@0.34.0': - resolution: {integrity: sha512-FU/A0OdkNKfqQ4d7CC8KceTVGoCy3BemFgVjbXL/K5FnAafEjqqWInQ531oNvBejpMdm1NSkfbp97CfILeTW7A==} - - '@cosmjs/stream@0.34.0': - resolution: {integrity: sha512-87pWCl4g1Cm11cX0iK8nSQYs7oswPUShlwOF8feIrxwC+bqLJh/oEtl7yjjXD2ie8UgtPZAvo9GQ2OTCMpK3Ww==} - - '@cosmjs/tendermint-rpc@0.34.0': - resolution: {integrity: sha512-riUuEG8VG90zJAe6r+mklRSHDZ64fb9JGU/JtQM8YIiwakrkruK21vtiejjgU9da5PHziabta0+N5SYUvHV+bA==} - - '@cosmjs/utils@0.34.0': - resolution: {integrity: sha512-yj8ET2NKCHTFodo8guyEFvE3ZAu1eyp/LiH/oyesNoR6g2Se+aG4ViMMrD4ApoGf2bRtQTC4JWWODQSNUVteJg==} - - '@csstools/selector-resolve-nested@3.1.0': - resolution: {integrity: sha512-mf1LEW0tJLKfWyvn5KdDrhpxHyuxpbNwTIwOYLIvsTffeyOf85j5oIzfG0yosxDgx/sswlqBnESYUcQH0vgZ0g==} - engines: {node: '>=18'} - peerDependencies: - postcss-selector-parser: ^7.0.0 - - '@csstools/selector-specificity@5.0.0': - resolution: {integrity: sha512-PCqQV3c4CoVm3kdPhyeZ07VmBRdH2EpMFA/pd9OASpOEC3aXNGoqPDAZ80D0cLpMBxnmk0+yNhGsEx31hq7Gtw==} - engines: {node: '>=18'} - peerDependencies: - postcss-selector-parser: ^7.0.0 - - '@esbuild/aix-ppc64@0.25.1': - resolution: {integrity: sha512-kfYGy8IdzTGy+z0vFGvExZtxkFlA4zAxgKEahG9KE1ScBjpQnFsNOX8KTU5ojNru5ed5CVoJYXFtoxaq5nFbjQ==} - engines: {node: '>=18'} - cpu: [ppc64] - os: [aix] - - '@esbuild/aix-ppc64@0.25.11': - resolution: {integrity: sha512-Xt1dOL13m8u0WE8iplx9Ibbm+hFAO0GsU2P34UNoDGvZYkY8ifSiy6Zuc1lYxfG7svWE2fzqCUmFp5HCn51gJg==} - engines: {node: '>=18'} - cpu: [ppc64] - os: [aix] - - '@esbuild/android-arm64@0.25.1': - resolution: {integrity: sha512-50tM0zCJW5kGqgG7fQ7IHvQOcAn9TKiVRuQ/lN0xR+T2lzEFvAi1ZcS8DiksFcEpf1t/GYOeOfCAgDHFpkiSmA==} - engines: {node: '>=18'} - cpu: [arm64] - os: [android] - - '@esbuild/android-arm64@0.25.11': - resolution: {integrity: sha512-9slpyFBc4FPPz48+f6jyiXOx/Y4v34TUeDDXJpZqAWQn/08lKGeD8aDp9TMn9jDz2CiEuHwfhRmGBvpnd/PWIQ==} - engines: {node: '>=18'} - cpu: [arm64] - os: [android] - - '@esbuild/android-arm@0.25.1': - resolution: {integrity: sha512-dp+MshLYux6j/JjdqVLnMglQlFu+MuVeNrmT5nk6q07wNhCdSnB7QZj+7G8VMUGh1q+vj2Bq8kRsuyA00I/k+Q==} - engines: {node: '>=18'} - cpu: [arm] - os: [android] - - '@esbuild/android-arm@0.25.11': - resolution: {integrity: sha512-uoa7dU+Dt3HYsethkJ1k6Z9YdcHjTrSb5NUy66ZfZaSV8hEYGD5ZHbEMXnqLFlbBflLsl89Zke7CAdDJ4JI+Gg==} - engines: {node: '>=18'} - cpu: [arm] - os: [android] - - '@esbuild/android-x64@0.25.1': - resolution: {integrity: sha512-GCj6WfUtNldqUzYkN/ITtlhwQqGWu9S45vUXs7EIYf+7rCiiqH9bCloatO9VhxsL0Pji+PF4Lz2XXCES+Q8hDw==} - engines: {node: '>=18'} - cpu: [x64] - os: [android] - - '@esbuild/android-x64@0.25.11': - resolution: {integrity: sha512-Sgiab4xBjPU1QoPEIqS3Xx+R2lezu0LKIEcYe6pftr56PqPygbB7+szVnzoShbx64MUupqoE0KyRlN7gezbl8g==} - engines: {node: '>=18'} - cpu: [x64] - os: [android] - - '@esbuild/darwin-arm64@0.25.1': - resolution: {integrity: sha512-5hEZKPf+nQjYoSr/elb62U19/l1mZDdqidGfmFutVUjjUZrOazAtwK+Kr+3y0C/oeJfLlxo9fXb1w7L+P7E4FQ==} - engines: {node: '>=18'} - cpu: [arm64] - os: [darwin] - - '@esbuild/darwin-arm64@0.25.11': - resolution: {integrity: sha512-VekY0PBCukppoQrycFxUqkCojnTQhdec0vevUL/EDOCnXd9LKWqD/bHwMPzigIJXPhC59Vd1WFIL57SKs2mg4w==} - engines: {node: '>=18'} - cpu: [arm64] - os: [darwin] - - '@esbuild/darwin-x64@0.25.1': - resolution: {integrity: sha512-hxVnwL2Dqs3fM1IWq8Iezh0cX7ZGdVhbTfnOy5uURtao5OIVCEyj9xIzemDi7sRvKsuSdtCAhMKarxqtlyVyfA==} - engines: {node: '>=18'} - cpu: [x64] - os: [darwin] - - '@esbuild/darwin-x64@0.25.11': - resolution: {integrity: sha512-+hfp3yfBalNEpTGp9loYgbknjR695HkqtY3d3/JjSRUyPg/xd6q+mQqIb5qdywnDxRZykIHs3axEqU6l1+oWEQ==} - engines: {node: '>=18'} - cpu: [x64] - os: [darwin] - - '@esbuild/freebsd-arm64@0.25.1': - resolution: {integrity: sha512-1MrCZs0fZa2g8E+FUo2ipw6jw5qqQiH+tERoS5fAfKnRx6NXH31tXBKI3VpmLijLH6yriMZsxJtaXUyFt/8Y4A==} - engines: {node: '>=18'} - cpu: [arm64] - os: [freebsd] - - '@esbuild/freebsd-arm64@0.25.11': - resolution: {integrity: sha512-CmKjrnayyTJF2eVuO//uSjl/K3KsMIeYeyN7FyDBjsR3lnSJHaXlVoAK8DZa7lXWChbuOk7NjAc7ygAwrnPBhA==} - engines: {node: '>=18'} - cpu: [arm64] - os: [freebsd] - - '@esbuild/freebsd-x64@0.25.1': - resolution: {integrity: sha512-0IZWLiTyz7nm0xuIs0q1Y3QWJC52R8aSXxe40VUxm6BB1RNmkODtW6LHvWRrGiICulcX7ZvyH6h5fqdLu4gkww==} - engines: {node: '>=18'} - cpu: [x64] - os: [freebsd] - - '@esbuild/freebsd-x64@0.25.11': - resolution: {integrity: sha512-Dyq+5oscTJvMaYPvW3x3FLpi2+gSZTCE/1ffdwuM6G1ARang/mb3jvjxs0mw6n3Lsw84ocfo9CrNMqc5lTfGOw==} - engines: {node: '>=18'} - cpu: [x64] - os: [freebsd] - - '@esbuild/linux-arm64@0.25.1': - resolution: {integrity: sha512-jaN3dHi0/DDPelk0nLcXRm1q7DNJpjXy7yWaWvbfkPvI+7XNSc/lDOnCLN7gzsyzgu6qSAmgSvP9oXAhP973uQ==} - engines: {node: '>=18'} - cpu: [arm64] - os: [linux] - - '@esbuild/linux-arm64@0.25.11': - resolution: {integrity: sha512-Qr8AzcplUhGvdyUF08A1kHU3Vr2O88xxP0Tm8GcdVOUm25XYcMPp2YqSVHbLuXzYQMf9Bh/iKx7YPqECs6ffLA==} - engines: {node: '>=18'} - cpu: [arm64] - os: [linux] - - '@esbuild/linux-arm@0.25.1': - resolution: {integrity: sha512-NdKOhS4u7JhDKw9G3cY6sWqFcnLITn6SqivVArbzIaf3cemShqfLGHYMx8Xlm/lBit3/5d7kXvriTUGa5YViuQ==} - engines: {node: '>=18'} - cpu: [arm] - os: [linux] - - '@esbuild/linux-arm@0.25.11': - resolution: {integrity: sha512-TBMv6B4kCfrGJ8cUPo7vd6NECZH/8hPpBHHlYI3qzoYFvWu2AdTvZNuU/7hsbKWqu/COU7NIK12dHAAqBLLXgw==} - engines: {node: '>=18'} - cpu: [arm] - os: [linux] - - '@esbuild/linux-ia32@0.25.1': - resolution: {integrity: sha512-OJykPaF4v8JidKNGz8c/q1lBO44sQNUQtq1KktJXdBLn1hPod5rE/Hko5ugKKZd+D2+o1a9MFGUEIUwO2YfgkQ==} - engines: {node: '>=18'} - cpu: [ia32] - os: [linux] - - '@esbuild/linux-ia32@0.25.11': - resolution: {integrity: sha512-TmnJg8BMGPehs5JKrCLqyWTVAvielc615jbkOirATQvWWB1NMXY77oLMzsUjRLa0+ngecEmDGqt5jiDC6bfvOw==} - engines: {node: '>=18'} - cpu: [ia32] - os: [linux] - - '@esbuild/linux-loong64@0.25.1': - resolution: {integrity: sha512-nGfornQj4dzcq5Vp835oM/o21UMlXzn79KobKlcs3Wz9smwiifknLy4xDCLUU0BWp7b/houtdrgUz7nOGnfIYg==} - engines: {node: '>=18'} - cpu: [loong64] - os: [linux] - - '@esbuild/linux-loong64@0.25.11': - resolution: {integrity: sha512-DIGXL2+gvDaXlaq8xruNXUJdT5tF+SBbJQKbWy/0J7OhU8gOHOzKmGIlfTTl6nHaCOoipxQbuJi7O++ldrxgMw==} - engines: {node: '>=18'} - cpu: [loong64] - os: [linux] - - '@esbuild/linux-mips64el@0.25.1': - resolution: {integrity: sha512-1osBbPEFYwIE5IVB/0g2X6i1qInZa1aIoj1TdL4AaAb55xIIgbg8Doq6a5BzYWgr+tEcDzYH67XVnTmUzL+nXg==} - engines: {node: '>=18'} - cpu: [mips64el] - os: [linux] - - '@esbuild/linux-mips64el@0.25.11': - resolution: {integrity: sha512-Osx1nALUJu4pU43o9OyjSCXokFkFbyzjXb6VhGIJZQ5JZi8ylCQ9/LFagolPsHtgw6himDSyb5ETSfmp4rpiKQ==} - engines: {node: '>=18'} - cpu: [mips64el] - os: [linux] - - '@esbuild/linux-ppc64@0.25.1': - resolution: {integrity: sha512-/6VBJOwUf3TdTvJZ82qF3tbLuWsscd7/1w+D9LH0W/SqUgM5/JJD0lrJ1fVIfZsqB6RFmLCe0Xz3fmZc3WtyVg==} - engines: {node: '>=18'} - cpu: [ppc64] - os: [linux] - - '@esbuild/linux-ppc64@0.25.11': - resolution: {integrity: sha512-nbLFgsQQEsBa8XSgSTSlrnBSrpoWh7ioFDUmwo158gIm5NNP+17IYmNWzaIzWmgCxq56vfr34xGkOcZ7jX6CPw==} - engines: {node: '>=18'} - cpu: [ppc64] - os: [linux] - - '@esbuild/linux-riscv64@0.25.1': - resolution: {integrity: sha512-nSut/Mx5gnilhcq2yIMLMe3Wl4FK5wx/o0QuuCLMtmJn+WeWYoEGDN1ipcN72g1WHsnIbxGXd4i/MF0gTcuAjQ==} - engines: {node: '>=18'} - cpu: [riscv64] - os: [linux] - - '@esbuild/linux-riscv64@0.25.11': - resolution: {integrity: sha512-HfyAmqZi9uBAbgKYP1yGuI7tSREXwIb438q0nqvlpxAOs3XnZ8RsisRfmVsgV486NdjD7Mw2UrFSw51lzUk1ww==} - engines: {node: '>=18'} - cpu: [riscv64] - os: [linux] - - '@esbuild/linux-s390x@0.25.1': - resolution: {integrity: sha512-cEECeLlJNfT8kZHqLarDBQso9a27o2Zd2AQ8USAEoGtejOrCYHNtKP8XQhMDJMtthdF4GBmjR2au3x1udADQQQ==} - engines: {node: '>=18'} - cpu: [s390x] - os: [linux] - - '@esbuild/linux-s390x@0.25.11': - resolution: {integrity: sha512-HjLqVgSSYnVXRisyfmzsH6mXqyvj0SA7pG5g+9W7ESgwA70AXYNpfKBqh1KbTxmQVaYxpzA/SvlB9oclGPbApw==} - engines: {node: '>=18'} - cpu: [s390x] - os: [linux] - - '@esbuild/linux-x64@0.25.1': - resolution: {integrity: sha512-xbfUhu/gnvSEg+EGovRc+kjBAkrvtk38RlerAzQxvMzlB4fXpCFCeUAYzJvrnhFtdeyVCDANSjJvOvGYoeKzFA==} - engines: {node: '>=18'} - cpu: [x64] - os: [linux] - - '@esbuild/linux-x64@0.25.11': - resolution: {integrity: sha512-HSFAT4+WYjIhrHxKBwGmOOSpphjYkcswF449j6EjsjbinTZbp8PJtjsVK1XFJStdzXdy/jaddAep2FGY+wyFAQ==} - engines: {node: '>=18'} - cpu: [x64] - os: [linux] - - '@esbuild/netbsd-arm64@0.25.1': - resolution: {integrity: sha512-O96poM2XGhLtpTh+s4+nP7YCCAfb4tJNRVZHfIE7dgmax+yMP2WgMd2OecBuaATHKTHsLWHQeuaxMRnCsH8+5g==} - engines: {node: '>=18'} - cpu: [arm64] - os: [netbsd] - - '@esbuild/netbsd-arm64@0.25.11': - resolution: {integrity: sha512-hr9Oxj1Fa4r04dNpWr3P8QKVVsjQhqrMSUzZzf+LZcYjZNqhA3IAfPQdEh1FLVUJSiu6sgAwp3OmwBfbFgG2Xg==} - engines: {node: '>=18'} - cpu: [arm64] - os: [netbsd] - - '@esbuild/netbsd-x64@0.25.1': - resolution: {integrity: sha512-X53z6uXip6KFXBQ+Krbx25XHV/NCbzryM6ehOAeAil7X7oa4XIq+394PWGnwaSQ2WRA0KI6PUO6hTO5zeF5ijA==} - engines: {node: '>=18'} - cpu: [x64] - os: [netbsd] - - '@esbuild/netbsd-x64@0.25.11': - resolution: {integrity: sha512-u7tKA+qbzBydyj0vgpu+5h5AeudxOAGncb8N6C9Kh1N4n7wU1Xw1JDApsRjpShRpXRQlJLb9wY28ELpwdPcZ7A==} - engines: {node: '>=18'} - cpu: [x64] - os: [netbsd] - - '@esbuild/openbsd-arm64@0.25.1': - resolution: {integrity: sha512-Na9T3szbXezdzM/Kfs3GcRQNjHzM6GzFBeU1/6IV/npKP5ORtp9zbQjvkDJ47s6BCgaAZnnnu/cY1x342+MvZg==} - engines: {node: '>=18'} - cpu: [arm64] - os: [openbsd] - - '@esbuild/openbsd-arm64@0.25.11': - resolution: {integrity: sha512-Qq6YHhayieor3DxFOoYM1q0q1uMFYb7cSpLD2qzDSvK1NAvqFi8Xgivv0cFC6J+hWVw2teCYltyy9/m/14ryHg==} - engines: {node: '>=18'} - cpu: [arm64] - os: [openbsd] - - '@esbuild/openbsd-x64@0.25.1': - resolution: {integrity: sha512-T3H78X2h1tszfRSf+txbt5aOp/e7TAz3ptVKu9Oyir3IAOFPGV6O9c2naym5TOriy1l0nNf6a4X5UXRZSGX/dw==} - engines: {node: '>=18'} - cpu: [x64] - os: [openbsd] - - '@esbuild/openbsd-x64@0.25.11': - resolution: {integrity: sha512-CN+7c++kkbrckTOz5hrehxWN7uIhFFlmS/hqziSFVWpAzpWrQoAG4chH+nN3Be+Kzv/uuo7zhX716x3Sn2Jduw==} - engines: {node: '>=18'} - cpu: [x64] - os: [openbsd] - - '@esbuild/openharmony-arm64@0.25.11': - resolution: {integrity: sha512-rOREuNIQgaiR+9QuNkbkxubbp8MSO9rONmwP5nKncnWJ9v5jQ4JxFnLu4zDSRPf3x4u+2VN4pM4RdyIzDty/wQ==} - engines: {node: '>=18'} - cpu: [arm64] - os: [openharmony] - - '@esbuild/sunos-x64@0.25.1': - resolution: {integrity: sha512-2H3RUvcmULO7dIE5EWJH8eubZAI4xw54H1ilJnRNZdeo8dTADEZ21w6J22XBkXqGJbe0+wnNJtw3UXRoLJnFEg==} - engines: {node: '>=18'} - cpu: [x64] - os: [sunos] - - '@esbuild/sunos-x64@0.25.11': - resolution: {integrity: sha512-nq2xdYaWxyg9DcIyXkZhcYulC6pQ2FuCgem3LI92IwMgIZ69KHeY8T4Y88pcwoLIjbed8n36CyKoYRDygNSGhA==} - engines: {node: '>=18'} - cpu: [x64] - os: [sunos] - - '@esbuild/win32-arm64@0.25.1': - resolution: {integrity: sha512-GE7XvrdOzrb+yVKB9KsRMq+7a2U/K5Cf/8grVFRAGJmfADr/e/ODQ134RK2/eeHqYV5eQRFxb1hY7Nr15fv1NQ==} - engines: {node: '>=18'} - cpu: [arm64] - os: [win32] - - '@esbuild/win32-arm64@0.25.11': - resolution: {integrity: sha512-3XxECOWJq1qMZ3MN8srCJ/QfoLpL+VaxD/WfNRm1O3B4+AZ/BnLVgFbUV3eiRYDMXetciH16dwPbbHqwe1uU0Q==} - engines: {node: '>=18'} - cpu: [arm64] - os: [win32] - - '@esbuild/win32-ia32@0.25.1': - resolution: {integrity: sha512-uOxSJCIcavSiT6UnBhBzE8wy3n0hOkJsBOzy7HDAuTDE++1DJMRRVCPGisULScHL+a/ZwdXPpXD3IyFKjA7K8A==} - engines: {node: '>=18'} - cpu: [ia32] - os: [win32] - - '@esbuild/win32-ia32@0.25.11': - resolution: {integrity: sha512-3ukss6gb9XZ8TlRyJlgLn17ecsK4NSQTmdIXRASVsiS2sQ6zPPZklNJT5GR5tE/MUarymmy8kCEf5xPCNCqVOA==} - engines: {node: '>=18'} - cpu: [ia32] - os: [win32] - - '@esbuild/win32-x64@0.25.1': - resolution: {integrity: sha512-Y1EQdcfwMSeQN/ujR5VayLOJ1BHaK+ssyk0AEzPjC+t1lITgsnccPqFjb6V+LsTp/9Iov4ysfjxLaGJ9RPtkVg==} - engines: {node: '>=18'} - cpu: [x64] - os: [win32] - - '@esbuild/win32-x64@0.25.11': - resolution: {integrity: sha512-D7Hpz6A2L4hzsRpPaCYkQnGOotdUpDzSGRIv9I+1ITdHROSFUWW95ZPZWQmGka1Fg7W3zFJowyn9WGwMJ0+KPA==} - engines: {node: '>=18'} - cpu: [x64] - os: [win32] - - '@fuel-ts/abi-coder@0.101.1': - resolution: {integrity: sha512-PgKO4BLo8dzwdJqHIMmOtoOiV/a8OIqPju9h3maOLXMDwgVXxL/NLku33iLP8CDuFu91AssAOg5XURTHDfQ1aQ==} - engines: {node: ^18.20.3 || ^20.0.0 || ^22.0.0} - - '@fuel-ts/abi-typegen@0.101.1': - resolution: {integrity: sha512-4s4Zf+5Ohdym9bl/Cebl7kwufaKJ9C2nJNt5EB+0bXmVArl8zOpP67U+cQSVXawMUVryBVM3mY7Ay2p/WD9wDg==} - engines: {node: ^18.20.3 || ^20.0.0 || ^22.0.0} - hasBin: true - - '@fuel-ts/account@0.101.1': - resolution: {integrity: sha512-x+UfuBaCvb9KYT+wIJba3RL21nR4JH0qZevDs/jzw9cLMsLl8AYLKMg2wS9rhR5OCoa9PbsOe9DDrDI+y3BpVA==} - engines: {node: ^18.20.3 || ^20.0.0 || ^22.0.0} - - '@fuel-ts/address@0.101.1': - resolution: {integrity: sha512-l+PvQ2kB/zS/TW7S3/UjjaJ95UNflWizmKr97M13gkOdP99UuI2InYu9zjH72Azbt3LR/RMilHMTyZeWRSV42w==} - engines: {node: ^18.20.3 || ^20.0.0 || ^22.0.0} - - '@fuel-ts/contract@0.101.1': - resolution: {integrity: sha512-UBOjDIYqO1EY8qirjxpEUsW0K2+fR8mC0xDI8k0c1Aes3YVAZyMmpf6ZWvjF5BVElu4kO8pFXr6xcQoDn6TuMw==} - engines: {node: ^18.20.3 || ^20.0.0 || ^22.0.0} - - '@fuel-ts/crypto@0.101.1': - resolution: {integrity: sha512-Dy6Q1NbdGojyT0q3mrZu72hSTlXfNprKA6A6vJHKkwRcwFphnrZHAubVfjzus4ZeQf9fdcqZrfWLUG76/F6r9g==} - engines: {node: ^18.20.3 || ^20.0.0 || ^22.0.0} - - '@fuel-ts/errors@0.101.1': - resolution: {integrity: sha512-BPp3/tD3YyxbV/qGujwrUOluyB4abEHOD1GIgvUGKiLy9S3TNjBzIPLYG0ARVcswvYTEh8r7/hoZcRKtpNpcEQ==} - engines: {node: ^18.20.3 || ^20.0.0 || ^22.0.0} - - '@fuel-ts/hasher@0.101.1': - resolution: {integrity: sha512-diLLZbMvwy6ivkZEBDzh6HXkqPzxCVJov29A4A+ILwvKcXHultJ/36bxj3S415cj5DtgVj8KBoqeo1Sw7cg+rg==} - engines: {node: ^18.20.3 || ^20.0.0 || ^22.0.0} - - '@fuel-ts/math@0.101.1': - resolution: {integrity: sha512-F1bGLZN71DmL5h1/znlXgWahL8A28RMur4B2MscTp/sFyqQ9tHlpEDjdF2ajr3lSxlMWohDJbElCNramLqE/Tg==} - engines: {node: ^18.20.3 || ^20.0.0 || ^22.0.0} - - '@fuel-ts/merkle@0.101.1': - resolution: {integrity: sha512-JJEdTQ2BxWHjX09caf42Ebfc32J0dHx/dv9pXfvpxc3BUgdRE8gM0Wvrqq/cu6S2XD/Y6vQp/qhOq9PXWJUuKg==} - engines: {node: ^18.20.3 || ^20.0.0 || ^22.0.0} - - '@fuel-ts/program@0.101.1': - resolution: {integrity: sha512-6ManClwCW7NI4jE3BoaNWStHyGEWcrD7hkK+9T5+hESY0ckGiBGMuKvR3VhVaTsTRVfqMx/m1kPSu2O5BY/vrA==} - engines: {node: ^18.20.3 || ^20.0.0 || ^22.0.0} - - '@fuel-ts/recipes@0.101.1': - resolution: {integrity: sha512-DVQfE7pnoFBmTNwBPrL2qN5jlp8w9rCD9aQKwvBaPwvi4UYiTg1elcWlX5/mEhUAnGlDIYOQ4XFuxLZAgmDUww==} - engines: {node: ^18.20.3 || ^20.0.0 || ^22.0.0} - - '@fuel-ts/script@0.101.1': - resolution: {integrity: sha512-6s6SKciwOYM/MK1DAE7Cd19hTL5FOG+FtPP9IvZ+UwmNz7zydD2LXHdTcOjTPZnhmzvhBrlfH2CUAsOqhMHGpg==} - engines: {node: ^18.20.3 || ^20.0.0 || ^22.0.0} - - '@fuel-ts/transactions@0.101.1': - resolution: {integrity: sha512-VLCtwOO5PD31rxSnGbBaJuQO8AwvqUwwRfXrE3fLzrreJKyUM5K2XZHsfQq9dtd/RWaaOUPNMp7ztVQzKebfUQ==} - engines: {node: ^18.20.3 || ^20.0.0 || ^22.0.0} - - '@fuel-ts/utils@0.101.1': - resolution: {integrity: sha512-H7j38/quroMccPrjFrnn+Cuui6iPpyH15NKdBT2XVv96rk9XX2DG5aBIGn+nYqPTA8+W+a7sp3U65sgckyZ4Rg==} - engines: {node: ^18.20.3 || ^20.0.0 || ^22.0.0} - peerDependencies: - vitest: 3.0.9 - - '@fuel-ts/versions@0.101.1': - resolution: {integrity: sha512-3/tYZBbCaShkzfrVEBulm83f3MJaUpOCK4q3BpAxvbhWHsKS9AxbLhHWQ0RZUXII5OJmGnSpWfy0Bhe7FYo93A==} - engines: {node: ^18.20.3 || ^20.0.0 || ^22.0.0} - hasBin: true - - '@fuels/vm-asm@0.60.2': - resolution: {integrity: sha512-wkCu63jTGJWpRZQirTaB8S4/gyoebEJLk3AKfnykt/lgWp1U9iHOcCICVHQP547i+y8jEVKwk18+huINFyYVFQ==} - - '@graphql-typed-document-node/core@3.2.0': - resolution: {integrity: sha512-mB9oAsNCm9aM3/SOv4YtBMqZbYj10R7dkq8byBqxGY/ncFwhf2oQzMV+LCRlWoDSEBJ3COiR1yeDvMtsoOsuFQ==} - peerDependencies: - graphql: ^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 - - '@improbable-eng/grpc-web@0.15.0': - resolution: {integrity: sha512-ERft9/0/8CmYalqOVnJnpdDry28q+j+nAlFFARdjyxXDJ+Mhgv9+F600QC8BR9ygOfrXRlAk6CvST2j+JCpQPg==} - peerDependencies: - google-protobuf: ^3.14.0 - - '@isaacs/cliui@8.0.2': - resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} - engines: {node: '>=12'} - - '@isaacs/fs-minipass@4.0.1': - resolution: {integrity: sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==} - engines: {node: '>=18.0.0'} - - '@jridgewell/gen-mapping@0.3.13': - resolution: {integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==} - - '@jridgewell/resolve-uri@3.1.2': - resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} - engines: {node: '>=6.0.0'} - - '@jridgewell/sourcemap-codec@1.5.5': - resolution: {integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==} - - '@jridgewell/trace-mapping@0.3.31': - resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==} - - '@lottiefiles/dotlottie-react@0.14.2': - resolution: {integrity: sha512-RR4r0HrKQbOAw6iS6C3mRARS2iu+yI+G1vICoUsRMHzlUUk1/26l3WyAjhcG+KoaGoKmORx8FgHjTNr4Sr/2Ug==} - peerDependencies: - react: ^17 || ^18 || ^19 - - '@lottiefiles/dotlottie-web@0.47.0': - resolution: {integrity: sha512-YN6wSB4iYZBYEAFKEs/taufrPH3rfNlUA632Ib61WoR58TALAJ1ZX8yDIGUBT28byMJhZR4+xdpRX4v7X8OeBQ==} - - '@metamask/safe-event-emitter@3.1.2': - resolution: {integrity: sha512-5yb2gMI1BDm0JybZezeoX/3XhPDOtTbcFvpTXM9kxsoZjPZFh4XciqRbpD6N86HYZqWDhEaKUDuOyR0sQHEjMA==} - engines: {node: '>=12.0.0'} - - '@msgpackr-extract/msgpackr-extract-darwin-arm64@3.0.3': - resolution: {integrity: sha512-QZHtlVgbAdy2zAqNA9Gu1UpIuI8Xvsd1v8ic6B2pZmeFnFcMWiPLfWXh7TVw4eGEZ/C9TH281KwhVoeQUKbyjw==} - cpu: [arm64] - os: [darwin] - - '@msgpackr-extract/msgpackr-extract-darwin-x64@3.0.3': - resolution: {integrity: sha512-mdzd3AVzYKuUmiWOQ8GNhl64/IoFGol569zNRdkLReh6LRLHOXxU4U8eq0JwaD8iFHdVGqSy4IjFL4reoWCDFw==} - cpu: [x64] - os: [darwin] - - '@msgpackr-extract/msgpackr-extract-linux-arm64@3.0.3': - resolution: {integrity: sha512-YxQL+ax0XqBJDZiKimS2XQaf+2wDGVa1enVRGzEvLLVFeqa5kx2bWbtcSXgsxjQB7nRqqIGFIcLteF/sHeVtQg==} - cpu: [arm64] - os: [linux] - - '@msgpackr-extract/msgpackr-extract-linux-arm@3.0.3': - resolution: {integrity: sha512-fg0uy/dG/nZEXfYilKoRe7yALaNmHoYeIoJuJ7KJ+YyU2bvY8vPv27f7UKhGRpY6euFYqEVhxCFZgAUNQBM3nw==} - cpu: [arm] - os: [linux] - - '@msgpackr-extract/msgpackr-extract-linux-x64@3.0.3': - resolution: {integrity: sha512-cvwNfbP07pKUfq1uH+S6KJ7dT9K8WOE4ZiAcsrSes+UY55E/0jLYc+vq+DO7jlmqRb5zAggExKm0H7O/CBaesg==} - cpu: [x64] - os: [linux] - - '@msgpackr-extract/msgpackr-extract-win32-x64@3.0.3': - resolution: {integrity: sha512-x0fWaQtYp4E6sktbsdAqnehxDgEc/VwM7uLsRCYWaiGu0ykYdZPiS8zCWdnjHwyiumousxfBm4SO31eXqwEZhQ==} - cpu: [x64] - os: [win32] - - '@noble/ciphers@1.3.0': - resolution: {integrity: sha512-2I0gnIVPtfnMw9ee9h1dJG7tp81+8Ob3OJb3Mv37rx5L40/b0i7djjCVvGOVqc9AEIQyvyu1i6ypKdFw8R8gQw==} - engines: {node: ^14.21.3 || >=16} - - '@noble/curves@1.2.0': - resolution: {integrity: sha512-oYclrNgRaM9SsBUBVbb8M6DTV7ZHRTKugureoYEncY5c65HOmRzvSiTE3y5CYaPYJA/GVkrhXEoF0M3Ya9PMnw==} - - '@noble/curves@1.4.2': - resolution: {integrity: sha512-TavHr8qycMChk8UwMld0ZDRvatedkzWfH8IiaeGCfymOP5i0hSCozz9vHOL0nkwk7HRMlFnAiKpS2jrUmSybcw==} - - '@noble/curves@1.8.1': - resolution: {integrity: sha512-warwspo+UYUPep0Q+vtdVB4Ugn8GGQj8iyB3gnRWsztmUHTI3S1nhdiWNsPUGL0vud7JlRRk1XEu7Lq1KGTnMQ==} - engines: {node: ^14.21.3 || >=16} - - '@noble/curves@1.9.1': - resolution: {integrity: sha512-k11yZxZg+t+gWvBbIswW0yoJlu8cHOC7dhunwOzoWH/mXGBiYyR4YY6hAEK/3EUs4UpB8la1RfdRpeGsFHkWsA==} - engines: {node: ^14.21.3 || >=16} - - '@noble/curves@1.9.7': - resolution: {integrity: sha512-gbKGcRUYIjA3/zCCNaWDciTMFI0dCkvou3TL8Zmy5Nc7sJ47a0jtOeZoTaMxkuqRo9cRhjOdZJXegxYE5FN/xw==} - engines: {node: ^14.21.3 || >=16} - - '@noble/hashes@1.3.2': - resolution: {integrity: sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ==} - engines: {node: '>= 16'} - - '@noble/hashes@1.4.0': - resolution: {integrity: sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==} - engines: {node: '>= 16'} - - '@noble/hashes@1.7.1': - resolution: {integrity: sha512-B8XBPsn4vT/KJAGqDzbwztd+6Yte3P4V7iafm24bxgDe/mlRuK6xmWPuCNrKt2vDafZ8MfJLlchDG/vYafQEjQ==} - engines: {node: ^14.21.3 || >=16} - - '@noble/hashes@1.8.0': - resolution: {integrity: sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==} - engines: {node: ^14.21.3 || >=16} - - '@pkgjs/parseargs@0.11.0': - resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} - engines: {node: '>=14'} - - '@rollup/plugin-alias@5.1.1': - resolution: {integrity: sha512-PR9zDb+rOzkRb2VD+EuKB7UC41vU5DIwZ5qqCpk0KJudcWAyi8rvYOhS7+L5aZCspw1stTViLgN5v6FF1p5cgQ==} - engines: {node: '>=14.0.0'} - peerDependencies: - rollup: ^4.0.0 - peerDependenciesMeta: - rollup: - optional: true - - '@rollup/plugin-commonjs@25.0.8': - resolution: {integrity: sha512-ZEZWTK5n6Qde0to4vS9Mr5x/0UZoqCxPVR9KRUjU4kA2sO7GEUn1fop0DAwpO6z0Nw/kJON9bDmSxdWxO/TT1A==} - engines: {node: '>=14.0.0'} - peerDependencies: - rollup: ^4.0.0 - peerDependenciesMeta: - rollup: - optional: true - - '@rollup/plugin-json@6.1.0': - resolution: {integrity: sha512-EGI2te5ENk1coGeADSIwZ7G2Q8CJS2sF120T7jLw4xFw9n7wIOXHo+kIYRAoVpJAN+kmqZSoO3Fp4JtoNF4ReA==} - engines: {node: '>=14.0.0'} - peerDependencies: - rollup: ^4.0.0 - peerDependenciesMeta: - rollup: - optional: true - - '@rollup/plugin-node-resolve@15.3.1': - resolution: {integrity: sha512-tgg6b91pAybXHJQMAAwW9VuWBO6Thi+q7BCNARLwSqlmsHz0XYURtGvh/AuwSADXSI4h/2uHbs7s4FzlZDGSGA==} - engines: {node: '>=14.0.0'} - peerDependencies: - rollup: ^4.0.0 - peerDependenciesMeta: - rollup: - optional: true - - '@rollup/plugin-typescript@11.1.6': - resolution: {integrity: sha512-R92yOmIACgYdJ7dJ97p4K69I8gg6IEHt8M7dUBxN3W6nrO8uUxX5ixl0yU/N3aZTi8WhPuICvOHXQvF6FaykAA==} - engines: {node: '>=14.0.0'} - peerDependencies: - rollup: ^4.0.0 - tslib: '*' - typescript: ^5.0.0 - peerDependenciesMeta: - rollup: - optional: true - tslib: - optional: true - - '@rollup/pluginutils@4.2.1': - resolution: {integrity: sha512-iKnFXr7NkdZAIHiIWE+BX5ULi/ucVFYWD6TbAV+rZctiRTY2PL6tsIKhoIOaoskiWAkgu+VsbXgUVDNLHf+InQ==} - engines: {node: '>= 8.0.0'} - - '@rollup/pluginutils@5.3.0': - resolution: {integrity: sha512-5EdhGZtnu3V88ces7s53hhfK5KSASnJZv8Lulpc04cWO3REESroJXg73DFsOmgbU2BhwV0E20bu2IDZb3VKW4Q==} - engines: {node: '>=14.0.0'} - peerDependencies: - rollup: ^4.0.0 - peerDependenciesMeta: - rollup: - optional: true - - '@rollup/rollup-android-arm-eabi@4.52.4': - resolution: {integrity: sha512-BTm2qKNnWIQ5auf4deoetINJm2JzvihvGb9R6K/ETwKLql/Bb3Eg2H1FBp1gUb4YGbydMA3jcmQTR73q7J+GAA==} - cpu: [arm] - os: [android] - - '@rollup/rollup-android-arm64@4.52.4': - resolution: {integrity: sha512-P9LDQiC5vpgGFgz7GSM6dKPCiqR3XYN1WwJKA4/BUVDjHpYsf3iBEmVz62uyq20NGYbiGPR5cNHI7T1HqxNs2w==} - cpu: [arm64] - os: [android] - - '@rollup/rollup-darwin-arm64@4.52.4': - resolution: {integrity: sha512-QRWSW+bVccAvZF6cbNZBJwAehmvG9NwfWHwMy4GbWi/BQIA/laTIktebT2ipVjNncqE6GLPxOok5hsECgAxGZg==} - cpu: [arm64] - os: [darwin] - - '@rollup/rollup-darwin-x64@4.52.4': - resolution: {integrity: sha512-hZgP05pResAkRJxL1b+7yxCnXPGsXU0fG9Yfd6dUaoGk+FhdPKCJ5L1Sumyxn8kvw8Qi5PvQ8ulenUbRjzeCTw==} - cpu: [x64] - os: [darwin] - - '@rollup/rollup-freebsd-arm64@4.52.4': - resolution: {integrity: sha512-xmc30VshuBNUd58Xk4TKAEcRZHaXlV+tCxIXELiE9sQuK3kG8ZFgSPi57UBJt8/ogfhAF5Oz4ZSUBN77weM+mQ==} - cpu: [arm64] - os: [freebsd] - - '@rollup/rollup-freebsd-x64@4.52.4': - resolution: {integrity: sha512-WdSLpZFjOEqNZGmHflxyifolwAiZmDQzuOzIq9L27ButpCVpD7KzTRtEG1I0wMPFyiyUdOO+4t8GvrnBLQSwpw==} - cpu: [x64] - os: [freebsd] - - '@rollup/rollup-linux-arm-gnueabihf@4.52.4': - resolution: {integrity: sha512-xRiOu9Of1FZ4SxVbB0iEDXc4ddIcjCv2aj03dmW8UrZIW7aIQ9jVJdLBIhxBI+MaTnGAKyvMwPwQnoOEvP7FgQ==} - cpu: [arm] - os: [linux] - - '@rollup/rollup-linux-arm-musleabihf@4.52.4': - resolution: {integrity: sha512-FbhM2p9TJAmEIEhIgzR4soUcsW49e9veAQCziwbR+XWB2zqJ12b4i/+hel9yLiD8pLncDH4fKIPIbt5238341Q==} - cpu: [arm] - os: [linux] - - '@rollup/rollup-linux-arm64-gnu@4.52.4': - resolution: {integrity: sha512-4n4gVwhPHR9q/g8lKCyz0yuaD0MvDf7dV4f9tHt0C73Mp8h38UCtSCSE6R9iBlTbXlmA8CjpsZoujhszefqueg==} - cpu: [arm64] - os: [linux] - - '@rollup/rollup-linux-arm64-musl@4.52.4': - resolution: {integrity: sha512-u0n17nGA0nvi/11gcZKsjkLj1QIpAuPFQbR48Subo7SmZJnGxDpspyw2kbpuoQnyK+9pwf3pAoEXerJs/8Mi9g==} - cpu: [arm64] - os: [linux] - - '@rollup/rollup-linux-loong64-gnu@4.52.4': - resolution: {integrity: sha512-0G2c2lpYtbTuXo8KEJkDkClE/+/2AFPdPAbmaHoE870foRFs4pBrDehilMcrSScrN/fB/1HTaWO4bqw+ewBzMQ==} - cpu: [loong64] - os: [linux] - - '@rollup/rollup-linux-ppc64-gnu@4.52.4': - resolution: {integrity: sha512-teSACug1GyZHmPDv14VNbvZFX779UqWTsd7KtTM9JIZRDI5NUwYSIS30kzI8m06gOPB//jtpqlhmraQ68b5X2g==} - cpu: [ppc64] - os: [linux] - - '@rollup/rollup-linux-riscv64-gnu@4.52.4': - resolution: {integrity: sha512-/MOEW3aHjjs1p4Pw1Xk4+3egRevx8Ji9N6HUIA1Ifh8Q+cg9dremvFCUbOX2Zebz80BwJIgCBUemjqhU5XI5Eg==} - cpu: [riscv64] - os: [linux] - - '@rollup/rollup-linux-riscv64-musl@4.52.4': - resolution: {integrity: sha512-1HHmsRyh845QDpEWzOFtMCph5Ts+9+yllCrREuBR/vg2RogAQGGBRC8lDPrPOMnrdOJ+mt1WLMOC2Kao/UwcvA==} - cpu: [riscv64] - os: [linux] - - '@rollup/rollup-linux-s390x-gnu@4.52.4': - resolution: {integrity: sha512-seoeZp4L/6D1MUyjWkOMRU6/iLmCU2EjbMTyAG4oIOs1/I82Y5lTeaxW0KBfkUdHAWN7j25bpkt0rjnOgAcQcA==} - cpu: [s390x] - os: [linux] - - '@rollup/rollup-linux-x64-gnu@4.52.4': - resolution: {integrity: sha512-Wi6AXf0k0L7E2gteNsNHUs7UMwCIhsCTs6+tqQ5GPwVRWMaflqGec4Sd8n6+FNFDw9vGcReqk2KzBDhCa1DLYg==} - cpu: [x64] - os: [linux] - - '@rollup/rollup-linux-x64-musl@4.52.4': - resolution: {integrity: sha512-dtBZYjDmCQ9hW+WgEkaffvRRCKm767wWhxsFW3Lw86VXz/uJRuD438/XvbZT//B96Vs8oTA8Q4A0AfHbrxP9zw==} - cpu: [x64] - os: [linux] - - '@rollup/rollup-openharmony-arm64@4.52.4': - resolution: {integrity: sha512-1ox+GqgRWqaB1RnyZXL8PD6E5f7YyRUJYnCqKpNzxzP0TkaUh112NDrR9Tt+C8rJ4x5G9Mk8PQR3o7Ku2RKqKA==} - cpu: [arm64] - os: [openharmony] - - '@rollup/rollup-win32-arm64-msvc@4.52.4': - resolution: {integrity: sha512-8GKr640PdFNXwzIE0IrkMWUNUomILLkfeHjXBi/nUvFlpZP+FA8BKGKpacjW6OUUHaNI6sUURxR2U2g78FOHWQ==} - cpu: [arm64] - os: [win32] - - '@rollup/rollup-win32-ia32-msvc@4.52.4': - resolution: {integrity: sha512-AIy/jdJ7WtJ/F6EcfOb2GjR9UweO0n43jNObQMb6oGxkYTfLcnN7vYYpG+CN3lLxrQkzWnMOoNSHTW54pgbVxw==} - cpu: [ia32] - os: [win32] - - '@rollup/rollup-win32-x64-gnu@4.52.4': - resolution: {integrity: sha512-UF9KfsH9yEam0UjTwAgdK0anlQ7c8/pWPU2yVjyWcF1I1thABt6WXE47cI71pGiZ8wGvxohBoLnxM04L/wj8mQ==} - cpu: [x64] - os: [win32] - - '@rollup/rollup-win32-x64-msvc@4.52.4': - resolution: {integrity: sha512-bf9PtUa0u8IXDVxzRToFQKsNCRz9qLYfR/MpECxl4mRoWYjAeFjgxj1XdZr2M/GNVpT05p+LgQOHopYDlUu6/w==} - cpu: [x64] - os: [win32] - - '@scure/base@1.1.9': - resolution: {integrity: sha512-8YKhl8GHiNI/pU2VMaofa2Tor7PJRAjwQLBBuilkJ9L5+13yVbC7JO/wS7piioAvPSwR3JKM1IJ/u4xQzbcXKg==} - - '@scure/base@1.2.6': - resolution: {integrity: sha512-g/nm5FgUa//MCj1gV09zTJTaM6KBAHqLN907YVQqf7zC49+DcO4B1so4ZX07Ef10Twr6nuqYEH9GEggFXA4Fmg==} - - '@scure/bip32@1.4.0': - resolution: {integrity: sha512-sVUpc0Vq3tXCkDGYVWGIZTRfnvu8LoTDaev7vbwh0omSvVORONr960MQWdKqJDCReIEmTj3PAr73O3aoxz7OPg==} - - '@scure/bip32@1.7.0': - resolution: {integrity: sha512-E4FFX/N3f4B80AKWp5dP6ow+flD1LQZo/w8UnLGYZO674jS6YnYeepycOOksv+vLPSpgN35wgKgy+ybfTb2SMw==} - - '@scure/bip39@1.3.0': - resolution: {integrity: sha512-disdg7gHuTDZtY+ZdkmLpPCk7fxZSu3gBiEGuoC1XYxv9cGx3Z6cpTggCgW6odSOOIXCiDjuGejW+aJKCY/pIQ==} - - '@scure/bip39@1.6.0': - resolution: {integrity: sha512-+lF0BbLiJNwVlev4eKelw1WWLaiKXw7sSl8T6FvBlWkdX+94aGJ4o8XjUdlyhTCjd8c+B3KT3JfS8P0bLRNU6A==} - - '@starkware-industries/starkware-crypto-utils@0.2.1': - resolution: {integrity: sha512-rA5O9b53zaoBOQwQxBd0cbumFbQoBm9NH/vfu+o0Cq3oouEbNPALneLlLjOmFEId2/WOJ5ecC64rFLI/PwuIPQ==} - - '@tailwindcss/node@4.1.10': - resolution: {integrity: sha512-2ACf1znY5fpRBwRhMgj9ZXvb2XZW8qs+oTfotJ2C5xR0/WNL7UHZ7zXl6s+rUqedL1mNi+0O+WQr5awGowS3PQ==} - - '@tailwindcss/oxide-android-arm64@4.1.10': - resolution: {integrity: sha512-VGLazCoRQ7rtsCzThaI1UyDu/XRYVyH4/EWiaSX6tFglE+xZB5cvtC5Omt0OQ+FfiIVP98su16jDVHDEIuH4iQ==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [android] - - '@tailwindcss/oxide-darwin-arm64@4.1.10': - resolution: {integrity: sha512-ZIFqvR1irX2yNjWJzKCqTCcHZbgkSkSkZKbRM3BPzhDL/18idA8uWCoopYA2CSDdSGFlDAxYdU2yBHwAwx8euQ==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [darwin] - - '@tailwindcss/oxide-darwin-x64@4.1.10': - resolution: {integrity: sha512-eCA4zbIhWUFDXoamNztmS0MjXHSEJYlvATzWnRiTqJkcUteSjO94PoRHJy1Xbwp9bptjeIxxBHh+zBWFhttbrQ==} - engines: {node: '>= 10'} - cpu: [x64] - os: [darwin] - - '@tailwindcss/oxide-freebsd-x64@4.1.10': - resolution: {integrity: sha512-8/392Xu12R0cc93DpiJvNpJ4wYVSiciUlkiOHOSOQNH3adq9Gi/dtySK7dVQjXIOzlpSHjeCL89RUUI8/GTI6g==} - engines: {node: '>= 10'} - cpu: [x64] - os: [freebsd] - - '@tailwindcss/oxide-linux-arm-gnueabihf@4.1.10': - resolution: {integrity: sha512-t9rhmLT6EqeuPT+MXhWhlRYIMSfh5LZ6kBrC4FS6/+M1yXwfCtp24UumgCWOAJVyjQwG+lYva6wWZxrfvB+NhQ==} - engines: {node: '>= 10'} - cpu: [arm] - os: [linux] - - '@tailwindcss/oxide-linux-arm64-gnu@4.1.10': - resolution: {integrity: sha512-3oWrlNlxLRxXejQ8zImzrVLuZ/9Z2SeKoLhtCu0hpo38hTO2iL86eFOu4sVR8cZc6n3z7eRXXqtHJECa6mFOvA==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [linux] - - '@tailwindcss/oxide-linux-arm64-musl@4.1.10': - resolution: {integrity: sha512-saScU0cmWvg/Ez4gUmQWr9pvY9Kssxt+Xenfx1LG7LmqjcrvBnw4r9VjkFcqmbBb7GCBwYNcZi9X3/oMda9sqQ==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [linux] - - '@tailwindcss/oxide-linux-x64-gnu@4.1.10': - resolution: {integrity: sha512-/G3ao/ybV9YEEgAXeEg28dyH6gs1QG8tvdN9c2MNZdUXYBaIY/Gx0N6RlJzfLy/7Nkdok4kaxKPHKJUlAaoTdA==} - engines: {node: '>= 10'} - cpu: [x64] - os: [linux] - - '@tailwindcss/oxide-linux-x64-musl@4.1.10': - resolution: {integrity: sha512-LNr7X8fTiKGRtQGOerSayc2pWJp/9ptRYAa4G+U+cjw9kJZvkopav1AQc5HHD+U364f71tZv6XamaHKgrIoVzA==} - engines: {node: '>= 10'} - cpu: [x64] - os: [linux] - - '@tailwindcss/oxide-wasm32-wasi@4.1.10': - resolution: {integrity: sha512-d6ekQpopFQJAcIK2i7ZzWOYGZ+A6NzzvQ3ozBvWFdeyqfOZdYHU66g5yr+/HC4ipP1ZgWsqa80+ISNILk+ae/Q==} - engines: {node: '>=14.0.0'} - cpu: [wasm32] - bundledDependencies: - - '@napi-rs/wasm-runtime' - - '@emnapi/core' - - '@emnapi/runtime' - - '@tybys/wasm-util' - - '@emnapi/wasi-threads' - - tslib - - '@tailwindcss/oxide-win32-arm64-msvc@4.1.10': - resolution: {integrity: sha512-i1Iwg9gRbwNVOCYmnigWCCgow8nDWSFmeTUU5nbNx3rqbe4p0kRbEqLwLJbYZKmSSp23g4N6rCDmm7OuPBXhDA==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [win32] - - '@tailwindcss/oxide-win32-x64-msvc@4.1.10': - resolution: {integrity: sha512-sGiJTjcBSfGq2DVRtaSljq5ZgZS2SDHSIfhOylkBvHVjwOsodBhnb3HdmiKkVuUGKD0I7G63abMOVaskj1KpOA==} - engines: {node: '>= 10'} - cpu: [x64] - os: [win32] - - '@tailwindcss/oxide@4.1.10': - resolution: {integrity: sha512-v0C43s7Pjw+B9w21htrQwuFObSkio2aV/qPx/mhrRldbqxbWJK6KizM+q7BF1/1CmuLqZqX3CeYF7s7P9fbA8Q==} - engines: {node: '>= 10'} - - '@tailwindcss/postcss@4.1.10': - resolution: {integrity: sha512-B+7r7ABZbkXJwpvt2VMnS6ujcDoR2OOcFaqrLIo1xbcdxje4Vf+VgJdBzNNbrAjBj/rLZ66/tlQ1knIGNLKOBQ==} - - '@tronweb3/tronwallet-abstract-adapter@1.1.9': - resolution: {integrity: sha512-2wev5T/Z+Yt96nv2upZeq54v8zk8aXCg0p6yx1BpfY2y25lC0jEiul+F/6o5s2uIUXe2ENdbpMiGQz8+/Jy1EQ==} - engines: {node: '>=16', pnpm: '>=7'} - - '@trysound/sax@0.2.0': - resolution: {integrity: sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==} - engines: {node: '>=10.13.0'} - - '@types/bn.js@5.1.6': - resolution: {integrity: sha512-Xh8vSwUeMKeYYrj3cX4lGQgFSF/N03r+tv4AiLl1SucqV+uTQpxRcnM8AkXKHwYP9ZPXOYXRr2KPXpVlIvqh9w==} - - '@types/bn.js@5.2.0': - resolution: {integrity: sha512-DLbJ1BPqxvQhIGbeu8VbUC1DiAiahHtAYvA0ZEAa4P31F7IaArc8z3C3BRQdWX4mtLQuABG4yzp76ZrS02Ui1Q==} - - '@types/estree@1.0.8': - resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==} - - '@types/node@20.19.22': - resolution: {integrity: sha512-hRnu+5qggKDSyWHlnmThnUqg62l29Aj/6vcYgUaSFL9oc7DVjeWEQN3PRgdSc6F8d9QRMWkf36CLMch1Do/+RQ==} - - '@types/node@22.7.5': - resolution: {integrity: sha512-jML7s2NAzMWc//QSJ1a3prpk78cOPchGvXJsC3C6R6PSMoooztvRVQEz89gmBTBY1SPMaqo5teB4uNHPdetShQ==} - - '@types/node@24.8.1': - resolution: {integrity: sha512-alv65KGRadQVfVcG69MuB4IzdYVpRwMG/mq8KWOaoOdyY617P5ivaDiMCGOFDWD2sAn5Q0mR3mRtUOgm99hL9Q==} - - '@types/pbkdf2@3.1.2': - resolution: {integrity: sha512-uRwJqmiXmh9++aSu1VNEn3iIxWOhd8AHXNSdlaLfdAAdSTY9jYVeGWnzejM3dvrkbqE3/hyQkQQ29IFATEGlew==} - - '@types/react-dom@19.1.6': - resolution: {integrity: sha512-4hOiT/dwO8Ko0gV1m/TJZYk3y0KBnY9vzDh7W+DH17b2HFSOGgdj33dhihPeuy3l0q23+4e+hoXHV6hCC4dCXw==} - peerDependencies: - '@types/react': ^19.0.0 - - '@types/react@19.1.8': - resolution: {integrity: sha512-AwAfQ2Wa5bCx9WP8nZL2uMZWod7J7/JSplxbTmBQ5ms6QpqNYm672H0Vu9ZVKVngQ+ii4R/byguVEUZQyeg44g==} - - '@types/resolve@1.20.2': - resolution: {integrity: sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==} - - '@types/secp256k1@4.0.7': - resolution: {integrity: sha512-Rcvjl6vARGAKRO6jHeKMatGrvOMGrR/AR11N1x2LqintPCyDZ7NBhrh238Z2VZc7aM7KIwnFpFQ7fnfK4H/9Qw==} - - '@types/ws@8.18.1': - resolution: {integrity: sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==} - - '@vitest/expect@3.0.9': - resolution: {integrity: sha512-5eCqRItYgIML7NNVgJj6TVCmdzE7ZVgJhruW0ziSQV4V7PvLkDL1bBkBdcTs/VuIz0IxPb5da1IDSqc1TR9eig==} - - '@vitest/mocker@3.0.9': - resolution: {integrity: sha512-ryERPIBOnvevAkTq+L1lD+DTFBRcjueL9lOUfXsLfwP92h4e+Heb+PjiqS3/OURWPtywfafK0kj++yDFjWUmrA==} - peerDependencies: - msw: ^2.4.9 - vite: ^5.0.0 || ^6.0.0 - peerDependenciesMeta: - msw: - optional: true - vite: - optional: true - - '@vitest/pretty-format@3.0.9': - resolution: {integrity: sha512-OW9F8t2J3AwFEwENg3yMyKWweF7oRJlMyHOMIhO5F3n0+cgQAJZBjNgrF8dLwFTEXl5jUqBLXd9QyyKv8zEcmA==} - - '@vitest/pretty-format@3.2.4': - resolution: {integrity: sha512-IVNZik8IVRJRTr9fxlitMKeJeXFFFN0JaB9PHPGQ8NKQbGpfjlTx9zO4RefN8gp7eqjNy8nyK3NZmBzOPeIxtA==} - - '@vitest/runner@3.0.9': - resolution: {integrity: sha512-NX9oUXgF9HPfJSwl8tUZCMP1oGx2+Sf+ru6d05QjzQz4OwWg0psEzwY6VexP2tTHWdOkhKHUIZH+fS6nA7jfOw==} - - '@vitest/snapshot@3.0.9': - resolution: {integrity: sha512-AiLUiuZ0FuA+/8i19mTYd+re5jqjEc2jZbgJ2up0VY0Ddyyxg/uUtBDpIFAy4uzKaQxOW8gMgBdAJJ2ydhu39A==} - - '@vitest/spy@3.0.9': - resolution: {integrity: sha512-/CcK2UDl0aQ2wtkp3YVWldrpLRNCfVcIOFGlVGKO4R5eajsH393Z1yiXLVQ7vWsj26JOEjeZI0x5sm5P4OGUNQ==} - - '@vitest/utils@3.0.9': - resolution: {integrity: sha512-ilHM5fHhZ89MCp5aAaM9uhfl1c2JdxVxl3McqsdVyVNN6JffnEen8UMCdRTzOhGXNQGo5GNL9QugHrz727Wnng==} - - abitype@1.1.0: - resolution: {integrity: sha512-6Vh4HcRxNMLA0puzPjM5GBgT4aAcFGKZzSgAXvuZ27shJP6NEpielTuqbBmZILR5/xd0PizkBGy5hReKz9jl5A==} - peerDependencies: - typescript: ^5.0.0 - zod: ^3.22.0 || ^4.0.0 - peerDependenciesMeta: - typescript: - optional: true - zod: - optional: true - - abitype@1.1.1: - resolution: {integrity: sha512-Loe5/6tAgsBukY95eGaPSDmQHIjRZYQq8PB1MpsNccDIK8WiV+Uw6WzaIXipvaxTEL2yEB0OpEaQv3gs8pkS9Q==} - peerDependencies: - typescript: ^5.0.0 - zod: ^3.22.0 || ^4.0.0 - peerDependenciesMeta: - typescript: - optional: true - zod: - optional: true - - aes-js@3.1.2: - resolution: {integrity: sha512-e5pEa2kBnBOgR4Y/p20pskXI74UEz7de8ZGVo58asOtvSVG5YAbJeELPZxOmt+Bnz3rX753YKhfIn4X4l1PPRQ==} - - aes-js@4.0.0-beta.5: - resolution: {integrity: sha512-G965FqalsNyrPqgEGON7nIx1e/OVENSgiEIzyC63haUMuvNnwIgIjMs52hlTCKhkBny7A2ORNlfY9Zu+jmGk1Q==} - - ansi-regex@5.0.1: - resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} - engines: {node: '>=8'} - - ansi-regex@6.2.2: - resolution: {integrity: sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==} - engines: {node: '>=12'} - - ansi-styles@4.3.0: - resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} - engines: {node: '>=8'} - - ansi-styles@6.2.3: - resolution: {integrity: sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==} - engines: {node: '>=12'} - - anymatch@3.1.3: - resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} - engines: {node: '>= 8'} - - asn1.js@4.10.1: - resolution: {integrity: sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==} - - assert@2.1.0: - resolution: {integrity: sha512-eLHpSK/Y4nhMJ07gDaAzoX/XAKS8PSaojml3M0DM4JpV1LAi5JOJ/p6H/XWrl8L+DzVEvVCW1z3vWAaB9oTsQw==} - - assertion-error@2.0.1: - resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==} - engines: {node: '>=12'} - - async@2.6.4: - resolution: {integrity: sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==} - - asynckit@0.4.0: - resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} - - autoprefixer@10.4.21: - resolution: {integrity: sha512-O+A6LWV5LDHSJD3LjHYoNi4VLsj/Whi7k6zG12xTYaU4cQ8oxQGckXNX8cRHK5yOZ/ppVHe0ZBXGzSV9jXdVbQ==} - engines: {node: ^10 || ^12 || >=14} - hasBin: true - peerDependencies: - postcss: ^8.1.0 - - available-typed-arrays@1.0.7: - resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==} - engines: {node: '>= 0.4'} - - axios@1.11.0: - resolution: {integrity: sha512-1Lx3WLFQWm3ooKDYZD1eXmoGO9fxYQjrycfHFC8P0sCfQVXyROp0p9PFWBehewBOdCwHc+f/b8I0fMto5eSfwA==} - - axios@1.12.2: - resolution: {integrity: sha512-vMJzPewAlRyOgxV2dU0Cuz2O8zzzx9VYtbJOaBgXFeLc4IV/Eg50n4LowmehOOR61S8ZMpc2K5Sa7g6A4jfkUw==} - - balanced-match@1.0.2: - resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} - - base-x@3.0.11: - resolution: {integrity: sha512-xz7wQ8xDhdyP7tQxwdteLYeFfS68tSMNCZ/Y37WJ4bhGfKPpqEIlmIyueQHqOyoPhE6xNUqjzRr8ra0eF9VRvA==} - - base64-js@1.5.1: - resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} - - baseline-browser-mapping@2.8.17: - resolution: {integrity: sha512-j5zJcx6golJYTG6c05LUZ3Z8Gi+M62zRT/ycz4Xq4iCOdpcxwg7ngEYD4KA0eWZC7U17qh/Smq8bYbACJ0ipBA==} - hasBin: true - - bech32@1.1.4: - resolution: {integrity: sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ==} - - bignumber.js@9.1.2: - resolution: {integrity: sha512-2/mKyZH9K85bzOEfhXDBFZTGd1CTs+5IHpeFQo9luiBG7hghdC851Pj2WAhb6E3R6b9tZj/XKhbg4fum+Kepug==} - - binary-extensions@2.3.0: - resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==} - engines: {node: '>=8'} - - bip39@3.1.0: - resolution: {integrity: sha512-c9kiwdk45Do5GL0vJMe7tS95VjCii65mYAH7DfWl3uW8AVzXKQVUm64i3hzVybBDMp9r7j9iNxR85+ul8MdN/A==} - - blakejs@1.2.1: - resolution: {integrity: sha512-QXUSXI3QVc/gJME0dBpXrag1kbzOqCjCX8/b54ntNyW6sjtoqxqRk3LTmXzaJoh71zMsDCjM+47jS7XiwN/+fQ==} - - bn.js@4.12.2: - resolution: {integrity: sha512-n4DSx829VRTRByMRGdjQ9iqsN0Bh4OolPsFnaZBLcbi8iXcB+kJ9s7EnRt4wILZNV3kPLHkRVfOc/HvhC3ovDw==} - - bn.js@5.2.1: - resolution: {integrity: sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ==} - - bn.js@5.2.2: - resolution: {integrity: sha512-v2YAxEmKaBLahNwE1mjp4WON6huMNeuDvagFZW+ASCuA/ku0bXR9hSMw0XpiqMoA3+rmnyck/tPRSFQkoC9Cuw==} - - boolbase@1.0.0: - resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==} - - brace-expansion@2.0.2: - resolution: {integrity: sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==} - - braces@3.0.3: - resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} - engines: {node: '>=8'} - - brorand@1.1.0: - resolution: {integrity: sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==} - - browser-headers@0.4.1: - resolution: {integrity: sha512-CA9hsySZVo9371qEHjHZtYxV2cFtVj5Wj/ZHi8ooEsrtm4vOnl9Y9HmyYWk9q+05d7K3rdoAE0j3MVEFVvtQtg==} - - browserify-aes@1.2.0: - resolution: {integrity: sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==} - - browserify-cipher@1.0.1: - resolution: {integrity: sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==} - - browserify-des@1.0.2: - resolution: {integrity: sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==} - - browserify-rsa@4.1.1: - resolution: {integrity: sha512-YBjSAiTqM04ZVei6sXighu679a3SqWORA3qZTEqZImnlkDIFtKc6pNutpjyZ8RJTjQtuYfeetkxM11GwoYXMIQ==} - engines: {node: '>= 0.10'} - - browserify-sign@4.2.5: - resolution: {integrity: sha512-C2AUdAJg6rlM2W5QMp2Q4KGQMVBwR1lIimTsUnutJ8bMpW5B52pGpR2gEnNBNwijumDo5FojQ0L9JrXA8m4YEw==} - engines: {node: '>= 0.10'} - - browserslist@4.26.3: - resolution: {integrity: sha512-lAUU+02RFBuCKQPj/P6NgjlbCnLBMp4UtgTx7vNHd3XSIJF87s9a5rA3aH2yw3GS9DqZAUbOtZdCCiZeVRqt0w==} - engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} - hasBin: true - - bs58@4.0.1: - resolution: {integrity: sha512-Ok3Wdf5vOIlBrgCvTq96gBkJw+JUEzdBgyaza5HLtPm7yTHkjRy8+JzNyHF7BHa0bNWOQIp3m5YF0nnFcOIKLw==} - - bs58check@2.1.2: - resolution: {integrity: sha512-0TS1jicxdU09dwJMNZtVAfzPi6Q6QeN0pM1Fkzrjn+XYHvzMKPU3pHVpva+769iNVSfIYWf7LJ6WR+BuuMf8cA==} - - buffer-xor@1.0.3: - resolution: {integrity: sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ==} - - buffer@6.0.3: - resolution: {integrity: sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==} - - bundle-require@5.1.0: - resolution: {integrity: sha512-3WrrOuZiyaaZPWiEt4G3+IffISVC9HYlWueJEBWED4ZH4aIAC2PnkdnuRrR94M+w6yGWn4AglWtJtBI8YqvgoA==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - peerDependencies: - esbuild: '>=0.18' - - cac@6.7.14: - resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==} - engines: {node: '>=8'} - - call-bind-apply-helpers@1.0.2: - resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==} - engines: {node: '>= 0.4'} - - call-bind@1.0.8: - resolution: {integrity: sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==} - engines: {node: '>= 0.4'} - - call-bound@1.0.4: - resolution: {integrity: sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==} - engines: {node: '>= 0.4'} - - caniuse-api@3.0.0: - resolution: {integrity: sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw==} - - caniuse-lite@1.0.30001751: - resolution: {integrity: sha512-A0QJhug0Ly64Ii3eIqHu5X51ebln3k4yTUkY1j8drqpWHVreg/VLijN48cZ1bYPiqOQuqpkIKnzr/Ul8V+p6Cw==} - - chai@5.3.3: - resolution: {integrity: sha512-4zNhdJD/iOjSH0A05ea+Ke6MU5mmpQcbQsSOkgdaUMJ9zTlDTD/GYlwohmIE2u0gaxHYiVHEn1Fw9mZ/ktJWgw==} - engines: {node: '>=18'} - - chalk@4.1.2: - resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} - engines: {node: '>=10'} - - check-error@2.1.1: - resolution: {integrity: sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==} - engines: {node: '>= 16'} - - chokidar@3.6.0: - resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==} - engines: {node: '>= 8.10.0'} - - chownr@3.0.0: - resolution: {integrity: sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==} - engines: {node: '>=18'} - - cipher-base@1.0.7: - resolution: {integrity: sha512-Mz9QMT5fJe7bKI7MH31UilT5cEK5EHHRCccw/YRFsRY47AuNgaV6HY3rscp0/I4Q+tTW/5zoqpSeRRI54TkDWA==} - engines: {node: '>= 0.10'} - - class-variance-authority@0.7.1: - resolution: {integrity: sha512-Ka+9Trutv7G8M6WT6SeiRWz792K5qEqIGEGzXKhAE6xOWAY6pPH8U+9IY3oCMv6kqTmLsv7Xh/2w2RigkePMsg==} - - cli-table@0.3.11: - resolution: {integrity: sha512-IqLQi4lO0nIB4tcdTpN4LCB9FI3uqrJZK7RC515EnhZ6qBaglkIgICb1wjeAqpdoOabm1+SuQtkXIPdYC93jhQ==} - engines: {node: '>= 0.2.0'} - - clsx@2.1.1: - resolution: {integrity: sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==} - engines: {node: '>=6'} - - color-convert@2.0.1: - resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} - engines: {node: '>=7.0.0'} - - color-name@1.1.4: - resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} - - colord@2.9.3: - resolution: {integrity: sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==} - - colors@1.0.3: - resolution: {integrity: sha512-pFGrxThWcWQ2MsAz6RtgeWe4NK2kUE1WfsrvvlctdII745EW9I0yflqhe7++M5LEc7bV2c/9/5zc8sFcpL0Drw==} - engines: {node: '>=0.1.90'} - - combined-stream@1.0.8: - resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} - engines: {node: '>= 0.8'} - - commander@13.1.0: - resolution: {integrity: sha512-/rFeCpNJQbhSZjGVwO9RFV3xPqbnERS8MmIQzCtD/zl6gpJuV/bMLuN92oG3F7d8oDEHHRrujSXNUr8fpjntKw==} - engines: {node: '>=18'} - - commander@7.2.0: - resolution: {integrity: sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==} - engines: {node: '>= 10'} - - commondir@1.0.1: - resolution: {integrity: sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==} - - concat-with-sourcemaps@1.1.0: - resolution: {integrity: sha512-4gEjHJFT9e+2W/77h/DS5SGUgwDaOwprX8L/gl5+3ixnzkVJJsZWDSelmN3Oilw3LNDZjZV0yqH1hLG3k6nghg==} - - core-util-is@1.0.3: - resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} - - cosmjs-types@0.9.0: - resolution: {integrity: sha512-MN/yUe6mkJwHnCFfsNPeCfXVhyxHYW6c/xDUzrSbBycYzw++XvWDMJArXp2pLdgD6FQ8DW79vkPjeNKVrXaHeQ==} - - create-ecdh@4.0.4: - resolution: {integrity: sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A==} - - create-hash@1.2.0: - resolution: {integrity: sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==} - - create-hmac@1.1.7: - resolution: {integrity: sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==} - - cross-fetch@3.2.0: - resolution: {integrity: sha512-Q+xVJLoGOeIMXZmbUK4HYk+69cQH6LudR0Vu/pRm2YlU/hDV9CiS0gKUMaWY5f2NeUH9C1nV3bsTlCo0FsTV1Q==} - - cross-fetch@4.1.0: - resolution: {integrity: sha512-uKm5PU+MHTootlWEY+mZ4vvXoCn4fLQxT9dSc1sXVMSFkINTJVN8cAQROpwcKm8bJ/c7rgZVIBWzH5T78sNZZw==} - - cross-spawn@7.0.6: - resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} - engines: {node: '>= 8'} - - crypto-browserify@3.12.1: - resolution: {integrity: sha512-r4ESw/IlusD17lgQi1O20Fa3qNnsckR126TdUuBgAu7GBYSIPvdNyONd3Zrxh0xCwA4+6w/TDArBPsMvhur+KQ==} - engines: {node: '>= 0.10'} - - css-declaration-sorter@6.4.1: - resolution: {integrity: sha512-rtdthzxKuyq6IzqX6jEcIzQF/YqccluefyCYheovBOLhFT/drQA9zj/UbRAa9J7C0o6EG6u3E6g+vKkay7/k3g==} - engines: {node: ^10 || ^12 || >=14} - peerDependencies: - postcss: ^8.0.9 - - css-select@4.3.0: - resolution: {integrity: sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==} - - css-tree@1.1.3: - resolution: {integrity: sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==} - engines: {node: '>=8.0.0'} - - css-what@6.2.2: - resolution: {integrity: sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA==} - engines: {node: '>= 6'} - - cssesc@3.0.0: - resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==} - engines: {node: '>=4'} - hasBin: true - - cssnano-preset-default@5.2.14: - resolution: {integrity: sha512-t0SFesj/ZV2OTylqQVOrFgEh5uanxbO6ZAdeCrNsUQ6fVuXwYTxJPNAGvGTxHbD68ldIJNec7PyYZDBrfDQ+6A==} - engines: {node: ^10 || ^12 || >=14.0} - peerDependencies: - postcss: ^8.2.15 - - cssnano-utils@3.1.0: - resolution: {integrity: sha512-JQNR19/YZhz4psLX/rQ9M83e3z2Wf/HdJbryzte4a3NSuafyp9w/I4U+hx5C2S9g41qlstH7DEWnZaaj83OuEA==} - engines: {node: ^10 || ^12 || >=14.0} - peerDependencies: - postcss: ^8.2.15 - - cssnano@5.1.15: - resolution: {integrity: sha512-j+BKgDcLDQA+eDifLx0EO4XSA56b7uut3BQFH+wbSaSTuGLuiyTa/wbRYthUXX8LC9mLg+WWKe8h+qJuwTAbHw==} - engines: {node: ^10 || ^12 || >=14.0} - peerDependencies: - postcss: ^8.2.15 - - csso@4.2.0: - resolution: {integrity: sha512-wvlcdIbf6pwKEk7vHj8/Bkc0B4ylXZruLvOgs9doS5eOsOpuodOV2zJChSpkp+pRpYQLQMeF04nr3Z68Sta9jA==} - engines: {node: '>=8.0.0'} - - csstype@3.1.3: - resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==} - - debug@3.2.7: - resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==} - peerDependencies: - supports-color: '*' - peerDependenciesMeta: - supports-color: - optional: true - - debug@4.4.3: - resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==} - engines: {node: '>=6.0'} - peerDependencies: - supports-color: '*' - peerDependenciesMeta: - supports-color: - optional: true - - decimal.js@10.6.0: - resolution: {integrity: sha512-YpgQiITW3JXGntzdUmyUR1V812Hn8T1YVXhCu+wO3OpS4eU9l4YdD3qjyiKdV6mvV29zapkMeD390UVEf2lkUg==} - - deep-eql@5.0.2: - resolution: {integrity: sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==} - engines: {node: '>=6'} - - deepmerge@4.3.1: - resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==} - engines: {node: '>=0.10.0'} - - define-data-property@1.1.4: - resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==} - engines: {node: '>= 0.4'} - - define-properties@1.2.1: - resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==} - engines: {node: '>= 0.4'} - - delayed-stream@1.0.0: - resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} - engines: {node: '>=0.4.0'} - - des.js@1.1.0: - resolution: {integrity: sha512-r17GxjhUCjSRy8aiJpr8/UadFIzMzJGexI3Nmz4ADi9LYSFx4gTBp80+NaX/YsXWWLhpZ7v/v/ubEc/bCNfKwg==} - - detect-libc@2.1.2: - resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==} - engines: {node: '>=8'} - - diffie-hellman@5.0.3: - resolution: {integrity: sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==} - - dom-serializer@1.4.1: - resolution: {integrity: sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==} - - domelementtype@2.3.0: - resolution: {integrity: sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==} - - domhandler@4.3.1: - resolution: {integrity: sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==} - engines: {node: '>= 4'} - - domutils@2.8.0: - resolution: {integrity: sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==} - - dunder-proto@1.0.1: - resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} - engines: {node: '>= 0.4'} - - eastasianwidth@0.2.0: - resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} - - electron-to-chromium@1.5.237: - resolution: {integrity: sha512-icUt1NvfhGLar5lSWH3tHNzablaA5js3HVHacQimfP8ViEBOQv+L7DKEuHdbTZ0SKCO1ogTJTIL1Gwk9S6Qvcg==} - - elliptic@6.6.1: - resolution: {integrity: sha512-RaddvvMatK2LJHqFJ+YA4WysVN5Ita9E35botqIYspQ4TkRAlCicdzKOjlyv/1Za5RyTNn7di//eEV0uTAfe3g==} - - emoji-regex@8.0.0: - resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} - - emoji-regex@9.2.2: - resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} - - enc-utils@3.0.0: - resolution: {integrity: sha512-e57t/Z2HzWOLwOp7DZcV0VMEY8t7ptWwsxyp6kM2b2zrk6JqIpXxzkruHAMiBsy5wg9jp/183GdiRXCvBtzsYg==} - - enhanced-resolve@5.18.3: - resolution: {integrity: sha512-d4lC8xfavMeBjzGr2vECC3fsGXziXZQyJxD868h2M/mBI3PwAuODxAkLkq5HYuvrPYcUtiLzsTo8U3PgX3Ocww==} - engines: {node: '>=10.13.0'} - - entities@2.2.0: - resolution: {integrity: sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==} - - es-define-property@1.0.1: - resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==} - engines: {node: '>= 0.4'} - - es-errors@1.3.0: - resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} - engines: {node: '>= 0.4'} - - es-module-lexer@1.7.0: - resolution: {integrity: sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==} - - es-object-atoms@1.1.1: - resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==} - engines: {node: '>= 0.4'} - - es-set-tostringtag@2.1.0: - resolution: {integrity: sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==} - engines: {node: '>= 0.4'} - - es-toolkit@1.40.0: - resolution: {integrity: sha512-8o6w0KFmU0CiIl0/Q/BCEOabF2IJaELM1T2PWj6e8KqzHv1gdx+7JtFnDwOx1kJH/isJ5NwlDG1nCr1HrRF94Q==} - - esbuild@0.25.1: - resolution: {integrity: sha512-BGO5LtrGC7vxnqucAe/rmvKdJllfGaYWdyABvyMoXQlfYMb2bbRuReWR5tEGE//4LcNJj9XrkovTqNYRFZHAMQ==} - engines: {node: '>=18'} - hasBin: true - - esbuild@0.25.11: - resolution: {integrity: sha512-KohQwyzrKTQmhXDW1PjCv3Tyspn9n5GcY2RTDqeORIdIJY8yKIF7sTSopFmn/wpMPW4rdPXI0UE5LJLuq3bx0Q==} - engines: {node: '>=18'} - hasBin: true - - escalade@3.2.0: - resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} - engines: {node: '>=6'} - - estree-walker@0.6.1: - resolution: {integrity: sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==} - - estree-walker@2.0.2: - resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==} - - estree-walker@3.0.3: - resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==} - - ethereum-cryptography@0.1.3: - resolution: {integrity: sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ==} - - ethereum-cryptography@2.2.1: - resolution: {integrity: sha512-r/W8lkHSiTLxUxW8Rf3u4HGB0xQweG2RyETjywylKZSzLWoWAijRz8WCuOtJ6wah+avllXBqZuk29HCCvhEIRg==} - - ethereumjs-util@7.1.5: - resolution: {integrity: sha512-SDl5kKrQAudFBUe5OJM9Ac6WmMyYmXX/6sTmLZ3ffG2eY6ZIGBes3pEDxNN6V72WyOw4CPD5RomKdsa8DAAwLg==} - engines: {node: '>=10.0.0'} - - ethereumjs-wallet@1.0.2: - resolution: {integrity: sha512-CCWV4RESJgRdHIvFciVQFnCHfqyhXWchTPlkfp28Qc53ufs+doi5I/cV2+xeK9+qEo25XCWfP9MiL+WEPAZfdA==} - deprecated: 'New package name format for new versions: @ethereumjs/wallet. Please update.' - - ethers@6.13.5: - resolution: {integrity: sha512-+knKNieu5EKRThQJWwqaJ10a6HE9sSehGeqWN65//wE7j47ZpFhKAnHB/JJFibwwg61I/koxaPsXbXpD/skNOQ==} - engines: {node: '>=14.0.0'} - - event-iterator@2.0.0: - resolution: {integrity: sha512-KGft0ldl31BZVV//jj+IAIGCxkvvUkkON+ScH6zfoX+l+omX6001ggyRSpI0Io2Hlro0ThXotswCtfzS8UkIiQ==} - - eventemitter3@4.0.7: - resolution: {integrity: sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==} - - eventemitter3@5.0.1: - resolution: {integrity: sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==} - - events@3.3.0: - resolution: {integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==} - engines: {node: '>=0.8.x'} - - evp_bytestokey@1.0.3: - resolution: {integrity: sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==} - - expect-type@1.2.2: - resolution: {integrity: sha512-JhFGDVJ7tmDJItKhYgJCGLOWjuK9vPxiXoUFLwLDc99NlmklilbiQJwoctZtt13+xMw91MCk/REan6MWHqDjyA==} - engines: {node: '>=12.0.0'} - - fdir@6.5.0: - resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==} - engines: {node: '>=12.0.0'} - peerDependencies: - picomatch: ^3 || ^4 - peerDependenciesMeta: - picomatch: - optional: true - - fflate@0.8.2: - resolution: {integrity: sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A==} - - fill-range@7.1.1: - resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} - engines: {node: '>=8'} - - find-cache-dir@3.3.2: - resolution: {integrity: sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==} - engines: {node: '>=8'} - - find-up@4.1.0: - resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==} - engines: {node: '>=8'} - - follow-redirects@1.15.11: - resolution: {integrity: sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==} - engines: {node: '>=4.0'} - peerDependencies: - debug: '*' - peerDependenciesMeta: - debug: - optional: true - - for-each@0.3.5: - resolution: {integrity: sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==} - engines: {node: '>= 0.4'} - - foreground-child@3.3.1: - resolution: {integrity: sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==} - engines: {node: '>=14'} - - form-data@4.0.4: - resolution: {integrity: sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==} - engines: {node: '>= 6'} - - fraction.js@4.3.7: - resolution: {integrity: sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==} - - framer-motion@12.23.24: - resolution: {integrity: sha512-HMi5HRoRCTou+3fb3h9oTLyJGBxHfW+HnNE25tAXOvVx/IvwMHK0cx7IR4a2ZU6sh3IX1Z+4ts32PcYBOqka8w==} - peerDependencies: - '@emotion/is-prop-valid': '*' - react: ^18.0.0 || ^19.0.0 - react-dom: ^18.0.0 || ^19.0.0 - peerDependenciesMeta: - '@emotion/is-prop-valid': - optional: true - react: - optional: true - react-dom: - optional: true - - fs-extra@10.1.0: - resolution: {integrity: sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==} - engines: {node: '>=12'} - - fs.realpath@1.0.0: - resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} - - fsevents@2.3.3: - resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} - engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} - os: [darwin] - - fuels@0.101.1: - resolution: {integrity: sha512-/0LwAynHrKZZn4aw7QkyVc+Af+MIwlg82eCVSdAUVDJ+/pQ6Oma+aZyqjynmsKEuOlvkzw+jhUReGoWqexF4tg==} - engines: {node: ^18.20.3 || ^20.0.0 || ^22.0.0} - hasBin: true - - function-bind@1.1.2: - resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} - - generator-function@2.0.1: - resolution: {integrity: sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g==} - engines: {node: '>= 0.4'} - - generic-names@4.0.0: - resolution: {integrity: sha512-ySFolZQfw9FoDb3ed9d80Cm9f0+r7qj+HJkWjeD9RBfpxEVTlVhol+gvaQB/78WbwYfbnNh8nWHHBSlg072y6A==} - - get-intrinsic@1.3.0: - resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==} - engines: {node: '>= 0.4'} - - get-proto@1.0.1: - resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==} - engines: {node: '>= 0.4'} - - glob-parent@5.1.2: - resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} - engines: {node: '>= 6'} - - glob@10.4.5: - resolution: {integrity: sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==} - hasBin: true - - glob@8.1.0: - resolution: {integrity: sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==} - engines: {node: '>=12'} - deprecated: Glob versions prior to v9 are no longer supported - - globalthis@1.0.4: - resolution: {integrity: sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==} - engines: {node: '>= 0.4'} - - google-protobuf@3.21.4: - resolution: {integrity: sha512-MnG7N936zcKTco4Jd2PX2U96Kf9PxygAPKBug+74LHzmHXmceN16MmRcdgZv+DGef/S9YvQAfRsNCn4cjf9yyQ==} - - gopd@1.2.0: - resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==} - engines: {node: '>= 0.4'} - - graceful-fs@4.2.11: - resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} - - graphql-request@6.1.0: - resolution: {integrity: sha512-p+XPfS4q7aIpKVcgmnZKhMNqhltk20hfXtkaIkTfjjmiKMJ5xrt5c743cL03y/K7y1rg3WrIC49xGiEQ4mxdNw==} - peerDependencies: - graphql: 14 - 16 - - graphql-tag@2.12.6: - resolution: {integrity: sha512-FdSNcu2QQcWnM2VNvSCCDCVS5PpPqpzgFT8+GXzqJuoDd0CBncxCY278u4mhRO7tMgo2JjgJA5aZ+nWSQ/Z+xg==} - engines: {node: '>=10'} - peerDependencies: - graphql: ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 - - graphql@16.10.0: - resolution: {integrity: sha512-AjqGKbDGUFRKIRCP9tCKiIGHyriz2oHEbPIbEtcSLSs4YjReZOIPQQWek4+6hjw62H9QShXHyaGivGiYVLeYFQ==} - engines: {node: ^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0} - - handlebars@4.7.8: - resolution: {integrity: sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==} - engines: {node: '>=0.4.7'} - hasBin: true - - has-flag@4.0.0: - resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} - engines: {node: '>=8'} - - has-property-descriptors@1.0.2: - resolution: {integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==} - - has-symbols@1.1.0: - resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==} - engines: {node: '>= 0.4'} - - has-tostringtag@1.0.2: - resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==} - engines: {node: '>= 0.4'} - - hash-base@3.0.5: - resolution: {integrity: sha512-vXm0l45VbcHEVlTCzs8M+s0VeYsB2lnlAaThoLKGXr3bE/VWDOelNUnycUPEhKEaXARL2TEFjBOyUiM6+55KBg==} - engines: {node: '>= 0.10'} - - hash-base@3.1.2: - resolution: {integrity: sha512-Bb33KbowVTIj5s7Ked1OsqHUeCpz//tPwR+E2zJgJKo9Z5XolZ9b6bdUgjmYlwnWhoOQKoTd1TYToZGn5mAYOg==} - engines: {node: '>= 0.8'} - - hash.js@1.1.7: - resolution: {integrity: sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==} - - hasown@2.0.2: - resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} - engines: {node: '>= 0.4'} - - hmac-drbg@1.0.1: - resolution: {integrity: sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg==} - - husky@8.0.3: - resolution: {integrity: sha512-+dQSyqPh4x1hlO1swXBiNb2HzTDN1I2IGLQx1GrBuiqFJfoMrnZWwVmatvSiO+Iz8fBUnf+lekwNo4c2LlXItg==} - engines: {node: '>=14'} - hasBin: true - - icss-replace-symbols@1.1.0: - resolution: {integrity: sha512-chIaY3Vh2mh2Q3RGXttaDIzeiPvaVXJ+C4DAh/w3c37SKZ/U6PGMmuicR2EQQp9bKG8zLMCl7I+PtIoOOPp8Gg==} - - icss-utils@5.1.0: - resolution: {integrity: sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==} - engines: {node: ^10 || ^12 || >= 14} - peerDependencies: - postcss: ^8.1.0 - - ieee754@1.2.1: - resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} - - import-cwd@3.0.0: - resolution: {integrity: sha512-4pnzH16plW+hgvRECbDWpQl3cqtvSofHWh44met7ESfZ8UZOWWddm8hEyDTqREJ9RbYHY8gi8DqmaelApoOGMg==} - engines: {node: '>=8'} - - import-from@3.0.0: - resolution: {integrity: sha512-CiuXOFFSzkU5x/CR0+z7T91Iht4CXgfCxVOFRhh2Zyhg5wOpWvvDLQUsWl+gcN+QscYBjez8hDCt85O7RLDttQ==} - engines: {node: '>=8'} - - inflight@1.0.6: - resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} - deprecated: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful. - - inherits@2.0.4: - resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} - - is-arguments@1.2.0: - resolution: {integrity: sha512-7bVbi0huj/wrIAOzb8U1aszg9kdi3KN/CyU19CTI7tAoZYEZoL9yCDXpbXN+uPsuWnP02cyug1gleqq+TU+YCA==} - engines: {node: '>= 0.4'} - - is-binary-path@2.1.0: - resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} - engines: {node: '>=8'} - - is-callable@1.2.7: - resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==} - engines: {node: '>= 0.4'} - - is-core-module@2.16.1: - resolution: {integrity: sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==} - engines: {node: '>= 0.4'} - - is-extglob@2.1.1: - resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} - engines: {node: '>=0.10.0'} - - is-fullwidth-code-point@3.0.0: - resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} - engines: {node: '>=8'} - - is-generator-function@1.1.2: - resolution: {integrity: sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA==} - engines: {node: '>= 0.4'} - - is-glob@4.0.3: - resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} - engines: {node: '>=0.10.0'} - - is-module@1.0.0: - resolution: {integrity: sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==} - - is-nan@1.3.2: - resolution: {integrity: sha512-E+zBKpQ2t6MEo1VsonYmluk9NxGrbzpeeLC2xIViuO2EjU2xsXsBPwTr3Ykv9l08UYEVEdWeRZNouaZqF6RN0w==} - engines: {node: '>= 0.4'} - - is-number@7.0.0: - resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} - engines: {node: '>=0.12.0'} - - is-reference@1.2.1: - resolution: {integrity: sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ==} - - is-regex@1.2.1: - resolution: {integrity: sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==} - engines: {node: '>= 0.4'} - - is-typed-array@1.1.15: - resolution: {integrity: sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==} - engines: {node: '>= 0.4'} - - is-typedarray@1.0.0: - resolution: {integrity: sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==} - - isarray@1.0.0: - resolution: {integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==} - - isarray@2.0.5: - resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==} - - isexe@2.0.0: - resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} - - isomorphic-ws@4.0.1: - resolution: {integrity: sha512-BhBvN2MBpWTaSHdWRb/bwdZJ1WaehQ2L1KngkCkfLUGF0mAWAT1sQUQacEmQ0jXkFw/czDXPNQSL5u2/Krsz1w==} - peerDependencies: - ws: '*' - - isows@1.0.7: - resolution: {integrity: sha512-I1fSfDCZL5P0v33sVqeTDSpcstAg/N+wF5HS033mogOVIp4B+oHC7oOCsA3axAbBSGTJ8QubbNmnIRN/h8U7hg==} - peerDependencies: - ws: '*' - - it-stream-types@2.0.2: - resolution: {integrity: sha512-Rz/DEZ6Byn/r9+/SBCuJhpPATDF9D+dz5pbgSUyBsCDtza6wtNATrz/jz1gDyNanC3XdLboriHnOC925bZRBww==} - - it-ws@6.1.5: - resolution: {integrity: sha512-uWjMtpy5HqhSd/LlrlP3fhYrr7rUfJFFMABv0F5d6n13Q+0glhZthwUKpEAVhDrXY95Tb1RB5lLqqef+QbVNaw==} - engines: {node: '>=16.0.0', npm: '>=7.0.0'} - - jackspeak@3.4.3: - resolution: {integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==} - - jiti@2.6.1: - resolution: {integrity: sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==} - hasBin: true - - joycon@3.1.1: - resolution: {integrity: sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==} - engines: {node: '>=10'} - - js-sha3@0.8.0: - resolution: {integrity: sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==} - - js-tokens@4.0.0: - resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} - - jsonfile@6.2.0: - resolution: {integrity: sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==} - - keccak@3.0.4: - resolution: {integrity: sha512-3vKuW0jV8J3XNTzvfyicFR5qvxrSAGl7KIhvgOu5cmWwM7tZRj3fMbj/pfIf4be7aznbc+prBWGjywox/g2Y6Q==} - engines: {node: '>=10.0.0'} - - libsodium-sumo@0.7.15: - resolution: {integrity: sha512-5tPmqPmq8T8Nikpm1Nqj0hBHvsLFCXvdhBFV7SGOitQPZAA6jso8XoL0r4L7vmfKXr486fiQInvErHtEvizFMw==} - - libsodium-wrappers-sumo@0.7.15: - resolution: {integrity: sha512-aSWY8wKDZh5TC7rMvEdTHoyppVq/1dTSAeAR7H6pzd6QRT3vQWcT5pGwCotLcpPEOLXX6VvqihSPkpEhYAjANA==} - - lightningcss-darwin-arm64@1.30.1: - resolution: {integrity: sha512-c8JK7hyE65X1MHMN+Viq9n11RRC7hgin3HhYKhrMyaXflk5GVplZ60IxyoVtzILeKr+xAJwg6zK6sjTBJ0FKYQ==} - engines: {node: '>= 12.0.0'} - cpu: [arm64] - os: [darwin] - - lightningcss-darwin-x64@1.30.1: - resolution: {integrity: sha512-k1EvjakfumAQoTfcXUcHQZhSpLlkAuEkdMBsI/ivWw9hL+7FtilQc0Cy3hrx0AAQrVtQAbMI7YjCgYgvn37PzA==} - engines: {node: '>= 12.0.0'} - cpu: [x64] - os: [darwin] - - lightningcss-freebsd-x64@1.30.1: - resolution: {integrity: sha512-kmW6UGCGg2PcyUE59K5r0kWfKPAVy4SltVeut+umLCFoJ53RdCUWxcRDzO1eTaxf/7Q2H7LTquFHPL5R+Gjyig==} - engines: {node: '>= 12.0.0'} - cpu: [x64] - os: [freebsd] - - lightningcss-linux-arm-gnueabihf@1.30.1: - resolution: {integrity: sha512-MjxUShl1v8pit+6D/zSPq9S9dQ2NPFSQwGvxBCYaBYLPlCWuPh9/t1MRS8iUaR8i+a6w7aps+B4N0S1TYP/R+Q==} - engines: {node: '>= 12.0.0'} - cpu: [arm] - os: [linux] - - lightningcss-linux-arm64-gnu@1.30.1: - resolution: {integrity: sha512-gB72maP8rmrKsnKYy8XUuXi/4OctJiuQjcuqWNlJQ6jZiWqtPvqFziskH3hnajfvKB27ynbVCucKSm2rkQp4Bw==} - engines: {node: '>= 12.0.0'} - cpu: [arm64] - os: [linux] - - lightningcss-linux-arm64-musl@1.30.1: - resolution: {integrity: sha512-jmUQVx4331m6LIX+0wUhBbmMX7TCfjF5FoOH6SD1CttzuYlGNVpA7QnrmLxrsub43ClTINfGSYyHe2HWeLl5CQ==} - engines: {node: '>= 12.0.0'} - cpu: [arm64] - os: [linux] - - lightningcss-linux-x64-gnu@1.30.1: - resolution: {integrity: sha512-piWx3z4wN8J8z3+O5kO74+yr6ze/dKmPnI7vLqfSqI8bccaTGY5xiSGVIJBDd5K5BHlvVLpUB3S2YCfelyJ1bw==} - engines: {node: '>= 12.0.0'} - cpu: [x64] - os: [linux] - - lightningcss-linux-x64-musl@1.30.1: - resolution: {integrity: sha512-rRomAK7eIkL+tHY0YPxbc5Dra2gXlI63HL+v1Pdi1a3sC+tJTcFrHX+E86sulgAXeI7rSzDYhPSeHHjqFhqfeQ==} - engines: {node: '>= 12.0.0'} - cpu: [x64] - os: [linux] - - lightningcss-win32-arm64-msvc@1.30.1: - resolution: {integrity: sha512-mSL4rqPi4iXq5YVqzSsJgMVFENoa4nGTT/GjO2c0Yl9OuQfPsIfncvLrEW6RbbB24WtZ3xP/2CCmI3tNkNV4oA==} - engines: {node: '>= 12.0.0'} - cpu: [arm64] - os: [win32] - - lightningcss-win32-x64-msvc@1.30.1: - resolution: {integrity: sha512-PVqXh48wh4T53F/1CCu8PIPCxLzWyCnn/9T5W1Jpmdy5h9Cwd+0YQS6/LwhHXSafuc61/xg9Lv5OrCby6a++jg==} - engines: {node: '>= 12.0.0'} - cpu: [x64] - os: [win32] - - lightningcss@1.30.1: - resolution: {integrity: sha512-xi6IyHML+c9+Q3W0S4fCQJOym42pyurFiJUHEcEyHS0CeKzia4yZDEsLlqOFykxOdHpNy0NmvVO31vcSqAxJCg==} - engines: {node: '>= 12.0.0'} - - lilconfig@2.1.0: - resolution: {integrity: sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==} - engines: {node: '>=10'} - - load-tsconfig@0.2.5: - resolution: {integrity: sha512-IXO6OCs9yg8tMKzfPZ1YmheJbZCiEsnBdcB03l0OcfK9prKnJb96siuHCr5Fl37/yo9DnKU+TLpxzTUspw9shg==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - - loader-utils@3.3.1: - resolution: {integrity: sha512-FMJTLMXfCLMLfJxcX9PFqX5qD88Z5MRGaZCVzfuqeZSPsyiBzs+pahDQjbIWz2QIzPZz0NX9Zy4FX3lmK6YHIg==} - engines: {node: '>= 12.13.0'} - - locate-path@5.0.0: - resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==} - engines: {node: '>=8'} - - lodash.camelcase@4.3.0: - resolution: {integrity: sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==} - - lodash.memoize@4.1.2: - resolution: {integrity: sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==} - - lodash.uniq@4.5.0: - resolution: {integrity: sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==} - - lodash@4.17.21: - resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} - - long@5.3.2: - resolution: {integrity: sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==} - - loupe@3.2.1: - resolution: {integrity: sha512-CdzqowRJCeLU72bHvWqwRBBlLcMEtIvGrlvef74kMnV2AolS9Y8xUv1I0U/MNAWMhBlKIoyuEgoJ0t/bbwHbLQ==} - - lru-cache@10.4.3: - resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} - - magic-string@0.30.19: - resolution: {integrity: sha512-2N21sPY9Ws53PZvsEpVtNuSW+ScYbQdp4b9qUaL+9QkHUrGFKo56Lg9Emg5s9V/qrtNBmiR01sYhUOwu3H+VOw==} - - make-dir@3.1.0: - resolution: {integrity: sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==} - engines: {node: '>=8'} - - math-intrinsics@1.1.0: - resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==} - engines: {node: '>= 0.4'} - - md5.js@1.3.5: - resolution: {integrity: sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==} - - mdn-data@2.0.14: - resolution: {integrity: sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==} - - miller-rabin@4.0.1: - resolution: {integrity: sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==} - hasBin: true - - mime-db@1.52.0: - resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} - engines: {node: '>= 0.6'} - - mime-types@2.1.35: - resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} - engines: {node: '>= 0.6'} - - minimalistic-assert@1.0.1: - resolution: {integrity: sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==} - - minimalistic-crypto-utils@1.0.1: - resolution: {integrity: sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==} - - minimatch@5.1.6: - resolution: {integrity: sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==} - engines: {node: '>=10'} - - minimatch@9.0.5: - resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==} - engines: {node: '>=16 || 14 >=14.17'} - - minimist@1.2.8: - resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} - - minipass@7.1.2: - resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==} - engines: {node: '>=16 || 14 >=14.17'} - - minizlib@3.1.0: - resolution: {integrity: sha512-KZxYo1BUkWD2TVFLr0MQoM8vUUigWD3LlD83a/75BqC+4qE0Hb1Vo5v1FgcfaNXvfXzr+5EhQ6ing/CaBijTlw==} - engines: {node: '>= 18'} - - mkdirp@0.5.6: - resolution: {integrity: sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==} - hasBin: true - - mkdirp@3.0.1: - resolution: {integrity: sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==} - engines: {node: '>=10'} - hasBin: true - - motion-dom@12.23.23: - resolution: {integrity: sha512-n5yolOs0TQQBRUFImrRfs/+6X4p3Q4n1dUEqt/H58Vx7OW6RF+foWEgmTVDhIWJIMXOuNNL0apKH2S16en9eiA==} - - motion-utils@12.23.6: - resolution: {integrity: sha512-eAWoPgr4eFEOFfg2WjIsMoqJTW6Z8MTUCgn/GZ3VRpClWBdnbjryiA3ZSNLyxCTmCQx4RmYX6jX1iWHbenUPNQ==} - - motion@12.23.0: - resolution: {integrity: sha512-PPNwblArRH9GRC4F3KtOTiIaYd+mtp324vYq3HIL+ueseoAVqPRK5TPFTAQBcIprfVd0NWo3DLzZSiyWaYFXXQ==} - peerDependencies: - '@emotion/is-prop-valid': '*' - react: ^18.0.0 || ^19.0.0 - react-dom: ^18.0.0 || ^19.0.0 - peerDependenciesMeta: - '@emotion/is-prop-valid': - optional: true - react: - optional: true - react-dom: - optional: true - - ms@2.1.3: - resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} - - msgpackr-extract@3.0.3: - resolution: {integrity: sha512-P0efT1C9jIdVRefqjzOQ9Xml57zpOXnIuS+csaB4MdZbTdmGDLo8XhzBG1N7aO11gKDDkJvBLULeFTo46wwreA==} - hasBin: true - - msgpackr@1.11.5: - resolution: {integrity: sha512-UjkUHN0yqp9RWKy0Lplhh+wlpdt9oQBYgULZOiFhV3VclSF1JnSQWZ5r9gORQlNYaUKQoR8itv7g7z1xDDuACA==} - - multiformats@13.4.1: - resolution: {integrity: sha512-VqO6OSvLrFVAYYjgsr8tyv62/rCQhPgsZUXLTqoFLSgdkgiUYKYeArbt1uWLlEpkjxQe+P0+sHlbPEte1Bi06Q==} - - nanoid@3.3.11: - resolution: {integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==} - engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} - hasBin: true - - neo-async@2.6.2: - resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==} - - node-addon-api@2.0.2: - resolution: {integrity: sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA==} - - node-addon-api@5.1.0: - resolution: {integrity: sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA==} - - node-fetch@2.7.0: - resolution: {integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==} - engines: {node: 4.x || >=6.0.0} - peerDependencies: - encoding: ^0.1.0 - peerDependenciesMeta: - encoding: - optional: true - - node-gyp-build-optional-packages@5.2.2: - resolution: {integrity: sha512-s+w+rBWnpTMwSFbaE0UXsRlg7hU4FjekKU4eyAih5T8nJuNZT1nNsskXpxmeqSK9UzkBl6UgRlnKc8hz8IEqOw==} - hasBin: true - - node-gyp-build@4.8.4: - resolution: {integrity: sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ==} - hasBin: true - - node-releases@2.0.25: - resolution: {integrity: sha512-4auku8B/vw5psvTiiN9j1dAOsXvMoGqJuKJcR+dTdqiXEK20mMTk1UEo3HS16LeGQsVG6+qKTPM9u/qQ2LqATA==} - - normalize-path@3.0.0: - resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} - engines: {node: '>=0.10.0'} - - normalize-range@0.1.2: - resolution: {integrity: sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==} - engines: {node: '>=0.10.0'} - - normalize-url@6.1.0: - resolution: {integrity: sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==} - engines: {node: '>=10'} - - nth-check@2.1.1: - resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==} - - object-is@1.1.6: - resolution: {integrity: sha512-F8cZ+KfGlSGi09lJT7/Nd6KJZ9ygtvYC0/UYYLI9nmQKLMnydpB9yvbv9K1uSkEu7FU9vYPmVwLg328tX+ot3Q==} - engines: {node: '>= 0.4'} - - object-keys@1.1.1: - resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==} - engines: {node: '>= 0.4'} - - object.assign@4.1.7: - resolution: {integrity: sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==} - engines: {node: '>= 0.4'} - - once@1.4.0: - resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} - - ox@0.9.6: - resolution: {integrity: sha512-8SuCbHPvv2eZLYXrNmC0EC12rdzXQLdhnOMlHDW2wiCPLxBrOOJwX5L5E61by+UjTPOryqQiRSnjIKCI+GykKg==} - peerDependencies: - typescript: ^5.0.0 - peerDependenciesMeta: - typescript: - optional: true - - p-finally@1.0.0: - resolution: {integrity: sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==} - engines: {node: '>=4'} - - p-limit@2.3.0: - resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==} - engines: {node: '>=6'} - - p-locate@4.1.0: - resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==} - engines: {node: '>=8'} - - p-queue@6.6.2: - resolution: {integrity: sha512-RwFpb72c/BhQLEXIZ5K2e+AhgNVmIejGlTgiB9MzZ0e93GRvqZ7uSi0dvRF7/XIXDeNkra2fNHBxTyPDGySpjQ==} - engines: {node: '>=8'} - - p-timeout@3.2.0: - resolution: {integrity: sha512-rhIwUycgwwKcP9yTOOFK/AKsAopjjCakVqLHePO3CC6Mir1Z99xT+R63jZxAT5lFZLa2inS5h+ZS2GvR99/FBg==} - engines: {node: '>=8'} - - p-try@2.2.0: - resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} - engines: {node: '>=6'} - - package-json-from-dist@1.0.1: - resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==} - - parse-asn1@5.1.9: - resolution: {integrity: sha512-fIYNuZ/HastSb80baGOuPRo1O9cf4baWw5WsAp7dBuUzeTD/BoaG8sVTdlPFksBE2lF21dN+A1AnrpIjSWqHHg==} - engines: {node: '>= 0.10'} - - path-exists@4.0.0: - resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} - engines: {node: '>=8'} - - path-key@3.1.1: - resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} - engines: {node: '>=8'} - - path-parse@1.0.7: - resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} - - path-scurry@1.11.1: - resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==} - engines: {node: '>=16 || 14 >=14.18'} - - pathe@2.0.3: - resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==} - - pathval@2.0.1: - resolution: {integrity: sha512-//nshmD55c46FuFw26xV/xFAaB5HF9Xdap7HJBBnrKdAd6/GxDBaNA1870O79+9ueg61cZLSVc+OaFlfmObYVQ==} - engines: {node: '>= 14.16'} - - pbkdf2@3.1.5: - resolution: {integrity: sha512-Q3CG/cYvCO1ye4QKkuH7EXxs3VC/rI1/trd+qX2+PolbaKG0H+bgcZzrTt96mMyRtejk+JMCiLUn3y29W8qmFQ==} - engines: {node: '>= 0.10'} - - picocolors@1.1.1: - resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} - - picomatch@2.3.1: - resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} - engines: {node: '>=8.6'} - - picomatch@4.0.3: - resolution: {integrity: sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==} - engines: {node: '>=12'} - - pify@2.3.0: - resolution: {integrity: sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==} - engines: {node: '>=0.10.0'} - - pify@5.0.0: - resolution: {integrity: sha512-eW/gHNMlxdSP6dmG6uJip6FXN0EQBwm2clYYd8Wul42Cwu/DK8HEftzsapcNdYe2MfLiIwZqsDk2RDEsTE79hA==} - engines: {node: '>=10'} - - pkg-dir@4.2.0: - resolution: {integrity: sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==} - engines: {node: '>=8'} - - portfinder@1.0.32: - resolution: {integrity: sha512-on2ZJVVDXRADWE6jnQaX0ioEylzgBpQk8r55NE4wjXW1ZxO+BgDlY6DXwj20i0V8eB4SenDQ00WEaxfiIQPcxg==} - engines: {node: '>= 0.12.0'} - - possible-typed-array-names@1.1.0: - resolution: {integrity: sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==} - engines: {node: '>= 0.4'} - - postcss-calc@8.2.4: - resolution: {integrity: sha512-SmWMSJmB8MRnnULldx0lQIyhSNvuDl9HfrZkaqqE/WHAhToYsAvDq+yAsA/kIyINDszOp3Rh0GFoNuH5Ypsm3Q==} - peerDependencies: - postcss: ^8.2.2 - - postcss-colormin@5.3.1: - resolution: {integrity: sha512-UsWQG0AqTFQmpBegeLLc1+c3jIqBNB0zlDGRWR+dQ3pRKJL1oeMzyqmH3o2PIfn9MBdNrVPWhDbT769LxCTLJQ==} - engines: {node: ^10 || ^12 || >=14.0} - peerDependencies: - postcss: ^8.2.15 - - postcss-convert-values@5.1.3: - resolution: {integrity: sha512-82pC1xkJZtcJEfiLw6UXnXVXScgtBrjlO5CBmuDQc+dlb88ZYheFsjTn40+zBVi3DkfF7iezO0nJUPLcJK3pvA==} - engines: {node: ^10 || ^12 || >=14.0} - peerDependencies: - postcss: ^8.2.15 - - postcss-discard-comments@5.1.2: - resolution: {integrity: sha512-+L8208OVbHVF2UQf1iDmRcbdjJkuBF6IS29yBDSiWUIzpYaAhtNl6JYnYm12FnkeCwQqF5LeklOu6rAqgfBZqQ==} - engines: {node: ^10 || ^12 || >=14.0} - peerDependencies: - postcss: ^8.2.15 - - postcss-discard-duplicates@5.1.0: - resolution: {integrity: sha512-zmX3IoSI2aoenxHV6C7plngHWWhUOV3sP1T8y2ifzxzbtnuhk1EdPwm0S1bIUNaJ2eNbWeGLEwzw8huPD67aQw==} - engines: {node: ^10 || ^12 || >=14.0} - peerDependencies: - postcss: ^8.2.15 - - postcss-discard-empty@5.1.1: - resolution: {integrity: sha512-zPz4WljiSuLWsI0ir4Mcnr4qQQ5e1Ukc3i7UfE2XcrwKK2LIPIqE5jxMRxO6GbI3cv//ztXDsXwEWT3BHOGh3A==} - engines: {node: ^10 || ^12 || >=14.0} - peerDependencies: - postcss: ^8.2.15 - - postcss-discard-overridden@5.1.0: - resolution: {integrity: sha512-21nOL7RqWR1kasIVdKs8HNqQJhFxLsyRfAnUDm4Fe4t4mCWL9OJiHvlHPjcd8zc5Myu89b/7wZDnOSjFgeWRtw==} - engines: {node: ^10 || ^12 || >=14.0} - peerDependencies: - postcss: ^8.2.15 - - postcss-import@16.1.1: - resolution: {integrity: sha512-2xVS1NCZAfjtVdvXiyegxzJ447GyqCeEI5V7ApgQVOWnros1p5lGNovJNapwPpMombyFBfqDwt7AD3n2l0KOfQ==} - engines: {node: '>=18.0.0'} - peerDependencies: - postcss: ^8.0.0 - - postcss-load-config@3.1.4: - resolution: {integrity: sha512-6DiM4E7v4coTE4uzA8U//WhtPwyhiim3eyjEMFCnUpzbrkK9wJHgKDT2mR+HbtSrd/NubVaYTOpSpjUl8NQeRg==} - engines: {node: '>= 10'} - peerDependencies: - postcss: '>=8.0.9' - ts-node: '>=9.0.0' - peerDependenciesMeta: - postcss: - optional: true - ts-node: - optional: true - - postcss-merge-longhand@5.1.7: - resolution: {integrity: sha512-YCI9gZB+PLNskrK0BB3/2OzPnGhPkBEwmwhfYk1ilBHYVAZB7/tkTHFBAnCrvBBOmeYyMYw3DMjT55SyxMBzjQ==} - engines: {node: ^10 || ^12 || >=14.0} - peerDependencies: - postcss: ^8.2.15 - - postcss-merge-rules@5.1.4: - resolution: {integrity: sha512-0R2IuYpgU93y9lhVbO/OylTtKMVcHb67zjWIfCiKR9rWL3GUk1677LAqD/BcHizukdZEjT8Ru3oHRoAYoJy44g==} - engines: {node: ^10 || ^12 || >=14.0} - peerDependencies: - postcss: ^8.2.15 - - postcss-minify-font-values@5.1.0: - resolution: {integrity: sha512-el3mYTgx13ZAPPirSVsHqFzl+BBBDrXvbySvPGFnQcTI4iNslrPaFq4muTkLZmKlGk4gyFAYUBMH30+HurREyA==} - engines: {node: ^10 || ^12 || >=14.0} - peerDependencies: - postcss: ^8.2.15 - - postcss-minify-gradients@5.1.1: - resolution: {integrity: sha512-VGvXMTpCEo4qHTNSa9A0a3D+dxGFZCYwR6Jokk+/3oB6flu2/PnPXAh2x7x52EkY5xlIHLm+Le8tJxe/7TNhzw==} - engines: {node: ^10 || ^12 || >=14.0} - peerDependencies: - postcss: ^8.2.15 - - postcss-minify-params@5.1.4: - resolution: {integrity: sha512-+mePA3MgdmVmv6g+30rn57USjOGSAyuxUmkfiWpzalZ8aiBkdPYjXWtHuwJGm1v5Ojy0Z0LaSYhHaLJQB0P8Jw==} - engines: {node: ^10 || ^12 || >=14.0} - peerDependencies: - postcss: ^8.2.15 - - postcss-minify-selectors@5.2.1: - resolution: {integrity: sha512-nPJu7OjZJTsVUmPdm2TcaiohIwxP+v8ha9NehQ2ye9szv4orirRU3SDdtUmKH+10nzn0bAyOXZ0UEr7OpvLehg==} - engines: {node: ^10 || ^12 || >=14.0} - peerDependencies: - postcss: ^8.2.15 - - postcss-modules-extract-imports@3.1.0: - resolution: {integrity: sha512-k3kNe0aNFQDAZGbin48pL2VNidTF0w4/eASDsxlyspobzU3wZQLOGj7L9gfRe0Jo9/4uud09DsjFNH7winGv8Q==} - engines: {node: ^10 || ^12 || >= 14} - peerDependencies: - postcss: ^8.1.0 - - postcss-modules-local-by-default@4.2.0: - resolution: {integrity: sha512-5kcJm/zk+GJDSfw+V/42fJ5fhjL5YbFDl8nVdXkJPLLW+Vf9mTD5Xe0wqIaDnLuL2U6cDNpTr+UQ+v2HWIBhzw==} - engines: {node: ^10 || ^12 || >= 14} - peerDependencies: - postcss: ^8.1.0 - - postcss-modules-scope@3.2.1: - resolution: {integrity: sha512-m9jZstCVaqGjTAuny8MdgE88scJnCiQSlSrOWcTQgM2t32UBe+MUmFSO5t7VMSfAf/FJKImAxBav8ooCHJXCJA==} - engines: {node: ^10 || ^12 || >= 14} - peerDependencies: - postcss: ^8.1.0 - - postcss-modules-values@4.0.0: - resolution: {integrity: sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==} - engines: {node: ^10 || ^12 || >= 14} - peerDependencies: - postcss: ^8.1.0 - - postcss-modules@4.3.1: - resolution: {integrity: sha512-ItUhSUxBBdNamkT3KzIZwYNNRFKmkJrofvC2nWab3CPKhYBQ1f27XXh1PAPE27Psx58jeelPsxWB/+og+KEH0Q==} - peerDependencies: - postcss: ^8.0.0 - - postcss-nesting@13.0.2: - resolution: {integrity: sha512-1YCI290TX+VP0U/K/aFxzHzQWHWURL+CtHMSbex1lCdpXD1SoR2sYuxDu5aNI9lPoXpKTCggFZiDJbwylU0LEQ==} - engines: {node: '>=18'} - peerDependencies: - postcss: ^8.4 - - postcss-normalize-charset@5.1.0: - resolution: {integrity: sha512-mSgUJ+pd/ldRGVx26p2wz9dNZ7ji6Pn8VWBajMXFf8jk7vUoSrZ2lt/wZR7DtlZYKesmZI680qjr2CeFF2fbUg==} - engines: {node: ^10 || ^12 || >=14.0} - peerDependencies: - postcss: ^8.2.15 - - postcss-normalize-display-values@5.1.0: - resolution: {integrity: sha512-WP4KIM4o2dazQXWmFaqMmcvsKmhdINFblgSeRgn8BJ6vxaMyaJkwAzpPpuvSIoG/rmX3M+IrRZEz2H0glrQNEA==} - engines: {node: ^10 || ^12 || >=14.0} - peerDependencies: - postcss: ^8.2.15 - - postcss-normalize-positions@5.1.1: - resolution: {integrity: sha512-6UpCb0G4eofTCQLFVuI3EVNZzBNPiIKcA1AKVka+31fTVySphr3VUgAIULBhxZkKgwLImhzMR2Bw1ORK+37INg==} - engines: {node: ^10 || ^12 || >=14.0} - peerDependencies: - postcss: ^8.2.15 - - postcss-normalize-repeat-style@5.1.1: - resolution: {integrity: sha512-mFpLspGWkQtBcWIRFLmewo8aC3ImN2i/J3v8YCFUwDnPu3Xz4rLohDO26lGjwNsQxB3YF0KKRwspGzE2JEuS0g==} - engines: {node: ^10 || ^12 || >=14.0} - peerDependencies: - postcss: ^8.2.15 - - postcss-normalize-string@5.1.0: - resolution: {integrity: sha512-oYiIJOf4T9T1N4i+abeIc7Vgm/xPCGih4bZz5Nm0/ARVJ7K6xrDlLwvwqOydvyL3RHNf8qZk6vo3aatiw/go3w==} - engines: {node: ^10 || ^12 || >=14.0} - peerDependencies: - postcss: ^8.2.15 - - postcss-normalize-timing-functions@5.1.0: - resolution: {integrity: sha512-DOEkzJ4SAXv5xkHl0Wa9cZLF3WCBhF3o1SKVxKQAa+0pYKlueTpCgvkFAHfk+Y64ezX9+nITGrDZeVGgITJXjg==} - engines: {node: ^10 || ^12 || >=14.0} - peerDependencies: - postcss: ^8.2.15 - - postcss-normalize-unicode@5.1.1: - resolution: {integrity: sha512-qnCL5jzkNUmKVhZoENp1mJiGNPcsJCs1aaRmURmeJGES23Z/ajaln+EPTD+rBeNkSryI+2WTdW+lwcVdOikrpA==} - engines: {node: ^10 || ^12 || >=14.0} - peerDependencies: - postcss: ^8.2.15 - - postcss-normalize-url@5.1.0: - resolution: {integrity: sha512-5upGeDO+PVthOxSmds43ZeMeZfKH+/DKgGRD7TElkkyS46JXAUhMzIKiCa7BabPeIy3AQcTkXwVVN7DbqsiCew==} - engines: {node: ^10 || ^12 || >=14.0} - peerDependencies: - postcss: ^8.2.15 - - postcss-normalize-whitespace@5.1.1: - resolution: {integrity: sha512-83ZJ4t3NUDETIHTa3uEg6asWjSBYL5EdkVB0sDncx9ERzOKBVJIUeDO9RyA9Zwtig8El1d79HBp0JEi8wvGQnA==} - engines: {node: ^10 || ^12 || >=14.0} - peerDependencies: - postcss: ^8.2.15 - - postcss-ordered-values@5.1.3: - resolution: {integrity: sha512-9UO79VUhPwEkzbb3RNpqqghc6lcYej1aveQteWY+4POIwlqkYE21HKWaLDF6lWNuqCobEAyTovVhtI32Rbv2RQ==} - engines: {node: ^10 || ^12 || >=14.0} - peerDependencies: - postcss: ^8.2.15 - - postcss-reduce-initial@5.1.2: - resolution: {integrity: sha512-dE/y2XRaqAi6OvjzD22pjTUQ8eOfc6m/natGHgKFBK9DxFmIm69YmaRVQrGgFlEfc1HePIurY0TmDeROK05rIg==} - engines: {node: ^10 || ^12 || >=14.0} - peerDependencies: - postcss: ^8.2.15 - - postcss-reduce-transforms@5.1.0: - resolution: {integrity: sha512-2fbdbmgir5AvpW9RLtdONx1QoYG2/EtqpNQbFASDlixBbAYuTcJ0dECwlqNqH7VbaUnEnh8SrxOe2sRIn24XyQ==} - engines: {node: ^10 || ^12 || >=14.0} - peerDependencies: - postcss: ^8.2.15 - - postcss-selector-parser@6.1.2: - resolution: {integrity: sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==} - engines: {node: '>=4'} - - postcss-selector-parser@7.1.0: - resolution: {integrity: sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==} - engines: {node: '>=4'} - - postcss-svgo@5.1.0: - resolution: {integrity: sha512-D75KsH1zm5ZrHyxPakAxJWtkyXew5qwS70v56exwvw542d9CRtTo78K0WeFxZB4G7JXKKMbEZtZayTGdIky/eA==} - engines: {node: ^10 || ^12 || >=14.0} - peerDependencies: - postcss: ^8.2.15 - - postcss-unique-selectors@5.1.1: - resolution: {integrity: sha512-5JiODlELrz8L2HwxfPnhOWZYWDxVHWL83ufOv84NrcgipI7TaeRsatAhK4Tr2/ZiYldpK/wBvw5BD3qfaK96GA==} - engines: {node: ^10 || ^12 || >=14.0} - peerDependencies: - postcss: ^8.2.15 - - postcss-value-parser@4.2.0: - resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==} - - postcss@8.5.6: - resolution: {integrity: sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==} - engines: {node: ^10 || ^12 || >=14} - - prettier@3.6.2: - resolution: {integrity: sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ==} - engines: {node: '>=14'} - hasBin: true - - process-nextick-args@2.0.1: - resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==} - - promise.series@0.2.0: - resolution: {integrity: sha512-VWQJyU2bcDTgZw8kpfBpB/ejZASlCrzwz5f2hjb/zlujOEB4oeiAhHygAWq8ubsX2GVkD4kCU5V2dwOTaCY5EQ==} - engines: {node: '>=0.12'} - - property-expr@2.0.6: - resolution: {integrity: sha512-SVtmxhRE/CGkn3eZY1T6pC8Nln6Fr/lu1mKSgRud0eC73whjGfoAogbn78LkD8aFL0zz3bAFerKSnOl7NlErBA==} - - proxy-from-env@1.1.0: - resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} - - public-encrypt@4.0.3: - resolution: {integrity: sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==} - - ramda@0.30.1: - resolution: {integrity: sha512-tEF5I22zJnuclswcZMc8bDIrwRHRzf+NqVEmqg50ShAZMP7MWeR/RGDthfM/p+BlqvF2fXAzpn8i+SJcYD3alw==} - - randombytes@2.1.0: - resolution: {integrity: sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==} - - randomfill@1.0.4: - resolution: {integrity: sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==} - - react-dom@19.2.0: - resolution: {integrity: sha512-UlbRu4cAiGaIewkPyiRGJk0imDN2T3JjieT6spoL2UeSf5od4n5LB/mQ4ejmxhCFT1tYe8IvaFulzynWovsEFQ==} - peerDependencies: - react: ^19.2.0 - - react@19.2.0: - resolution: {integrity: sha512-tmbWg6W31tQLeB5cdIBOicJDJRR2KzXsV7uSK9iNfLWQ5bIZfxuPEHp7M8wiHyHnn0DD1i7w3Zmin0FtkrwoCQ==} - engines: {node: '>=0.10.0'} - - read-cache@1.0.0: - resolution: {integrity: sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==} - - readable-stream@2.3.8: - resolution: {integrity: sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==} - - readable-stream@3.6.2: - resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} - engines: {node: '>= 6'} - - readdirp@3.6.0: - resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} - engines: {node: '>=8.10.0'} - - readonly-date@1.0.0: - resolution: {integrity: sha512-tMKIV7hlk0h4mO3JTmmVuIlJVXjKk3Sep9Bf5OH0O+758ruuVkUy2J9SttDLm91IEX/WHlXPSpxMGjPj4beMIQ==} - - regenerator-runtime@0.14.1: - resolution: {integrity: sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==} - - resolve-from@5.0.0: - resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==} - engines: {node: '>=8'} - - resolve@1.22.10: - resolution: {integrity: sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==} - engines: {node: '>= 0.4'} - hasBin: true - - rimraf@5.0.10: - resolution: {integrity: sha512-l0OE8wL34P4nJH/H2ffoaniAokM2qSmrtXHmlpvYr5AVVX8msAyW0l8NVJFDxlSK4u3Uh/f41cQheDVdnYijwQ==} - hasBin: true - - ripemd160@2.0.3: - resolution: {integrity: sha512-5Di9UC0+8h1L6ZD2d7awM7E/T4uA1fJRlx6zk/NvdCCVEoAnFqvHmCuNeIKoCeIixBX/q8uM+6ycDvF8woqosA==} - engines: {node: '>= 0.8'} - - rlp@2.2.7: - resolution: {integrity: sha512-d5gdPmgQ0Z+AklL2NVXr/IoSjNZFfTVvQWzL/AM2AOcSzYP2xjlb0AC8YyCLc41MSNf6P6QVtjgPdmVtzb+4lQ==} - hasBin: true - - rollup-plugin-dts@6.2.3: - resolution: {integrity: sha512-UgnEsfciXSPpASuOelix7m4DrmyQgiaWBnvI0TM4GxuDh5FkqW8E5hu57bCxXB90VvR1WNfLV80yEDN18UogSA==} - engines: {node: '>=16'} - peerDependencies: - rollup: ^4.0.0 - typescript: ^5.0.0 - - rollup-plugin-postcss@4.0.2: - resolution: {integrity: sha512-05EaY6zvZdmvPUDi3uCcAQoESDcYnv8ogJJQRp6V5kZ6J6P7uAVJlrTZcaaA20wTH527YTnKfkAoPxWI/jPp4w==} - engines: {node: '>=10'} - peerDependencies: - postcss: 8.x - - rollup-plugin-typescript2@0.36.0: - resolution: {integrity: sha512-NB2CSQDxSe9+Oe2ahZbf+B4bh7pHwjV5L+RSYpCu7Q5ROuN94F9b6ioWwKfz3ueL3KTtmX4o2MUH2cgHDIEUsw==} - peerDependencies: - rollup: ^4.0.0 - typescript: ^5.0.0 - - rollup-pluginutils@2.8.2: - resolution: {integrity: sha512-EEp9NhnUkwY8aif6bxgovPHMoMoNr2FulJziTndpt5H9RdwC47GSGuII9XxpSdzVGM0GWrNPHV6ie1LTNJPaLQ==} - - rollup@4.52.4: - resolution: {integrity: sha512-CLEVl+MnPAiKh5pl4dEWSyMTpuflgNQiLGhMv8ezD5W/qP8AKvmYpCOKRRNOh7oRKnauBZ4SyeYkMS+1VSyKwQ==} - engines: {node: '>=18.0.0', npm: '>=8.0.0'} - hasBin: true - - safe-buffer@5.1.2: - resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==} - - safe-buffer@5.2.1: - resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} - - safe-identifier@0.4.2: - resolution: {integrity: sha512-6pNbSMW6OhAi9j+N8V+U715yBQsaWJ7eyEUaOrawX+isg5ZxhUlV1NipNtgaKHmFGiABwt+ZF04Ii+3Xjkg+8w==} - - safe-regex-test@1.1.0: - resolution: {integrity: sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==} - engines: {node: '>= 0.4'} - - scheduler@0.27.0: - resolution: {integrity: sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==} - - scrypt-js@3.0.1: - resolution: {integrity: sha512-cdwTTnqPu0Hyvf5in5asVdZocVDTNRmR7XEcJuIzMjJeSHybHl7vpB66AzwTaIg6CLSbtjcxc8fqcySfnTkccA==} - - secp256k1@4.0.4: - resolution: {integrity: sha512-6JfvwvjUOn8F/jUoBY2Q1v5WY5XS+rj8qSe0v8Y4ezH4InLgTEeOOPQsRll9OV429Pvo6BCHGavIyJfr3TAhsw==} - engines: {node: '>=18.0.0'} - - semver@6.3.1: - resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} - hasBin: true - - semver@7.7.1: - resolution: {integrity: sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==} - engines: {node: '>=10'} - hasBin: true - - semver@7.7.3: - resolution: {integrity: sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==} - engines: {node: '>=10'} - hasBin: true - - set-function-length@1.2.2: - resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==} - engines: {node: '>= 0.4'} - - setimmediate@1.0.5: - resolution: {integrity: sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==} - - sha.js@2.4.12: - resolution: {integrity: sha512-8LzC5+bvI45BjpfXU8V5fdU2mfeKiQe1D1gIMn7XUlF3OTUrpdJpPPH4EMAnF0DsHHdSZqCdSss5qCmJKuiO3w==} - engines: {node: '>= 0.10'} - hasBin: true - - shebang-command@2.0.0: - resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} - engines: {node: '>=8'} - - shebang-regex@3.0.0: - resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} - engines: {node: '>=8'} - - siginfo@2.0.0: - resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==} - - signal-exit@4.1.0: - resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} - engines: {node: '>=14'} - - source-map-js@1.2.1: - resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} - engines: {node: '>=0.10.0'} - - source-map@0.6.1: - resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} - engines: {node: '>=0.10.0'} - - stable@0.1.8: - resolution: {integrity: sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==} - deprecated: 'Modern JS already guarantees Array#sort() is a stable sort, so this library is deprecated. See the compatibility table on MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort#browser_compatibility' - - stackback@0.0.2: - resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==} - - std-env@3.10.0: - resolution: {integrity: sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==} - - stream-browserify@3.0.0: - resolution: {integrity: sha512-H73RAHsVBapbim0tU2JwwOiXUj+fikfiaoYAKHF3VJfA0pe2BCzkhAHBlLG6REzE+2WNZcxOXjK7lkso+9euLA==} - - string-hash@1.1.3: - resolution: {integrity: sha512-kJUvRUFK49aub+a7T1nNE66EJbZBMnBgoC1UbCZ5n6bsZKBRga4KgBRTMn/pFkeCZSYtNeSyMxPDM0AXWELk2A==} - - string-width@4.2.3: - resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} - engines: {node: '>=8'} - - string-width@5.1.2: - resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} - engines: {node: '>=12'} - - string_decoder@1.1.1: - resolution: {integrity: sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==} - - string_decoder@1.3.0: - resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} - - strip-ansi@6.0.1: - resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} - engines: {node: '>=8'} - - strip-ansi@7.1.2: - resolution: {integrity: sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==} - engines: {node: '>=12'} - - style-inject@0.3.0: - resolution: {integrity: sha512-IezA2qp+vcdlhJaVm5SOdPPTUu0FCEqfNSli2vRuSIBbu5Nq5UvygTk/VzeCqfLz2Atj3dVII5QBKGZRZ0edzw==} - - stylehacks@5.1.1: - resolution: {integrity: sha512-sBpcd5Hx7G6seo7b1LkpttvTz7ikD0LlH5RmdcBNb6fFR0Fl7LQwHDFr300q4cwUqi+IYrFGmsIHieMBfnN/Bw==} - engines: {node: ^10 || ^12 || >=14.0} - peerDependencies: - postcss: ^8.2.15 - - supports-color@7.2.0: - resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} - engines: {node: '>=8'} - - supports-preserve-symlinks-flag@1.0.0: - resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} - engines: {node: '>= 0.4'} - - svgo@2.8.0: - resolution: {integrity: sha512-+N/Q9kV1+F+UeWYoSiULYo4xYSDQlTgb+ayMobAXPwMnLvop7oxKMo9OzIrX5x3eS4L4f2UHhc9axXwY8DpChg==} - engines: {node: '>=10.13.0'} - hasBin: true - - symbol-observable@2.0.3: - resolution: {integrity: sha512-sQV7phh2WCYAn81oAkakC5qjq2Ml0g8ozqz03wOGnx9dDlG1de6yrF+0RAzSJD8fPUow3PTSMf2SAbOGxb93BA==} - engines: {node: '>=0.10'} - - tailwind-merge@3.3.1: - resolution: {integrity: sha512-gBXpgUm/3rp1lMZZrM/w7D8GKqshif0zAymAhbCyIt8KMe+0v9DQ7cdYLR4FHH/cKpdTXb+A/tKKU3eolfsI+g==} - - tailwindcss@4.1.10: - resolution: {integrity: sha512-P3nr6WkvKV/ONsTzj6Gb57sWPMX29EPNPopo7+FcpkQaNsrNpZ1pv8QmrYI2RqEKD7mlGqLnGovlcYnBK0IqUA==} - - tapable@2.3.0: - resolution: {integrity: sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg==} - engines: {node: '>=6'} - - tar@7.5.1: - resolution: {integrity: sha512-nlGpxf+hv0v7GkWBK2V9spgactGOp0qvfWRxUMjqHyzrt3SgwE48DIv/FhqPHJYLHpgW1opq3nERbz5Anq7n1g==} - engines: {node: '>=18'} - - tiny-case@1.0.3: - resolution: {integrity: sha512-Eet/eeMhkO6TX8mnUteS9zgPbUMQa4I6Kkp5ORiBD5476/m+PIRiumP5tmh5ioJpH7k51Kehawy2UDfsnxxY8Q==} - - tinybench@2.9.0: - resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==} - - tinyexec@0.3.2: - resolution: {integrity: sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==} - - tinyglobby@0.2.15: - resolution: {integrity: sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==} - engines: {node: '>=12.0.0'} - - tinypool@1.1.1: - resolution: {integrity: sha512-Zba82s87IFq9A9XmjiX5uZA/ARWDrB03OHlq+Vw1fSdt0I+4/Kutwy8BP4Y/y/aORMo61FQ0vIb5j44vSo5Pkg==} - engines: {node: ^18.0.0 || >=20.0.0} - - tinyrainbow@2.0.0: - resolution: {integrity: sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw==} - engines: {node: '>=14.0.0'} - - tinyspy@3.0.2: - resolution: {integrity: sha512-n1cw8k1k0x4pgA2+9XrOkFydTerNcJ1zWCO5Nn9scWHTD+5tp8dghT2x1uduQePZTZgd3Tupf+x9BxJjeJi77Q==} - engines: {node: '>=14.0.0'} - - to-buffer@1.2.2: - resolution: {integrity: sha512-db0E3UJjcFhpDhAF4tLo03oli3pwl3dbnzXOUIlRKrp+ldk/VUxzpWYZENsw2SZiuBjHAk7DfB0VU7NKdpb6sw==} - engines: {node: '>= 0.4'} - - to-regex-range@5.0.1: - resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} - engines: {node: '>=8.0'} - - toml@3.0.0: - resolution: {integrity: sha512-y/mWCZinnvxjTKYhJ+pYxwD0mRLVvOtdS2Awbgxln6iEnt4rk0yBxeSBHkGJcPucRiG0e55mwWp+g/05rsrd6w==} - - toposort@2.0.2: - resolution: {integrity: sha512-0a5EOkAUp8D4moMi2W8ZF8jcga7BgZd91O/yabJCFY8az+XSzeGyTKs0Aoo897iV1Nj6guFq8orWDS96z91oGg==} - - tr46@0.0.3: - resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} - - tronweb@6.0.4: - resolution: {integrity: sha512-+9Nc7H4FYVh2DcOnQG93WLm3UdlHSf9W+GXkfrXI77oLjTB1cptROJDKRSSxQBiOAyjjAJOOTuYDzlAkaLT85w==} - - tslib@2.7.0: - resolution: {integrity: sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==} - - tslib@2.8.1: - resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} - - type-fest@2.19.0: - resolution: {integrity: sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==} - engines: {node: '>=12.20'} - - type-fest@4.34.1: - resolution: {integrity: sha512-6kSc32kT0rbwxD6QL1CYe8IqdzN/J/ILMrNK+HMQCKH3insCDRY/3ITb0vcBss0a3t72fzh2YSzj8ko1HgwT3g==} - engines: {node: '>=16'} - - typed-array-buffer@1.0.3: - resolution: {integrity: sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==} - engines: {node: '>= 0.4'} - - typedarray-to-buffer@3.1.5: - resolution: {integrity: sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==} - - typescript@5.9.3: - resolution: {integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==} - engines: {node: '>=14.17'} - hasBin: true - - uglify-js@3.19.3: - resolution: {integrity: sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ==} - engines: {node: '>=0.8.0'} - hasBin: true - - uint8arrays@5.1.0: - resolution: {integrity: sha512-vA6nFepEmlSKkMBnLBaUMVvAC4G3CTmO58C12y4sq6WPDOR7mOFYOi7GlrQ4djeSbP6JG9Pv9tJDM97PedRSww==} - - undici-types@6.19.8: - resolution: {integrity: sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==} - - undici-types@6.21.0: - resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==} - - undici-types@7.14.0: - resolution: {integrity: sha512-QQiYxHuyZ9gQUIrmPo3IA+hUl4KYk8uSA7cHrcKd/l3p1OTpZcM0Tbp9x7FAtXdAYhlasd60ncPpgu6ihG6TOA==} - - universalify@2.0.1: - resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==} - engines: {node: '>= 10.0.0'} - - update-browserslist-db@1.1.3: - resolution: {integrity: sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==} - hasBin: true - peerDependencies: - browserslist: '>= 4.21.0' - - utf8@3.0.0: - resolution: {integrity: sha512-E8VjFIQ/TyQgp+TZfS6l8yp/xWppSAHzidGiRrqe4bK4XP9pTRyKFgGJpO3SN7zdX4DeomTrwaseCHovfpFcqQ==} - - util-deprecate@1.0.2: - resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} - - util@0.12.5: - resolution: {integrity: sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==} - - uuid@8.3.2: - resolution: {integrity: sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==} - hasBin: true - - validator@13.12.0: - resolution: {integrity: sha512-c1Q0mCiPlgdTVVVIJIrBuxNicYE+t/7oKeI9MWLj3fh/uq2Pxh/3eeWbVZ4OcGW1TUf53At0njHw5SMdA3tmMg==} - engines: {node: '>= 0.10'} - - viem@2.38.3: - resolution: {integrity: sha512-By2TutLv07iNHHtWqHHzjGipevYsfGqT7KQbGEmqLco1qTJxKnvBbSviqiu6/v/9REV6Q/FpmIxf2Z7/l5AbcQ==} - peerDependencies: - typescript: ^5.0.0 - peerDependenciesMeta: - typescript: - optional: true - - vite-node@3.0.9: - resolution: {integrity: sha512-w3Gdx7jDcuT9cNn9jExXgOyKmf5UOTb6WMHz8LGAm54eS1Elf5OuBhCxl6zJxGhEeIkgsE1WbHuoL0mj/UXqXg==} - engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} - hasBin: true - - vite@6.4.0: - resolution: {integrity: sha512-oLnWs9Hak/LOlKjeSpOwD6JMks8BeICEdYMJBf6P4Lac/pO9tKiv/XhXnAM7nNfSkZahjlCZu9sS50zL8fSnsw==} - engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} - hasBin: true - peerDependencies: - '@types/node': ^18.0.0 || ^20.0.0 || >=22.0.0 - jiti: '>=1.21.0' - less: '*' - lightningcss: ^1.21.0 - sass: '*' - sass-embedded: '*' - stylus: '*' - sugarss: '*' - terser: ^5.16.0 - tsx: ^4.8.1 - yaml: ^2.4.2 - peerDependenciesMeta: - '@types/node': - optional: true - jiti: - optional: true - less: - optional: true - lightningcss: - optional: true - sass: - optional: true - sass-embedded: - optional: true - stylus: - optional: true - sugarss: - optional: true - terser: - optional: true - tsx: - optional: true - yaml: - optional: true - - vitest@3.0.9: - resolution: {integrity: sha512-BbcFDqNyBlfSpATmTtXOAOj71RNKDDvjBM/uPfnxxVGrG+FSH2RQIwgeEngTaTkuU/h0ScFvf+tRcKfYXzBybQ==} - engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} - hasBin: true - peerDependencies: - '@edge-runtime/vm': '*' - '@types/debug': ^4.1.12 - '@types/node': ^18.0.0 || ^20.0.0 || >=22.0.0 - '@vitest/browser': 3.0.9 - '@vitest/ui': 3.0.9 - happy-dom: '*' - jsdom: '*' - peerDependenciesMeta: - '@edge-runtime/vm': - optional: true - '@types/debug': - optional: true - '@types/node': - optional: true - '@vitest/browser': - optional: true - '@vitest/ui': - optional: true - happy-dom: - optional: true - jsdom: - optional: true - - webidl-conversions@3.0.1: - resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} - - whatwg-url@5.0.0: - resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} - - which-typed-array@1.1.19: - resolution: {integrity: sha512-rEvr90Bck4WZt9HHFC4DJMsjvu7x+r6bImz0/BrbWb7A2djJ8hnZMrWnHo9F8ssv0OMErasDhftrfROTyqSDrw==} - engines: {node: '>= 0.4'} - - which@2.0.2: - resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} - engines: {node: '>= 8'} - hasBin: true - - why-is-node-running@2.3.0: - resolution: {integrity: sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==} - engines: {node: '>=8'} - hasBin: true - - wordwrap@1.0.0: - resolution: {integrity: sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==} - - wrap-ansi@7.0.0: - resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} - engines: {node: '>=10'} - - wrap-ansi@8.1.0: - resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==} - engines: {node: '>=12'} - - wrappy@1.0.2: - resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} - - ws@7.5.10: - resolution: {integrity: sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==} - engines: {node: '>=8.3.0'} - peerDependencies: - bufferutil: ^4.0.1 - utf-8-validate: ^5.0.2 - peerDependenciesMeta: - bufferutil: - optional: true - utf-8-validate: - optional: true - - ws@8.17.1: - resolution: {integrity: sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==} - engines: {node: '>=10.0.0'} - peerDependencies: - bufferutil: ^4.0.1 - utf-8-validate: '>=5.0.2' - peerDependenciesMeta: - bufferutil: - optional: true - utf-8-validate: - optional: true - - ws@8.18.3: - resolution: {integrity: sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==} - engines: {node: '>=10.0.0'} - peerDependencies: - bufferutil: ^4.0.1 - utf-8-validate: '>=5.0.2' - peerDependenciesMeta: - bufferutil: - optional: true - utf-8-validate: - optional: true - - xstream@11.14.0: - resolution: {integrity: sha512-1bLb+kKKtKPbgTK6i/BaoAn03g47PpFstlbe1BA+y3pNS/LfvcaghS5BFf9+EE1J+KwSQsEpfJvFN5GqFtiNmw==} - - yallist@5.0.0: - resolution: {integrity: sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==} - engines: {node: '>=18'} - - yaml@1.10.2: - resolution: {integrity: sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==} - engines: {node: '>= 6'} - - yup@1.6.1: - resolution: {integrity: sha512-JED8pB50qbA4FOkDol0bYF/p60qSEDQqBD0/qeIrUCG1KbPBIQ776fCUNb9ldbPcSTxA69g/47XTo4TqWiuXOA==} - -snapshots: - - '@adraffy/ens-normalize@1.10.1': {} - - '@adraffy/ens-normalize@1.11.1': {} - - '@alloc/quick-lru@5.2.0': {} - - '@ampproject/remapping@2.3.0': - dependencies: - '@jridgewell/gen-mapping': 0.3.13 - '@jridgewell/trace-mapping': 0.3.31 - - '@avail-project/ca-common@1.0.0-beta.7(@cosmjs/proto-signing@0.34.0)(@cosmjs/stargate@0.34.0)(axios@1.12.2)(decimal.js@10.6.0)(fuels@0.101.1(vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2)))(google-protobuf@3.21.4)(long@5.3.2)(msgpackr@1.11.5)(viem@2.38.3(typescript@5.9.3))': - dependencies: - '@bufbuild/protobuf': 2.9.0 - '@cosmjs/proto-signing': 0.34.0 - '@cosmjs/stargate': 0.34.0 - '@improbable-eng/grpc-web': 0.15.0(google-protobuf@3.21.4) - axios: 1.12.2 - browser-headers: 0.4.1 - decimal.js: 10.6.0 - es-toolkit: 1.40.0 - fuels: 0.101.1(vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2)) - long: 5.3.2 - msgpackr: 1.11.5 - tslib: 2.8.1 - viem: 2.38.3(typescript@5.9.3) - transitivePeerDependencies: - - google-protobuf - - '@babel/code-frame@7.27.1': - dependencies: - '@babel/helper-validator-identifier': 7.27.1 - js-tokens: 4.0.0 - picocolors: 1.1.1 - optional: true - - '@babel/helper-validator-identifier@7.27.1': - optional: true - - '@babel/runtime@7.26.10': - dependencies: - regenerator-runtime: 0.14.1 - - '@bufbuild/protobuf@2.9.0': {} - - '@cosmjs/amino@0.34.0': - dependencies: - '@cosmjs/crypto': 0.34.0 - '@cosmjs/encoding': 0.34.0 - '@cosmjs/math': 0.34.0 - '@cosmjs/utils': 0.34.0 - - '@cosmjs/crypto@0.34.0': - dependencies: - '@cosmjs/encoding': 0.34.0 - '@cosmjs/math': 0.34.0 - '@cosmjs/utils': 0.34.0 - '@noble/curves': 1.9.7 - '@noble/hashes': 1.8.0 - bn.js: 5.2.2 - libsodium-wrappers-sumo: 0.7.15 - - '@cosmjs/encoding@0.34.0': - dependencies: - base64-js: 1.5.1 - bech32: 1.1.4 - readonly-date: 1.0.0 - - '@cosmjs/json-rpc@0.34.0': - dependencies: - '@cosmjs/stream': 0.34.0 - xstream: 11.14.0 - - '@cosmjs/math@0.34.0': - dependencies: - bn.js: 5.2.2 - - '@cosmjs/proto-signing@0.34.0': - dependencies: - '@cosmjs/amino': 0.34.0 - '@cosmjs/crypto': 0.34.0 - '@cosmjs/encoding': 0.34.0 - '@cosmjs/math': 0.34.0 - '@cosmjs/utils': 0.34.0 - cosmjs-types: 0.9.0 - - '@cosmjs/socket@0.34.0': - dependencies: - '@cosmjs/stream': 0.34.0 - isomorphic-ws: 4.0.1(ws@7.5.10) - ws: 7.5.10 - xstream: 11.14.0 - transitivePeerDependencies: - - bufferutil - - utf-8-validate - - '@cosmjs/stargate@0.34.0': - dependencies: - '@cosmjs/amino': 0.34.0 - '@cosmjs/encoding': 0.34.0 - '@cosmjs/math': 0.34.0 - '@cosmjs/proto-signing': 0.34.0 - '@cosmjs/stream': 0.34.0 - '@cosmjs/tendermint-rpc': 0.34.0 - '@cosmjs/utils': 0.34.0 - cosmjs-types: 0.9.0 - transitivePeerDependencies: - - bufferutil - - encoding - - utf-8-validate - - '@cosmjs/stream@0.34.0': - dependencies: - xstream: 11.14.0 - - '@cosmjs/tendermint-rpc@0.34.0': - dependencies: - '@cosmjs/crypto': 0.34.0 - '@cosmjs/encoding': 0.34.0 - '@cosmjs/json-rpc': 0.34.0 - '@cosmjs/math': 0.34.0 - '@cosmjs/socket': 0.34.0 - '@cosmjs/stream': 0.34.0 - '@cosmjs/utils': 0.34.0 - cross-fetch: 4.1.0 - readonly-date: 1.0.0 - xstream: 11.14.0 - transitivePeerDependencies: - - bufferutil - - encoding - - utf-8-validate - - '@cosmjs/utils@0.34.0': {} - - '@csstools/selector-resolve-nested@3.1.0(postcss-selector-parser@7.1.0)': - dependencies: - postcss-selector-parser: 7.1.0 - - '@csstools/selector-specificity@5.0.0(postcss-selector-parser@7.1.0)': - dependencies: - postcss-selector-parser: 7.1.0 - - '@esbuild/aix-ppc64@0.25.1': - optional: true - - '@esbuild/aix-ppc64@0.25.11': - optional: true - - '@esbuild/android-arm64@0.25.1': - optional: true - - '@esbuild/android-arm64@0.25.11': - optional: true - - '@esbuild/android-arm@0.25.1': - optional: true - - '@esbuild/android-arm@0.25.11': - optional: true - - '@esbuild/android-x64@0.25.1': - optional: true - - '@esbuild/android-x64@0.25.11': - optional: true - - '@esbuild/darwin-arm64@0.25.1': - optional: true - - '@esbuild/darwin-arm64@0.25.11': - optional: true - - '@esbuild/darwin-x64@0.25.1': - optional: true - - '@esbuild/darwin-x64@0.25.11': - optional: true - - '@esbuild/freebsd-arm64@0.25.1': - optional: true - - '@esbuild/freebsd-arm64@0.25.11': - optional: true - - '@esbuild/freebsd-x64@0.25.1': - optional: true - - '@esbuild/freebsd-x64@0.25.11': - optional: true - - '@esbuild/linux-arm64@0.25.1': - optional: true - - '@esbuild/linux-arm64@0.25.11': - optional: true - - '@esbuild/linux-arm@0.25.1': - optional: true - - '@esbuild/linux-arm@0.25.11': - optional: true - - '@esbuild/linux-ia32@0.25.1': - optional: true - - '@esbuild/linux-ia32@0.25.11': - optional: true - - '@esbuild/linux-loong64@0.25.1': - optional: true - - '@esbuild/linux-loong64@0.25.11': - optional: true - - '@esbuild/linux-mips64el@0.25.1': - optional: true - - '@esbuild/linux-mips64el@0.25.11': - optional: true - - '@esbuild/linux-ppc64@0.25.1': - optional: true - - '@esbuild/linux-ppc64@0.25.11': - optional: true - - '@esbuild/linux-riscv64@0.25.1': - optional: true - - '@esbuild/linux-riscv64@0.25.11': - optional: true - - '@esbuild/linux-s390x@0.25.1': - optional: true - - '@esbuild/linux-s390x@0.25.11': - optional: true - - '@esbuild/linux-x64@0.25.1': - optional: true - - '@esbuild/linux-x64@0.25.11': - optional: true - - '@esbuild/netbsd-arm64@0.25.1': - optional: true - - '@esbuild/netbsd-arm64@0.25.11': - optional: true - - '@esbuild/netbsd-x64@0.25.1': - optional: true - - '@esbuild/netbsd-x64@0.25.11': - optional: true - - '@esbuild/openbsd-arm64@0.25.1': - optional: true - - '@esbuild/openbsd-arm64@0.25.11': - optional: true - - '@esbuild/openbsd-x64@0.25.1': - optional: true - - '@esbuild/openbsd-x64@0.25.11': - optional: true - - '@esbuild/openharmony-arm64@0.25.11': - optional: true - - '@esbuild/sunos-x64@0.25.1': - optional: true - - '@esbuild/sunos-x64@0.25.11': - optional: true - - '@esbuild/win32-arm64@0.25.1': - optional: true - - '@esbuild/win32-arm64@0.25.11': - optional: true - - '@esbuild/win32-ia32@0.25.1': - optional: true - - '@esbuild/win32-ia32@0.25.11': - optional: true - - '@esbuild/win32-x64@0.25.1': - optional: true - - '@esbuild/win32-x64@0.25.11': - optional: true - - '@fuel-ts/abi-coder@0.101.1(vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2))': - dependencies: - '@fuel-ts/crypto': 0.101.1(vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2)) - '@fuel-ts/errors': 0.101.1 - '@fuel-ts/hasher': 0.101.1(vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2)) - '@fuel-ts/math': 0.101.1 - '@fuel-ts/utils': 0.101.1(vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2)) - type-fest: 4.34.1 - transitivePeerDependencies: - - vitest - - '@fuel-ts/abi-typegen@0.101.1(vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2))': - dependencies: - '@fuel-ts/errors': 0.101.1 - '@fuel-ts/utils': 0.101.1(vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2)) - '@fuel-ts/versions': 0.101.1 - commander: 13.1.0 - glob: 10.4.5 - handlebars: 4.7.8 - mkdirp: 3.0.1 - ramda: 0.30.1 - rimraf: 5.0.10 - transitivePeerDependencies: - - vitest - - '@fuel-ts/account@0.101.1(vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2))': - dependencies: - '@fuel-ts/abi-coder': 0.101.1(vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2)) - '@fuel-ts/address': 0.101.1(vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2)) - '@fuel-ts/crypto': 0.101.1(vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2)) - '@fuel-ts/errors': 0.101.1 - '@fuel-ts/hasher': 0.101.1(vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2)) - '@fuel-ts/math': 0.101.1 - '@fuel-ts/merkle': 0.101.1(vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2)) - '@fuel-ts/transactions': 0.101.1(vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2)) - '@fuel-ts/utils': 0.101.1(vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2)) - '@fuel-ts/versions': 0.101.1 - '@fuels/vm-asm': 0.60.2 - '@noble/curves': 1.8.1 - events: 3.3.0 - graphql: 16.10.0 - graphql-request: 6.1.0(graphql@16.10.0) - graphql-tag: 2.12.6(graphql@16.10.0) - ramda: 0.30.1 - transitivePeerDependencies: - - encoding - - vitest - - '@fuel-ts/address@0.101.1(vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2))': - dependencies: - '@fuel-ts/crypto': 0.101.1(vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2)) - '@fuel-ts/errors': 0.101.1 - '@fuel-ts/utils': 0.101.1(vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2)) - '@noble/hashes': 1.7.1 - transitivePeerDependencies: - - vitest - - '@fuel-ts/contract@0.101.1(vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2))': - dependencies: - '@fuel-ts/abi-coder': 0.101.1(vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2)) - '@fuel-ts/account': 0.101.1(vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2)) - '@fuel-ts/crypto': 0.101.1(vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2)) - '@fuel-ts/errors': 0.101.1 - '@fuel-ts/hasher': 0.101.1(vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2)) - '@fuel-ts/math': 0.101.1 - '@fuel-ts/merkle': 0.101.1(vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2)) - '@fuel-ts/program': 0.101.1(vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2)) - '@fuel-ts/transactions': 0.101.1(vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2)) - '@fuel-ts/utils': 0.101.1(vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2)) - '@fuels/vm-asm': 0.60.2 - ramda: 0.30.1 - transitivePeerDependencies: - - encoding - - vitest - - '@fuel-ts/crypto@0.101.1(vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2))': - dependencies: - '@fuel-ts/errors': 0.101.1 - '@fuel-ts/utils': 0.101.1(vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2)) - '@noble/hashes': 1.7.1 - transitivePeerDependencies: - - vitest - - '@fuel-ts/errors@0.101.1': - dependencies: - '@fuel-ts/versions': 0.101.1 - - '@fuel-ts/hasher@0.101.1(vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2))': - dependencies: - '@fuel-ts/crypto': 0.101.1(vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2)) - '@fuel-ts/utils': 0.101.1(vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2)) - '@noble/hashes': 1.7.1 - transitivePeerDependencies: - - vitest - - '@fuel-ts/math@0.101.1': - dependencies: - '@fuel-ts/errors': 0.101.1 - '@types/bn.js': 5.1.6 - bn.js: 5.2.1 - - '@fuel-ts/merkle@0.101.1(vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2))': - dependencies: - '@fuel-ts/hasher': 0.101.1(vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2)) - '@fuel-ts/math': 0.101.1 - transitivePeerDependencies: - - vitest - - '@fuel-ts/program@0.101.1(vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2))': - dependencies: - '@fuel-ts/abi-coder': 0.101.1(vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2)) - '@fuel-ts/account': 0.101.1(vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2)) - '@fuel-ts/address': 0.101.1(vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2)) - '@fuel-ts/errors': 0.101.1 - '@fuel-ts/math': 0.101.1 - '@fuel-ts/transactions': 0.101.1(vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2)) - '@fuel-ts/utils': 0.101.1(vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2)) - '@fuels/vm-asm': 0.60.2 - ramda: 0.30.1 - transitivePeerDependencies: - - encoding - - vitest - - '@fuel-ts/recipes@0.101.1(vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2))': - dependencies: - '@fuel-ts/abi-coder': 0.101.1(vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2)) - '@fuel-ts/abi-typegen': 0.101.1(vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2)) - '@fuel-ts/account': 0.101.1(vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2)) - '@fuel-ts/address': 0.101.1(vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2)) - '@fuel-ts/contract': 0.101.1(vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2)) - '@fuel-ts/program': 0.101.1(vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2)) - '@fuel-ts/transactions': 0.101.1(vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2)) - '@fuel-ts/utils': 0.101.1(vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2)) - transitivePeerDependencies: - - encoding - - vitest - - '@fuel-ts/script@0.101.1(vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2))': - dependencies: - '@fuel-ts/abi-coder': 0.101.1(vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2)) - '@fuel-ts/account': 0.101.1(vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2)) - '@fuel-ts/errors': 0.101.1 - '@fuel-ts/math': 0.101.1 - '@fuel-ts/program': 0.101.1(vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2)) - '@fuel-ts/transactions': 0.101.1(vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2)) - '@fuel-ts/utils': 0.101.1(vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2)) - transitivePeerDependencies: - - encoding - - vitest - - '@fuel-ts/transactions@0.101.1(vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2))': - dependencies: - '@fuel-ts/abi-coder': 0.101.1(vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2)) - '@fuel-ts/address': 0.101.1(vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2)) - '@fuel-ts/errors': 0.101.1 - '@fuel-ts/hasher': 0.101.1(vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2)) - '@fuel-ts/math': 0.101.1 - '@fuel-ts/utils': 0.101.1(vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2)) - transitivePeerDependencies: - - vitest - - '@fuel-ts/utils@0.101.1(vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2))': - dependencies: - '@fuel-ts/errors': 0.101.1 - '@fuel-ts/math': 0.101.1 - '@fuel-ts/versions': 0.101.1 - fflate: 0.8.2 - vitest: 3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2) - - '@fuel-ts/versions@0.101.1': - dependencies: - chalk: 4.1.2 - cli-table: 0.3.11 - - '@fuels/vm-asm@0.60.2': {} - - '@graphql-typed-document-node/core@3.2.0(graphql@16.10.0)': - dependencies: - graphql: 16.10.0 - - '@improbable-eng/grpc-web@0.15.0(google-protobuf@3.21.4)': - dependencies: - browser-headers: 0.4.1 - google-protobuf: 3.21.4 - - '@isaacs/cliui@8.0.2': - dependencies: - string-width: 5.1.2 - string-width-cjs: string-width@4.2.3 - strip-ansi: 7.1.2 - strip-ansi-cjs: strip-ansi@6.0.1 - wrap-ansi: 8.1.0 - wrap-ansi-cjs: wrap-ansi@7.0.0 - - '@isaacs/fs-minipass@4.0.1': - dependencies: - minipass: 7.1.2 - - '@jridgewell/gen-mapping@0.3.13': - dependencies: - '@jridgewell/sourcemap-codec': 1.5.5 - '@jridgewell/trace-mapping': 0.3.31 - - '@jridgewell/resolve-uri@3.1.2': {} - - '@jridgewell/sourcemap-codec@1.5.5': {} - - '@jridgewell/trace-mapping@0.3.31': - dependencies: - '@jridgewell/resolve-uri': 3.1.2 - '@jridgewell/sourcemap-codec': 1.5.5 - - '@lottiefiles/dotlottie-react@0.14.2(react@19.2.0)': - dependencies: - '@lottiefiles/dotlottie-web': 0.47.0 - react: 19.2.0 - - '@lottiefiles/dotlottie-web@0.47.0': {} - - '@metamask/safe-event-emitter@3.1.2': {} - - '@msgpackr-extract/msgpackr-extract-darwin-arm64@3.0.3': - optional: true - - '@msgpackr-extract/msgpackr-extract-darwin-x64@3.0.3': - optional: true - - '@msgpackr-extract/msgpackr-extract-linux-arm64@3.0.3': - optional: true - - '@msgpackr-extract/msgpackr-extract-linux-arm@3.0.3': - optional: true - - '@msgpackr-extract/msgpackr-extract-linux-x64@3.0.3': - optional: true - - '@msgpackr-extract/msgpackr-extract-win32-x64@3.0.3': - optional: true - - '@noble/ciphers@1.3.0': {} - - '@noble/curves@1.2.0': - dependencies: - '@noble/hashes': 1.3.2 - - '@noble/curves@1.4.2': - dependencies: - '@noble/hashes': 1.4.0 - - '@noble/curves@1.8.1': - dependencies: - '@noble/hashes': 1.7.1 - - '@noble/curves@1.9.1': - dependencies: - '@noble/hashes': 1.8.0 - - '@noble/curves@1.9.7': - dependencies: - '@noble/hashes': 1.8.0 - - '@noble/hashes@1.3.2': {} - - '@noble/hashes@1.4.0': {} - - '@noble/hashes@1.7.1': {} - - '@noble/hashes@1.8.0': {} - - '@pkgjs/parseargs@0.11.0': - optional: true - - '@rollup/plugin-alias@5.1.1(rollup@4.52.4)': - optionalDependencies: - rollup: 4.52.4 - - '@rollup/plugin-commonjs@25.0.8(rollup@4.52.4)': - dependencies: - '@rollup/pluginutils': 5.3.0(rollup@4.52.4) - commondir: 1.0.1 - estree-walker: 2.0.2 - glob: 8.1.0 - is-reference: 1.2.1 - magic-string: 0.30.19 - optionalDependencies: - rollup: 4.52.4 - - '@rollup/plugin-json@6.1.0(rollup@4.52.4)': - dependencies: - '@rollup/pluginutils': 5.3.0(rollup@4.52.4) - optionalDependencies: - rollup: 4.52.4 - - '@rollup/plugin-node-resolve@15.3.1(rollup@4.52.4)': - dependencies: - '@rollup/pluginutils': 5.3.0(rollup@4.52.4) - '@types/resolve': 1.20.2 - deepmerge: 4.3.1 - is-module: 1.0.0 - resolve: 1.22.10 - optionalDependencies: - rollup: 4.52.4 - - '@rollup/plugin-typescript@11.1.6(rollup@4.52.4)(tslib@2.8.1)(typescript@5.9.3)': - dependencies: - '@rollup/pluginutils': 5.3.0(rollup@4.52.4) - resolve: 1.22.10 - typescript: 5.9.3 - optionalDependencies: - rollup: 4.52.4 - tslib: 2.8.1 - - '@rollup/pluginutils@4.2.1': - dependencies: - estree-walker: 2.0.2 - picomatch: 2.3.1 - - '@rollup/pluginutils@5.3.0(rollup@4.52.4)': - dependencies: - '@types/estree': 1.0.8 - estree-walker: 2.0.2 - picomatch: 4.0.3 - optionalDependencies: - rollup: 4.52.4 - - '@rollup/rollup-android-arm-eabi@4.52.4': - optional: true - - '@rollup/rollup-android-arm64@4.52.4': - optional: true - - '@rollup/rollup-darwin-arm64@4.52.4': - optional: true - - '@rollup/rollup-darwin-x64@4.52.4': - optional: true - - '@rollup/rollup-freebsd-arm64@4.52.4': - optional: true - - '@rollup/rollup-freebsd-x64@4.52.4': - optional: true - - '@rollup/rollup-linux-arm-gnueabihf@4.52.4': - optional: true - - '@rollup/rollup-linux-arm-musleabihf@4.52.4': - optional: true - - '@rollup/rollup-linux-arm64-gnu@4.52.4': - optional: true - - '@rollup/rollup-linux-arm64-musl@4.52.4': - optional: true - - '@rollup/rollup-linux-loong64-gnu@4.52.4': - optional: true - - '@rollup/rollup-linux-ppc64-gnu@4.52.4': - optional: true - - '@rollup/rollup-linux-riscv64-gnu@4.52.4': - optional: true - - '@rollup/rollup-linux-riscv64-musl@4.52.4': - optional: true - - '@rollup/rollup-linux-s390x-gnu@4.52.4': - optional: true - - '@rollup/rollup-linux-x64-gnu@4.52.4': - optional: true - - '@rollup/rollup-linux-x64-musl@4.52.4': - optional: true - - '@rollup/rollup-openharmony-arm64@4.52.4': - optional: true - - '@rollup/rollup-win32-arm64-msvc@4.52.4': - optional: true - - '@rollup/rollup-win32-ia32-msvc@4.52.4': - optional: true - - '@rollup/rollup-win32-x64-gnu@4.52.4': - optional: true - - '@rollup/rollup-win32-x64-msvc@4.52.4': - optional: true - - '@scure/base@1.1.9': {} - - '@scure/base@1.2.6': {} - - '@scure/bip32@1.4.0': - dependencies: - '@noble/curves': 1.4.2 - '@noble/hashes': 1.4.0 - '@scure/base': 1.1.9 - - '@scure/bip32@1.7.0': - dependencies: - '@noble/curves': 1.9.7 - '@noble/hashes': 1.8.0 - '@scure/base': 1.2.6 - - '@scure/bip39@1.3.0': - dependencies: - '@noble/hashes': 1.4.0 - '@scure/base': 1.1.9 - - '@scure/bip39@1.6.0': - dependencies: - '@noble/hashes': 1.8.0 - '@scure/base': 1.2.6 - - '@starkware-industries/starkware-crypto-utils@0.2.1': - dependencies: - assert: 2.1.0 - bip39: 3.1.0 - bn.js: 4.12.2 - brorand: 1.1.0 - buffer: 6.0.3 - crypto-browserify: 3.12.1 - elliptic: 6.6.1 - enc-utils: 3.0.0 - ethereumjs-wallet: 1.0.2 - hash.js: 1.1.7 - hmac-drbg: 1.0.1 - inherits: 2.0.4 - js-sha3: 0.8.0 - minimalistic-assert: 1.0.1 - minimalistic-crypto-utils: 1.0.1 - stream-browserify: 3.0.0 - - '@tailwindcss/node@4.1.10': - dependencies: - '@ampproject/remapping': 2.3.0 - enhanced-resolve: 5.18.3 - jiti: 2.6.1 - lightningcss: 1.30.1 - magic-string: 0.30.19 - source-map-js: 1.2.1 - tailwindcss: 4.1.10 - - '@tailwindcss/oxide-android-arm64@4.1.10': - optional: true - - '@tailwindcss/oxide-darwin-arm64@4.1.10': - optional: true - - '@tailwindcss/oxide-darwin-x64@4.1.10': - optional: true - - '@tailwindcss/oxide-freebsd-x64@4.1.10': - optional: true - - '@tailwindcss/oxide-linux-arm-gnueabihf@4.1.10': - optional: true - - '@tailwindcss/oxide-linux-arm64-gnu@4.1.10': - optional: true - - '@tailwindcss/oxide-linux-arm64-musl@4.1.10': - optional: true - - '@tailwindcss/oxide-linux-x64-gnu@4.1.10': - optional: true - - '@tailwindcss/oxide-linux-x64-musl@4.1.10': - optional: true - - '@tailwindcss/oxide-wasm32-wasi@4.1.10': - optional: true - - '@tailwindcss/oxide-win32-arm64-msvc@4.1.10': - optional: true - - '@tailwindcss/oxide-win32-x64-msvc@4.1.10': - optional: true - - '@tailwindcss/oxide@4.1.10': - dependencies: - detect-libc: 2.1.2 - tar: 7.5.1 - optionalDependencies: - '@tailwindcss/oxide-android-arm64': 4.1.10 - '@tailwindcss/oxide-darwin-arm64': 4.1.10 - '@tailwindcss/oxide-darwin-x64': 4.1.10 - '@tailwindcss/oxide-freebsd-x64': 4.1.10 - '@tailwindcss/oxide-linux-arm-gnueabihf': 4.1.10 - '@tailwindcss/oxide-linux-arm64-gnu': 4.1.10 - '@tailwindcss/oxide-linux-arm64-musl': 4.1.10 - '@tailwindcss/oxide-linux-x64-gnu': 4.1.10 - '@tailwindcss/oxide-linux-x64-musl': 4.1.10 - '@tailwindcss/oxide-wasm32-wasi': 4.1.10 - '@tailwindcss/oxide-win32-arm64-msvc': 4.1.10 - '@tailwindcss/oxide-win32-x64-msvc': 4.1.10 - - '@tailwindcss/postcss@4.1.10': - dependencies: - '@alloc/quick-lru': 5.2.0 - '@tailwindcss/node': 4.1.10 - '@tailwindcss/oxide': 4.1.10 - postcss: 8.5.6 - tailwindcss: 4.1.10 - - '@tronweb3/tronwallet-abstract-adapter@1.1.9': - dependencies: - eventemitter3: 4.0.7 - tronweb: 6.0.4 - transitivePeerDependencies: - - bufferutil - - debug - - utf-8-validate - - '@trysound/sax@0.2.0': {} - - '@types/bn.js@5.1.6': - dependencies: - '@types/node': 24.8.1 - - '@types/bn.js@5.2.0': - dependencies: - '@types/node': 24.8.1 - - '@types/estree@1.0.8': {} - - '@types/node@20.19.22': - dependencies: - undici-types: 6.21.0 - - '@types/node@22.7.5': - dependencies: - undici-types: 6.19.8 - - '@types/node@24.8.1': - dependencies: - undici-types: 7.14.0 - - '@types/pbkdf2@3.1.2': - dependencies: - '@types/node': 24.8.1 - - '@types/react-dom@19.1.6(@types/react@19.1.8)': - dependencies: - '@types/react': 19.1.8 - - '@types/react@19.1.8': - dependencies: - csstype: 3.1.3 - - '@types/resolve@1.20.2': {} - - '@types/secp256k1@4.0.7': - dependencies: - '@types/node': 24.8.1 - - '@types/ws@8.18.1': - dependencies: - '@types/node': 24.8.1 - - '@vitest/expect@3.0.9': - dependencies: - '@vitest/spy': 3.0.9 - '@vitest/utils': 3.0.9 - chai: 5.3.3 - tinyrainbow: 2.0.0 - - '@vitest/mocker@3.0.9(vite@6.4.0(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2))': - dependencies: - '@vitest/spy': 3.0.9 - estree-walker: 3.0.3 - magic-string: 0.30.19 - optionalDependencies: - vite: 6.4.0(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2) - - '@vitest/pretty-format@3.0.9': - dependencies: - tinyrainbow: 2.0.0 - - '@vitest/pretty-format@3.2.4': - dependencies: - tinyrainbow: 2.0.0 - - '@vitest/runner@3.0.9': - dependencies: - '@vitest/utils': 3.0.9 - pathe: 2.0.3 - - '@vitest/snapshot@3.0.9': - dependencies: - '@vitest/pretty-format': 3.0.9 - magic-string: 0.30.19 - pathe: 2.0.3 - - '@vitest/spy@3.0.9': - dependencies: - tinyspy: 3.0.2 - - '@vitest/utils@3.0.9': - dependencies: - '@vitest/pretty-format': 3.0.9 - loupe: 3.2.1 - tinyrainbow: 2.0.0 - - abitype@1.1.0(typescript@5.9.3): - optionalDependencies: - typescript: 5.9.3 - - abitype@1.1.1(typescript@5.9.3): - optionalDependencies: - typescript: 5.9.3 - - aes-js@3.1.2: {} - - aes-js@4.0.0-beta.5: {} - - ansi-regex@5.0.1: {} - - ansi-regex@6.2.2: {} - - ansi-styles@4.3.0: - dependencies: - color-convert: 2.0.1 - - ansi-styles@6.2.3: {} - - anymatch@3.1.3: - dependencies: - normalize-path: 3.0.0 - picomatch: 2.3.1 - - asn1.js@4.10.1: - dependencies: - bn.js: 4.12.2 - inherits: 2.0.4 - minimalistic-assert: 1.0.1 - - assert@2.1.0: - dependencies: - call-bind: 1.0.8 - is-nan: 1.3.2 - object-is: 1.1.6 - object.assign: 4.1.7 - util: 0.12.5 - - assertion-error@2.0.1: {} - - async@2.6.4: - dependencies: - lodash: 4.17.21 - - asynckit@0.4.0: {} - - autoprefixer@10.4.21(postcss@8.5.6): - dependencies: - browserslist: 4.26.3 - caniuse-lite: 1.0.30001751 - fraction.js: 4.3.7 - normalize-range: 0.1.2 - picocolors: 1.1.1 - postcss: 8.5.6 - postcss-value-parser: 4.2.0 - - available-typed-arrays@1.0.7: - dependencies: - possible-typed-array-names: 1.1.0 - - axios@1.11.0: - dependencies: - follow-redirects: 1.15.11 - form-data: 4.0.4 - proxy-from-env: 1.1.0 - transitivePeerDependencies: - - debug - - axios@1.12.2: - dependencies: - follow-redirects: 1.15.11 - form-data: 4.0.4 - proxy-from-env: 1.1.0 - transitivePeerDependencies: - - debug - - balanced-match@1.0.2: {} - - base-x@3.0.11: - dependencies: - safe-buffer: 5.2.1 - - base64-js@1.5.1: {} - - baseline-browser-mapping@2.8.17: {} - - bech32@1.1.4: {} - - bignumber.js@9.1.2: {} - - binary-extensions@2.3.0: {} - - bip39@3.1.0: - dependencies: - '@noble/hashes': 1.8.0 - - blakejs@1.2.1: {} - - bn.js@4.12.2: {} - - bn.js@5.2.1: {} - - bn.js@5.2.2: {} - - boolbase@1.0.0: {} - - brace-expansion@2.0.2: - dependencies: - balanced-match: 1.0.2 - - braces@3.0.3: - dependencies: - fill-range: 7.1.1 - - brorand@1.1.0: {} - - browser-headers@0.4.1: {} - - browserify-aes@1.2.0: - dependencies: - buffer-xor: 1.0.3 - cipher-base: 1.0.7 - create-hash: 1.2.0 - evp_bytestokey: 1.0.3 - inherits: 2.0.4 - safe-buffer: 5.2.1 - - browserify-cipher@1.0.1: - dependencies: - browserify-aes: 1.2.0 - browserify-des: 1.0.2 - evp_bytestokey: 1.0.3 - - browserify-des@1.0.2: - dependencies: - cipher-base: 1.0.7 - des.js: 1.1.0 - inherits: 2.0.4 - safe-buffer: 5.2.1 - - browserify-rsa@4.1.1: - dependencies: - bn.js: 5.2.2 - randombytes: 2.1.0 - safe-buffer: 5.2.1 - - browserify-sign@4.2.5: - dependencies: - bn.js: 5.2.2 - browserify-rsa: 4.1.1 - create-hash: 1.2.0 - create-hmac: 1.1.7 - elliptic: 6.6.1 - inherits: 2.0.4 - parse-asn1: 5.1.9 - readable-stream: 2.3.8 - safe-buffer: 5.2.1 - - browserslist@4.26.3: - dependencies: - baseline-browser-mapping: 2.8.17 - caniuse-lite: 1.0.30001751 - electron-to-chromium: 1.5.237 - node-releases: 2.0.25 - update-browserslist-db: 1.1.3(browserslist@4.26.3) - - bs58@4.0.1: - dependencies: - base-x: 3.0.11 - - bs58check@2.1.2: - dependencies: - bs58: 4.0.1 - create-hash: 1.2.0 - safe-buffer: 5.2.1 - - buffer-xor@1.0.3: {} - - buffer@6.0.3: - dependencies: - base64-js: 1.5.1 - ieee754: 1.2.1 - - bundle-require@5.1.0(esbuild@0.25.1): - dependencies: - esbuild: 0.25.1 - load-tsconfig: 0.2.5 - - cac@6.7.14: {} - - call-bind-apply-helpers@1.0.2: - dependencies: - es-errors: 1.3.0 - function-bind: 1.1.2 - - call-bind@1.0.8: - dependencies: - call-bind-apply-helpers: 1.0.2 - es-define-property: 1.0.1 - get-intrinsic: 1.3.0 - set-function-length: 1.2.2 - - call-bound@1.0.4: - dependencies: - call-bind-apply-helpers: 1.0.2 - get-intrinsic: 1.3.0 - - caniuse-api@3.0.0: - dependencies: - browserslist: 4.26.3 - caniuse-lite: 1.0.30001751 - lodash.memoize: 4.1.2 - lodash.uniq: 4.5.0 - - caniuse-lite@1.0.30001751: {} - - chai@5.3.3: - dependencies: - assertion-error: 2.0.1 - check-error: 2.1.1 - deep-eql: 5.0.2 - loupe: 3.2.1 - pathval: 2.0.1 - - chalk@4.1.2: - dependencies: - ansi-styles: 4.3.0 - supports-color: 7.2.0 - - check-error@2.1.1: {} - - chokidar@3.6.0: - dependencies: - anymatch: 3.1.3 - braces: 3.0.3 - glob-parent: 5.1.2 - is-binary-path: 2.1.0 - is-glob: 4.0.3 - normalize-path: 3.0.0 - readdirp: 3.6.0 - optionalDependencies: - fsevents: 2.3.3 - - chownr@3.0.0: {} - - cipher-base@1.0.7: - dependencies: - inherits: 2.0.4 - safe-buffer: 5.2.1 - to-buffer: 1.2.2 - - class-variance-authority@0.7.1: - dependencies: - clsx: 2.1.1 - - cli-table@0.3.11: - dependencies: - colors: 1.0.3 - - clsx@2.1.1: {} - - color-convert@2.0.1: - dependencies: - color-name: 1.1.4 - - color-name@1.1.4: {} - - colord@2.9.3: {} - - colors@1.0.3: {} - - combined-stream@1.0.8: - dependencies: - delayed-stream: 1.0.0 - - commander@13.1.0: {} - - commander@7.2.0: {} - - commondir@1.0.1: {} - - concat-with-sourcemaps@1.1.0: - dependencies: - source-map: 0.6.1 - - core-util-is@1.0.3: {} - - cosmjs-types@0.9.0: {} - - create-ecdh@4.0.4: - dependencies: - bn.js: 4.12.2 - elliptic: 6.6.1 - - create-hash@1.2.0: - dependencies: - cipher-base: 1.0.7 - inherits: 2.0.4 - md5.js: 1.3.5 - ripemd160: 2.0.3 - sha.js: 2.4.12 - - create-hmac@1.1.7: - dependencies: - cipher-base: 1.0.7 - create-hash: 1.2.0 - inherits: 2.0.4 - ripemd160: 2.0.3 - safe-buffer: 5.2.1 - sha.js: 2.4.12 - - cross-fetch@3.2.0: - dependencies: - node-fetch: 2.7.0 - transitivePeerDependencies: - - encoding - - cross-fetch@4.1.0: - dependencies: - node-fetch: 2.7.0 - transitivePeerDependencies: - - encoding - - cross-spawn@7.0.6: - dependencies: - path-key: 3.1.1 - shebang-command: 2.0.0 - which: 2.0.2 - - crypto-browserify@3.12.1: - dependencies: - browserify-cipher: 1.0.1 - browserify-sign: 4.2.5 - create-ecdh: 4.0.4 - create-hash: 1.2.0 - create-hmac: 1.1.7 - diffie-hellman: 5.0.3 - hash-base: 3.0.5 - inherits: 2.0.4 - pbkdf2: 3.1.5 - public-encrypt: 4.0.3 - randombytes: 2.1.0 - randomfill: 1.0.4 - - css-declaration-sorter@6.4.1(postcss@8.5.6): - dependencies: - postcss: 8.5.6 - - css-select@4.3.0: - dependencies: - boolbase: 1.0.0 - css-what: 6.2.2 - domhandler: 4.3.1 - domutils: 2.8.0 - nth-check: 2.1.1 - - css-tree@1.1.3: - dependencies: - mdn-data: 2.0.14 - source-map: 0.6.1 - - css-what@6.2.2: {} - - cssesc@3.0.0: {} - - cssnano-preset-default@5.2.14(postcss@8.5.6): - dependencies: - css-declaration-sorter: 6.4.1(postcss@8.5.6) - cssnano-utils: 3.1.0(postcss@8.5.6) - postcss: 8.5.6 - postcss-calc: 8.2.4(postcss@8.5.6) - postcss-colormin: 5.3.1(postcss@8.5.6) - postcss-convert-values: 5.1.3(postcss@8.5.6) - postcss-discard-comments: 5.1.2(postcss@8.5.6) - postcss-discard-duplicates: 5.1.0(postcss@8.5.6) - postcss-discard-empty: 5.1.1(postcss@8.5.6) - postcss-discard-overridden: 5.1.0(postcss@8.5.6) - postcss-merge-longhand: 5.1.7(postcss@8.5.6) - postcss-merge-rules: 5.1.4(postcss@8.5.6) - postcss-minify-font-values: 5.1.0(postcss@8.5.6) - postcss-minify-gradients: 5.1.1(postcss@8.5.6) - postcss-minify-params: 5.1.4(postcss@8.5.6) - postcss-minify-selectors: 5.2.1(postcss@8.5.6) - postcss-normalize-charset: 5.1.0(postcss@8.5.6) - postcss-normalize-display-values: 5.1.0(postcss@8.5.6) - postcss-normalize-positions: 5.1.1(postcss@8.5.6) - postcss-normalize-repeat-style: 5.1.1(postcss@8.5.6) - postcss-normalize-string: 5.1.0(postcss@8.5.6) - postcss-normalize-timing-functions: 5.1.0(postcss@8.5.6) - postcss-normalize-unicode: 5.1.1(postcss@8.5.6) - postcss-normalize-url: 5.1.0(postcss@8.5.6) - postcss-normalize-whitespace: 5.1.1(postcss@8.5.6) - postcss-ordered-values: 5.1.3(postcss@8.5.6) - postcss-reduce-initial: 5.1.2(postcss@8.5.6) - postcss-reduce-transforms: 5.1.0(postcss@8.5.6) - postcss-svgo: 5.1.0(postcss@8.5.6) - postcss-unique-selectors: 5.1.1(postcss@8.5.6) - - cssnano-utils@3.1.0(postcss@8.5.6): - dependencies: - postcss: 8.5.6 - - cssnano@5.1.15(postcss@8.5.6): - dependencies: - cssnano-preset-default: 5.2.14(postcss@8.5.6) - lilconfig: 2.1.0 - postcss: 8.5.6 - yaml: 1.10.2 - - csso@4.2.0: - dependencies: - css-tree: 1.1.3 - - csstype@3.1.3: {} - - debug@3.2.7: - dependencies: - ms: 2.1.3 - - debug@4.4.3: - dependencies: - ms: 2.1.3 - - decimal.js@10.6.0: {} - - deep-eql@5.0.2: {} - - deepmerge@4.3.1: {} - - define-data-property@1.1.4: - dependencies: - es-define-property: 1.0.1 - es-errors: 1.3.0 - gopd: 1.2.0 - - define-properties@1.2.1: - dependencies: - define-data-property: 1.1.4 - has-property-descriptors: 1.0.2 - object-keys: 1.1.1 - - delayed-stream@1.0.0: {} - - des.js@1.1.0: - dependencies: - inherits: 2.0.4 - minimalistic-assert: 1.0.1 - - detect-libc@2.1.2: {} - - diffie-hellman@5.0.3: - dependencies: - bn.js: 4.12.2 - miller-rabin: 4.0.1 - randombytes: 2.1.0 - - dom-serializer@1.4.1: - dependencies: - domelementtype: 2.3.0 - domhandler: 4.3.1 - entities: 2.2.0 - - domelementtype@2.3.0: {} - - domhandler@4.3.1: - dependencies: - domelementtype: 2.3.0 - - domutils@2.8.0: - dependencies: - dom-serializer: 1.4.1 - domelementtype: 2.3.0 - domhandler: 4.3.1 - - dunder-proto@1.0.1: - dependencies: - call-bind-apply-helpers: 1.0.2 - es-errors: 1.3.0 - gopd: 1.2.0 - - eastasianwidth@0.2.0: {} - - electron-to-chromium@1.5.237: {} - - elliptic@6.6.1: - dependencies: - bn.js: 4.12.2 - brorand: 1.1.0 - hash.js: 1.1.7 - hmac-drbg: 1.0.1 - inherits: 2.0.4 - minimalistic-assert: 1.0.1 - minimalistic-crypto-utils: 1.0.1 - - emoji-regex@8.0.0: {} - - emoji-regex@9.2.2: {} - - enc-utils@3.0.0: - dependencies: - is-typedarray: 1.0.0 - typedarray-to-buffer: 3.1.5 - - enhanced-resolve@5.18.3: - dependencies: - graceful-fs: 4.2.11 - tapable: 2.3.0 - - entities@2.2.0: {} - - es-define-property@1.0.1: {} - - es-errors@1.3.0: {} - - es-module-lexer@1.7.0: {} - - es-object-atoms@1.1.1: - dependencies: - es-errors: 1.3.0 - - es-set-tostringtag@2.1.0: - dependencies: - es-errors: 1.3.0 - get-intrinsic: 1.3.0 - has-tostringtag: 1.0.2 - hasown: 2.0.2 - - es-toolkit@1.40.0: {} - - esbuild@0.25.1: - optionalDependencies: - '@esbuild/aix-ppc64': 0.25.1 - '@esbuild/android-arm': 0.25.1 - '@esbuild/android-arm64': 0.25.1 - '@esbuild/android-x64': 0.25.1 - '@esbuild/darwin-arm64': 0.25.1 - '@esbuild/darwin-x64': 0.25.1 - '@esbuild/freebsd-arm64': 0.25.1 - '@esbuild/freebsd-x64': 0.25.1 - '@esbuild/linux-arm': 0.25.1 - '@esbuild/linux-arm64': 0.25.1 - '@esbuild/linux-ia32': 0.25.1 - '@esbuild/linux-loong64': 0.25.1 - '@esbuild/linux-mips64el': 0.25.1 - '@esbuild/linux-ppc64': 0.25.1 - '@esbuild/linux-riscv64': 0.25.1 - '@esbuild/linux-s390x': 0.25.1 - '@esbuild/linux-x64': 0.25.1 - '@esbuild/netbsd-arm64': 0.25.1 - '@esbuild/netbsd-x64': 0.25.1 - '@esbuild/openbsd-arm64': 0.25.1 - '@esbuild/openbsd-x64': 0.25.1 - '@esbuild/sunos-x64': 0.25.1 - '@esbuild/win32-arm64': 0.25.1 - '@esbuild/win32-ia32': 0.25.1 - '@esbuild/win32-x64': 0.25.1 - - esbuild@0.25.11: - optionalDependencies: - '@esbuild/aix-ppc64': 0.25.11 - '@esbuild/android-arm': 0.25.11 - '@esbuild/android-arm64': 0.25.11 - '@esbuild/android-x64': 0.25.11 - '@esbuild/darwin-arm64': 0.25.11 - '@esbuild/darwin-x64': 0.25.11 - '@esbuild/freebsd-arm64': 0.25.11 - '@esbuild/freebsd-x64': 0.25.11 - '@esbuild/linux-arm': 0.25.11 - '@esbuild/linux-arm64': 0.25.11 - '@esbuild/linux-ia32': 0.25.11 - '@esbuild/linux-loong64': 0.25.11 - '@esbuild/linux-mips64el': 0.25.11 - '@esbuild/linux-ppc64': 0.25.11 - '@esbuild/linux-riscv64': 0.25.11 - '@esbuild/linux-s390x': 0.25.11 - '@esbuild/linux-x64': 0.25.11 - '@esbuild/netbsd-arm64': 0.25.11 - '@esbuild/netbsd-x64': 0.25.11 - '@esbuild/openbsd-arm64': 0.25.11 - '@esbuild/openbsd-x64': 0.25.11 - '@esbuild/openharmony-arm64': 0.25.11 - '@esbuild/sunos-x64': 0.25.11 - '@esbuild/win32-arm64': 0.25.11 - '@esbuild/win32-ia32': 0.25.11 - '@esbuild/win32-x64': 0.25.11 - - escalade@3.2.0: {} - - estree-walker@0.6.1: {} - - estree-walker@2.0.2: {} - - estree-walker@3.0.3: - dependencies: - '@types/estree': 1.0.8 - - ethereum-cryptography@0.1.3: - dependencies: - '@types/pbkdf2': 3.1.2 - '@types/secp256k1': 4.0.7 - blakejs: 1.2.1 - browserify-aes: 1.2.0 - bs58check: 2.1.2 - create-hash: 1.2.0 - create-hmac: 1.1.7 - hash.js: 1.1.7 - keccak: 3.0.4 - pbkdf2: 3.1.5 - randombytes: 2.1.0 - safe-buffer: 5.2.1 - scrypt-js: 3.0.1 - secp256k1: 4.0.4 - setimmediate: 1.0.5 - - ethereum-cryptography@2.2.1: - dependencies: - '@noble/curves': 1.4.2 - '@noble/hashes': 1.4.0 - '@scure/bip32': 1.4.0 - '@scure/bip39': 1.3.0 - - ethereumjs-util@7.1.5: - dependencies: - '@types/bn.js': 5.2.0 - bn.js: 5.2.2 - create-hash: 1.2.0 - ethereum-cryptography: 0.1.3 - rlp: 2.2.7 - - ethereumjs-wallet@1.0.2: - dependencies: - aes-js: 3.1.2 - bs58check: 2.1.2 - ethereum-cryptography: 0.1.3 - ethereumjs-util: 7.1.5 - randombytes: 2.1.0 - scrypt-js: 3.0.1 - utf8: 3.0.0 - uuid: 8.3.2 - - ethers@6.13.5: - dependencies: - '@adraffy/ens-normalize': 1.10.1 - '@noble/curves': 1.2.0 - '@noble/hashes': 1.3.2 - '@types/node': 22.7.5 - aes-js: 4.0.0-beta.5 - tslib: 2.7.0 - ws: 8.17.1 - transitivePeerDependencies: - - bufferutil - - utf-8-validate - - event-iterator@2.0.0: {} - - eventemitter3@4.0.7: {} - - eventemitter3@5.0.1: {} - - events@3.3.0: {} - - evp_bytestokey@1.0.3: - dependencies: - md5.js: 1.3.5 - safe-buffer: 5.2.1 - - expect-type@1.2.2: {} - - fdir@6.5.0(picomatch@4.0.3): - optionalDependencies: - picomatch: 4.0.3 - - fflate@0.8.2: {} - - fill-range@7.1.1: - dependencies: - to-regex-range: 5.0.1 - - find-cache-dir@3.3.2: - dependencies: - commondir: 1.0.1 - make-dir: 3.1.0 - pkg-dir: 4.2.0 - - find-up@4.1.0: - dependencies: - locate-path: 5.0.0 - path-exists: 4.0.0 - - follow-redirects@1.15.11: {} - - for-each@0.3.5: - dependencies: - is-callable: 1.2.7 - - foreground-child@3.3.1: - dependencies: - cross-spawn: 7.0.6 - signal-exit: 4.1.0 - - form-data@4.0.4: - dependencies: - asynckit: 0.4.0 - combined-stream: 1.0.8 - es-set-tostringtag: 2.1.0 - hasown: 2.0.2 - mime-types: 2.1.35 - - fraction.js@4.3.7: {} - - framer-motion@12.23.24(react-dom@19.2.0(react@19.2.0))(react@19.2.0): - dependencies: - motion-dom: 12.23.23 - motion-utils: 12.23.6 - tslib: 2.8.1 - optionalDependencies: - react: 19.2.0 - react-dom: 19.2.0(react@19.2.0) - - fs-extra@10.1.0: - dependencies: - graceful-fs: 4.2.11 - jsonfile: 6.2.0 - universalify: 2.0.1 - - fs.realpath@1.0.0: {} - - fsevents@2.3.3: - optional: true - - fuels@0.101.1(vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2)): - dependencies: - '@fuel-ts/abi-coder': 0.101.1(vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2)) - '@fuel-ts/abi-typegen': 0.101.1(vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2)) - '@fuel-ts/account': 0.101.1(vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2)) - '@fuel-ts/address': 0.101.1(vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2)) - '@fuel-ts/contract': 0.101.1(vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2)) - '@fuel-ts/crypto': 0.101.1(vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2)) - '@fuel-ts/errors': 0.101.1 - '@fuel-ts/hasher': 0.101.1(vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2)) - '@fuel-ts/math': 0.101.1 - '@fuel-ts/program': 0.101.1(vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2)) - '@fuel-ts/recipes': 0.101.1(vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2)) - '@fuel-ts/script': 0.101.1(vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2)) - '@fuel-ts/transactions': 0.101.1(vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2)) - '@fuel-ts/utils': 0.101.1(vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2)) - '@fuel-ts/versions': 0.101.1 - '@fuels/vm-asm': 0.60.2 - bundle-require: 5.1.0(esbuild@0.25.1) - chalk: 4.1.2 - chokidar: 3.6.0 - commander: 13.1.0 - esbuild: 0.25.1 - glob: 10.4.5 - handlebars: 4.7.8 - joycon: 3.1.1 - lodash.camelcase: 4.3.0 - portfinder: 1.0.32 - toml: 3.0.0 - uglify-js: 3.19.3 - yup: 1.6.1 - transitivePeerDependencies: - - encoding - - supports-color - - vitest - - function-bind@1.1.2: {} - - generator-function@2.0.1: {} - - generic-names@4.0.0: - dependencies: - loader-utils: 3.3.1 - - get-intrinsic@1.3.0: - dependencies: - call-bind-apply-helpers: 1.0.2 - es-define-property: 1.0.1 - es-errors: 1.3.0 - es-object-atoms: 1.1.1 - function-bind: 1.1.2 - get-proto: 1.0.1 - gopd: 1.2.0 - has-symbols: 1.1.0 - hasown: 2.0.2 - math-intrinsics: 1.1.0 - - get-proto@1.0.1: - dependencies: - dunder-proto: 1.0.1 - es-object-atoms: 1.1.1 - - glob-parent@5.1.2: - dependencies: - is-glob: 4.0.3 - - glob@10.4.5: - dependencies: - foreground-child: 3.3.1 - jackspeak: 3.4.3 - minimatch: 9.0.5 - minipass: 7.1.2 - package-json-from-dist: 1.0.1 - path-scurry: 1.11.1 - - glob@8.1.0: - dependencies: - fs.realpath: 1.0.0 - inflight: 1.0.6 - inherits: 2.0.4 - minimatch: 5.1.6 - once: 1.4.0 - - globalthis@1.0.4: - dependencies: - define-properties: 1.2.1 - gopd: 1.2.0 - - google-protobuf@3.21.4: {} - - gopd@1.2.0: {} - - graceful-fs@4.2.11: {} - - graphql-request@6.1.0(graphql@16.10.0): - dependencies: - '@graphql-typed-document-node/core': 3.2.0(graphql@16.10.0) - cross-fetch: 3.2.0 - graphql: 16.10.0 - transitivePeerDependencies: - - encoding - - graphql-tag@2.12.6(graphql@16.10.0): - dependencies: - graphql: 16.10.0 - tslib: 2.8.1 - - graphql@16.10.0: {} - - handlebars@4.7.8: - dependencies: - minimist: 1.2.8 - neo-async: 2.6.2 - source-map: 0.6.1 - wordwrap: 1.0.0 - optionalDependencies: - uglify-js: 3.19.3 - - has-flag@4.0.0: {} - - has-property-descriptors@1.0.2: - dependencies: - es-define-property: 1.0.1 - - has-symbols@1.1.0: {} - - has-tostringtag@1.0.2: - dependencies: - has-symbols: 1.1.0 - - hash-base@3.0.5: - dependencies: - inherits: 2.0.4 - safe-buffer: 5.2.1 - - hash-base@3.1.2: - dependencies: - inherits: 2.0.4 - readable-stream: 2.3.8 - safe-buffer: 5.2.1 - to-buffer: 1.2.2 - - hash.js@1.1.7: - dependencies: - inherits: 2.0.4 - minimalistic-assert: 1.0.1 - - hasown@2.0.2: - dependencies: - function-bind: 1.1.2 - - hmac-drbg@1.0.1: - dependencies: - hash.js: 1.1.7 - minimalistic-assert: 1.0.1 - minimalistic-crypto-utils: 1.0.1 - - husky@8.0.3: {} - - icss-replace-symbols@1.1.0: {} - - icss-utils@5.1.0(postcss@8.5.6): - dependencies: - postcss: 8.5.6 - - ieee754@1.2.1: {} - - import-cwd@3.0.0: - dependencies: - import-from: 3.0.0 - - import-from@3.0.0: - dependencies: - resolve-from: 5.0.0 - - inflight@1.0.6: - dependencies: - once: 1.4.0 - wrappy: 1.0.2 - - inherits@2.0.4: {} - - is-arguments@1.2.0: - dependencies: - call-bound: 1.0.4 - has-tostringtag: 1.0.2 - - is-binary-path@2.1.0: - dependencies: - binary-extensions: 2.3.0 - - is-callable@1.2.7: {} - - is-core-module@2.16.1: - dependencies: - hasown: 2.0.2 - - is-extglob@2.1.1: {} - - is-fullwidth-code-point@3.0.0: {} - - is-generator-function@1.1.2: - dependencies: - call-bound: 1.0.4 - generator-function: 2.0.1 - get-proto: 1.0.1 - has-tostringtag: 1.0.2 - safe-regex-test: 1.1.0 - - is-glob@4.0.3: - dependencies: - is-extglob: 2.1.1 - - is-module@1.0.0: {} - - is-nan@1.3.2: - dependencies: - call-bind: 1.0.8 - define-properties: 1.2.1 - - is-number@7.0.0: {} - - is-reference@1.2.1: - dependencies: - '@types/estree': 1.0.8 - - is-regex@1.2.1: - dependencies: - call-bound: 1.0.4 - gopd: 1.2.0 - has-tostringtag: 1.0.2 - hasown: 2.0.2 - - is-typed-array@1.1.15: - dependencies: - which-typed-array: 1.1.19 - - is-typedarray@1.0.0: {} - - isarray@1.0.0: {} - - isarray@2.0.5: {} - - isexe@2.0.0: {} - - isomorphic-ws@4.0.1(ws@7.5.10): - dependencies: - ws: 7.5.10 - - isows@1.0.7(ws@8.18.3): - dependencies: - ws: 8.18.3 - - it-stream-types@2.0.2: {} - - it-ws@6.1.5: - dependencies: - '@types/ws': 8.18.1 - event-iterator: 2.0.0 - it-stream-types: 2.0.2 - uint8arrays: 5.1.0 - ws: 8.18.3 - transitivePeerDependencies: - - bufferutil - - utf-8-validate - - jackspeak@3.4.3: - dependencies: - '@isaacs/cliui': 8.0.2 - optionalDependencies: - '@pkgjs/parseargs': 0.11.0 - - jiti@2.6.1: {} - - joycon@3.1.1: {} - - js-sha3@0.8.0: {} - - js-tokens@4.0.0: - optional: true - - jsonfile@6.2.0: - dependencies: - universalify: 2.0.1 - optionalDependencies: - graceful-fs: 4.2.11 - - keccak@3.0.4: - dependencies: - node-addon-api: 2.0.2 - node-gyp-build: 4.8.4 - readable-stream: 3.6.2 - - libsodium-sumo@0.7.15: {} - - libsodium-wrappers-sumo@0.7.15: - dependencies: - libsodium-sumo: 0.7.15 - - lightningcss-darwin-arm64@1.30.1: - optional: true - - lightningcss-darwin-x64@1.30.1: - optional: true - - lightningcss-freebsd-x64@1.30.1: - optional: true - - lightningcss-linux-arm-gnueabihf@1.30.1: - optional: true - - lightningcss-linux-arm64-gnu@1.30.1: - optional: true - - lightningcss-linux-arm64-musl@1.30.1: - optional: true - - lightningcss-linux-x64-gnu@1.30.1: - optional: true - - lightningcss-linux-x64-musl@1.30.1: - optional: true - - lightningcss-win32-arm64-msvc@1.30.1: - optional: true - - lightningcss-win32-x64-msvc@1.30.1: - optional: true - - lightningcss@1.30.1: - dependencies: - detect-libc: 2.1.2 - optionalDependencies: - lightningcss-darwin-arm64: 1.30.1 - lightningcss-darwin-x64: 1.30.1 - lightningcss-freebsd-x64: 1.30.1 - lightningcss-linux-arm-gnueabihf: 1.30.1 - lightningcss-linux-arm64-gnu: 1.30.1 - lightningcss-linux-arm64-musl: 1.30.1 - lightningcss-linux-x64-gnu: 1.30.1 - lightningcss-linux-x64-musl: 1.30.1 - lightningcss-win32-arm64-msvc: 1.30.1 - lightningcss-win32-x64-msvc: 1.30.1 - - lilconfig@2.1.0: {} - - load-tsconfig@0.2.5: {} - - loader-utils@3.3.1: {} - - locate-path@5.0.0: - dependencies: - p-locate: 4.1.0 - - lodash.camelcase@4.3.0: {} - - lodash.memoize@4.1.2: {} - - lodash.uniq@4.5.0: {} - - lodash@4.17.21: {} - - long@5.3.2: {} - - loupe@3.2.1: {} - - lru-cache@10.4.3: {} - - magic-string@0.30.19: - dependencies: - '@jridgewell/sourcemap-codec': 1.5.5 - - make-dir@3.1.0: - dependencies: - semver: 6.3.1 - - math-intrinsics@1.1.0: {} - - md5.js@1.3.5: - dependencies: - hash-base: 3.0.5 - inherits: 2.0.4 - safe-buffer: 5.2.1 - - mdn-data@2.0.14: {} - - miller-rabin@4.0.1: - dependencies: - bn.js: 4.12.2 - brorand: 1.1.0 - - mime-db@1.52.0: {} - - mime-types@2.1.35: - dependencies: - mime-db: 1.52.0 - - minimalistic-assert@1.0.1: {} - - minimalistic-crypto-utils@1.0.1: {} - - minimatch@5.1.6: - dependencies: - brace-expansion: 2.0.2 - - minimatch@9.0.5: - dependencies: - brace-expansion: 2.0.2 - - minimist@1.2.8: {} - - minipass@7.1.2: {} - - minizlib@3.1.0: - dependencies: - minipass: 7.1.2 - - mkdirp@0.5.6: - dependencies: - minimist: 1.2.8 - - mkdirp@3.0.1: {} - - motion-dom@12.23.23: - dependencies: - motion-utils: 12.23.6 - - motion-utils@12.23.6: {} - - motion@12.23.0(react-dom@19.2.0(react@19.2.0))(react@19.2.0): - dependencies: - framer-motion: 12.23.24(react-dom@19.2.0(react@19.2.0))(react@19.2.0) - tslib: 2.8.1 - optionalDependencies: - react: 19.2.0 - react-dom: 19.2.0(react@19.2.0) - - ms@2.1.3: {} - - msgpackr-extract@3.0.3: - dependencies: - node-gyp-build-optional-packages: 5.2.2 - optionalDependencies: - '@msgpackr-extract/msgpackr-extract-darwin-arm64': 3.0.3 - '@msgpackr-extract/msgpackr-extract-darwin-x64': 3.0.3 - '@msgpackr-extract/msgpackr-extract-linux-arm': 3.0.3 - '@msgpackr-extract/msgpackr-extract-linux-arm64': 3.0.3 - '@msgpackr-extract/msgpackr-extract-linux-x64': 3.0.3 - '@msgpackr-extract/msgpackr-extract-win32-x64': 3.0.3 - optional: true - - msgpackr@1.11.5: - optionalDependencies: - msgpackr-extract: 3.0.3 - - multiformats@13.4.1: {} - - nanoid@3.3.11: {} - - neo-async@2.6.2: {} - - node-addon-api@2.0.2: {} - - node-addon-api@5.1.0: {} - - node-fetch@2.7.0: - dependencies: - whatwg-url: 5.0.0 - - node-gyp-build-optional-packages@5.2.2: - dependencies: - detect-libc: 2.1.2 - optional: true - - node-gyp-build@4.8.4: {} - - node-releases@2.0.25: {} - - normalize-path@3.0.0: {} - - normalize-range@0.1.2: {} - - normalize-url@6.1.0: {} - - nth-check@2.1.1: - dependencies: - boolbase: 1.0.0 - - object-is@1.1.6: - dependencies: - call-bind: 1.0.8 - define-properties: 1.2.1 - - object-keys@1.1.1: {} - - object.assign@4.1.7: - dependencies: - call-bind: 1.0.8 - call-bound: 1.0.4 - define-properties: 1.2.1 - es-object-atoms: 1.1.1 - has-symbols: 1.1.0 - object-keys: 1.1.1 - - once@1.4.0: - dependencies: - wrappy: 1.0.2 - - ox@0.9.6(typescript@5.9.3): - dependencies: - '@adraffy/ens-normalize': 1.11.1 - '@noble/ciphers': 1.3.0 - '@noble/curves': 1.9.1 - '@noble/hashes': 1.8.0 - '@scure/bip32': 1.7.0 - '@scure/bip39': 1.6.0 - abitype: 1.1.1(typescript@5.9.3) - eventemitter3: 5.0.1 - optionalDependencies: - typescript: 5.9.3 - transitivePeerDependencies: - - zod - - p-finally@1.0.0: {} - - p-limit@2.3.0: - dependencies: - p-try: 2.2.0 - - p-locate@4.1.0: - dependencies: - p-limit: 2.3.0 - - p-queue@6.6.2: - dependencies: - eventemitter3: 4.0.7 - p-timeout: 3.2.0 - - p-timeout@3.2.0: - dependencies: - p-finally: 1.0.0 - - p-try@2.2.0: {} - - package-json-from-dist@1.0.1: {} - - parse-asn1@5.1.9: - dependencies: - asn1.js: 4.10.1 - browserify-aes: 1.2.0 - evp_bytestokey: 1.0.3 - pbkdf2: 3.1.5 - safe-buffer: 5.2.1 - - path-exists@4.0.0: {} - - path-key@3.1.1: {} - - path-parse@1.0.7: {} - - path-scurry@1.11.1: - dependencies: - lru-cache: 10.4.3 - minipass: 7.1.2 - - pathe@2.0.3: {} - - pathval@2.0.1: {} - - pbkdf2@3.1.5: - dependencies: - create-hash: 1.2.0 - create-hmac: 1.1.7 - ripemd160: 2.0.3 - safe-buffer: 5.2.1 - sha.js: 2.4.12 - to-buffer: 1.2.2 - - picocolors@1.1.1: {} - - picomatch@2.3.1: {} - - picomatch@4.0.3: {} - - pify@2.3.0: {} - - pify@5.0.0: {} - - pkg-dir@4.2.0: - dependencies: - find-up: 4.1.0 - - portfinder@1.0.32: - dependencies: - async: 2.6.4 - debug: 3.2.7 - mkdirp: 0.5.6 - transitivePeerDependencies: - - supports-color - - possible-typed-array-names@1.1.0: {} - - postcss-calc@8.2.4(postcss@8.5.6): - dependencies: - postcss: 8.5.6 - postcss-selector-parser: 6.1.2 - postcss-value-parser: 4.2.0 - - postcss-colormin@5.3.1(postcss@8.5.6): - dependencies: - browserslist: 4.26.3 - caniuse-api: 3.0.0 - colord: 2.9.3 - postcss: 8.5.6 - postcss-value-parser: 4.2.0 - - postcss-convert-values@5.1.3(postcss@8.5.6): - dependencies: - browserslist: 4.26.3 - postcss: 8.5.6 - postcss-value-parser: 4.2.0 - - postcss-discard-comments@5.1.2(postcss@8.5.6): - dependencies: - postcss: 8.5.6 - - postcss-discard-duplicates@5.1.0(postcss@8.5.6): - dependencies: - postcss: 8.5.6 - - postcss-discard-empty@5.1.1(postcss@8.5.6): - dependencies: - postcss: 8.5.6 - - postcss-discard-overridden@5.1.0(postcss@8.5.6): - dependencies: - postcss: 8.5.6 - - postcss-import@16.1.1(postcss@8.5.6): - dependencies: - postcss: 8.5.6 - postcss-value-parser: 4.2.0 - read-cache: 1.0.0 - resolve: 1.22.10 - - postcss-load-config@3.1.4(postcss@8.5.6): - dependencies: - lilconfig: 2.1.0 - yaml: 1.10.2 - optionalDependencies: - postcss: 8.5.6 - - postcss-merge-longhand@5.1.7(postcss@8.5.6): - dependencies: - postcss: 8.5.6 - postcss-value-parser: 4.2.0 - stylehacks: 5.1.1(postcss@8.5.6) - - postcss-merge-rules@5.1.4(postcss@8.5.6): - dependencies: - browserslist: 4.26.3 - caniuse-api: 3.0.0 - cssnano-utils: 3.1.0(postcss@8.5.6) - postcss: 8.5.6 - postcss-selector-parser: 6.1.2 - - postcss-minify-font-values@5.1.0(postcss@8.5.6): - dependencies: - postcss: 8.5.6 - postcss-value-parser: 4.2.0 - - postcss-minify-gradients@5.1.1(postcss@8.5.6): - dependencies: - colord: 2.9.3 - cssnano-utils: 3.1.0(postcss@8.5.6) - postcss: 8.5.6 - postcss-value-parser: 4.2.0 - - postcss-minify-params@5.1.4(postcss@8.5.6): - dependencies: - browserslist: 4.26.3 - cssnano-utils: 3.1.0(postcss@8.5.6) - postcss: 8.5.6 - postcss-value-parser: 4.2.0 - - postcss-minify-selectors@5.2.1(postcss@8.5.6): - dependencies: - postcss: 8.5.6 - postcss-selector-parser: 6.1.2 - - postcss-modules-extract-imports@3.1.0(postcss@8.5.6): - dependencies: - postcss: 8.5.6 - - postcss-modules-local-by-default@4.2.0(postcss@8.5.6): - dependencies: - icss-utils: 5.1.0(postcss@8.5.6) - postcss: 8.5.6 - postcss-selector-parser: 7.1.0 - postcss-value-parser: 4.2.0 - - postcss-modules-scope@3.2.1(postcss@8.5.6): - dependencies: - postcss: 8.5.6 - postcss-selector-parser: 7.1.0 - - postcss-modules-values@4.0.0(postcss@8.5.6): - dependencies: - icss-utils: 5.1.0(postcss@8.5.6) - postcss: 8.5.6 - - postcss-modules@4.3.1(postcss@8.5.6): - dependencies: - generic-names: 4.0.0 - icss-replace-symbols: 1.1.0 - lodash.camelcase: 4.3.0 - postcss: 8.5.6 - postcss-modules-extract-imports: 3.1.0(postcss@8.5.6) - postcss-modules-local-by-default: 4.2.0(postcss@8.5.6) - postcss-modules-scope: 3.2.1(postcss@8.5.6) - postcss-modules-values: 4.0.0(postcss@8.5.6) - string-hash: 1.1.3 - - postcss-nesting@13.0.2(postcss@8.5.6): - dependencies: - '@csstools/selector-resolve-nested': 3.1.0(postcss-selector-parser@7.1.0) - '@csstools/selector-specificity': 5.0.0(postcss-selector-parser@7.1.0) - postcss: 8.5.6 - postcss-selector-parser: 7.1.0 - - postcss-normalize-charset@5.1.0(postcss@8.5.6): - dependencies: - postcss: 8.5.6 - - postcss-normalize-display-values@5.1.0(postcss@8.5.6): - dependencies: - postcss: 8.5.6 - postcss-value-parser: 4.2.0 - - postcss-normalize-positions@5.1.1(postcss@8.5.6): - dependencies: - postcss: 8.5.6 - postcss-value-parser: 4.2.0 - - postcss-normalize-repeat-style@5.1.1(postcss@8.5.6): - dependencies: - postcss: 8.5.6 - postcss-value-parser: 4.2.0 - - postcss-normalize-string@5.1.0(postcss@8.5.6): - dependencies: - postcss: 8.5.6 - postcss-value-parser: 4.2.0 - - postcss-normalize-timing-functions@5.1.0(postcss@8.5.6): - dependencies: - postcss: 8.5.6 - postcss-value-parser: 4.2.0 - - postcss-normalize-unicode@5.1.1(postcss@8.5.6): - dependencies: - browserslist: 4.26.3 - postcss: 8.5.6 - postcss-value-parser: 4.2.0 - - postcss-normalize-url@5.1.0(postcss@8.5.6): - dependencies: - normalize-url: 6.1.0 - postcss: 8.5.6 - postcss-value-parser: 4.2.0 - - postcss-normalize-whitespace@5.1.1(postcss@8.5.6): - dependencies: - postcss: 8.5.6 - postcss-value-parser: 4.2.0 - - postcss-ordered-values@5.1.3(postcss@8.5.6): - dependencies: - cssnano-utils: 3.1.0(postcss@8.5.6) - postcss: 8.5.6 - postcss-value-parser: 4.2.0 - - postcss-reduce-initial@5.1.2(postcss@8.5.6): - dependencies: - browserslist: 4.26.3 - caniuse-api: 3.0.0 - postcss: 8.5.6 - - postcss-reduce-transforms@5.1.0(postcss@8.5.6): - dependencies: - postcss: 8.5.6 - postcss-value-parser: 4.2.0 - - postcss-selector-parser@6.1.2: - dependencies: - cssesc: 3.0.0 - util-deprecate: 1.0.2 - - postcss-selector-parser@7.1.0: - dependencies: - cssesc: 3.0.0 - util-deprecate: 1.0.2 - - postcss-svgo@5.1.0(postcss@8.5.6): - dependencies: - postcss: 8.5.6 - postcss-value-parser: 4.2.0 - svgo: 2.8.0 - - postcss-unique-selectors@5.1.1(postcss@8.5.6): - dependencies: - postcss: 8.5.6 - postcss-selector-parser: 6.1.2 - - postcss-value-parser@4.2.0: {} - - postcss@8.5.6: - dependencies: - nanoid: 3.3.11 - picocolors: 1.1.1 - source-map-js: 1.2.1 - - prettier@3.6.2: {} - - process-nextick-args@2.0.1: {} - - promise.series@0.2.0: {} - - property-expr@2.0.6: {} - - proxy-from-env@1.1.0: {} - - public-encrypt@4.0.3: - dependencies: - bn.js: 4.12.2 - browserify-rsa: 4.1.1 - create-hash: 1.2.0 - parse-asn1: 5.1.9 - randombytes: 2.1.0 - safe-buffer: 5.2.1 - - ramda@0.30.1: {} - - randombytes@2.1.0: - dependencies: - safe-buffer: 5.2.1 - - randomfill@1.0.4: - dependencies: - randombytes: 2.1.0 - safe-buffer: 5.2.1 - - react-dom@19.2.0(react@19.2.0): - dependencies: - react: 19.2.0 - scheduler: 0.27.0 - - react@19.2.0: {} - - read-cache@1.0.0: - dependencies: - pify: 2.3.0 - - readable-stream@2.3.8: - dependencies: - core-util-is: 1.0.3 - inherits: 2.0.4 - isarray: 1.0.0 - process-nextick-args: 2.0.1 - safe-buffer: 5.1.2 - string_decoder: 1.1.1 - util-deprecate: 1.0.2 - - readable-stream@3.6.2: - dependencies: - inherits: 2.0.4 - string_decoder: 1.3.0 - util-deprecate: 1.0.2 - - readdirp@3.6.0: - dependencies: - picomatch: 2.3.1 - - readonly-date@1.0.0: {} - - regenerator-runtime@0.14.1: {} - - resolve-from@5.0.0: {} - - resolve@1.22.10: - dependencies: - is-core-module: 2.16.1 - path-parse: 1.0.7 - supports-preserve-symlinks-flag: 1.0.0 - - rimraf@5.0.10: - dependencies: - glob: 10.4.5 - - ripemd160@2.0.3: - dependencies: - hash-base: 3.1.2 - inherits: 2.0.4 - - rlp@2.2.7: - dependencies: - bn.js: 5.2.2 - - rollup-plugin-dts@6.2.3(rollup@4.52.4)(typescript@5.9.3): - dependencies: - magic-string: 0.30.19 - rollup: 4.52.4 - typescript: 5.9.3 - optionalDependencies: - '@babel/code-frame': 7.27.1 - - rollup-plugin-postcss@4.0.2(postcss@8.5.6): - dependencies: - chalk: 4.1.2 - concat-with-sourcemaps: 1.1.0 - cssnano: 5.1.15(postcss@8.5.6) - import-cwd: 3.0.0 - p-queue: 6.6.2 - pify: 5.0.0 - postcss: 8.5.6 - postcss-load-config: 3.1.4(postcss@8.5.6) - postcss-modules: 4.3.1(postcss@8.5.6) - promise.series: 0.2.0 - resolve: 1.22.10 - rollup-pluginutils: 2.8.2 - safe-identifier: 0.4.2 - style-inject: 0.3.0 - transitivePeerDependencies: - - ts-node - - rollup-plugin-typescript2@0.36.0(rollup@4.52.4)(typescript@5.9.3): - dependencies: - '@rollup/pluginutils': 4.2.1 - find-cache-dir: 3.3.2 - fs-extra: 10.1.0 - rollup: 4.52.4 - semver: 7.7.3 - tslib: 2.8.1 - typescript: 5.9.3 - - rollup-pluginutils@2.8.2: - dependencies: - estree-walker: 0.6.1 - - rollup@4.52.4: - dependencies: - '@types/estree': 1.0.8 - optionalDependencies: - '@rollup/rollup-android-arm-eabi': 4.52.4 - '@rollup/rollup-android-arm64': 4.52.4 - '@rollup/rollup-darwin-arm64': 4.52.4 - '@rollup/rollup-darwin-x64': 4.52.4 - '@rollup/rollup-freebsd-arm64': 4.52.4 - '@rollup/rollup-freebsd-x64': 4.52.4 - '@rollup/rollup-linux-arm-gnueabihf': 4.52.4 - '@rollup/rollup-linux-arm-musleabihf': 4.52.4 - '@rollup/rollup-linux-arm64-gnu': 4.52.4 - '@rollup/rollup-linux-arm64-musl': 4.52.4 - '@rollup/rollup-linux-loong64-gnu': 4.52.4 - '@rollup/rollup-linux-ppc64-gnu': 4.52.4 - '@rollup/rollup-linux-riscv64-gnu': 4.52.4 - '@rollup/rollup-linux-riscv64-musl': 4.52.4 - '@rollup/rollup-linux-s390x-gnu': 4.52.4 - '@rollup/rollup-linux-x64-gnu': 4.52.4 - '@rollup/rollup-linux-x64-musl': 4.52.4 - '@rollup/rollup-openharmony-arm64': 4.52.4 - '@rollup/rollup-win32-arm64-msvc': 4.52.4 - '@rollup/rollup-win32-ia32-msvc': 4.52.4 - '@rollup/rollup-win32-x64-gnu': 4.52.4 - '@rollup/rollup-win32-x64-msvc': 4.52.4 - fsevents: 2.3.3 - - safe-buffer@5.1.2: {} - - safe-buffer@5.2.1: {} - - safe-identifier@0.4.2: {} - - safe-regex-test@1.1.0: - dependencies: - call-bound: 1.0.4 - es-errors: 1.3.0 - is-regex: 1.2.1 - - scheduler@0.27.0: {} - - scrypt-js@3.0.1: {} - - secp256k1@4.0.4: - dependencies: - elliptic: 6.6.1 - node-addon-api: 5.1.0 - node-gyp-build: 4.8.4 - - semver@6.3.1: {} - - semver@7.7.1: {} - - semver@7.7.3: {} - - set-function-length@1.2.2: - dependencies: - define-data-property: 1.1.4 - es-errors: 1.3.0 - function-bind: 1.1.2 - get-intrinsic: 1.3.0 - gopd: 1.2.0 - has-property-descriptors: 1.0.2 - - setimmediate@1.0.5: {} - - sha.js@2.4.12: - dependencies: - inherits: 2.0.4 - safe-buffer: 5.2.1 - to-buffer: 1.2.2 - - shebang-command@2.0.0: - dependencies: - shebang-regex: 3.0.0 - - shebang-regex@3.0.0: {} - - siginfo@2.0.0: {} - - signal-exit@4.1.0: {} - - source-map-js@1.2.1: {} - - source-map@0.6.1: {} - - stable@0.1.8: {} - - stackback@0.0.2: {} - - std-env@3.10.0: {} - - stream-browserify@3.0.0: - dependencies: - inherits: 2.0.4 - readable-stream: 3.6.2 - - string-hash@1.1.3: {} - - string-width@4.2.3: - dependencies: - emoji-regex: 8.0.0 - is-fullwidth-code-point: 3.0.0 - strip-ansi: 6.0.1 - - string-width@5.1.2: - dependencies: - eastasianwidth: 0.2.0 - emoji-regex: 9.2.2 - strip-ansi: 7.1.2 - - string_decoder@1.1.1: - dependencies: - safe-buffer: 5.1.2 - - string_decoder@1.3.0: - dependencies: - safe-buffer: 5.2.1 - - strip-ansi@6.0.1: - dependencies: - ansi-regex: 5.0.1 - - strip-ansi@7.1.2: - dependencies: - ansi-regex: 6.2.2 - - style-inject@0.3.0: {} - - stylehacks@5.1.1(postcss@8.5.6): - dependencies: - browserslist: 4.26.3 - postcss: 8.5.6 - postcss-selector-parser: 6.1.2 - - supports-color@7.2.0: - dependencies: - has-flag: 4.0.0 - - supports-preserve-symlinks-flag@1.0.0: {} - - svgo@2.8.0: - dependencies: - '@trysound/sax': 0.2.0 - commander: 7.2.0 - css-select: 4.3.0 - css-tree: 1.1.3 - csso: 4.2.0 - picocolors: 1.1.1 - stable: 0.1.8 - - symbol-observable@2.0.3: {} - - tailwind-merge@3.3.1: {} - - tailwindcss@4.1.10: {} - - tapable@2.3.0: {} - - tar@7.5.1: - dependencies: - '@isaacs/fs-minipass': 4.0.1 - chownr: 3.0.0 - minipass: 7.1.2 - minizlib: 3.1.0 - yallist: 5.0.0 - - tiny-case@1.0.3: {} - - tinybench@2.9.0: {} - - tinyexec@0.3.2: {} - - tinyglobby@0.2.15: - dependencies: - fdir: 6.5.0(picomatch@4.0.3) - picomatch: 4.0.3 - - tinypool@1.1.1: {} - - tinyrainbow@2.0.0: {} - - tinyspy@3.0.2: {} - - to-buffer@1.2.2: - dependencies: - isarray: 2.0.5 - safe-buffer: 5.2.1 - typed-array-buffer: 1.0.3 - - to-regex-range@5.0.1: - dependencies: - is-number: 7.0.0 - - toml@3.0.0: {} - - toposort@2.0.2: {} - - tr46@0.0.3: {} - - tronweb@6.0.4: - dependencies: - '@babel/runtime': 7.26.10 - axios: 1.11.0 - bignumber.js: 9.1.2 - ethereum-cryptography: 2.2.1 - ethers: 6.13.5 - eventemitter3: 5.0.1 - google-protobuf: 3.21.4 - semver: 7.7.1 - validator: 13.12.0 - transitivePeerDependencies: - - bufferutil - - debug - - utf-8-validate - - tslib@2.7.0: {} - - tslib@2.8.1: {} - - type-fest@2.19.0: {} - - type-fest@4.34.1: {} - - typed-array-buffer@1.0.3: - dependencies: - call-bound: 1.0.4 - es-errors: 1.3.0 - is-typed-array: 1.1.15 - - typedarray-to-buffer@3.1.5: - dependencies: - is-typedarray: 1.0.0 - - typescript@5.9.3: {} - - uglify-js@3.19.3: {} - - uint8arrays@5.1.0: - dependencies: - multiformats: 13.4.1 - - undici-types@6.19.8: {} - - undici-types@6.21.0: {} - - undici-types@7.14.0: {} - - universalify@2.0.1: {} - - update-browserslist-db@1.1.3(browserslist@4.26.3): - dependencies: - browserslist: 4.26.3 - escalade: 3.2.0 - picocolors: 1.1.1 - - utf8@3.0.0: {} - - util-deprecate@1.0.2: {} - - util@0.12.5: - dependencies: - inherits: 2.0.4 - is-arguments: 1.2.0 - is-generator-function: 1.1.2 - is-typed-array: 1.1.15 - which-typed-array: 1.1.19 - - uuid@8.3.2: {} - - validator@13.12.0: {} - - viem@2.38.3(typescript@5.9.3): - dependencies: - '@noble/curves': 1.9.1 - '@noble/hashes': 1.8.0 - '@scure/bip32': 1.7.0 - '@scure/bip39': 1.6.0 - abitype: 1.1.0(typescript@5.9.3) - isows: 1.0.7(ws@8.18.3) - ox: 0.9.6(typescript@5.9.3) - ws: 8.18.3 - optionalDependencies: - typescript: 5.9.3 - transitivePeerDependencies: - - bufferutil - - utf-8-validate - - zod - - vite-node@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2): - dependencies: - cac: 6.7.14 - debug: 4.4.3 - es-module-lexer: 1.7.0 - pathe: 2.0.3 - vite: 6.4.0(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2) - transitivePeerDependencies: - - '@types/node' - - jiti - - less - - lightningcss - - sass - - sass-embedded - - stylus - - sugarss - - supports-color - - terser - - tsx - - yaml - - vite@6.4.0(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2): - dependencies: - esbuild: 0.25.11 - fdir: 6.5.0(picomatch@4.0.3) - picomatch: 4.0.3 - postcss: 8.5.6 - rollup: 4.52.4 - tinyglobby: 0.2.15 - optionalDependencies: - '@types/node': 20.19.22 - fsevents: 2.3.3 - jiti: 2.6.1 - lightningcss: 1.30.1 - yaml: 1.10.2 - - vitest@3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2): - dependencies: - '@vitest/expect': 3.0.9 - '@vitest/mocker': 3.0.9(vite@6.4.0(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2)) - '@vitest/pretty-format': 3.2.4 - '@vitest/runner': 3.0.9 - '@vitest/snapshot': 3.0.9 - '@vitest/spy': 3.0.9 - '@vitest/utils': 3.0.9 - chai: 5.3.3 - debug: 4.4.3 - expect-type: 1.2.2 - magic-string: 0.30.19 - pathe: 2.0.3 - std-env: 3.10.0 - tinybench: 2.9.0 - tinyexec: 0.3.2 - tinypool: 1.1.1 - tinyrainbow: 2.0.0 - vite: 6.4.0(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2) - vite-node: 3.0.9(@types/node@20.19.22)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@1.10.2) - why-is-node-running: 2.3.0 - optionalDependencies: - '@types/node': 20.19.22 - transitivePeerDependencies: - - jiti - - less - - lightningcss - - msw - - sass - - sass-embedded - - stylus - - sugarss - - supports-color - - terser - - tsx - - yaml - - webidl-conversions@3.0.1: {} - - whatwg-url@5.0.0: - dependencies: - tr46: 0.0.3 - webidl-conversions: 3.0.1 - - which-typed-array@1.1.19: - dependencies: - available-typed-arrays: 1.0.7 - call-bind: 1.0.8 - call-bound: 1.0.4 - for-each: 0.3.5 - get-proto: 1.0.1 - gopd: 1.2.0 - has-tostringtag: 1.0.2 - - which@2.0.2: - dependencies: - isexe: 2.0.0 - - why-is-node-running@2.3.0: - dependencies: - siginfo: 2.0.0 - stackback: 0.0.2 - - wordwrap@1.0.0: {} - - wrap-ansi@7.0.0: - dependencies: - ansi-styles: 4.3.0 - string-width: 4.2.3 - strip-ansi: 6.0.1 - - wrap-ansi@8.1.0: - dependencies: - ansi-styles: 6.2.3 - string-width: 5.1.2 - strip-ansi: 7.1.2 - - wrappy@1.0.2: {} - - ws@7.5.10: {} - - ws@8.17.1: {} - - ws@8.18.3: {} - - xstream@11.14.0: - dependencies: - globalthis: 1.0.4 - symbol-observable: 2.0.3 - - yallist@5.0.0: {} - - yaml@1.10.2: {} - - yup@1.6.1: - dependencies: - property-expr: 2.0.6 - tiny-case: 1.0.3 - toposort: 2.0.2 - type-fest: 2.19.0 diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml deleted file mode 100644 index 4340350e..00000000 --- a/pnpm-workspace.yaml +++ /dev/null @@ -1,2 +0,0 @@ -packages: - - 'packages/*' \ No newline at end of file diff --git a/packages/core/rollup.config.mjs b/rollup.config.mjs similarity index 74% rename from packages/core/rollup.config.mjs rename to rollup.config.mjs index 09894fbf..897e9ba9 100644 --- a/packages/core/rollup.config.mjs +++ b/rollup.config.mjs @@ -2,7 +2,6 @@ import resolve from '@rollup/plugin-node-resolve'; import commonjs from '@rollup/plugin-commonjs'; import typescript from 'rollup-plugin-typescript2'; import json from '@rollup/plugin-json'; -import alias from '@rollup/plugin-alias'; import dts from 'rollup-plugin-dts'; import { defineConfig } from 'rollup'; import { createRequire } from 'node:module'; @@ -14,12 +13,8 @@ const shouldGenerateSourceMaps = false; // Base configuration for core (no React, no CSS) const baseConfig = { - input: 'index.ts', + input: 'src/index.ts', plugins: [ - alias({ - // Alias is not used for externals but kept for future non-externalized builds - entries: [{ find: '@nexus/commons', replacement: './commons' }], - }), json(), resolve({ browser: true, @@ -49,7 +44,6 @@ const baseConfig = { '@cosmjs/stargate', '@starkware-industries/starkware-crypto-utils', '@metamask/safe-event-emitter', - '@nexus/commons', 'decimal.js', 'fuels', 'long', @@ -57,7 +51,6 @@ const baseConfig = { 'tslib', 'axios', 'es-toolkit', - './commons', ], treeshake: { // Preserve side effects for external deps like tronweb that rely on global proto init @@ -78,40 +71,21 @@ export default defineConfig([ sourcemap: shouldGenerateSourceMaps, exports: 'named', interop: 'auto', - paths: { - '@nexus/commons': './commons', - '@nexus/commons/constants': './commons/constants', - }, }, { file: 'dist/index.esm.js', format: 'esm', sourcemap: shouldGenerateSourceMaps, exports: 'named', - paths: { - '@nexus/commons': './commons', - '@nexus/commons/constants': './commons/constants', - }, }, ], }, // TypeScript declarations { - input: 'index.ts', + input: 'src/index.ts', output: [{ file: 'dist/index.d.ts', format: 'esm' }], - plugins: [ - dts(), - // Rewrite import specifiers in generated d.ts - { - name: 'rewrite-commons-imports-dts', - renderChunk(code) { - return code - .replace(/@nexus\/commons\/constants/g, './commons/constants') - .replace(/@nexus\/commons/g, './commons'); - }, - }, - ], + plugins: [dts()], external: [ ...Object.keys(packageJson.peerDependencies || {}), /^viem/, @@ -126,10 +100,8 @@ export default defineConfig([ 'long', 'msgpackr', 'tslib', - '@nexus/commons', 'axios', 'es-toolkit', - './commons', ], }, ]); diff --git a/scripts/README.md b/scripts/README.md index 16e63569..5c96be0b 100644 --- a/scripts/README.md +++ b/scripts/README.md @@ -115,8 +115,3 @@ Scripts will exit with error codes if: - `--yes` or `--ci`: skip interactive prompts (useful in CI; also bypasses the main-branch prompt on prod). - `--dry-run` or `-n`: simulate publish (runs `npm pack` instead of `npm publish`; skips git push/tag). - -## Internal Commons - -- `@nexus/commons` is internal and kept out of published dependencies. -- Both scripts bundle `commons` into `dist/commons` so consumers never install it directly. diff --git a/packages/commons/constants/index.ts b/src/commons/constants/index.ts similarity index 100% rename from packages/commons/constants/index.ts rename to src/commons/constants/index.ts diff --git a/packages/commons/index.ts b/src/commons/index.ts similarity index 100% rename from packages/commons/index.ts rename to src/commons/index.ts diff --git a/packages/commons/types/bridge-steps.ts b/src/commons/types/bridge-steps.ts similarity index 100% rename from packages/commons/types/bridge-steps.ts rename to src/commons/types/bridge-steps.ts diff --git a/packages/commons/types/contract-types.ts b/src/commons/types/contract-types.ts similarity index 100% rename from packages/commons/types/contract-types.ts rename to src/commons/types/contract-types.ts diff --git a/packages/commons/types/index.ts b/src/commons/types/index.ts similarity index 100% rename from packages/commons/types/index.ts rename to src/commons/types/index.ts diff --git a/packages/commons/types/integration-types.ts b/src/commons/types/integration-types.ts similarity index 100% rename from packages/commons/types/integration-types.ts rename to src/commons/types/integration-types.ts diff --git a/packages/commons/types/service-types.ts b/src/commons/types/service-types.ts similarity index 100% rename from packages/commons/types/service-types.ts rename to src/commons/types/service-types.ts diff --git a/packages/commons/types/swap-steps.ts b/src/commons/types/swap-steps.ts similarity index 100% rename from packages/commons/types/swap-steps.ts rename to src/commons/types/swap-steps.ts diff --git a/packages/commons/types/swap-types.ts b/src/commons/types/swap-types.ts similarity index 100% rename from packages/commons/types/swap-types.ts rename to src/commons/types/swap-types.ts diff --git a/packages/commons/utils/format.ts b/src/commons/utils/format.ts similarity index 100% rename from packages/commons/utils/format.ts rename to src/commons/utils/format.ts diff --git a/packages/commons/utils/index.ts b/src/commons/utils/index.ts similarity index 100% rename from packages/commons/utils/index.ts rename to src/commons/utils/index.ts diff --git a/packages/commons/utils/logger.ts b/src/commons/utils/logger.ts similarity index 100% rename from packages/commons/utils/logger.ts rename to src/commons/utils/logger.ts diff --git a/packages/core/index.ts b/src/index.ts similarity index 93% rename from packages/core/index.ts rename to src/index.ts index a54e289d..107b2806 100644 --- a/packages/core/index.ts +++ b/src/index.ts @@ -31,7 +31,7 @@ export type { SUPPORTED_TOKENS, ChainMetadata, TokenMetadata, -} from '@nexus/commons'; +} from './commons'; export { CHAIN_METADATA, @@ -45,7 +45,7 @@ export { DESTINATION_SWAP_TOKENS, BRIDGE_STEPS, SWAP_STEPS, -} from '@nexus/commons'; +} from './commons'; // Re-export everything from commons (includes constants, utils, and types) -export * from '@nexus/commons'; +export * from './commons'; diff --git a/packages/core/integrations/tenderly.ts b/src/integrations/tenderly.ts similarity index 98% rename from packages/core/integrations/tenderly.ts rename to src/integrations/tenderly.ts index 020a5a3c..851077d4 100644 --- a/packages/core/integrations/tenderly.ts +++ b/src/integrations/tenderly.ts @@ -7,9 +7,9 @@ import { type BundleSimulationRequest, type BackendBundleResponse, } from './types'; -import { logger } from '@nexus/commons'; +import { logger } from '../commons'; import axios from 'axios'; -import { Errors } from 'sdk/ca-base/errors'; +import { Errors } from '../sdk/ca-base/errors'; /** * Backend simulation result interface diff --git a/packages/core/integrations/types.ts b/src/integrations/types.ts similarity index 100% rename from packages/core/integrations/types.ts rename to src/integrations/types.ts diff --git a/packages/core/sdk/ca-base/abi/erc20.ts b/src/sdk/ca-base/abi/erc20.ts similarity index 100% rename from packages/core/sdk/ca-base/abi/erc20.ts rename to src/sdk/ca-base/abi/erc20.ts diff --git a/packages/core/sdk/ca-base/abi/gasOracle.ts b/src/sdk/ca-base/abi/gasOracle.ts similarity index 100% rename from packages/core/sdk/ca-base/abi/gasOracle.ts rename to src/sdk/ca-base/abi/gasOracle.ts diff --git a/packages/core/sdk/ca-base/abi/misc.ts b/src/sdk/ca-base/abi/misc.ts similarity index 100% rename from packages/core/sdk/ca-base/abi/misc.ts rename to src/sdk/ca-base/abi/misc.ts diff --git a/packages/core/sdk/ca-base/abi/vault.ts b/src/sdk/ca-base/abi/vault.ts similarity index 100% rename from packages/core/sdk/ca-base/abi/vault.ts rename to src/sdk/ca-base/abi/vault.ts diff --git a/packages/core/sdk/ca-base/ca.ts b/src/sdk/ca-base/ca.ts similarity index 99% rename from packages/core/sdk/ca-base/ca.ts rename to src/sdk/ca-base/ca.ts index 09ef8108..6779478b 100644 --- a/packages/core/sdk/ca-base/ca.ts +++ b/src/sdk/ca-base/ca.ts @@ -24,7 +24,7 @@ import { Chain, TransferParams, BridgeParams, -} from '@nexus/commons'; +} from '../../commons'; import { createBridgeParams } from './requestHandlers/helpers'; import { ChainListType, @@ -43,7 +43,7 @@ import { OnEventParam, OnSwapIntentHook, TronAdapter, -} from '@nexus/commons'; +} from '../../commons'; import { cosmosFeeGrant, fetchMyIntents, @@ -65,7 +65,10 @@ import { getSwapSupportedChains } from './swap/utils'; import { utils } from 'tronweb'; import BridgeHandler from './requestHandlers/bridge'; import { BridgeAndExecuteQuery } from './query/bridgeAndExecute'; -import { BackendSimulationClient, createBackendSimulationClient } from 'integrations/tenderly'; +import { + BackendSimulationClient, + createBackendSimulationClient, +} from '../../integrations/tenderly'; import { createBridgeAndTransferParams } from './query/bridgeAndTransfer'; import getMaxValueForBridge from './requestHandlers/bridgeMax'; import { Errors } from './errors'; diff --git a/packages/core/sdk/ca-base/chains.ts b/src/sdk/ca-base/chains.ts similarity index 99% rename from packages/core/sdk/ca-base/chains.ts rename to src/sdk/ca-base/chains.ts index 5670ec78..71491bfb 100644 --- a/packages/core/sdk/ca-base/chains.ts +++ b/src/sdk/ca-base/chains.ts @@ -6,7 +6,7 @@ import { Universe, } from '@avail-project/ca-common'; import { getLogoFromSymbol, ZERO_ADDRESS } from './constants'; -import { Chain, SUPPORTED_CHAINS, TOKEN_CONTRACT_ADDRESSES, TokenInfo } from '@nexus/commons'; +import { Chain, SUPPORTED_CHAINS, TOKEN_CONTRACT_ADDRESSES, TokenInfo } from '../../commons'; import { convertToHexAddressByUniverse, equalFold } from './utils'; import { Errors } from './errors'; import { Hex } from 'viem'; diff --git a/packages/core/sdk/ca-base/config.ts b/src/sdk/ca-base/config.ts similarity index 97% rename from packages/core/sdk/ca-base/config.ts rename to src/sdk/ca-base/config.ts index b5960070..ca4f286c 100644 --- a/packages/core/sdk/ca-base/config.ts +++ b/src/sdk/ca-base/config.ts @@ -1,6 +1,6 @@ import { Environment } from '@avail-project/ca-common'; -import { NetworkConfig } from '@nexus/commons'; +import { NetworkConfig } from '../../commons'; // Testnet with mainnet tokens const CORAL_CONFIG: NetworkConfig = { diff --git a/packages/core/sdk/ca-base/constants.ts b/src/sdk/ca-base/constants.ts similarity index 100% rename from packages/core/sdk/ca-base/constants.ts rename to src/sdk/ca-base/constants.ts diff --git a/packages/core/sdk/ca-base/errors.ts b/src/sdk/ca-base/errors.ts similarity index 100% rename from packages/core/sdk/ca-base/errors.ts rename to src/sdk/ca-base/errors.ts diff --git a/packages/core/sdk/ca-base/index.ts b/src/sdk/ca-base/index.ts similarity index 93% rename from packages/core/sdk/ca-base/index.ts rename to src/sdk/ca-base/index.ts index ecf0a6c3..d725b7ba 100644 --- a/packages/core/sdk/ca-base/index.ts +++ b/src/sdk/ca-base/index.ts @@ -14,6 +14,6 @@ export type { UserAssetDatum as UserAsset, BridgeStepType, SwapStepType, -} from '@nexus/commons'; +} from '../../commons'; export { Environment as Network, RequestForFunds } from '@avail-project/ca-common'; diff --git a/packages/core/sdk/ca-base/nexusError.ts b/src/sdk/ca-base/nexusError.ts similarity index 100% rename from packages/core/sdk/ca-base/nexusError.ts rename to src/sdk/ca-base/nexusError.ts diff --git a/packages/core/sdk/ca-base/query/bridgeAndExecute.ts b/src/sdk/ca-base/query/bridgeAndExecute.ts similarity index 99% rename from packages/core/sdk/ca-base/query/bridgeAndExecute.ts rename to src/sdk/ca-base/query/bridgeAndExecute.ts index 9e348cc7..27b7b8be 100644 --- a/packages/core/sdk/ca-base/query/bridgeAndExecute.ts +++ b/src/sdk/ca-base/query/bridgeAndExecute.ts @@ -16,7 +16,7 @@ import { NEXUS_EVENTS, BRIDGE_STEPS, BridgeStepType, -} from '@nexus/commons'; +} from '../../../commons'; import { createPublicClient, Hex, @@ -39,7 +39,7 @@ import { getL1Fee, } from '../utils'; import { packERC20Approve } from '../swap/utils'; -import { BackendSimulationClient } from 'integrations/tenderly'; +import { BackendSimulationClient } from '../../../integrations/tenderly'; import BridgeHandler from '../requestHandlers/bridge'; import { Errors } from '../errors'; diff --git a/packages/core/sdk/ca-base/query/bridgeAndTransfer.ts b/src/sdk/ca-base/query/bridgeAndTransfer.ts similarity index 97% rename from packages/core/sdk/ca-base/query/bridgeAndTransfer.ts rename to src/sdk/ca-base/query/bridgeAndTransfer.ts index cb5d4a65..5b9e8808 100644 --- a/packages/core/sdk/ca-base/query/bridgeAndTransfer.ts +++ b/src/sdk/ca-base/query/bridgeAndTransfer.ts @@ -1,5 +1,5 @@ import { mulDecimals } from '../utils'; -import { ChainListType, BridgeAndExecuteParams, Tx, TransferParams } from '@nexus/commons'; +import { ChainListType, BridgeAndExecuteParams, Tx, TransferParams } from '../../../commons'; import { encodeFunctionData } from 'viem'; import { ERC20ABI } from '@avail-project/ca-common'; import { Errors } from '../errors'; diff --git a/packages/core/sdk/ca-base/query/index.ts b/src/sdk/ca-base/query/index.ts similarity index 100% rename from packages/core/sdk/ca-base/query/index.ts rename to src/sdk/ca-base/query/index.ts diff --git a/packages/core/sdk/ca-base/requestHandlers/bridge.ts b/src/sdk/ca-base/requestHandlers/bridge.ts similarity index 99% rename from packages/core/sdk/ca-base/requestHandlers/bridge.ts rename to src/sdk/ca-base/requestHandlers/bridge.ts index 499d5640..8572b529 100644 --- a/packages/core/sdk/ca-base/requestHandlers/bridge.ts +++ b/src/sdk/ca-base/requestHandlers/bridge.ts @@ -37,7 +37,7 @@ import { NEXUS_EVENTS, BridgeStepType, BRIDGE_STEPS, -} from '@nexus/commons'; +} from '../../../commons'; import { convertGasToToken, convertIntent, @@ -89,10 +89,7 @@ const logger = getLogger(); class BridgeHandler { protected steps: BridgeStepType[] = []; protected params: Required; - constructor( - params: Params, - readonly options: IBridgeOptions, - ) { + constructor(params: Params, readonly options: IBridgeOptions) { this.params = { ...params, recipient: retrieveAddress(params.dstChain.universe, options), diff --git a/packages/core/sdk/ca-base/requestHandlers/bridgeMax.ts b/src/sdk/ca-base/requestHandlers/bridgeMax.ts similarity index 95% rename from packages/core/sdk/ca-base/requestHandlers/bridgeMax.ts rename to src/sdk/ca-base/requestHandlers/bridgeMax.ts index 17fca6a4..5d7edacd 100644 --- a/packages/core/sdk/ca-base/requestHandlers/bridgeMax.ts +++ b/src/sdk/ca-base/requestHandlers/bridgeMax.ts @@ -1,4 +1,4 @@ -import { BridgeParams, IBridgeOptions } from '@nexus/commons'; +import { BridgeParams, IBridgeOptions } from '../../../commons'; import { getBalances, calculateMaxBridgeFee, getFeeStore, mulDecimals, UserAssets } from '../utils'; import { Errors } from '../errors'; diff --git a/packages/core/sdk/ca-base/requestHandlers/helpers.ts b/src/sdk/ca-base/requestHandlers/helpers.ts similarity index 91% rename from packages/core/sdk/ca-base/requestHandlers/helpers.ts rename to src/sdk/ca-base/requestHandlers/helpers.ts index cfca2762..376b55be 100644 --- a/packages/core/sdk/ca-base/requestHandlers/helpers.ts +++ b/src/sdk/ca-base/requestHandlers/helpers.ts @@ -1,6 +1,6 @@ import { Errors } from '../errors'; import { mulDecimals } from '../utils'; -import { BridgeParams, ChainListType } from '@nexus/commons'; +import { BridgeParams, ChainListType } from '../../../commons'; const createBridgeParams = (input: BridgeParams, chainList: ChainListType) => { const { chain: dstChain, token: dstToken } = chainList.getChainAndTokenFromSymbol( diff --git a/packages/core/sdk/ca-base/steps.ts b/src/sdk/ca-base/steps.ts similarity index 98% rename from packages/core/sdk/ca-base/steps.ts rename to src/sdk/ca-base/steps.ts index 10087a23..69a9998b 100644 --- a/packages/core/sdk/ca-base/steps.ts +++ b/src/sdk/ca-base/steps.ts @@ -5,7 +5,7 @@ import { ChainListType, Intent, onAllowanceHookSource, -} from '@nexus/commons'; +} from '../../commons'; import { Errors } from './errors'; const INTENT_FINISH_STEPS = [BRIDGE_STEPS.INTENT_FULFILLED]; diff --git a/packages/core/sdk/ca-base/swap/abi.ts b/src/sdk/ca-base/swap/abi.ts similarity index 100% rename from packages/core/sdk/ca-base/swap/abi.ts rename to src/sdk/ca-base/swap/abi.ts diff --git a/packages/core/sdk/ca-base/swap/calibur.abi.ts b/src/sdk/ca-base/swap/calibur.abi.ts similarity index 100% rename from packages/core/sdk/ca-base/swap/calibur.abi.ts rename to src/sdk/ca-base/swap/calibur.abi.ts diff --git a/packages/core/sdk/ca-base/swap/constants.ts b/src/sdk/ca-base/swap/constants.ts similarity index 100% rename from packages/core/sdk/ca-base/swap/constants.ts rename to src/sdk/ca-base/swap/constants.ts diff --git a/packages/core/sdk/ca-base/swap/data.ts b/src/sdk/ca-base/swap/data.ts similarity index 99% rename from packages/core/sdk/ca-base/swap/data.ts rename to src/sdk/ca-base/swap/data.ts index b07d4fc8..14b81cc1 100644 --- a/packages/core/sdk/ca-base/swap/data.ts +++ b/src/sdk/ca-base/swap/data.ts @@ -3,7 +3,7 @@ import { Hex, PublicClient } from 'viem'; import { toHex } from 'viem/utils'; import { ChainList } from '../chains'; -import { TokenInfo } from '@nexus/commons'; +import { TokenInfo } from '../../../commons'; import { convertTo32BytesHex, equalFold } from '../utils'; import { EADDRESS } from './constants'; import { convertToEVMAddress, determinePermitVariantAndVersion } from './utils'; diff --git a/packages/core/sdk/ca-base/swap/errors.ts b/src/sdk/ca-base/swap/errors.ts similarity index 100% rename from packages/core/sdk/ca-base/swap/errors.ts rename to src/sdk/ca-base/swap/errors.ts diff --git a/packages/core/sdk/ca-base/swap/ob.ts b/src/sdk/ca-base/swap/ob.ts similarity index 99% rename from packages/core/sdk/ca-base/swap/ob.ts rename to src/sdk/ca-base/swap/ob.ts index 5426d4b3..e9f705c0 100644 --- a/packages/core/sdk/ca-base/swap/ob.ts +++ b/src/sdk/ca-base/swap/ob.ts @@ -16,7 +16,7 @@ import Decimal from 'decimal.js'; import { orderBy, retry } from 'es-toolkit'; import Long from 'long'; import { Hex, PrivateKeyAccount, toBytes, WalletClient } from 'viem'; -import { getLogger, SWAP_STEPS, SwapStepType } from '@nexus/commons'; +import { getLogger, SWAP_STEPS, SwapStepType } from '../../../commons'; import { divDecimals, equalFold, minutesToMs, waitForTxReceipt } from '../utils'; import { EADDRESS, SWEEPER_ADDRESS } from './constants'; import { getTokenDecimals } from './data'; @@ -48,7 +48,7 @@ import { RFFDepositCallMap, SBCTx, Tx, -} from '@nexus/commons'; +} from '../../../commons'; import { SwapRoute } from './route'; import { Errors } from '../errors'; @@ -510,10 +510,7 @@ class DestinationSwapHandler { class SourceSwapsHandler { private disposableCache: { [k: string]: Tx } = {}; private swaps: Map; - constructor( - data: SwapRoute['source'], - private options: Options, - ) { + constructor(data: SwapRoute['source'], private options: Options) { this.swaps = this.groupAndOrder(data.swaps); for (const [chainID, swapQuotes] of this.iterate(this.swaps)) { this.options.cache.addSetCodeQuery({ diff --git a/packages/core/sdk/ca-base/swap/rff.ts b/src/sdk/ca-base/swap/rff.ts similarity index 99% rename from packages/core/sdk/ca-base/swap/rff.ts rename to src/sdk/ca-base/swap/rff.ts index 70d173d9..5bca8e25 100644 --- a/packages/core/sdk/ca-base/swap/rff.ts +++ b/src/sdk/ca-base/swap/rff.ts @@ -13,7 +13,7 @@ import { } from 'viem'; import { Errors } from '../errors'; import { createRFFromIntent } from '../utils'; -import { getLogger, Intent, NetworkConfig } from '@nexus/commons'; +import { getLogger, Intent, NetworkConfig } from '../../../commons'; import { convertAddressByUniverse, evmWaitForFill, @@ -33,7 +33,7 @@ import { RFFDepositCallMap, Tx, ChainListType, -} from '@nexus/commons'; +} from '../../../commons'; const logger = getLogger(); diff --git a/packages/core/sdk/ca-base/swap/route.ts b/src/sdk/ca-base/swap/route.ts similarity index 99% rename from packages/core/sdk/ca-base/swap/route.ts rename to src/sdk/ca-base/swap/route.ts index b222ad57..f7b289ad 100644 --- a/packages/core/sdk/ca-base/swap/route.ts +++ b/src/sdk/ca-base/swap/route.ts @@ -16,14 +16,14 @@ import { import Decimal from 'decimal.js'; import { ByteArray, Hex, toBytes } from 'viem'; import { ZERO_ADDRESS } from '../constants'; -import { getLogger, OraclePriceResponse } from '@nexus/commons'; +import { getLogger, OraclePriceResponse } from '../../../commons'; import { ExactInSwapInput, ExactOutSwapInput, SwapData, SwapMode, SwapParams, -} from '@nexus/commons'; +} from '../../../commons'; import { calculateMaxBridgeFees, convertTo32BytesHex, @@ -44,7 +44,7 @@ import { } from './errors'; import { createIntent } from './rff'; import { calculateValue, convertTo32Bytes, convertToEVMAddress } from './utils'; -import { BridgeAsset } from '@nexus/commons'; +import { BridgeAsset } from '../../../commons'; import { Errors } from '../errors'; const logger = getLogger(); diff --git a/packages/core/sdk/ca-base/swap/sbc.ts b/src/sdk/ca-base/swap/sbc.ts similarity index 99% rename from packages/core/sdk/ca-base/swap/sbc.ts rename to src/sdk/ca-base/swap/sbc.ts index 7bde7248..25e78c22 100644 --- a/packages/core/sdk/ca-base/swap/sbc.ts +++ b/src/sdk/ca-base/swap/sbc.ts @@ -17,7 +17,7 @@ import { waitForTxReceipt } from '../utils'; import CaliburABI from './calibur.abi'; import { CALIBUR_ADDRESS, CALIBUR_EIP712, ZERO_BYTES_20, ZERO_BYTES_32 } from './constants'; import { Cache, convertTo32Bytes, isAuthorizationCodeSet, PublicClientList } from './utils'; -import { getLogger, ChainListType, CaliburSBCTypes, SBCTx, Tx } from '@nexus/commons'; +import { getLogger, ChainListType, CaliburSBCTypes, SBCTx, Tx } from '../../../commons'; const logger = getLogger(); diff --git a/packages/core/sdk/ca-base/swap/swap.ts b/src/sdk/ca-base/swap/swap.ts similarity index 99% rename from packages/core/sdk/ca-base/swap/swap.ts rename to src/sdk/ca-base/swap/swap.ts index 6e46969b..8f23b49a 100644 --- a/packages/core/sdk/ca-base/swap/swap.ts +++ b/src/sdk/ca-base/swap/swap.ts @@ -14,9 +14,9 @@ import { NEXUS_EVENTS, SWAP_STEPS, SwapStepType, -} from '@nexus/commons'; +} from '../../../commons'; -import { getLogger } from '@nexus/commons'; +import { getLogger } from '../../../commons'; import { divDecimals } from '../utils'; import { BEBOP_API_KEY, LIFI_API_KEY, ZERO_BYTES_32 } from './constants'; import { BridgeHandler, DestinationSwapHandler, SourceSwapsHandler } from './ob'; diff --git a/packages/core/sdk/ca-base/swap/utils.ts b/src/sdk/ca-base/swap/utils.ts similarity index 99% rename from packages/core/sdk/ca-base/swap/utils.ts rename to src/sdk/ca-base/swap/utils.ts index ad207325..9c57ae03 100644 --- a/packages/core/sdk/ca-base/swap/utils.ts +++ b/src/sdk/ca-base/swap/utils.ts @@ -43,13 +43,13 @@ import { } from 'viem'; import { ERC20PermitABI, ERC20PermitEIP2612PolygonType, ERC20PermitEIP712Type } from '../abi/erc20'; import { getLogoFromSymbol, ZERO_ADDRESS } from '../constants'; -import { getLogger } from '@nexus/commons'; +import { getLogger } from '../../../commons'; import { Chain, SuccessfulSwapResult, UnifiedBalanceResponseData, UserAssetDatum, -} from '@nexus/commons'; +} from '../../../commons'; import { convertAddressByUniverse, convertTo32BytesHex, @@ -72,7 +72,7 @@ import { SwapIntent, Tx, ChainListType, -} from '@nexus/commons'; +} from '../../../commons'; import Long from 'long'; import { Errors } from '../errors'; @@ -500,8 +500,9 @@ export const determinePermitVariantAndVersion = async ( functionExists(client, contractAddress, daiPermitData), getVersion(client, contractAddress), ]; - const [canonicalPermitResponse, daiPermitResponse, versionResponse] = - await Promise.allSettled(promises); + const [canonicalPermitResponse, daiPermitResponse, versionResponse] = await Promise.allSettled( + promises, + ); let variant = PermitVariant.Unsupported; if (canonicalPermitResponse.status === 'fulfilled') { diff --git a/packages/core/sdk/ca-base/utils/api.utils.ts b/src/sdk/ca-base/utils/api.utils.ts similarity index 99% rename from packages/core/sdk/ca-base/utils/api.utils.ts rename to src/sdk/ca-base/utils/api.utils.ts index 248ea340..b69ae019 100644 --- a/packages/core/sdk/ca-base/utils/api.utils.ts +++ b/src/sdk/ca-base/utils/api.utils.ts @@ -21,7 +21,7 @@ import { SponsoredApprovalDataArray, UnifiedBalanceResponseData, ChainListType, -} from '@nexus/commons'; +} from '../../../commons'; import { convertAddressByUniverse, convertToHexAddressByUniverse, diff --git a/packages/core/sdk/ca-base/utils/balance.utils.ts b/src/sdk/ca-base/utils/balance.utils.ts similarity index 98% rename from packages/core/sdk/ca-base/utils/balance.utils.ts rename to src/sdk/ca-base/utils/balance.utils.ts index d302ddc3..4d8f2739 100644 --- a/packages/core/sdk/ca-base/utils/balance.utils.ts +++ b/src/sdk/ca-base/utils/balance.utils.ts @@ -1,5 +1,5 @@ import { Environment } from '@avail-project/ca-common'; -import { ChainListType, logger, SUPPORTED_CHAINS, UserAssetDatum } from '@nexus/commons'; +import { ChainListType, logger, SUPPORTED_CHAINS, UserAssetDatum } from '../../../commons'; import { // createPublicClientWithFallback, equalFold, @@ -200,8 +200,8 @@ function getBalanceStorageSlot(token: string, chainId: number): number { return token === 'USDC' ? DEFAULT_SLOT.USDC : token === 'USDT' - ? DEFAULT_SLOT.USDT - : DEFAULT_SLOT.ETH; + ? DEFAULT_SLOT.USDT + : DEFAULT_SLOT.ETH; } // export const getGasFeeFromBridgeParams = async (input: MaxBridgeParams, dstChain: Chain) => { diff --git a/packages/core/sdk/ca-base/utils/common.utils.ts b/src/sdk/ca-base/utils/common.utils.ts similarity index 99% rename from packages/core/sdk/ca-base/utils/common.utils.ts rename to src/sdk/ca-base/utils/common.utils.ts index 1bdc882b..1310875c 100644 --- a/packages/core/sdk/ca-base/utils/common.utils.ts +++ b/src/sdk/ca-base/utils/common.utils.ts @@ -36,7 +36,7 @@ import { import { TronWeb } from 'tronweb'; import { ChainList } from '../chains'; import { FUEL_BASE_ASSET_ID, isNativeAddress, ZERO_ADDRESS } from '../constants'; -import { getLogger, IBridgeOptions } from '@nexus/commons'; +import { getLogger, IBridgeOptions } from '../../../commons'; import { EthereumProvider, Intent, @@ -50,7 +50,7 @@ import { NexusNetwork, UserAssetDatum, Chain, -} from '@nexus/commons'; +} from '../../../commons'; import { FeeStore } from './api.utils'; import { requestTimeout, waitForIntentFulfilment } from './contract.utils'; import { cosmosCreateDoubleCheckTx, cosmosFillCheck, cosmosRefundIntent } from './cosmos.utils'; diff --git a/packages/core/sdk/ca-base/utils/contract.utils.ts b/src/sdk/ca-base/utils/contract.utils.ts similarity index 99% rename from packages/core/sdk/ca-base/utils/contract.utils.ts rename to src/sdk/ca-base/utils/contract.utils.ts index 51f11394..5dc4457e 100644 --- a/packages/core/sdk/ca-base/utils/contract.utils.ts +++ b/src/sdk/ca-base/utils/contract.utils.ts @@ -24,14 +24,14 @@ import gasOracleABI from '../abi/gasOracle'; import { FillEvent } from '../abi/vault'; import { ZERO_ADDRESS } from '../constants'; import { Errors } from '../errors'; -import { getLogger } from '@nexus/commons'; +import { getLogger } from '../../../commons'; import { ChainListType, Chain, EVMTransaction, GetAllowanceParams, SetAllowanceParams, -} from '@nexus/commons'; +} from '../../../commons'; import { equalFold, minutesToMs } from './common.utils'; const logger = getLogger(); diff --git a/packages/core/sdk/ca-base/utils/cosmos.utils.ts b/src/sdk/ca-base/utils/cosmos.utils.ts similarity index 99% rename from packages/core/sdk/ca-base/utils/cosmos.utils.ts rename to src/sdk/ca-base/utils/cosmos.utils.ts index 714377aa..0a98a5fa 100644 --- a/packages/core/sdk/ca-base/utils/cosmos.utils.ts +++ b/src/sdk/ca-base/utils/cosmos.utils.ts @@ -11,7 +11,7 @@ import { isDeliverTxFailure, isDeliverTxSuccess } from '@cosmjs/stargate'; import axios from 'axios'; import { connect } from 'it-ws/client'; import Long from 'long'; -import { getLogger } from '@nexus/commons'; +import { getLogger } from '../../../commons'; import { checkIntentFilled, vscCreateFeeGrant } from './api.utils'; import { Errors } from '../errors'; diff --git a/packages/core/sdk/ca-base/utils/index.ts b/src/sdk/ca-base/utils/index.ts similarity index 100% rename from packages/core/sdk/ca-base/utils/index.ts rename to src/sdk/ca-base/utils/index.ts diff --git a/packages/core/sdk/ca-base/utils/rff.utils.ts b/src/sdk/ca-base/utils/rff.utils.ts similarity index 99% rename from packages/core/sdk/ca-base/utils/rff.utils.ts rename to src/sdk/ca-base/utils/rff.utils.ts index 6ffefe14..adb3c4a6 100644 --- a/packages/core/sdk/ca-base/utils/rff.utils.ts +++ b/src/sdk/ca-base/utils/rff.utils.ts @@ -1,6 +1,6 @@ import { MsgCreateRequestForFunds, OmniversalRFF, Universe } from '@avail-project/ca-common'; import { FUEL_BASE_ASSET_ID, INTENT_EXPIRY, isNativeAddress, ZERO_ADDRESS } from '../constants'; -import { getLogger, ChainListType, Intent, IBridgeOptions, BridgeAsset } from '@nexus/commons'; +import { getLogger, ChainListType, Intent, IBridgeOptions, BridgeAsset } from '../../../commons'; import { convertTo32Bytes, convertTo32BytesHex, diff --git a/packages/core/sdk/ca-base/utils/tron.utils.ts b/src/sdk/ca-base/utils/tron.utils.ts similarity index 100% rename from packages/core/sdk/ca-base/utils/tron.utils.ts rename to src/sdk/ca-base/utils/tron.utils.ts diff --git a/packages/core/sdk/index.ts b/src/sdk/index.ts similarity index 97% rename from packages/core/sdk/index.ts rename to src/sdk/index.ts index 968d4fdb..60bca2df 100644 --- a/packages/core/sdk/index.ts +++ b/src/sdk/index.ts @@ -25,8 +25,8 @@ import type { OnEventParam, BridgeMaxResult, OnSwapIntentHook, -} from '@nexus/commons'; -import { logger } from '@nexus/commons'; +} from '../commons'; +import { logger } from '../commons'; import { CA } from './ca-base'; import { AdapterProps } from '@tronweb3/tronwallet-abstract-adapter'; @@ -116,7 +116,9 @@ export class NexusSDK extends CA { /** * Simulate transfer transaction to get costs and fees */ - public async simulateBridgeAndTransfer(params: TransferParams): Promise { + public async simulateBridgeAndTransfer( + params: TransferParams, + ): Promise { return this._simulateBridgeAndTransfer(params); } diff --git a/packages/core/sdk/utils.ts b/src/sdk/utils.ts similarity index 98% rename from packages/core/sdk/utils.ts rename to src/sdk/utils.ts index 7d3929cb..6af80100 100644 --- a/packages/core/sdk/utils.ts +++ b/src/sdk/utils.ts @@ -15,7 +15,7 @@ import { ChainListType, formatTokenBalance, formatTokenBalanceParts, -} from '@nexus/commons'; +} from '../commons'; import { getCoinbasePrices, getSupportedChains } from './ca-base/utils'; import { getSwapSupportedChains } from './ca-base/swap/utils'; diff --git a/tsconfig.json b/tsconfig.json index 95dd3671..29316c44 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,9 +1,8 @@ { "compilerOptions": { - "target": "es2020", + "target": "es2024", "module": "esnext", "lib": ["dom", "esnext"], - "importHelpers": true, "declaration": true, "sourceMap": true, "strict": true, @@ -16,15 +15,7 @@ "skipLibCheck": true, "forceConsistentCasingInFileNames": true, "allowSyntheticDefaultImports": true, - "resolveJsonModule": true, - "baseUrl": ".", - "paths": { - "@avail-project/nexus-core": ["packages/core/index.ts"], - "@avail-project/nexus-core/*": ["packages/core/*"], - "@nexus/commons": ["packages/commons/index.ts"], - "@nexus/commons/*": ["packages/commons/*"] - } + "resolveJsonModule": true }, - "include": ["packages/**/*"], - "exclude": ["node_modules", "**/dist", "**/node_modules"] + "include": ["src/**/*"] } From 8202f6ba15fbbec04bc6ef36b9cb6992ce205e37 Mon Sep 17 00:00:00 2001 From: Abhishek Date: Thu, 13 Nov 2025 16:42:29 +0400 Subject: [PATCH 08/51] fix: updated to using bigint in bridge and bridgeAndTransfer (#69) --- README.md | 12 ++++++------ src/commons/types/index.ts | 4 ++-- src/sdk/ca-base/query/bridgeAndExecute.ts | 4 ++-- src/sdk/ca-base/query/bridgeAndTransfer.ts | 8 +++----- src/sdk/ca-base/requestHandlers/helpers.ts | 3 +-- 5 files changed, 14 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index fff555fe..04cf32e7 100644 --- a/README.md +++ b/README.md @@ -39,7 +39,7 @@ console.log('Balances:', balances); const bridgeResult = await sdk.bridge( { token: 'USDC', - amount: "1.5", + amount: 1_500_000n, recipient: '0x...' // Optional chainId: 137, // Polygon }, @@ -57,7 +57,7 @@ const bridgeResult = await sdk.bridge( const transferResult = await sdk.bridgeAndTransfer( { token: 'ETH', - amount: "1.5", + amount: 1_500_000n, chainId: 1, // Ethereum recipient: '0x742d35Cc6634C0532925a3b8D4C9db96c4b4Db45', }, @@ -248,8 +248,8 @@ const allBalances = await sdk.getUnifiedBalances(true); // Includes swappable to ## 🌉 Bridge Operations ```typescript -const result = await sdk.bridge({ token: 'USDC', amount: '83.50', chainId: 137 }); -const simulation = await sdk.simulateBridge({ token: 'USDC', amount: '83.50', chainId: 137 }); +const result = await sdk.bridge({ token: 'USDC', amount: 83_500_000n, chainId: 137 }); +const simulation = await sdk.simulateBridge({ token: 'USDC', amount: 83_500_000n, chainId: 137 }); ``` --- @@ -259,13 +259,13 @@ const simulation = await sdk.simulateBridge({ token: 'USDC', amount: '83.50', ch ```typescript const result = await sdk.bridgeAndTransfer({ token: 'USDC', - amount: '1.53', + amount: 1_530_000n, chainId: 42161, recipient: '0x...', }); const simulation = await sdk.simulateBridgeAndTransfer({ token: 'USDC', - amount: '1.53', + amount: 1_530_000n, // = 1.53 USDC chainId: 42161, recipient: '0x...', }); diff --git a/src/commons/types/index.ts b/src/commons/types/index.ts index bc4ab826..407d8854 100644 --- a/src/commons/types/index.ts +++ b/src/commons/types/index.ts @@ -102,7 +102,7 @@ export type DynamicParamBuilder = ( export interface BridgeParams { recipient?: Hex; token: string; - amount: string; + amount: bigint; toChainId: number; gas?: bigint; sourceChains?: number[]; @@ -144,7 +144,7 @@ export type TronAdapter = AdapterProps & { */ export interface TransferParams { token: string; - amount: string; + amount: bigint; toChainId: number; recipient: `0x${string}`; sourceChains?: number[]; diff --git a/src/sdk/ca-base/query/bridgeAndExecute.ts b/src/sdk/ca-base/query/bridgeAndExecute.ts index 27b7b8be..51767b22 100644 --- a/src/sdk/ca-base/query/bridgeAndExecute.ts +++ b/src/sdk/ca-base/query/bridgeAndExecute.ts @@ -182,7 +182,7 @@ class BridgeAndExecuteQuery { if (!skipBridge) { bridgeResult = await this.simulateBridgeWrapper({ token: token.symbol, - amount: divDecimals(BigInt(tokenAmount), token.decimals).toFixed(), + amount: tokenAmount, toChainId: params.toChainId, sourceChains: params.sourceChains, gas: gasAmount, @@ -250,7 +250,7 @@ class BridgeAndExecuteQuery { bridgeResult = await this.bridgeWrapper( { token: token.symbol, - amount: divDecimals(BigInt(tokenAmount), token.decimals).toFixed(), + amount: tokenAmount, toChainId: params.toChainId, sourceChains: params.sourceChains, gas: gasAmount, diff --git a/src/sdk/ca-base/query/bridgeAndTransfer.ts b/src/sdk/ca-base/query/bridgeAndTransfer.ts index 5b9e8808..12f9096c 100644 --- a/src/sdk/ca-base/query/bridgeAndTransfer.ts +++ b/src/sdk/ca-base/query/bridgeAndTransfer.ts @@ -13,12 +13,10 @@ const createBridgeAndTransferParams = ( throw Errors.tokenNotFound(input.token, input.toChainId); } - const tokenAmountInBigint = mulDecimals(input.amount, token.decimals); - const tx: Tx = token.isNative ? { to: input.recipient, - value: tokenAmountInBigint, + value: input.amount, data: '0x', } : { @@ -27,13 +25,13 @@ const createBridgeAndTransferParams = ( data: encodeFunctionData({ abi: ERC20ABI, functionName: 'transfer', - args: [input.recipient, tokenAmountInBigint], + args: [input.recipient, input.amount], }), }; return { toChainId: input.toChainId, - amount: tokenAmountInBigint, + amount: input.amount, token: input.token, execute: tx, }; diff --git a/src/sdk/ca-base/requestHandlers/helpers.ts b/src/sdk/ca-base/requestHandlers/helpers.ts index 376b55be..f351852b 100644 --- a/src/sdk/ca-base/requestHandlers/helpers.ts +++ b/src/sdk/ca-base/requestHandlers/helpers.ts @@ -1,5 +1,4 @@ import { Errors } from '../errors'; -import { mulDecimals } from '../utils'; import { BridgeParams, ChainListType } from '../../../commons'; const createBridgeParams = (input: BridgeParams, chainList: ChainListType) => { @@ -12,7 +11,7 @@ const createBridgeParams = (input: BridgeParams, chainList: ChainListType) => { } const params = { - tokenAmount: mulDecimals(input.amount, dstToken.decimals), + tokenAmount: input.amount, nativeAmount: input.gas ?? 0n, dstToken, dstChain, From ccd770e8466326a913bd81e6333e90a7c3b6d6ef Mon Sep 17 00:00:00 2001 From: Jeremy Date: Thu, 13 Nov 2025 12:47:05 -0300 Subject: [PATCH 09/51] feat: Adds opentelemetry and emit logs on Error cases. --- package-lock.json | 237 ++++++++++++++++++++++++++++++++++ package.json | 4 + src/sdk/ca-base/nexusError.ts | 11 +- src/sdk/telemetry.ts | 20 +++ 4 files changed, 271 insertions(+), 1 deletion(-) create mode 100644 src/sdk/telemetry.ts diff --git a/package-lock.json b/package-lock.json index 45eb58d4..c7817da8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,6 +13,10 @@ "@cosmjs/proto-signing": "^0.34.0", "@cosmjs/stargate": "^0.34.0", "@metamask/safe-event-emitter": "3.1.2", + "@opentelemetry/api-logs": "0.208.0", + "@opentelemetry/exporter-logs-otlp-http": "0.208.0", + "@opentelemetry/resources": "2.2.0", + "@opentelemetry/sdk-logs": "0.208.0", "@starkware-industries/starkware-crypto-utils": "^0.2.1", "@tronweb3/tronwallet-abstract-adapter": "^1.1.9", "axios": "^1.12.2", @@ -1216,6 +1220,162 @@ "url": "https://paulmillr.com/funding/" } }, + "node_modules/@opentelemetry/api": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/api/-/api-1.9.0.tgz", + "integrity": "sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg==", + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/@opentelemetry/api-logs": { + "version": "0.208.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/api-logs/-/api-logs-0.208.0.tgz", + "integrity": "sha512-CjruKY9V6NMssL/T1kAFgzosF1v9o6oeN+aX5JB/C/xPNtmgIJqcXHG7fA82Ou1zCpWGl4lROQUKwUNE1pMCyg==", + "dependencies": { + "@opentelemetry/api": "^1.3.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/@opentelemetry/core": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-2.2.0.tgz", + "integrity": "sha512-FuabnnUm8LflnieVxs6eP7Z383hgQU4W1e3KJS6aOG3RxWxcHyBxH8fDMHNgu/gFx/M2jvTOW/4/PHhLz6bjWw==", + "dependencies": { + "@opentelemetry/semantic-conventions": "^1.29.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.0.0 <1.10.0" + } + }, + "node_modules/@opentelemetry/exporter-logs-otlp-http": { + "version": "0.208.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-logs-otlp-http/-/exporter-logs-otlp-http-0.208.0.tgz", + "integrity": "sha512-jOv40Bs9jy9bZVLo/i8FwUiuCvbjWDI+ZW13wimJm4LjnlwJxGgB+N/VWOZUTpM+ah/awXeQqKdNlpLf2EjvYg==", + "dependencies": { + "@opentelemetry/api-logs": "0.208.0", + "@opentelemetry/core": "2.2.0", + "@opentelemetry/otlp-exporter-base": "0.208.0", + "@opentelemetry/otlp-transformer": "0.208.0", + "@opentelemetry/sdk-logs": "0.208.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/otlp-exporter-base": { + "version": "0.208.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-exporter-base/-/otlp-exporter-base-0.208.0.tgz", + "integrity": "sha512-gMd39gIfVb2OgxldxUtOwGJYSH8P1kVFFlJLuut32L6KgUC4gl1dMhn+YC2mGn0bDOiQYSk/uHOdSjuKp58vvA==", + "dependencies": { + "@opentelemetry/core": "2.2.0", + "@opentelemetry/otlp-transformer": "0.208.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/otlp-transformer": { + "version": "0.208.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-transformer/-/otlp-transformer-0.208.0.tgz", + "integrity": "sha512-DCFPY8C6lAQHUNkzcNT9R+qYExvsk6C5Bto2pbNxgicpcSWbe2WHShLxkOxIdNcBiYPdVHv/e7vH7K6TI+C+fQ==", + "dependencies": { + "@opentelemetry/api-logs": "0.208.0", + "@opentelemetry/core": "2.2.0", + "@opentelemetry/resources": "2.2.0", + "@opentelemetry/sdk-logs": "0.208.0", + "@opentelemetry/sdk-metrics": "2.2.0", + "@opentelemetry/sdk-trace-base": "2.2.0", + "protobufjs": "^7.3.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/resources": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-2.2.0.tgz", + "integrity": "sha512-1pNQf/JazQTMA0BiO5NINUzH0cbLbbl7mntLa4aJNmCCXSj0q03T5ZXXL0zw4G55TjdL9Tz32cznGClf+8zr5A==", + "dependencies": { + "@opentelemetry/core": "2.2.0", + "@opentelemetry/semantic-conventions": "^1.29.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.3.0 <1.10.0" + } + }, + "node_modules/@opentelemetry/sdk-logs": { + "version": "0.208.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-logs/-/sdk-logs-0.208.0.tgz", + "integrity": "sha512-QlAyL1jRpOeaqx7/leG1vJMp84g0xKP6gJmfELBpnI4O/9xPX+Hu5m1POk9Kl+veNkyth5t19hRlN6tNY1sjbA==", + "dependencies": { + "@opentelemetry/api-logs": "0.208.0", + "@opentelemetry/core": "2.2.0", + "@opentelemetry/resources": "2.2.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.4.0 <1.10.0" + } + }, + "node_modules/@opentelemetry/sdk-metrics": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-metrics/-/sdk-metrics-2.2.0.tgz", + "integrity": "sha512-G5KYP6+VJMZzpGipQw7Giif48h6SGQ2PFKEYCybeXJsOCB4fp8azqMAAzE5lnnHK3ZVwYQrgmFbsUJO/zOnwGw==", + "dependencies": { + "@opentelemetry/core": "2.2.0", + "@opentelemetry/resources": "2.2.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.9.0 <1.10.0" + } + }, + "node_modules/@opentelemetry/sdk-trace-base": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-2.2.0.tgz", + "integrity": "sha512-xWQgL0Bmctsalg6PaXExmzdedSp3gyKV8mQBwK/j9VGdCDu2fmXIb2gAehBKbkXCpJ4HPkgv3QfoJWRT4dHWbw==", + "dependencies": { + "@opentelemetry/core": "2.2.0", + "@opentelemetry/resources": "2.2.0", + "@opentelemetry/semantic-conventions": "^1.29.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.3.0 <1.10.0" + } + }, + "node_modules/@opentelemetry/semantic-conventions": { + "version": "1.38.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.38.0.tgz", + "integrity": "sha512-kocjix+/sSggfJhwXqClZ3i9Y/MI0fp7b+g7kCRm6psy2dsf8uApTRclwG18h8Avm7C9+fnt+O36PspJ/OzoWg==", + "engines": { + "node": ">=14" + } + }, "node_modules/@pkgjs/parseargs": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", @@ -1226,6 +1386,60 @@ "node": ">=14" } }, + "node_modules/@protobufjs/aspromise": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", + "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==" + }, + "node_modules/@protobufjs/base64": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", + "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==" + }, + "node_modules/@protobufjs/codegen": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz", + "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==" + }, + "node_modules/@protobufjs/eventemitter": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", + "integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==" + }, + "node_modules/@protobufjs/fetch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz", + "integrity": "sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==", + "dependencies": { + "@protobufjs/aspromise": "^1.1.1", + "@protobufjs/inquire": "^1.1.0" + } + }, + "node_modules/@protobufjs/float": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", + "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==" + }, + "node_modules/@protobufjs/inquire": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz", + "integrity": "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==" + }, + "node_modules/@protobufjs/path": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", + "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==" + }, + "node_modules/@protobufjs/pool": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", + "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==" + }, + "node_modules/@protobufjs/utf8": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", + "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==" + }, "node_modules/@rollup/plugin-commonjs": { "version": "25.0.8", "resolved": "https://registry.npmjs.org/@rollup/plugin-commonjs/-/plugin-commonjs-25.0.8.tgz", @@ -4757,6 +4971,29 @@ "integrity": "sha512-SVtmxhRE/CGkn3eZY1T6pC8Nln6Fr/lu1mKSgRud0eC73whjGfoAogbn78LkD8aFL0zz3bAFerKSnOl7NlErBA==", "license": "MIT" }, + "node_modules/protobufjs": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.5.4.tgz", + "integrity": "sha512-CvexbZtbov6jW2eXAvLukXjXUW1TzFaivC46BpWc/3BpcCysb5Vffu+B3XHMm8lVEuy2Mm4XGex8hBSg1yapPg==", + "hasInstallScript": true, + "dependencies": { + "@protobufjs/aspromise": "^1.1.2", + "@protobufjs/base64": "^1.1.2", + "@protobufjs/codegen": "^2.0.4", + "@protobufjs/eventemitter": "^1.1.0", + "@protobufjs/fetch": "^1.1.0", + "@protobufjs/float": "^1.0.2", + "@protobufjs/inquire": "^1.1.0", + "@protobufjs/path": "^1.1.2", + "@protobufjs/pool": "^1.1.0", + "@protobufjs/utf8": "^1.1.0", + "@types/node": ">=13.7.0", + "long": "^5.0.0" + }, + "engines": { + "node": ">=12.0.0" + } + }, "node_modules/proxy-from-env": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", diff --git a/package.json b/package.json index 9288204f..94c43aaa 100644 --- a/package.json +++ b/package.json @@ -40,6 +40,10 @@ "@cosmjs/proto-signing": "^0.34.0", "@cosmjs/stargate": "^0.34.0", "@metamask/safe-event-emitter": "3.1.2", + "@opentelemetry/api-logs": "0.208.0", + "@opentelemetry/exporter-logs-otlp-http": "0.208.0", + "@opentelemetry/resources": "2.2.0", + "@opentelemetry/sdk-logs": "0.208.0", "@starkware-industries/starkware-crypto-utils": "^0.2.1", "@tronweb3/tronwallet-abstract-adapter": "^1.1.9", "axios": "^1.12.2", diff --git a/src/sdk/ca-base/nexusError.ts b/src/sdk/ca-base/nexusError.ts index ceefca9d..ca925df2 100644 --- a/src/sdk/ca-base/nexusError.ts +++ b/src/sdk/ca-base/nexusError.ts @@ -1,3 +1,5 @@ +import { AnyValueMap, SeverityNumber } from '@opentelemetry/api-logs'; +import telemetryLogger from '../telemetry'; export interface NexusErrorData { context?: string; // Where or why it happened cause?: unknown; // Optional nested error @@ -52,7 +54,14 @@ export const ERROR_CODES = { export type ErrorCode = (typeof ERROR_CODES)[keyof typeof ERROR_CODES]; export function createError(code: ErrorCode, message: string, data?: NexusErrorData): NexusError { - return new NexusError(code, message, data); + const nexusError = new NexusError(code, message, data); + telemetryLogger.emit({ + body: message, + severityNumber: SeverityNumber.ERROR, + severityText: 'ERROR', + attributes: data as AnyValueMap + }) + return nexusError } /* --- Expected handling --- diff --git a/src/sdk/telemetry.ts b/src/sdk/telemetry.ts new file mode 100644 index 00000000..44a717c8 --- /dev/null +++ b/src/sdk/telemetry.ts @@ -0,0 +1,20 @@ +import { LoggerProvider, BatchLogRecordProcessor } from '@opentelemetry/sdk-logs'; +import { OTLPLogExporter } from '@opentelemetry/exporter-logs-otlp-http'; +import { logs } from '@opentelemetry/api-logs'; +import { resourceFromAttributes } from '@opentelemetry/resources'; + +const resource = resourceFromAttributes({ 'service.name': 'nexus-sdk-internal-logs' }); + +const loggerProvider = new LoggerProvider({ + resource: resource, + processors: [ + new BatchLogRecordProcessor(new OTLPLogExporter({ + url: 'https://otel.avail.so/v1/logs', + })) + ] +}); + +logs.setGlobalLoggerProvider(loggerProvider); +const telemetryLogger = logs.getLogger('nexus-telemetry-logger'); + +export default telemetryLogger; \ No newline at end of file From 26c894a6af026ceedd08899a0da32e3c73386719 Mon Sep 17 00:00:00 2001 From: Jeremy Date: Thu, 13 Nov 2025 12:48:55 -0300 Subject: [PATCH 10/51] lint EOF --- src/sdk/telemetry.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sdk/telemetry.ts b/src/sdk/telemetry.ts index 44a717c8..c1aa76e1 100644 --- a/src/sdk/telemetry.ts +++ b/src/sdk/telemetry.ts @@ -17,4 +17,4 @@ const loggerProvider = new LoggerProvider({ logs.setGlobalLoggerProvider(loggerProvider); const telemetryLogger = logs.getLogger('nexus-telemetry-logger'); -export default telemetryLogger; \ No newline at end of file +export default telemetryLogger; From 5ea77cb487717796807fadadac6ad9b2fc1f0304 Mon Sep 17 00:00:00 2001 From: Jeremy Date: Thu, 13 Nov 2025 19:33:55 -0300 Subject: [PATCH 11/51] fix: Add header to allow wildcard CORS origin --- src/sdk/telemetry.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/sdk/telemetry.ts b/src/sdk/telemetry.ts index c1aa76e1..5b9fa51e 100644 --- a/src/sdk/telemetry.ts +++ b/src/sdk/telemetry.ts @@ -10,6 +10,7 @@ const loggerProvider = new LoggerProvider({ processors: [ new BatchLogRecordProcessor(new OTLPLogExporter({ url: 'https://otel.avail.so/v1/logs', + headers: { 'x-otlp-force-fetch': '1' } })) ] }); From 03dd94ad2c1ff4de4095f5d0a52338b0738deba9 Mon Sep 17 00:00:00 2001 From: Jeremy Date: Thu, 13 Nov 2025 22:37:30 -0300 Subject: [PATCH 12/51] fix: Failed tsc validation + bumps script for build --- package.json | 1 + scripts/local-pack.sh | 16 +++------------- src/sdk/ca-base/query/bridgeAndExecute.ts | 1 - src/sdk/ca-base/query/bridgeAndTransfer.ts | 1 - 4 files changed, 4 insertions(+), 15 deletions(-) diff --git a/package.json b/package.json index 9288204f..ebd7830c 100644 --- a/package.json +++ b/package.json @@ -12,6 +12,7 @@ "scripts": { "build": "rollup -c", "dev": "rollup -c -w", + "clean": "rimraf dist dist-tarballs", "typecheck": "tsc --noEmit" }, "sideEffects": false, diff --git a/scripts/local-pack.sh b/scripts/local-pack.sh index c5f1008b..53307055 100755 --- a/scripts/local-pack.sh +++ b/scripts/local-pack.sh @@ -19,22 +19,13 @@ DEST_DIR="$ROOT_DIR/dist-tarballs" cd "$ROOT_DIR" -# Pre-flight -if [[ ! -f package.json ]] || [[ ! -d packages ]]; then - err "Run from repo root" - exit 1 -fi - -mkdir -p "$DEST_DIR" - info "Cleaning and building packages..." -pnpm run clean -pnpm -F @nexus/commons build -pnpm -F @avail-project/nexus-core build +npm run clean +npm -F run build +mkdir -p "$DEST_DIR" # Pack core (already named @avail-project/nexus-core; remove workspace-only deps) info "Packing core as @avail-project/nexus-core (local tarball)..." -pushd packages/core >/dev/null cp package.json package.json.backup # Remove @nexus/commons (bundled into dist) @@ -42,7 +33,6 @@ node -e "const fs=require('fs');const p=JSON.parse(fs.readFileSync('package.json CORE_TARBALL=$(npm pack --pack-destination "$DEST_DIR" --silent) mv package.json.backup package.json -popd >/dev/null info "Created core tarball: $DEST_DIR/$CORE_TARBALL (name: @avail-project/nexus-core)" diff --git a/src/sdk/ca-base/query/bridgeAndExecute.ts b/src/sdk/ca-base/query/bridgeAndExecute.ts index 51767b22..bdf0338e 100644 --- a/src/sdk/ca-base/query/bridgeAndExecute.ts +++ b/src/sdk/ca-base/query/bridgeAndExecute.ts @@ -28,7 +28,6 @@ import { } from 'viem'; import { createExplorerTxURL, - divDecimals, mulDecimals, UserAssets, waitForTxReceipt, diff --git a/src/sdk/ca-base/query/bridgeAndTransfer.ts b/src/sdk/ca-base/query/bridgeAndTransfer.ts index 12f9096c..4b879fe3 100644 --- a/src/sdk/ca-base/query/bridgeAndTransfer.ts +++ b/src/sdk/ca-base/query/bridgeAndTransfer.ts @@ -1,4 +1,3 @@ -import { mulDecimals } from '../utils'; import { ChainListType, BridgeAndExecuteParams, Tx, TransferParams } from '../../../commons'; import { encodeFunctionData } from 'viem'; import { ERC20ABI } from '@avail-project/ca-common'; From 4a801033184c976162860d36d1384a071138bd2c Mon Sep 17 00:00:00 2001 From: Jeremy Date: Fri, 14 Nov 2025 00:03:52 -0300 Subject: [PATCH 13/51] feat: Enhance log attributes --- src/sdk/ca-base/nexusError.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/sdk/ca-base/nexusError.ts b/src/sdk/ca-base/nexusError.ts index ca925df2..4b7f9f36 100644 --- a/src/sdk/ca-base/nexusError.ts +++ b/src/sdk/ca-base/nexusError.ts @@ -59,7 +59,11 @@ export function createError(code: ErrorCode, message: string, data?: NexusErrorD body: message, severityNumber: SeverityNumber.ERROR, severityText: 'ERROR', - attributes: data as AnyValueMap + attributes: { + data: nexusError.data, + cause: nexusError.cause, + stackTrace: nexusError.stack + } as AnyValueMap }) return nexusError } From 8f796346bab9e90e0037c0b1fe7062b5fc76b05b Mon Sep 17 00:00:00 2001 From: Abhishek Date: Fri, 14 Nov 2025 09:48:56 +0400 Subject: [PATCH 14/51] fix: checking recipient before defaulting to self, removed arcana wallet check (#74) * fix: checking recipient before defaulting to self, removed arcana wallet check * fix: removed unused variable * fix: default to min allowance when hook is not set --- package.json | 2 +- src/commons/utils/index.ts | 215 +-------------------- src/sdk/ca-base/ca.ts | 16 +- src/sdk/ca-base/requestHandlers/bridge.ts | 2 +- src/sdk/ca-base/requestHandlers/helpers.ts | 2 +- src/sdk/ca-base/utils/common.utils.ts | 10 - 6 files changed, 13 insertions(+), 234 deletions(-) diff --git a/package.json b/package.json index ebd7830c..5d153eab 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@avail-project/nexus-core", - "version": "1.0.0-beta.26", + "version": "1.0.0-beta.28", "description": "Nexus headless SDK for cross-chain transactions", "main": "./dist/index.js", "module": "./dist/index.esm.js", diff --git a/src/commons/utils/index.ts b/src/commons/utils/index.ts index 08f0a52a..2a2b7d1d 100644 --- a/src/commons/utils/index.ts +++ b/src/commons/utils/index.ts @@ -4,7 +4,6 @@ import { MAINNET_CHAINS, TESTNET_CHAINS, TESTNET_TOKEN_METADATA, - TOKEN_CONTRACT_ADDRESSES, } from '../constants'; import Decimal from 'decimal.js'; import { @@ -12,20 +11,8 @@ import { SUPPORTED_CHAINS_IDS, SUPPORTED_TOKENS, TokenMetadata, - EthereumProvider, - Block, - TransactionReceipt, } from '../types/index'; -import { - encodeFunctionData, - type Abi, - type Address, - type Chain, - isAddress, - isHash, - createPublicClient, - custom, -} from 'viem'; +import { encodeFunctionData, type Abi, type Address, type Chain, isAddress, isHash } from 'viem'; import { mainnet, polygon, arbitrum, optimism, base } from 'viem/chains'; import { logger } from '../utils/logger'; @@ -291,206 +278,6 @@ export function getBlockExplorerUrl(chainId: number, txHash: string): string { return `${baseUrl}/tx/${txHash}`; } -/** - * Search for transaction hash in block transactions - */ -async function searchTransactionInBlock( - provider: EthereumProvider, - fromAddress: string, -): Promise<`0x${string}` | null> { - const latestBlock = (await provider.request({ - method: 'eth_getBlockByNumber', - params: ['latest', true], - })) as Block; - - if (!latestBlock?.transactions) return null; - - for (const tx of latestBlock.transactions) { - if (tx.from?.toLowerCase() === fromAddress.toLowerCase()) { - if (validateTransactionHash(tx.hash)) { - return tx.hash; - } - } - } - - return null; -} - -/** - * Poll for transaction hash with timeout - */ -async function pollForTransactionHash( - provider: EthereumProvider, - fromAddress: string, - timeout: number, -): Promise<{ success: boolean; hash?: `0x${string}`; error?: string }> { - const startTime = Date.now(); - - while (Date.now() - startTime < timeout) { - const hash = await searchTransactionInBlock(provider, fromAddress); - if (hash) { - return { success: true, hash }; - } - await wait(2000); - } - - return { success: false, error: 'Transaction hash not found within timeout period' }; -} - -/** - * Get transaction hash with multiple fallback strategies - */ -export async function getTransactionHashWithFallback( - provider: EthereumProvider, - response: unknown, - options: { - enablePolling?: boolean; - timeout?: number; - fromAddress?: string; - } = {}, -): Promise<{ success: boolean; hash?: `0x${string}`; error?: string }> { - const { enablePolling = false, timeout = 30000, fromAddress } = options; - - // Strategy 1: Direct response validation - if (validateTransactionHash(response)) { - return { success: true, hash: response }; - } - - // Strategy 2: Transaction polling (if enabled) - if (enablePolling && fromAddress) { - try { - return await pollForTransactionHash(provider, fromAddress, timeout); - } catch (error) { - return { - success: false, - error: `Transaction polling failed: ${extractErrorMessage(error, 'polling')}`, - }; - } - } - - return { - success: false, - error: `Invalid transaction hash response: ${typeof response}${enablePolling ? ' (polling disabled)' : ''}`, - }; -} - -/** - * Enhanced transaction receipt waiting using Viem - */ -export async function waitForTransactionReceipt( - provider: EthereumProvider, - txHash: `0x${string}`, - options: { - timeout?: number; - requiredConfirmations?: number; - pollingInterval?: number; - } = {}, - chainId: number = 1, -): Promise<{ - success: boolean; - receipt?: TransactionReceipt; - confirmations?: number; - error?: string; -}> { - const { - timeout = 300000, // 5 minutes default - requiredConfirmations = 1, - pollingInterval = 2000, - } = options; - - try { - const client = createPublicClient({ - chain: getViemChain(chainId), - transport: custom(provider), - }); - - // Use Viem's waitForTransactionReceipt with timeout - const receipt = await client.waitForTransactionReceipt({ - hash: txHash, - timeout, - pollingInterval, - }); - - // Check transaction status - if (receipt.status === 'reverted') { - return { - success: false, - error: 'Transaction failed (reverted)', - receipt, - }; - } - - // Get current block number for confirmation count - const currentBlock = await client.getBlockNumber(); - const confirmations = Number(currentBlock - receipt.blockNumber) + 1; - - // Check if we have enough confirmations - if (confirmations >= requiredConfirmations) { - return { - success: true, - receipt, - confirmations, - }; - } - - const confirmationStartTime = Date.now(); - const confirmationTimeout = timeout || 300000; - - // Wait for additional confirmations if needed - while (true) { - await wait(pollingInterval); - - if (Date.now() - confirmationStartTime > confirmationTimeout) { - return { - success: false, - error: `Confirmation timeout: only ${confirmations} of ${requiredConfirmations} confirmations received`, - receipt, - confirmations, - }; - } - - const latestBlock = await client.getBlockNumber(); - const currentConfirmations = Number(latestBlock - receipt.blockNumber) + 1; - - if (currentConfirmations >= requiredConfirmations) { - return { - success: true, - receipt, - confirmations: currentConfirmations, - }; - } - } - } catch (error) { - const errorMessage = - error instanceof Error - ? error.message - : (error as { shortMessage?: string; message?: string })?.shortMessage || - (error as { shortMessage?: string; message?: string })?.message || - 'Transaction receipt timeout'; - return { - success: false, - error: errorMessage, - }; - } -} - -/** - * Utility function to get token contract address for a specific token and chain - * @param token Token symbol (e.g., 'USDC', 'USDT') - * @param chainId Chain ID - * @param isTestnet Whether to use testnet addresses - * @returns Contract address or undefined if not found - */ -export function getTokenContractAddress( - token: SUPPORTED_TOKENS, - chainId: SUPPORTED_CHAINS_IDS, -): string | undefined { - const registry = TOKEN_CONTRACT_ADDRESSES; - // @ts-expect-error - const address = registry[token]?.[chainId]; - return address || undefined; -} - // Export logger utilities from commons export { LOG_LEVEL, diff --git a/src/sdk/ca-base/ca.ts b/src/sdk/ca-base/ca.ts index 6779478b..219cb9f1 100644 --- a/src/sdk/ca-base/ca.ts +++ b/src/sdk/ca-base/ca.ts @@ -49,7 +49,6 @@ import { fetchMyIntents, getSDKConfig, getSupportedChains, - isArcanaWallet, minutesToMs, refundExpiredIntents, tronHexToEvmAddress, @@ -113,12 +112,11 @@ export class CA { onIntent: OnIntentHook; onSwapIntent: OnSwapIntentHook; } = { - onAllowance: (data) => data.allow(data.sources.map(() => 'max')), + onAllowance: (data) => data.allow(data.sources.map(() => 'min')), onIntent: (data) => data.allow(), onSwapIntent: (data) => data.allow(), }; protected _initStatus = INIT_STATUS.CREATED; - protected _isArcanaProvider = false; protected _networkConfig: NetworkConfig; protected _refundInterval: number | undefined; protected _initPromise: Promise | null = null; @@ -151,7 +149,7 @@ export class CA { chainList: this.chainList, cosmos: this.#cosmos!, fuel: this._fuel, - evm: this._evm!, + evm: this._evm, hooks: this._hooks, tron: this._tron, networkConfig: this._networkConfig, @@ -162,10 +160,14 @@ export class CA { }; protected async _calculateMaxForBridge(params: Omit) { + if (!this._evm) { + throw Errors.sdkNotInitialized(); + } + return getMaxValueForBridge(params, { chainList: this.chainList, fuel: this._fuel, - evm: this._evm!, + evm: this._evm, tron: this._tron, networkConfig: this._networkConfig, }); @@ -176,10 +178,12 @@ export class CA { if (this._evm) { this._evm.provider.removeListener('accountsChanged', this.onAccountsChanged); } + if (this._refundInterval) { clearInterval(this._refundInterval); this._refundInterval = undefined; } + this._initStatus = INIT_STATUS.CREATED; }; @@ -320,8 +324,6 @@ export class CA { provider, address, }; - - this._isArcanaProvider = isArcanaWallet(provider); } public async _setTronAdapter(adapter: TronAdapter) { diff --git a/src/sdk/ca-base/requestHandlers/bridge.ts b/src/sdk/ca-base/requestHandlers/bridge.ts index 8572b529..5a89685a 100644 --- a/src/sdk/ca-base/requestHandlers/bridge.ts +++ b/src/sdk/ca-base/requestHandlers/bridge.ts @@ -92,7 +92,7 @@ class BridgeHandler { constructor(params: Params, readonly options: IBridgeOptions) { this.params = { ...params, - recipient: retrieveAddress(params.dstChain.universe, options), + recipient: params.recipient ?? retrieveAddress(params.dstChain.universe, options), }; console.log({ params: this.params, options }); } diff --git a/src/sdk/ca-base/requestHandlers/helpers.ts b/src/sdk/ca-base/requestHandlers/helpers.ts index f351852b..47315285 100644 --- a/src/sdk/ca-base/requestHandlers/helpers.ts +++ b/src/sdk/ca-base/requestHandlers/helpers.ts @@ -15,7 +15,7 @@ const createBridgeParams = (input: BridgeParams, chainList: ChainListType) => { nativeAmount: input.gas ?? 0n, dstToken, dstChain, - recipientAddress: input.recipient, + recipient: input.recipient, sourceChains: input.sourceChains ?? [], }; diff --git a/src/sdk/ca-base/utils/common.utils.ts b/src/sdk/ca-base/utils/common.utils.ts index 1310875c..85e0bbea 100644 --- a/src/sdk/ca-base/utils/common.utils.ts +++ b/src/sdk/ca-base/utils/common.utils.ts @@ -38,7 +38,6 @@ import { ChainList } from '../chains'; import { FUEL_BASE_ASSET_ID, isNativeAddress, ZERO_ADDRESS } from '../constants'; import { getLogger, IBridgeOptions } from '../../../commons'; import { - EthereumProvider, Intent, Network, NetworkConfig, @@ -327,14 +326,6 @@ const getSupportedChains = (env: Environment = Environment.CORAL) => { }); }; -const isArcanaWallet = (p: EthereumProvider) => { - if ('isArcana' in p && p.isArcana) { - return true; - } - - return false; -}; - const createRequestEVMSignature = async ( evmRFF: EVMRFF, evmAddress: `0x${string}`, @@ -942,7 +933,6 @@ export { getSDKConfig, getSupportedChains, hexTo0xString, - isArcanaWallet, minutesToMs, mulDecimals, refundExpiredIntents, From d9ad73ad444c21f3bf36db4df93e3fe268de918b Mon Sep 17 00:00:00 2001 From: Abhishek Date: Fri, 14 Nov 2025 12:32:59 +0400 Subject: [PATCH 15/51] fix: removed unused code (#75) * fix: removed unused code from commons * fix: removed more unused code * fix: moved viem to dependency --- package-lock.json | 27 +-- package.json | 6 +- src/commons/index.ts | 1 - src/commons/types/index.ts | 2 - src/commons/types/service-types.ts | 65 ------ src/commons/utils/format.ts | 18 +- src/commons/utils/index.ts | 290 +------------------------ src/sdk/ca-base/utils/balance.utils.ts | 24 -- src/sdk/utils.ts | 22 +- 9 files changed, 30 insertions(+), 425 deletions(-) delete mode 100644 src/commons/types/service-types.ts diff --git a/package-lock.json b/package-lock.json index 45eb58d4..c5ab0f4e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@avail-project/nexus-core", - "version": "1.0.0-beta.26", + "version": "1.0.0-beta.28", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@avail-project/nexus-core", - "version": "1.0.0-beta.26", + "version": "1.0.0-beta.28", "license": "MIT", "dependencies": { "@avail-project/ca-common": "1.0.0-beta.7", @@ -23,7 +23,8 @@ "long": "^5.3.2", "msgpackr": "^1.11.5", "tronweb": "^6.0.4", - "tslib": "2.8.1" + "tslib": "2.8.1", + "viem": "^2.31.7" }, "devDependencies": { "@rollup/plugin-commonjs": "^25.0.8", @@ -34,9 +35,6 @@ "rollup-plugin-dts": "^6.2.3", "rollup-plugin-typescript2": "0.36.0", "typescript": "^5.9.3" - }, - "peerDependencies": { - "viem": "^2.31.7" } }, "node_modules/@adraffy/ens-normalize": { @@ -1181,7 +1179,6 @@ "resolved": "https://registry.npmjs.org/@noble/ciphers/-/ciphers-1.3.0.tgz", "integrity": "sha512-2I0gnIVPtfnMw9ee9h1dJG7tp81+8Ob3OJb3Mv37rx5L40/b0i7djjCVvGOVqc9AEIQyvyu1i6ypKdFw8R8gQw==", "license": "MIT", - "peer": true, "engines": { "node": "^14.21.3 || >=16" }, @@ -1639,7 +1636,6 @@ "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.2.6.tgz", "integrity": "sha512-g/nm5FgUa//MCj1gV09zTJTaM6KBAHqLN907YVQqf7zC49+DcO4B1so4ZX07Ef10Twr6nuqYEH9GEggFXA4Fmg==", "license": "MIT", - "peer": true, "funding": { "url": "https://paulmillr.com/funding/" } @@ -1649,7 +1645,6 @@ "resolved": "https://registry.npmjs.org/@scure/bip32/-/bip32-1.7.0.tgz", "integrity": "sha512-E4FFX/N3f4B80AKWp5dP6ow+flD1LQZo/w8UnLGYZO674jS6YnYeepycOOksv+vLPSpgN35wgKgy+ybfTb2SMw==", "license": "MIT", - "peer": true, "dependencies": { "@noble/curves": "~1.9.0", "@noble/hashes": "~1.8.0", @@ -1664,7 +1659,6 @@ "resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.6.0.tgz", "integrity": "sha512-+lF0BbLiJNwVlev4eKelw1WWLaiKXw7sSl8T6FvBlWkdX+94aGJ4o8XjUdlyhTCjd8c+B3KT3JfS8P0bLRNU6A==", "license": "MIT", - "peer": true, "dependencies": { "@noble/hashes": "~1.8.0", "@scure/base": "~1.2.5" @@ -1929,7 +1923,6 @@ "resolved": "https://registry.npmjs.org/abitype/-/abitype-1.1.0.tgz", "integrity": "sha512-6Vh4HcRxNMLA0puzPjM5GBgT4aAcFGKZzSgAXvuZ27shJP6NEpielTuqbBmZILR5/xd0PizkBGy5hReKz9jl5A==", "license": "MIT", - "peer": true, "funding": { "url": "https://github.com/sponsors/wevm" }, @@ -3918,7 +3911,6 @@ } ], "license": "MIT", - "peer": true, "peerDependencies": { "ws": "*" } @@ -4463,7 +4455,6 @@ } ], "license": "MIT", - "peer": true, "dependencies": { "@adraffy/ens-normalize": "^1.11.0", "@noble/ciphers": "^1.3.0", @@ -4487,15 +4478,13 @@ "version": "1.11.1", "resolved": "https://registry.npmjs.org/@adraffy/ens-normalize/-/ens-normalize-1.11.1.tgz", "integrity": "sha512-nhCBV3quEgesuf7c7KYfperqSS14T8bYuvJ8PcLJp6znkZpFc0AuW4qBtr8eKVyPPe/8RSr7sglCWPU5eaxwKQ==", - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/ox/node_modules/@noble/curves": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.9.1.tgz", "integrity": "sha512-k11yZxZg+t+gWvBbIswW0yoJlu8cHOC7dhunwOzoWH/mXGBiYyR4YY6hAEK/3EUs4UpB8la1RfdRpeGsFHkWsA==", "license": "MIT", - "peer": true, "dependencies": { "@noble/hashes": "1.8.0" }, @@ -4510,8 +4499,7 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==", - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/p-limit": { "version": "2.3.0", @@ -5832,7 +5820,6 @@ } ], "license": "MIT", - "peer": true, "dependencies": { "@noble/curves": "1.9.1", "@noble/hashes": "1.8.0", @@ -5857,7 +5844,6 @@ "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.9.1.tgz", "integrity": "sha512-k11yZxZg+t+gWvBbIswW0yoJlu8cHOC7dhunwOzoWH/mXGBiYyR4YY6hAEK/3EUs4UpB8la1RfdRpeGsFHkWsA==", "license": "MIT", - "peer": true, "dependencies": { "@noble/hashes": "1.8.0" }, @@ -5873,7 +5859,6 @@ "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.3.tgz", "integrity": "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==", "license": "MIT", - "peer": true, "engines": { "node": ">=10.0.0" }, diff --git a/package.json b/package.json index 5d153eab..4cb0fa80 100644 --- a/package.json +++ b/package.json @@ -51,7 +51,8 @@ "long": "^5.3.2", "msgpackr": "^1.11.5", "tronweb": "^6.0.4", - "tslib": "2.8.1" + "tslib": "2.8.1", + "viem": "^2.31.7" }, "devDependencies": { "@rollup/plugin-commonjs": "^25.0.8", @@ -63,9 +64,6 @@ "rollup-plugin-typescript2": "0.36.0", "typescript": "^5.9.3" }, - "peerDependencies": { - "viem": "^2.31.7" - }, "publishConfig": { "access": "public" } diff --git a/src/commons/index.ts b/src/commons/index.ts index 4c4062bb..613dda2e 100644 --- a/src/commons/index.ts +++ b/src/commons/index.ts @@ -2,7 +2,6 @@ export * from './types'; export * from './types/swap-steps'; export * from './types/bridge-steps'; -export * from './types/service-types'; export * from './types/integration-types'; export * from './types/swap-types'; export * from './types/contract-types'; diff --git a/src/commons/types/index.ts b/src/commons/types/index.ts index 407d8854..1f1a0d40 100644 --- a/src/commons/types/index.ts +++ b/src/commons/types/index.ts @@ -1,7 +1,6 @@ import { SUPPORTED_CHAINS } from '../constants'; import { TransactionReceipt, ByteArray, Hex, WalletClient } from 'viem'; import { ChainDatum, Environment, PermitVariant, Universe } from '@avail-project/ca-common'; -import * as ServiceTypes from './service-types'; import Decimal from 'decimal.js'; import { SwapIntent } from './swap-types'; import { FuelConnector, Provider } from 'fuels'; @@ -660,7 +659,6 @@ export type UserAssetDatum = { }; export type { - ServiceTypes, OnIntentHook, OnAllowanceHookData, OnIntentHookData, diff --git a/src/commons/types/service-types.ts b/src/commons/types/service-types.ts deleted file mode 100644 index e86318af..00000000 --- a/src/commons/types/service-types.ts +++ /dev/null @@ -1,65 +0,0 @@ -import type { TransactionReceipt } from 'viem'; -import type { SUPPORTED_TOKENS, EthereumProvider } from './index'; - -/** - * Service-specific types for the adapter architecture - */ - -/** - * Transaction handling options - */ -export interface TransactionOptions { - enableTransactionPolling?: boolean; - transactionTimeout?: number; - waitForReceipt?: boolean; - receiptTimeout?: number; - requiredConfirmations?: number; -} - -/** - * Transaction result with receipt information - */ -export interface TransactionResult { - receipt?: TransactionReceipt; - confirmations?: number; - gasUsed?: string; - effectiveGasPrice?: string; -} - -/** - * Execute preparation result - */ -export interface ExecutePreparation { - provider: EthereumProvider; - fromAddress: string; - encodedData: `0x${string}`; - value?: string; -} - -/** - * Approval transaction result - */ -export interface ApprovalResult { - transactionHash?: string; - wasNeeded: boolean; - error?: string; - confirmed?: boolean; -} - -/** - * Chain switching result - */ -export interface ChainSwitchResult { - success: boolean; - error?: string; -} - -/** - * Token approval info for service operations - */ -export interface TokenApprovalInfo { - token: SUPPORTED_TOKENS; - amount: string; - spenderAddress: string; - chainId: number; -} diff --git a/src/commons/utils/format.ts b/src/commons/utils/format.ts index 8a627854..350b36c0 100644 --- a/src/commons/utils/format.ts +++ b/src/commons/utils/format.ts @@ -13,7 +13,23 @@ * use `formatTokenBalanceParts` which returns structured parts. */ -import { formatUnits } from 'viem'; +import { formatUnits, isAddress } from 'viem'; + +/** + * Truncate an address for display purposes + */ +export function truncateAddress( + address: string, + startLength: number = 6, + endLength: number = 4, +): string { + if (!isAddress(address)) return address; + + if (address.length <= startLength + endLength + 2) return address; + + return `${address.slice(0, startLength)}...${address.slice(-endLength)}`; +} + export interface FormatTokenBalanceOptions { decimals?: number; // when value is base units (bigint) symbol?: string; // e.g., "ETH" diff --git a/src/commons/utils/index.ts b/src/commons/utils/index.ts index 2a2b7d1d..b945270a 100644 --- a/src/commons/utils/index.ts +++ b/src/commons/utils/index.ts @@ -1,290 +1,2 @@ -import { - TOKEN_METADATA, - CHAIN_METADATA, - MAINNET_CHAINS, - TESTNET_CHAINS, - TESTNET_TOKEN_METADATA, -} from '../constants'; -import Decimal from 'decimal.js'; -import { - ChainMetadata, - SUPPORTED_CHAINS_IDS, - SUPPORTED_TOKENS, - TokenMetadata, -} from '../types/index'; -import { encodeFunctionData, type Abi, type Address, type Chain, isAddress, isHash } from 'viem'; -import { mainnet, polygon, arbitrum, optimism, base } from 'viem/chains'; -import { logger } from '../utils/logger'; - export * from './format'; - -/** - * Shared utility for standardized error message extraction - */ -export function extractErrorMessage(error: unknown, fallbackContext: string): string { - return error instanceof Error ? error.message : `Unknown ${fallbackContext} error`; -} - -export function wait(ms: number): Promise { - return new Promise((resolve) => setTimeout(resolve, ms)); -} - -/** - * Get Viem chain configuration for supported chains - */ -export function getViemChain(chainId: number): Chain { - switch (chainId) { - case 1: - return mainnet; - case 137: - return polygon; - case 42161: - return arbitrum; - case 10: - return optimism; - case 8453: - return base; - default: - // Return a basic chain config for unsupported chains - return { - id: chainId, - name: `Chain ${chainId}`, - nativeCurrency: { name: 'ETH', symbol: 'ETH', decimals: 18 }, - rpcUrls: { - default: { http: [] }, - public: { http: [] }, - }, - }; - } -} - -/** - * Parse units from a human-readable string to wei/smallest unit using Decimal.js - */ -export function parseUnits(value: string, decimals: number): bigint { - const valueDecimal = new Decimal(value); - const multiplier = new Decimal(10).pow(decimals); - const result = valueDecimal.mul(multiplier); - - return BigInt(result.toFixed(0)); -} - -/** - * Format units from wei/smallest unit to human-readable string using Decimal.js - */ -export function formatUnits(value: bigint, decimals: number): string { - const valueDecimal = new Decimal(value.toString()); - const divisor = new Decimal(10).pow(decimals); - const result = valueDecimal.div(divisor); - - return result.toFixed(); -} - -/** - * Validate if a string is a valid Ethereum address using viem - */ -export function isValidAddress(address: string): address is Address { - return isAddress(address); -} - -/** - * Get mainnet token metadata by symbol - */ -export const getMainnetTokenMetadata = (symbol: SUPPORTED_TOKENS): TokenMetadata | undefined => { - return TOKEN_METADATA[symbol]; -}; - -/** - * Get testnet token metadata by symbol - */ -export const getTestnetTokenMetadata = (symbol: SUPPORTED_TOKENS): TokenMetadata | undefined => { - return TESTNET_TOKEN_METADATA[symbol]; -}; - -/** - * Get token metadata by symbol (defaults to mainnet, kept for backward compatibility) - */ -export const getTokenMetadata = (symbol: SUPPORTED_TOKENS): TokenMetadata | undefined => { - return TOKEN_METADATA[symbol]; -}; - -/** - * Get chain metadata by chain ID - */ -export function getChainMetadata(chainId: SUPPORTED_CHAINS_IDS): ChainMetadata { - return CHAIN_METADATA[chainId]; -} - -/** - * Truncate an address for display purposes - */ -export function truncateAddress( - address: string, - startLength: number = 6, - endLength: number = 4, -): string { - if (!isValidAddress(address)) return address; - - if (address.length <= startLength + endLength + 2) return address; - - return `${address.slice(0, startLength)}...${address.slice(-endLength)}`; -} - -/** - * Convert chain ID to hex format - */ -export function chainIdToHex(chainId: number): string { - return `0x${chainId.toString(16)}`; -} - -/** - * Convert hex chain ID to number - */ -export function hexToChainId(hex: string): number { - return parseInt(hex, 16); -} - -export const isMainnetChain = (chainId: SUPPORTED_CHAINS_IDS): boolean => { - return (MAINNET_CHAINS as readonly number[]).includes(chainId); -}; - -export const isTestnetChain = (chainId: SUPPORTED_CHAINS_IDS): boolean => { - return (TESTNET_CHAINS as readonly number[]).includes(chainId); -}; - -/** - * Enhanced contract parameter validation with detailed error messages - */ -export function validateContractParams(params: { - contractAddress: string; - contractAbi: Abi; - functionName: string; - functionParams: readonly unknown[]; - chainId: number; -}): { isValid: boolean; error?: string } { - const { contractAddress, contractAbi, functionName, functionParams, chainId } = params; - - // Validate contract address - if (!contractAddress || typeof contractAddress !== 'string') { - return { isValid: false, error: 'Contract address is required and must be a string' }; - } - - if (!isAddress(contractAddress)) { - return { isValid: false, error: 'Contract address must be a checksummed Ethereum address' }; - } - - // Validate ABI - if (!Array.isArray(contractAbi) || contractAbi.length === 0) { - return { isValid: false, error: 'Contract ABI is required and must be a non-empty array' }; - } - - // Validate function name - if (!functionName || typeof functionName !== 'string') { - return { isValid: false, error: 'Function name is required and must be a string' }; - } - - // Find function in ABI - const functionAbi = contractAbi.find( - (item) => item.type === 'function' && item.name === functionName, - ); - - if (!functionAbi) { - return { isValid: false, error: `Function '${functionName}' not found in contract ABI` }; - } - - // Validate parameters count - const expectedParamsCount = functionAbi.inputs?.length ?? 0; - const providedParamsCount = functionParams?.length || 0; - - if (expectedParamsCount !== providedParamsCount) { - return { - isValid: false, - error: `Function '${functionName}' expects ${expectedParamsCount} parameters, but ${providedParamsCount} were provided`, - }; - } - - // Validate chain ID - if (!chainId || !CHAIN_METADATA[chainId]) { - return { isValid: false, error: `Unsupported chain ID: ${chainId}` }; - } - - return { isValid: true }; -} - -/** - * Enhanced contract call encoding with comprehensive error handling - */ -export function encodeContractCall(params: { - contractAbi: Abi; - functionName: string; - functionParams: readonly unknown[]; -}): { success: boolean; data?: `0x${string}`; error?: string } { - try { - const { contractAbi, functionName, functionParams } = params; - - const data = encodeFunctionData({ - abi: contractAbi, - functionName, - args: functionParams, - }); - - return { success: true, data }; - } catch (error) { - return { - success: false, - error: `Failed to encode contract call: ${extractErrorMessage(error, 'encoding')}`, - }; - } -} - -/** - * Validate and ensure a value is a valid transaction hash - */ -export function validateTransactionHash(value: unknown): value is `0x${string}` { - if (typeof value !== 'string') return false; - return isHash(value); -} - -/** - * Validate hex response from RPC calls - */ -export function validateHexResponse( - value: unknown, - fieldName: string, -): { isValid: boolean; error?: string } { - if (typeof value !== 'string') { - return { isValid: false, error: `${fieldName} must be a string, got ${typeof value}` }; - } - - if (!value.startsWith('0x')) { - return { isValid: false, error: `${fieldName} must be a hex string starting with 0x` }; - } - - return { isValid: true }; -} - -/** - * Enhanced block explorer URL generation with fallback support - */ -export function getBlockExplorerUrl(chainId: number, txHash: string): string { - const chainMetadata = CHAIN_METADATA[chainId]; - - if (!chainMetadata?.blockExplorerUrls?.[0]) { - logger.warn(`No block explorer URL found for chain ${chainId}`); - return ''; - } - - const baseUrl = chainMetadata.blockExplorerUrls[0]; - return `${baseUrl}/tx/${txHash}`; -} - -// Export logger utilities from commons -export { - LOG_LEVEL, - setExceptionReporter, - setLogLevel, - getLogger, - logger, - type LogLevel, - type ExceptionReporter, -} from '../utils/logger'; +export * from './logger'; diff --git a/src/sdk/ca-base/utils/balance.utils.ts b/src/sdk/ca-base/utils/balance.utils.ts index 4d8f2739..b3688135 100644 --- a/src/sdk/ca-base/utils/balance.utils.ts +++ b/src/sdk/ca-base/utils/balance.utils.ts @@ -1,7 +1,6 @@ import { Environment } from '@avail-project/ca-common'; import { ChainListType, logger, SUPPORTED_CHAINS, UserAssetDatum } from '../../../commons'; import { - // createPublicClientWithFallback, equalFold, getEVMBalancesForAddress, getFuelBalancesForAddress, @@ -11,7 +10,6 @@ import { import { encodePacked, Hex, keccak256, pad, toHex } from 'viem'; import { balancesToAssets, getAnkrBalances, toFlatBalance } from '../swap/utils'; import { filterSupportedTokens } from '../swap/data'; -// import { Errors } from '../errors'; const getKeyForStorage = ({ evmAddress, @@ -203,25 +201,3 @@ function getBalanceStorageSlot(token: string, chainId: number): number { ? DEFAULT_SLOT.USDT : DEFAULT_SLOT.ETH; } - -// export const getGasFeeFromBridgeParams = async (input: MaxBridgeParams, dstChain: Chain) => { -// let nativeAmount = 0n; -// if ('gas' in input && input.gas) { -// if ('gasPrice' in input && input.gasPrice) { -// nativeAmount = input.gas * input.gasPrice; -// } else { -// const pc = createPublicClientWithFallback(dstChain); -// const estimateGasPriceResponse = await pc.estimateFeesPerGas(); -// const gasUnitPrice = -// estimateGasPriceResponse.maxFeePerGas ?? estimateGasPriceResponse.gasPrice ?? 0n; -// if (gasUnitPrice == 0n) { -// throw Errors.gasPriceError({ -// chainId: dstChain.id, -// }); -// } -// nativeAmount = input.gas * gasUnitPrice; -// } -// } - -// return nativeAmount; -// }; diff --git a/src/sdk/utils.ts b/src/sdk/utils.ts index 6af80100..ad7371f0 100644 --- a/src/sdk/utils.ts +++ b/src/sdk/utils.ts @@ -1,15 +1,6 @@ import { type SUPPORTED_CHAINS, - parseUnits as utilParseUnits, - formatUnits as utilFormatUnits, - isValidAddress as utilIsValidAddress, truncateAddress as utilTruncateAddress, - chainIdToHex as utilChainIdToHex, - hexToChainId as utilHexToChainId, - getMainnetTokenMetadata as utilGetMainnetTokenMetadata, - getTestnetTokenMetadata as utilGetTestnetTokenMetadata, - getTokenMetadata as utilGetTokenMetadata, - getChainMetadata as utilGetChainMetadata, SupportedChainsResult, Network, ChainListType, @@ -18,21 +9,16 @@ import { } from '../commons'; import { getCoinbasePrices, getSupportedChains } from './ca-base/utils'; import { getSwapSupportedChains } from './ca-base/swap/utils'; +import { formatUnits, isAddress, parseUnits } from 'viem'; export class NexusUtils { constructor(private readonly chainList: ChainListType) {} formatTokenBalance = formatTokenBalance; formatTokenBalanceParts = formatTokenBalanceParts; - parseUnits = utilParseUnits; - formatUnits = utilFormatUnits; - isValidAddress = utilIsValidAddress; + parseUnits = parseUnits; + formatUnits = formatUnits; + isValidAddress = isAddress; truncateAddress = utilTruncateAddress; - chainIdToHex = utilChainIdToHex; - hexToChainId = utilHexToChainId; - getMainnetTokenMetadata = utilGetMainnetTokenMetadata; - getTestnetTokenMetadata = utilGetTestnetTokenMetadata; - getTokenMetadata = utilGetTokenMetadata; - getChainMetadata = utilGetChainMetadata; getCoinbaseRates = async (): Promise> => { return getCoinbasePrices(); From e945c1ba2521799a4cfb08dd8c26d0acde961b1f Mon Sep 17 00:00:00 2001 From: Abhishek Date: Fri, 14 Nov 2025 16:05:26 +0400 Subject: [PATCH 16/51] fix: corrected the create-rff status code (#76) * fix: corrected the create-rff status code * fix: use provider directly to switch chain in paid approval --- .gitignore | 2 ++ src/commons/types/index.ts | 1 + src/sdk/ca-base/requestHandlers/bridge.ts | 27 ++++++++++++++++------- src/sdk/ca-base/utils/api.utils.ts | 2 +- src/sdk/ca-base/utils/contract.utils.ts | 4 +++- 5 files changed, 26 insertions(+), 10 deletions(-) diff --git a/.gitignore b/.gitignore index d20eded1..a642f3f6 100644 --- a/.gitignore +++ b/.gitignore @@ -26,6 +26,8 @@ yarn-error.log* .DS_Store Thumbs.db +*.tgz + # IDE .idea/ .vscode/ diff --git a/src/commons/types/index.ts b/src/commons/types/index.ts index 1f1a0d40..559d7f6b 100644 --- a/src/commons/types/index.ts +++ b/src/commons/types/index.ts @@ -262,6 +262,7 @@ export type IBridgeOptions = { evm: { address: `0x${string}`; client: WalletClient; + provider: EthereumProvider; }; fuel?: { address: string; diff --git a/src/sdk/ca-base/requestHandlers/bridge.ts b/src/sdk/ca-base/requestHandlers/bridge.ts index 5a89685a..ab5294bc 100644 --- a/src/sdk/ca-base/requestHandlers/bridge.ts +++ b/src/sdk/ca-base/requestHandlers/bridge.ts @@ -20,6 +20,7 @@ import { maxUint256, parseSignature, toHex, + TransactionReceipt, UserRejectedRequestError, webSocket, } from 'viem'; @@ -365,6 +366,7 @@ class BridgeHandler { ); } await Promise.race(promisesToRace); + logger.debug('Fill completed'); } private async processRFF(intent: Intent): Promise< @@ -614,7 +616,8 @@ class BridgeHandler { const originalChain = this.params.dstChain.id; logger.debug('setAllowances', { originalChain, input }); - const sponsoredApprovalParams: SponsoredApprovalDataArray = []; + const sponsoredApprovals: SponsoredApprovalDataArray = []; + const unsponsoredApprovals: Promise[] = []; try { for (const source of input) { const chain = this.options.chainList.getChainByID(source.chainID); @@ -645,7 +648,12 @@ class BridgeHandler { if (currency.permitVariant === PermitVariant.Unsupported || chain.id === 1) { if (chain.universe === Universe.ETHEREUM) { - await switchChain(this.options.evm.client, chain); + // await switchChain(this.options.evm.client, chain); + + await this.options.evm.provider.request({ + method: 'wallet_switchEthereumChain', + params: [{ chainId: toHex(chain.id) }], + }); const h = await this.options.evm.client .writeContract({ @@ -670,7 +678,7 @@ class BridgeHandler { this.markStepDone(BRIDGE_STEPS.ALLOWANCE_APPROVAL_REQUEST(chain)); - await waitForTxReceipt(h, publicClient); + unsponsoredApprovals.push(waitForTxReceipt(h, publicClient)); } else if (chain.universe === Universe.TRON) { if (!this.options.tron) { throw Errors.internal('Tron is available in sources but has no adapter/provider'); @@ -748,7 +756,7 @@ class BridgeHandler { this.markStepDone(BRIDGE_STEPS.ALLOWANCE_APPROVAL_REQUEST(chain)); - sponsoredApprovalParams.push({ + sponsoredApprovals.push({ address: convertTo32Bytes(account.address), chain_id: chainDatum.ChainID32, operations: [ @@ -766,13 +774,13 @@ class BridgeHandler { } } - if (sponsoredApprovalParams.length) { + if (sponsoredApprovals.length) { logger.debug('setAllowances:sponsoredApprovals', { - sponsoredApprovalParams, + sponsoredApprovals, }); const approvalHashes = await vscCreateSponsoredApprovals( this.options.networkConfig.VSC_DOMAIN, - sponsoredApprovalParams, + sponsoredApprovals, ); await Promise.all( @@ -791,6 +799,10 @@ class BridgeHandler { }), ); } + if (unsponsoredApprovals.length) { + await Promise.all(unsponsoredApprovals); + } + this.markStepDone(BRIDGE_STEPS.ALLOWANCE_COMPLETE); } catch (e) { logger.error('Error setting allowances', e); throw e; @@ -798,7 +810,6 @@ class BridgeHandler { if (this.params.dstChain.universe === Universe.ETHEREUM) { await switchChain(this.options.evm.client, this.params.dstChain); } - this.markStepDone(BRIDGE_STEPS.ALLOWANCE_COMPLETE); } } diff --git a/src/sdk/ca-base/utils/api.utils.ts b/src/sdk/ca-base/utils/api.utils.ts index b69ae019..7630a20f 100644 --- a/src/sdk/ca-base/utils/api.utils.ts +++ b/src/sdk/ca-base/utils/api.utils.ts @@ -525,7 +525,7 @@ const vscCreateRFF = async ( } } // Collection successful for a chain - case 0x1a: { + case 0x10: { if (collectionIndexes.includes(data.idx)) { receivedCollectionsACKs.push(data.idx); remove(collectionIndexes, (d) => d === data.idx); diff --git a/src/sdk/ca-base/utils/contract.utils.ts b/src/sdk/ca-base/utils/contract.utils.ts index 5dc4457e..978632ac 100644 --- a/src/sdk/ca-base/utils/contract.utils.ts +++ b/src/sdk/ca-base/utils/contract.utils.ts @@ -158,6 +158,7 @@ const waitForIntentFulfilment = async ( ac.signal.addEventListener( 'abort', () => { + logger.debug('waitForIntentFulfilment: got abort, going to unwatch'); unwatch(); return resolve('ok from outside'); }, @@ -249,6 +250,7 @@ const switchChain = async (client: WalletClient, chain: Chain) => { try { await client.switchChain({ id: chain.id }); } catch (e) { + logger.debug('error during switching chain', e); await client.addChain({ chain, }); @@ -297,7 +299,7 @@ async function signPermitForAddressAndValue( return ''; }); })(), - client.request({ method: 'eth_chainId' }, { dedupe: true }), + client.request({ method: 'eth_chainId' }), ]; switch (cur.permitVariant) { From f7630a66ed1c1fcc4f57014335a9a2f3ebd2f440 Mon Sep 17 00:00:00 2001 From: Abhishek Date: Mon, 17 Nov 2025 13:32:27 +0400 Subject: [PATCH 17/51] fix: intent denial signature using wrong error code (#79) --- src/sdk/ca-base/errors.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sdk/ca-base/errors.ts b/src/sdk/ca-base/errors.ts index 48a35566..84de84a9 100644 --- a/src/sdk/ca-base/errors.ts +++ b/src/sdk/ca-base/errors.ts @@ -64,7 +64,7 @@ export const Errors = { createError(ERROR_CODES.USER_DENIED_ALLOWANCE, 'User rejected the allowance.'), userRejectedIntentSignature: () => - createError(ERROR_CODES.USER_DENIED_ALLOWANCE, 'User rejected signing the intent hash.'), + createError(ERROR_CODES.USER_DENIED_INTENT_SIGNATURE, 'User rejected signing the intent hash.'), insufficientBalance: () => createError(ERROR_CODES.INSUFFICIENT_BALANCE, 'Insufficient balance to proceed.'), From bfec03e90ffa5e01ed0291135835d3567c67e753 Mon Sep 17 00:00:00 2001 From: Abhishek Date: Mon, 17 Nov 2025 19:28:45 +0400 Subject: [PATCH 18/51] fix: added currentRaw and minimumRaw in allowance hook (#81) * fix: added currentRaw and minimumRaw in allowance hook * fix: added missing validation on bridge params * fix: exposed NexusErrorData and added new type SupportedChainsAndTokenResult --------- Co-authored-by: decocereus --- src/commons/types/index.ts | 2 ++ src/commons/types/swap-types.ts | 9 +++++++- src/index.ts | 2 +- src/sdk/ca-base/errors.ts | 1 + src/sdk/ca-base/nexusError.ts | 25 +++++++++++----------- src/sdk/ca-base/requestHandlers/bridge.ts | 8 ++++--- src/sdk/ca-base/requestHandlers/helpers.ts | 4 ++++ src/sdk/ca-base/utils/common.utils.ts | 6 ++++-- src/sdk/utils.ts | 3 ++- 9 files changed, 40 insertions(+), 20 deletions(-) diff --git a/src/commons/types/index.ts b/src/commons/types/index.ts index 559d7f6b..44d28be5 100644 --- a/src/commons/types/index.ts +++ b/src/commons/types/index.ts @@ -441,7 +441,9 @@ type OnAllowanceHook = (data: OnAllowanceHookData) => void; export type onAllowanceHookSource = { allowance: { current: string; + currentRaw: bigint; minimum: string; + minimumRaw: bigint; }; chain: { id: number; diff --git a/src/commons/types/swap-types.ts b/src/commons/types/swap-types.ts index 973b7d15..c24a3f5d 100644 --- a/src/commons/types/swap-types.ts +++ b/src/commons/types/swap-types.ts @@ -3,7 +3,7 @@ import { DirectSecp256k1Wallet } from '@cosmjs/proto-signing'; import Decimal from 'decimal.js'; import { type Hex, PrivateKeyAccount, WalletClient } from 'viem'; -import { NetworkConfig, ChainListType, OnEventParam } from '../index'; +import { NetworkConfig, ChainListType, OnEventParam, TokenInfo } from '../index'; export type AuthorizationList = { address: Uint8Array; @@ -269,6 +269,13 @@ export type SupportedChainsResult = { name: string; }[]; +export type SupportedChainsAndTokensResult = { + id: number; + logo: string; + name: string; + tokens: TokenInfo[]; +}[]; + export type Tx = { data: Hex; to: Hex; diff --git a/src/index.ts b/src/index.ts index 107b2806..498995ce 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,6 +1,6 @@ // Core SDK entry point - headless, no React dependencies export { NexusSDK } from './sdk/index'; -export { NexusError, ERROR_CODES } from './sdk/ca-base/nexusError'; +export { NexusError, NexusErrorData, ERROR_CODES } from './sdk/ca-base/nexusError'; // Re-export types from commons for convenience export type { BridgeParams, diff --git a/src/sdk/ca-base/errors.ts b/src/sdk/ca-base/errors.ts index 84de84a9..735c240e 100644 --- a/src/sdk/ca-base/errors.ts +++ b/src/sdk/ca-base/errors.ts @@ -99,4 +99,5 @@ export const Errors = { simulationError: (msg: string) => createError(ERROR_CODES.SIMULATION_FAILED, `tenderly simulation failed: ${msg}`), rFFFeeExpired: () => createError(ERROR_CODES.RFF_FEE_EXPIRED, `fee is not adequate`), + invalidInput: (msg: string) => createError(ERROR_CODES.INVALID_INPUT, `input invalid: ${msg}`), }; diff --git a/src/sdk/ca-base/nexusError.ts b/src/sdk/ca-base/nexusError.ts index 4b7f9f36..282fa0c3 100644 --- a/src/sdk/ca-base/nexusError.ts +++ b/src/sdk/ca-base/nexusError.ts @@ -49,23 +49,24 @@ export const ERROR_CODES = { VAULT_CONTRACT_NOT_FOUND: 'VAULT_CONTRACT_NOT_FOUND', SLIPPAGE_EXCEEDED_ALLOWANCE: 'SLIPPAGE_EXCEEDED_ALLOWANCE', RFF_FEE_EXPIRED: 'RFF_FEE_EXPIRED', + INVALID_INPUT: 'INVALID_INPUT', } as const; export type ErrorCode = (typeof ERROR_CODES)[keyof typeof ERROR_CODES]; export function createError(code: ErrorCode, message: string, data?: NexusErrorData): NexusError { - const nexusError = new NexusError(code, message, data); - telemetryLogger.emit({ - body: message, - severityNumber: SeverityNumber.ERROR, - severityText: 'ERROR', - attributes: { - data: nexusError.data, - cause: nexusError.cause, - stackTrace: nexusError.stack - } as AnyValueMap - }) - return nexusError + const nexusError = new NexusError(code, message, data); + telemetryLogger.emit({ + body: message, + severityNumber: SeverityNumber.ERROR, + severityText: 'ERROR', + attributes: { + data: nexusError.data, + cause: nexusError.cause, + stackTrace: nexusError.stack, + } as AnyValueMap, + }); + return nexusError; } /* --- Expected handling --- diff --git a/src/sdk/ca-base/requestHandlers/bridge.ts b/src/sdk/ca-base/requestHandlers/bridge.ts index ab5294bc..13a845c0 100644 --- a/src/sdk/ca-base/requestHandlers/bridge.ts +++ b/src/sdk/ca-base/requestHandlers/bridge.ts @@ -227,8 +227,10 @@ class BridgeHandler { if (requiredAllowance > currentAllowance) { const d = { allowance: { - current: currentAllowance.toString(), - minimum: requiredAllowance.toString(), + current: divDecimals(allowances[s.chainID], token.decimals).toFixed(token.decimals), + currentRaw: currentAllowance, + minimum: s.amount.toFixed(token.decimals), + minimumRaw: requiredAllowance, }, chain: { id: chain.id, @@ -836,7 +838,7 @@ class BridgeHandler { if (typeof allowance === 'string' && equalFold(allowance, 'max')) { amount = maxUint256; } else if (typeof allowance === 'string' && equalFold(allowance, 'min')) { - amount = BigInt(source.allowance.minimum); + amount = source.allowance.minimumRaw; } else if (typeof allowance === 'string') { amount = mulDecimals(allowance, source.token.decimals); } else { diff --git a/src/sdk/ca-base/requestHandlers/helpers.ts b/src/sdk/ca-base/requestHandlers/helpers.ts index 47315285..bd8fb77f 100644 --- a/src/sdk/ca-base/requestHandlers/helpers.ts +++ b/src/sdk/ca-base/requestHandlers/helpers.ts @@ -2,6 +2,10 @@ import { Errors } from '../errors'; import { BridgeParams, ChainListType } from '../../../commons'; const createBridgeParams = (input: BridgeParams, chainList: ChainListType) => { + if (input.amount === 0n && (!input.gas || input.gas === 0n)) { + throw Errors.invalidInput(`input.amount & input.gas can't be 0`); + } + const { chain: dstChain, token: dstToken } = chainList.getChainAndTokenFromSymbol( input.toChainId, input.token, diff --git a/src/sdk/ca-base/utils/common.utils.ts b/src/sdk/ca-base/utils/common.utils.ts index 85e0bbea..b662d8d5 100644 --- a/src/sdk/ca-base/utils/common.utils.ts +++ b/src/sdk/ca-base/utils/common.utils.ts @@ -36,7 +36,7 @@ import { import { TronWeb } from 'tronweb'; import { ChainList } from '../chains'; import { FUEL_BASE_ASSET_ID, isNativeAddress, ZERO_ADDRESS } from '../constants'; -import { getLogger, IBridgeOptions } from '../../../commons'; +import { getLogger, IBridgeOptions, SupportedChainsAndTokensResult } from '../../../commons'; import { Intent, Network, @@ -314,7 +314,9 @@ const hexTo0xString = (hex: string): `0x${string}` => { return `0x${hex}`; }; -const getSupportedChains = (env: Environment = Environment.CORAL) => { +const getSupportedChains = ( + env: Environment = Environment.CORAL, +): SupportedChainsAndTokensResult => { const chainList = new ChainList(env); return chainList.chains.map((chain) => { return { diff --git a/src/sdk/utils.ts b/src/sdk/utils.ts index ad7371f0..8f44c6db 100644 --- a/src/sdk/utils.ts +++ b/src/sdk/utils.ts @@ -6,6 +6,7 @@ import { ChainListType, formatTokenBalance, formatTokenBalanceParts, + SupportedChainsAndTokensResult, } from '../commons'; import { getCoinbasePrices, getSupportedChains } from './ca-base/utils'; import { getSwapSupportedChains } from './ca-base/swap/utils'; @@ -24,7 +25,7 @@ export class NexusUtils { return getCoinbasePrices(); }; - getSupportedChains(env?: Network): SupportedChainsResult { + getSupportedChains(env?: Network): SupportedChainsAndTokensResult { return getSupportedChains(env); } From a344d8b3fb3ccc002fa471bd7793b4365e6ccb5b Mon Sep 17 00:00:00 2001 From: Abhishek Date: Mon, 17 Nov 2025 20:40:30 +0400 Subject: [PATCH 19/51] fix: update missing function call for reject error on allowance reject (#82) --- src/sdk/ca-base/requestHandlers/bridge.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sdk/ca-base/requestHandlers/bridge.ts b/src/sdk/ca-base/requestHandlers/bridge.ts index 13a845c0..46eed7de 100644 --- a/src/sdk/ca-base/requestHandlers/bridge.ts +++ b/src/sdk/ca-base/requestHandlers/bridge.ts @@ -854,7 +854,7 @@ class BridgeHandler { }; const deny = () => { - return reject(Errors.userRejectedAllowance); + return reject(Errors.userRejectedAllowance()); }; this.options.hooks.onAllowance({ From 3114ddc1ac3d06178d750bcb2e0b6422b3040501 Mon Sep 17 00:00:00 2001 From: Abhishek Date: Tue, 18 Nov 2025 08:46:21 +0400 Subject: [PATCH 20/51] fix: added helper function to convert decimal string to bigint (#84) --- src/sdk/ca-base/ca.ts | 13 +++++++++++++ src/sdk/index.ts | 7 +++++++ 2 files changed, 20 insertions(+) diff --git a/src/sdk/ca-base/ca.ts b/src/sdk/ca-base/ca.ts index 219cb9f1..396b0ec3 100644 --- a/src/sdk/ca-base/ca.ts +++ b/src/sdk/ca-base/ca.ts @@ -58,6 +58,7 @@ import { getBalancesForSwap, switchChain, intentTransform, + mulDecimals, } from './utils'; import { swap } from './swap/swap'; import { getSwapSupportedChains } from './swap/utils'; @@ -589,4 +590,16 @@ export class CA { private _storeSIWESignature(address: Hex, signature: string) { return storeSIWESignatureToLocalStorage(address, signature); } + + protected _convertTokenReadableAmountToBigInt = ( + amount: string, + tokenSymbol: string, + chainId: number, + ) => { + const token = this.chainList.getTokenInfoBySymbol(chainId, tokenSymbol); + if (!token) { + throw Errors.tokenNotFound(tokenSymbol, chainId); + } + return mulDecimals(amount, token.decimals); + }; } diff --git a/src/sdk/index.ts b/src/sdk/index.ts index 60bca2df..2487d6f7 100644 --- a/src/sdk/index.ts +++ b/src/sdk/index.ts @@ -211,4 +211,11 @@ export class NexusSDK extends CA { public isInitialized() { return this._isInitialized(); } + + /** + * Helper function to convert an input like "1.13" to 1_130_000n for input to other functions + * Number of decimals for a token depends on the chain. + * ex: USDC on BNB chain has 18 decimals and 6 decimals on most other chains. + */ + public convertTokenReadableAmountToBigInt = this._convertTokenReadableAmountToBigInt; } From 171f0fddc42bb8b31e786b80fa2ad605be062cba Mon Sep 17 00:00:00 2001 From: Abhishek Date: Tue, 18 Nov 2025 08:48:41 +0400 Subject: [PATCH 21/51] fix: better logging during create RFF (#83) * fix: better logging during create RFF --- src/sdk/ca-base/utils/api.utils.ts | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/src/sdk/ca-base/utils/api.utils.ts b/src/sdk/ca-base/utils/api.utils.ts index 7630a20f..37d370d2 100644 --- a/src/sdk/ca-base/utils/api.utils.ts +++ b/src/sdk/ca-base/utils/api.utils.ts @@ -491,11 +491,11 @@ const vscCreateRFF = async ( vscDomain: string, id: Long, msd: (s: BridgeStepType) => void, - expectedCollectionIndexes: number[], + expectedCollections: number[], ) => { const controller = new AbortController(); - const collectionIndexes = expectedCollectionIndexes.slice(); - const receivedCollectionsACKs: number[] = []; + const pendingCollections = expectedCollections.slice(); + const completedCollections: number[] = []; await retry( async () => { const connection = connect( @@ -513,27 +513,29 @@ const vscCreateRFF = async ( switch (data.status) { // Will be called at the end of all calls, regardless of status case 0xff: { - if (collectionIndexes.length === 0) { + if (pendingCollections.length === 0) { msd(BRIDGE_STEPS.INTENT_COLLECTION_COMPLETE); break responseLoop; } else { logger.debug('(vsc)create-rff:collections failed', { - expectedCollectionIndexes, - receivedCollectionsACKs, + expectedCollections, + completedCollections, }); - throw Errors.vscError('create-rff: some collections failed, retrying.'); + throw Errors.vscError( + `create-rff: collections failed. expected = ${expectedCollections}, got = ${completedCollections}`, + ); } } // Collection successful for a chain case 0x10: { - if (collectionIndexes.includes(data.idx)) { - receivedCollectionsACKs.push(data.idx); - remove(collectionIndexes, (d) => d === data.idx); + if (pendingCollections.includes(data.idx)) { + completedCollections.push(data.idx); + remove(pendingCollections, (d) => d === data.idx); } msd( BRIDGE_STEPS.INTENT_COLLECTION( - receivedCollectionsACKs.length, - expectedCollectionIndexes.length, + completedCollections.length, + expectedCollections.length, ), ); break; @@ -541,7 +543,7 @@ const vscCreateRFF = async ( // Collection failed or is not applicable(say for native) default: { - if (collectionIndexes.includes(data.idx)) { + if (pendingCollections.includes(data.idx)) { logger.debug(`vsc:create-rff:failed`, { data }); } else { logger.debug('vsc:create-rff:expectedError:ignore', { data }); From 1045d32091244f200404e2672e4dae0cd595ecc3 Mon Sep 17 00:00:00 2001 From: Abhishek Date: Tue, 18 Nov 2025 16:00:43 +0400 Subject: [PATCH 22/51] fix: updated ca-common, removed validium, updated sponsored approval error (#85) --- package-lock.json | 8 ++-- package.json | 4 +- src/commons/constants/index.ts | 4 +- src/sdk/ca-base/chains.ts | 72 +++++++++++++++--------------- src/sdk/ca-base/utils/api.utils.ts | 9 +++- 5 files changed, 51 insertions(+), 46 deletions(-) diff --git a/package-lock.json b/package-lock.json index c0c99c5f..098389ba 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,7 +9,7 @@ "version": "1.0.0-beta.28", "license": "MIT", "dependencies": { - "@avail-project/ca-common": "1.0.0-beta.7", + "@avail-project/ca-common": "1.0.0-dev.2", "@cosmjs/proto-signing": "^0.34.0", "@cosmjs/stargate": "^0.34.0", "@metamask/safe-event-emitter": "3.1.2", @@ -48,9 +48,9 @@ "license": "MIT" }, "node_modules/@avail-project/ca-common": { - "version": "1.0.0-beta.7", - "resolved": "https://registry.npmjs.org/@avail-project/ca-common/-/ca-common-1.0.0-beta.7.tgz", - "integrity": "sha512-TCRrAM5aW0A+DoQiqmY0UJcZn6R3Mtpbt7V57V6LG4Tu52j4CC8Eye2a8Uo37YoFDXilB+AKyK6Ia+U9Kjximw==", + "version": "1.0.0-dev.2", + "resolved": "https://registry.npmjs.org/@avail-project/ca-common/-/ca-common-1.0.0-dev.2.tgz", + "integrity": "sha512-3e7EcTpDv8uchHAq5xz7a/mKAjG7rgG3fd0ZPR8MDRn8y4biPyy79x6rmS8Qd4hJOXRrQvMUJ48bpVO1dPCAgQ==", "license": "MIT", "dependencies": { "@bufbuild/protobuf": "^2.6.0", diff --git a/package.json b/package.json index dcaafcc6..5060e4ba 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@avail-project/nexus-core", - "version": "1.0.0-beta.28", + "version": "1.0.0-beta.31", "description": "Nexus headless SDK for cross-chain transactions", "main": "./dist/index.js", "module": "./dist/index.esm.js", @@ -37,7 +37,7 @@ "author": "decocereus, makyl", "license": "MIT", "dependencies": { - "@avail-project/ca-common": "1.0.0-beta.7", + "@avail-project/ca-common": "1.0.0-dev.2", "@cosmjs/proto-signing": "^0.34.0", "@cosmjs/stargate": "^0.34.0", "@metamask/safe-event-emitter": "3.1.2", diff --git a/src/commons/constants/index.ts b/src/commons/constants/index.ts index 5e304a37..246d2ea9 100644 --- a/src/commons/constants/index.ts +++ b/src/commons/constants/index.ts @@ -23,7 +23,7 @@ export const TESTNET_CHAIN_IDS = { POLYGON_AMOY: 80002, MONAD_TESTNET: 10143, TRON_SHASTA: 2494104990, - VALIDIUM_TESTNET: 567, + // VALIDIUM_TESTNET: 567, } as const; export const SUPPORTED_CHAINS = { @@ -277,7 +277,7 @@ export const TOKEN_CONTRACT_ADDRESSES = { [SUPPORTED_CHAINS.HYPEREVM]: '0xb88339CB7199b77E23DB6E890353E22632Ba630f', // testnet chains [SUPPORTED_CHAINS.SEPOLIA]: '0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238', - [SUPPORTED_CHAINS.VALIDIUM_TESTNET]: '0x8Cf5f629Bb26FC3F92144e72bC4A3719A7DF07F3', + // [SUPPORTED_CHAINS.VALIDIUM_TESTNET]: '0x8Cf5f629Bb26FC3F92144e72bC4A3719A7DF07F3', [SUPPORTED_CHAINS.BASE_SEPOLIA]: '0x036CbD53842c5426634e7929541eC2318f3dCF7e', [SUPPORTED_CHAINS.ARBITRUM_SEPOLIA]: '0x75faf114eafb1BDbe2F0316DF893fd58CE46AA4d', [SUPPORTED_CHAINS.OPTIMISM_SEPOLIA]: '0x5fd84259d66Cd46123540766Be93DFE6D43130D7', diff --git a/src/sdk/ca-base/chains.ts b/src/sdk/ca-base/chains.ts index 71491bfb..aa934af0 100644 --- a/src/sdk/ca-base/chains.ts +++ b/src/sdk/ca-base/chains.ts @@ -434,42 +434,42 @@ const TESTNET_CHAINS: Chain[] = [ }, universe: Universe.ETHEREUM, }, - { - blockExplorers: { - default: { - name: 'Validium Testnet Explorer', - url: 'https://testnet.explorer.validium.network', - }, - }, - custom: { - icon: 'https://assets.coingecko.com/asset_platforms/images/279/large/ethereum.png', - knownTokens: [ - { - contractAddress: TOKEN_CONTRACT_ADDRESSES['USDC'][SUPPORTED_CHAINS.VALIDIUM_TESTNET], - decimals: 6, - logo: getLogoFromSymbol('USDC'), - name: 'USD Coin', - symbol: 'USDC', - }, - ], - }, - id: SUPPORTED_CHAINS.VALIDIUM_TESTNET, - name: 'Validium Testnet', - ankrName: '', - nativeCurrency: { - decimals: 18, - name: 'VLDM', - symbol: 'VLDM', - }, - rpcUrls: { - default: { - http: ['https://testnet.l2.rpc.validium.network'], - publicHttp: ['https://testnet.l2.rpc.validium.network'], - webSocket: ['wss://testnet.l2.rpc.validium.network/ws'], - }, - }, - universe: Universe.ETHEREUM, - }, + // { + // blockExplorers: { + // default: { + // name: 'Validium Testnet Explorer', + // url: 'https://testnet.explorer.validium.network', + // }, + // }, + // custom: { + // icon: 'https://assets.coingecko.com/asset_platforms/images/279/large/ethereum.png', + // knownTokens: [ + // { + // contractAddress: TOKEN_CONTRACT_ADDRESSES['USDC'][SUPPORTED_CHAINS.VALIDIUM_TESTNET], + // decimals: 6, + // logo: getLogoFromSymbol('USDC'), + // name: 'USD Coin', + // symbol: 'USDC', + // }, + // ], + // }, + // id: SUPPORTED_CHAINS.VALIDIUM_TESTNET, + // name: 'Validium Testnet', + // ankrName: '', + // nativeCurrency: { + // decimals: 18, + // name: 'VLDM', + // symbol: 'VLDM', + // }, + // rpcUrls: { + // default: { + // http: ['https://testnet.l2.rpc.validium.network'], + // publicHttp: ['https://testnet.l2.rpc.validium.network'], + // webSocket: ['wss://testnet.l2.rpc.validium.network/ws'], + // }, + // }, + // universe: Universe.ETHEREUM, + // }, ]; const MAINNET_CHAINS: Chain[] = [ diff --git a/src/sdk/ca-base/utils/api.utils.ts b/src/sdk/ca-base/utils/api.utils.ts index 37d370d2..db6fca21 100644 --- a/src/sdk/ca-base/utils/api.utils.ts +++ b/src/sdk/ca-base/utils/api.utils.ts @@ -407,6 +407,7 @@ type CreateSponsoredApprovalResponse = | { error: string; errored: true; + msg: string; part_idx: number; } | { error: true; msg: string } // why error not same struct? @@ -437,11 +438,15 @@ const vscCreateSponsoredApprovals = async ( logger.debug('vscCreateSponsoredApprovals', { data }); if ('errored' in data && data.errored) { - throw Errors.vscError(`create-sponsored-approvals: ${data.error}`); + throw Errors.vscError( + `failed to create sponsored approvals: ${data.msg ?? 'Backend sent failure.'}`, + ); } if ('error' in data && data.error) { - throw Errors.vscError(`create-sponsored-approvals: ${data.error}`); + throw Errors.vscError( + `failed to create sponsored approvals: ${data.msg ?? 'Backend sent failure.'}`, + ); } const inputData = input[data.part_idx]; From a6adb1591558b33020b7d633b15a2dae3ab766d5 Mon Sep 17 00:00:00 2001 From: Amartya Singh <53113365+decocereus@users.noreply.github.com> Date: Tue, 18 Nov 2025 17:50:59 +0530 Subject: [PATCH 23/51] Polyfill Fix | Update ca-common (#71) * fix: temporary package with buffer included * chore(core): beta release v1.0.0-beta.27 * fix: add Buffer polyfills and update package configurations - Implemented polyfills for Buffer methods in both core and commons packages to ensure compatibility. - Updated package.json files to specify side effects for polyfills and added Buffer as a dependency. - Enhanced Rollup configuration to preserve side effects for polyfill files during tree-shaking. * chore: update ca-common package * chore(core): dev release v0.0.2-dev.2 * fix: release script and build errors * chore: updated release script * fix: removed extra polyfills in commons * chore(core): dev release v0.0.2-dev.3 * 'lock-file' update * fix: added currentRaw and minimumRaw in allowance hook * fix: added missing validation on bridge params * fix: exposed NexusErrorData and added new type SupportedChainsAndTokenResult * chore(core): dev release v0.0.2-dev.4 * lock file update * fix: update missing function call for reject error on allowance reject * chore(core): dev release v0.0.2-dev.5 * chore(core): bump version to v0.0.2-dev.5 in package-lock.json --------- Co-authored-by: Abhishek --- package-lock.json | 5 ++- package.json | 1 + rollup.config.mjs | 1 + scripts/release-core.sh | 92 ++++++++--------------------------------- src/_polyfill.ts | 62 +++++++++++++++++++++++++++ src/index.ts | 1 + 6 files changed, 86 insertions(+), 76 deletions(-) create mode 100644 src/_polyfill.ts diff --git a/package-lock.json b/package-lock.json index 098389ba..6b113f0e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@avail-project/nexus-core", - "version": "1.0.0-beta.28", + "version": "1.0.0-beta.31", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@avail-project/nexus-core", - "version": "1.0.0-beta.28", + "version": "1.0.0-beta.31", "license": "MIT", "dependencies": { "@avail-project/ca-common": "1.0.0-dev.2", @@ -20,6 +20,7 @@ "@starkware-industries/starkware-crypto-utils": "^0.2.1", "@tronweb3/tronwallet-abstract-adapter": "^1.1.9", "axios": "^1.12.2", + "buffer": "6.0.3", "decimal.js": "^10.6.0", "es-toolkit": "^1.40.0", "fuels": "0.101.1", diff --git a/package.json b/package.json index 5060e4ba..547eda4e 100644 --- a/package.json +++ b/package.json @@ -51,6 +51,7 @@ "decimal.js": "^10.6.0", "es-toolkit": "^1.40.0", "fuels": "0.101.1", + "buffer": "6.0.3", "it-ws": "^6.1.5", "long": "^5.3.2", "msgpackr": "^1.11.5", diff --git a/rollup.config.mjs b/rollup.config.mjs index 897e9ba9..4beb091d 100644 --- a/rollup.config.mjs +++ b/rollup.config.mjs @@ -35,6 +35,7 @@ const baseConfig = { // Peer dependencies that consumers should install ...Object.keys(packageJson.peerDependencies || {}), /^viem/, + 'buffer', // External dependencies that consumers should install '@avail-project/ca-common', '@tronweb3/tronwallet-abstract-adapter', diff --git a/scripts/release-core.sh b/scripts/release-core.sh index e43aec1e..57a78313 100755 --- a/scripts/release-core.sh +++ b/scripts/release-core.sh @@ -47,16 +47,20 @@ if ! git rev-parse --git-dir > /dev/null 2>&1; then exit 1 fi -# Check if we're in the root directory -if [[ ! -f "package.json" ]] || [[ ! -d "packages/core" ]]; then - print_error "Please run this script from the monorepo root directory" +# Check if we're in the project root directory (single-package repo) +if [[ ! -f "package.json" ]]; then + print_error "Please run this script from the project root directory" exit 1 fi # Check for uncommitted changes if ! git diff-index --quiet HEAD --; then - print_error "There are uncommitted changes. Please commit or stash them first." - exit 1 + print_header "There are uncommitted changes. Are you sure you want to continue?" + read -p "Continue? (y/N): " _continue + if [[ $_continue != [yY] ]]; then + print_error "Aborting release." + exit 1 + fi fi # Get the release type from command line argument (positional defaults) @@ -125,19 +129,15 @@ print_header "Starting @avail-project/nexus-core $RELEASE_TYPE release ($VERSION # Run type checking print_status "Running type check..." -pnpm run typecheck:core +npm run typecheck # Clean previous builds print_status "Cleaning previous builds..." -pnpm run clean +rm -rf dist -# Build commons (dependency) -print_status "Building commons package..." -pnpm run build:commons - -# Build core package -print_status "Building @avail-project/nexus-core package..." -pnpm run build:core +# Build package +print_status "Building @avail-project/nexus-core package (single package repo)..." +npm run build if [[ "$RELEASE_TYPE" == "prod" ]]; then print_header "Creating production release..." @@ -157,25 +157,20 @@ if [[ "$RELEASE_TYPE" == "prod" ]]; then fi fi - # Version bump + # Version bump (root package.json) print_status "Bumping version (${CUSTOM_VERSION:+custom $CUSTOM_VERSION}${CUSTOM_VERSION:+, }$VERSION_TYPE)..." - cd packages/core if [[ -n "$CUSTOM_VERSION" ]]; then npm version "$CUSTOM_VERSION" --no-git-tag-version --allow-same-version else npm version $VERSION_TYPE --no-git-tag-version fi CORE_VERSION=$(node -p "require('./package.json').version") - cd ../.. - - # Update root package.json version to match - npm version $CORE_VERSION --no-git-tag-version --allow-same-version # Commit version changes (skip if no changes) if [[ $DRY_RUN -eq 1 ]]; then print_status "DRY RUN: would git add/commit version bumps for v$CORE_VERSION" else - git add packages/core/package.json package.json + git add package.json if git diff --cached --quiet; then print_status "No version changes to commit (prod)." else @@ -188,24 +183,6 @@ if [[ "$RELEASE_TYPE" == "prod" ]]; then git tag "core-v$CORE_VERSION" fi fi - - # Temporarily rename package for publishing - print_status "Preparing package for publishing as @avail-project/nexus-core..." - cd packages/core - - # Backup original package.json - cp package.json package.json.backup - - # Package already named @avail-project/nexus-core; no rename needed - - # Remove workspace-only dependencies that should be bundled (e.g., @nexus/commons) - node -e "const fs=require('fs');const p=JSON.parse(fs.readFileSync('package.json','utf8'));if(p.dependencies&&p.dependencies['@nexus/commons']){delete p.dependencies['@nexus/commons'];}fs.writeFileSync('package.json',JSON.stringify(p,null,2)+'\n');" - - # Bundle internal commons into dist (imports already aliased by Rollup) - print_status "Bundling internal @nexus/commons into dist..." - mkdir -p dist/commons - cp -R ../commons/dist/* dist/commons/ - # Publish to npm (or pack in dry-run) if [[ $DRY_RUN -eq 1 ]]; then print_status "DRY RUN: npm pack (skipping publish) for @avail-project/nexus-core@$CORE_VERSION" @@ -215,10 +192,6 @@ if [[ "$RELEASE_TYPE" == "prod" ]]; then npm publish --access public fi - # Restore original package.json - mv package.json.backup package.json - cd ../.. - # Push changes and tags if [[ $DRY_RUN -eq 1 ]]; then print_status "DRY RUN: skipping git push of branch and tag core-v$CORE_VERSION" @@ -235,9 +208,8 @@ if [[ "$RELEASE_TYPE" == "prod" ]]; then else print_header "Creating development release..." - # Compute next prerelease version with 0-9 rollover by publication time + # Compute next prerelease version with 0-9 rollover by publication time (root) print_status "Computing next $PRERELEASE_ID version with rollover logic..." - cd packages/core if [[ -n "$CUSTOM_VERSION" ]]; then PRERELEASE_VERSION="$CUSTOM_VERSION" else @@ -279,16 +251,12 @@ console.log(next); fi export PRERELEASE_VERSION npm version "$PRERELEASE_VERSION" --no-git-tag-version --allow-same-version - cd ../.. - - # Update root package.json to match - npm version "$PRERELEASE_VERSION" --no-git-tag-version --allow-same-version # Commit version changes (skip if no changes) if [[ $DRY_RUN -eq 1 ]]; then print_status "DRY RUN: would git add/commit dev bump to v$PRERELEASE_VERSION and tag core-v$PRERELEASE_VERSION" else - git add packages/core/package.json package.json + git add package.json if git diff --cached --quiet; then print_status "No version changes to commit (dev)." else @@ -301,26 +269,6 @@ console.log(next); git tag "core-v$PRERELEASE_VERSION" fi fi - - # Temporarily rename package for publishing - print_status "Preparing package for publishing as @avail-project/nexus-core..." - cd packages/core - - # Backup original package.json - cp package.json package.json.backup - - # Update package name for publishing - sed -i.tmp 's/"name": "@nexus\/core"/"name": "@avail-project\/nexus-core"/' package.json - rm package.json.tmp 2>/dev/null || true - - # Remove workspace-only dependencies that should be bundled (e.g., @nexus/commons) - node -e "const fs=require('fs');const p=JSON.parse(fs.readFileSync('package.json','utf8'));if(p.dependencies&&p.dependencies['@nexus/commons']){delete p.dependencies['@nexus/commons'];}fs.writeFileSync('package.json',JSON.stringify(p,null,2)+'\n');" - - # Bundle internal commons into dist (imports already aliased by Rollup) - print_status "Bundling internal @nexus/commons into dist..." - mkdir -p dist/commons - cp -R ../commons/dist/* dist/commons/ - # Publish to npm with prerelease tag (or pack in dry-run) if [[ $DRY_RUN -eq 1 ]]; then print_status "DRY RUN: npm pack (skipping publish) for @avail-project/nexus-core@$PRERELEASE_VERSION" @@ -336,10 +284,6 @@ console.log(next); fi fi - # Restore original package.json - mv package.json.backup package.json - cd ../.. - # Push changes and tags if [[ $DRY_RUN -eq 1 ]]; then print_status "DRY RUN: skipping git push of branch and tag core-v$PRERELEASE_VERSION" diff --git a/src/_polyfill.ts b/src/_polyfill.ts new file mode 100644 index 00000000..ae60c385 --- /dev/null +++ b/src/_polyfill.ts @@ -0,0 +1,62 @@ +import { Buffer as _Buffer } from 'buffer'; + +// Ensure Buffer is on globalThis +if (!(globalThis as any).Buffer) { + (globalThis as any).Buffer = _Buffer; +} + +// Add polyfills for missing methods +const proto = _Buffer.prototype as any; +if (proto && typeof proto.writeUint32BE !== 'function') { + if (typeof proto.writeUInt32BE === 'function') { + // Alias the capital I versions + proto.writeUint32BE = proto.writeUInt32BE; + proto.writeUint32LE = proto.writeUInt32LE; + proto.readUint32BE = proto.readUInt32BE; + proto.readUint32LE = proto.readUInt32LE; + } else { + // Fallback implementations + proto.writeUint32BE = function (value: number, offset: number = 0) { + offset = offset >>> 0; + const normalized = Number(value) >>> 0; + (this as any)[offset] = (normalized >>> 24) & 0xff; + (this as any)[offset + 1] = (normalized >>> 16) & 0xff; + (this as any)[offset + 2] = (normalized >>> 8) & 0xff; + (this as any)[offset + 3] = normalized & 0xff; + return offset + 4; + }; + proto.writeUint32LE = function (value: number, offset: number = 0) { + offset = offset >>> 0; + const normalized = Number(value) >>> 0; + (this as any)[offset] = normalized & 0xff; + (this as any)[offset + 1] = (normalized >>> 8) & 0xff; + (this as any)[offset + 2] = (normalized >>> 16) & 0xff; + (this as any)[offset + 3] = (normalized >>> 24) & 0xff; + return offset + 4; + }; + proto.readUint32BE = function (offset: number = 0) { + offset = offset >>> 0; + return ( + ((this as any)[offset] * 0x1000000 + + (((this as any)[offset + 1] << 16) | + ((this as any)[offset + 2] << 8) | + (this as any)[offset + 3])) >>> + 0 + ); + }; + proto.readUint32LE = function (offset: number = 0) { + offset = offset >>> 0; + return ( + ((this as any)[offset] | + ((this as any)[offset + 1] << 8) | + ((this as any)[offset + 2] << 16) | + ((this as any)[offset + 3] * 0x1000000)) >>> + 0 + ); + }; + } +} + +if (!(globalThis as any).process) { + (globalThis as any).process = { env: { NODE_ENV: 'production' } }; +} diff --git a/src/index.ts b/src/index.ts index 498995ce..629a1147 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,3 +1,4 @@ +import './_polyfill'; // Core SDK entry point - headless, no React dependencies export { NexusSDK } from './sdk/index'; export { NexusError, NexusErrorData, ERROR_CODES } from './sdk/ca-base/nexusError'; From b6330a162ae1d19162a085594b035e454bd34ed9 Mon Sep 17 00:00:00 2001 From: Abhishek Date: Wed, 19 Nov 2025 10:03:31 +0400 Subject: [PATCH 24/51] fix: swap bug fixes (#86) * fix: swap to use NexusError, replaced the usage * fix: swap insufficient balance issue, fixed faulty check of amount in case of exact in * fix: removed duplication of max bridge fee calculation * chore: update version and add prepublishOnly to package.json * fix: fixed using correct check on exact out requote * fix: naming update in swap classes * fix: fixed some regression issue in destination swap --- package.json | 6 +- src/sdk/ca-base/errors.ts | 8 +- src/sdk/ca-base/nexusError.ts | 1 + src/sdk/ca-base/swap/errors.ts | 17 --- src/sdk/ca-base/swap/ob.ts | 185 ++++++++++++++++------------- src/sdk/ca-base/swap/route.ts | 53 +++++---- src/sdk/ca-base/swap/utils.ts | 40 ++++--- src/sdk/ca-base/utils/rff.utils.ts | 65 +--------- 8 files changed, 171 insertions(+), 204 deletions(-) delete mode 100644 src/sdk/ca-base/swap/errors.ts diff --git a/package.json b/package.json index 547eda4e..a137577c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@avail-project/nexus-core", - "version": "1.0.0-beta.31", + "version": "1.0.0-beta.32", "description": "Nexus headless SDK for cross-chain transactions", "main": "./dist/index.js", "module": "./dist/index.esm.js", @@ -11,9 +11,11 @@ ], "scripts": { "build": "rollup -c", + "buildAndPack": "rollup -c && npm pack", "dev": "rollup -c -w", "clean": "rimraf dist dist-tarballs", - "typecheck": "tsc --noEmit" + "typecheck": "tsc --noEmit", + "prepublishOnly": "npm run build" }, "sideEffects": false, "exports": { diff --git a/src/sdk/ca-base/errors.ts b/src/sdk/ca-base/errors.ts index 735c240e..da4f67f8 100644 --- a/src/sdk/ca-base/errors.ts +++ b/src/sdk/ca-base/errors.ts @@ -1,3 +1,4 @@ +import { Hex } from 'viem'; import { ERROR_CODES, createError } from './nexusError'; export const Errors = { @@ -66,8 +67,8 @@ export const Errors = { userRejectedIntentSignature: () => createError(ERROR_CODES.USER_DENIED_INTENT_SIGNATURE, 'User rejected signing the intent hash.'), - insufficientBalance: () => - createError(ERROR_CODES.INSUFFICIENT_BALANCE, 'Insufficient balance to proceed.'), + insufficientBalance: (msg?: string) => + createError(ERROR_CODES.INSUFFICIENT_BALANCE, `Insufficient balance to proceed. ${msg}`), walletNotConnected: (walletType: string) => createError(ERROR_CODES.WALLET_NOT_CONNECTED, `Wallet is not connected for ${walletType}`), @@ -100,4 +101,7 @@ export const Errors = { createError(ERROR_CODES.SIMULATION_FAILED, `tenderly simulation failed: ${msg}`), rFFFeeExpired: () => createError(ERROR_CODES.RFF_FEE_EXPIRED, `fee is not adequate`), invalidInput: (msg: string) => createError(ERROR_CODES.INVALID_INPUT, `input invalid: ${msg}`), + noBalanceForAddress: (address: Hex) => { + createError(ERROR_CODES.NO_BALANCE_FOR_ADDRESS, `no balance found for user: ${address}`); + }, }; diff --git a/src/sdk/ca-base/nexusError.ts b/src/sdk/ca-base/nexusError.ts index 282fa0c3..b1966dda 100644 --- a/src/sdk/ca-base/nexusError.ts +++ b/src/sdk/ca-base/nexusError.ts @@ -50,6 +50,7 @@ export const ERROR_CODES = { SLIPPAGE_EXCEEDED_ALLOWANCE: 'SLIPPAGE_EXCEEDED_ALLOWANCE', RFF_FEE_EXPIRED: 'RFF_FEE_EXPIRED', INVALID_INPUT: 'INVALID_INPUT', + NO_BALANCE_FOR_ADDRESS: 'NO_BALANCE_FOR_ADDRESS', } as const; export type ErrorCode = (typeof ERROR_CODES)[keyof typeof ERROR_CODES]; diff --git a/src/sdk/ca-base/swap/errors.ts b/src/sdk/ca-base/swap/errors.ts deleted file mode 100644 index fdd83255..00000000 --- a/src/sdk/ca-base/swap/errors.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { Hex } from 'viem'; - -const ErrorChainDataNotFound = new Error('Chain data not found.'); -const ErrorCOTNotFound = (chainID: number) => new Error(`COT not found on chain: ${chainID}`); -const ErrorTokenNotFound = (address: Hex, chainID: number) => - new Error(`Token(${address}) not found on chain: ${chainID}`); -const ErrorSingleSourceHasNoSource = new Error('Single source swap has input source missing.'); -const ErrorInsufficientBalance = (available: string, required: string) => - new Error(`Insufficient balance: available:${available}, required:${required}.`); - -export { - ErrorChainDataNotFound, - ErrorCOTNotFound, - ErrorInsufficientBalance, - ErrorSingleSourceHasNoSource, - ErrorTokenNotFound, -}; diff --git a/src/sdk/ca-base/swap/ob.ts b/src/sdk/ca-base/swap/ob.ts index e9f705c0..9ac7ddb0 100644 --- a/src/sdk/ca-base/swap/ob.ts +++ b/src/sdk/ca-base/swap/ob.ts @@ -33,7 +33,7 @@ import { EADDRESS_32_BYTES, EXPECTED_CALIBUR_CODE, getAllowanceCacheKey, - getTxsFromQuote, + parseQuote, isNativeAddress, performDestinationSwap, PublicClientList, @@ -292,7 +292,7 @@ class BridgeHandler { } class DestinationSwapHandler { - private destinationCalls: Tx[] = []; + private eoaToEphCalls: Tx[] = []; constructor( private data: SwapRoute['destination'], private dstTokenInfo: { @@ -353,7 +353,7 @@ class DestinationSwapHandler { publicClient: this.options.publicClientList.get(this.dst.chainID), spender: this.options.address.ephemeral, }); - this.destinationCalls = this.destinationCalls.concat(txs); + this.eoaToEphCalls = txs; } } @@ -376,7 +376,7 @@ class DestinationSwapHandler { try { await this.executeSwap(metadata); } catch (retryError) { - logger.error('Destination swap failed after single retry.', { + logger.error('Destination swap failed even after retry.', { error: (retryError as Error)?.message ?? retryError, }); throw retryError; @@ -391,39 +391,48 @@ class DestinationSwapHandler { await this.requoteIfRequired(false); const { swap } = this.data; - const txs = getTxsFromQuote( - { - agg: swap.aggregator, - originalHolding: swap.originalHolding, - quote: swap.quote!, - req: swap.req, - }, - true, - ); - if (txs.approval) { - this.destinationCalls.push(txs.approval); + let calls: Tx[] = []; + + if (this.eoaToEphCalls.length > 0) { + calls = calls.concat(this.eoaToEphCalls); } - this.destinationCalls.push(txs.swap); - logger.debug('swap:destinationCalls', { - destinationCalls: this.destinationCalls, - }); + if (swap.quote) { + const quote = parseQuote( + { + agg: swap.aggregator, + originalHolding: swap.originalHolding, + quote: swap.quote, + req: swap.req, + }, + true, + ); - metadata.dst.swaps.push({ - agg: 0, - input_amt: toBytes(txs.amount), - input_contract: swap.req.inputToken, - input_decimals: swap.dstChainCOT.decimals, - output_amt: convertTo32Bytes(this.dst.amount ?? 0), - output_contract: convertTo32Bytes(this.dst.token), - output_decimals: this.dstTokenInfo.decimals, - }); + if (quote.swap.approval) { + calls.push(quote.swap.approval); + } + calls.push(quote.swap.tx); + + logger.debug('swap:destinationCalls', { + destinationCalls: calls, + }); + + metadata.dst.swaps.push({ + agg: 0, + input_amt: convertTo32Bytes(quote.input.amount), + input_contract: swap.req.inputToken, + input_decimals: swap.dstChainCOT.decimals, + output_amt: convertTo32Bytes(this.dst.amount ?? 0), + output_contract: convertTo32Bytes(this.dst.token), + output_decimals: this.dstTokenInfo.decimals, + }); - this.options.emitter.emit(SWAP_STEPS.DESTINATION_SWAP_BATCH_TX(false)); + this.options.emitter.emit(SWAP_STEPS.DESTINATION_SWAP_BATCH_TX(false)); + } // Add sweeper tx - this.destinationCalls = this.destinationCalls.concat( + calls = calls.concat( createSweeperTxs({ cache: this.options.cache, chainID: this.dst.chainID, @@ -438,7 +447,7 @@ class DestinationSwapHandler { const hash = await performDestinationSwap({ actualAddress: this.options.address.eoa, cache: this.options.cache, - calls: this.destinationCalls, + calls, chain: this.options.chainList.getChainByID(this.dst.chainID)!, chainList: this.options.chainList, COT: this.options.cot.currencyID, @@ -464,6 +473,13 @@ class DestinationSwapHandler { * If `force` = true, always requote regardless of expiry check. */ private async requoteIfRequired(force = false) { + // There wasn't any quote to begin with so nothing to requote. + // Happens when dst token is COT, just need to send from ephemeral -> EOA + // Maybe FIXME: Bridge can directly send to EOA in these cases - save gas. + if (!this.data.swap.quote) { + return; + } + const { swap } = this.data; let requote = force; @@ -482,20 +498,37 @@ class DestinationSwapHandler { logger.debug('Requoting destination swap...'); const newSwap = await this.data.fetchDestinationSwapDetails(); - if (!newSwap.quote) throw new Error('Failed to requote destination swap.'); + if (!newSwap.quote) { + throw new Error('Failed to requote destination swap.'); + } - const isExactIn = this.dst.amount == undefined; + const isExactIn = this.data.type === 'EXACT_IN'; + logger.debug('destinationSwap Requote', { + isExactIn, + 'newSwap.min': newSwap.inputAmount.min.toFixed(), + 'newSwap.max': newSwap.inputAmount.max.toFixed(), + 'swap.min': swap.inputAmount.min.toFixed(), + 'swap.max': swap.inputAmount.max.toFixed(), + }); + + // EXACT_IN: min and max are same and input doesnt change so dont check here, + // In source swap failure cases it might have an issue. FIXME + // EXACT_OUT: min is the actual amount required so as long as it is within the range + // of previous [max, min] it should be executable. if ( !isExactIn && - newSwap.inputAmount.min.gte(swap.inputAmount.min) && - newSwap.inputAmount.min.lte(swap.inputAmount.max) + !( + newSwap.inputAmount.min.gte(swap.inputAmount.min) && + newSwap.inputAmount.min.lte(swap.inputAmount.max) + ) ) { throw new Error( - `Rates changed beyond tolerance. Before: ${swap.inputAmount.min.toFixed()}, After: ${newSwap.inputAmount.min.toFixed()}`, + `Rates changed beyond tolerance. Tolerance: ${swap.inputAmount.min.toFixed()}-${swap.inputAmount.max.toFixed()}, After: ${newSwap.inputAmount.min.toFixed()}`, ); } this.data = { + type: this.data.type, swap: newSwap, fetchDestinationSwapDetails: this.data.fetchDestinationSwapDetails, }; @@ -509,10 +542,10 @@ class DestinationSwapHandler { class SourceSwapsHandler { private disposableCache: { [k: string]: Tx } = {}; - private swaps: Map; + private swapsData: Map; constructor(data: SwapRoute['source'], private options: Options) { - this.swaps = this.groupAndOrder(data.swaps); - for (const [chainID, swapQuotes] of this.iterate(this.swaps)) { + this.swapsData = this.groupAndOrder(data.swaps); + for (const [chainID, swapQuotes] of this.iterate(this.swapsData)) { this.options.cache.addSetCodeQuery({ address: this.options.address.ephemeral, chainID: Number(chainID), @@ -536,34 +569,28 @@ class SourceSwapsHandler { } } - getSwapsAndMetadata(input: Swap[]) { - const swaps: { - amount: bigint; - approval: null | Tx; + getQuotesAndMetadata(input: Swap[]) { + const quotes: { input: { + amount: bigint; token: Bytes; decimals: number; symbol: string; }; - outputAmount: bigint; - outputToken: Bytes; - swap: { - data: Hex; - to: Hex; - value: bigint; - }; + output: { amount: bigint; token: Bytes }; + swap: { approval: Tx | null; tx: Tx }; }[] = []; const metadata: SwapMetadataTx['swaps'] = []; - for (const swap of input) { - const td = swap.getTxsData(); - const md = swap.getMetadata(); + for (const quoteData of input) { + const td = quoteData.getParsedQuote(); + const md = quoteData.getMetadata(); metadata.push(md); - swaps.push(td); + quotes.push(td); } - return { metadata, swaps }; + return { metadata, quotes }; } *iterate(input: Map) { @@ -575,7 +602,7 @@ class SourceSwapsHandler { async process( metadata: SwapMetadata, - input = this.swaps, + input = this.swapsData, retry = true, ): Promise<{ amount: Decimal; chainID: number; tokenAddress: `0x${string}` }[]> { logger.debug('sourceSwapsHandler', { @@ -603,7 +630,7 @@ class SourceSwapsHandler { tx_hash: new Uint8Array(), univ: Universe.ETHEREUM, }; - const { metadata: mtd, swaps } = this.getSwapsAndMetadata(swapQuotes); + const { metadata: mtd, quotes } = this.getQuotesAndMetadata(swapQuotes); const publicClient = this.options.publicClientList.get(chainID); const chain = this.options.chainList.getChainByID(Number(chainID)); if (!chain) { @@ -615,27 +642,27 @@ class SourceSwapsHandler { // 1. Source swap calls let amount = 0n; { - for (const swap of swaps) { - amount += swap.outputAmount; - if (isNativeAddress(convertToEVMAddress(swap.input.token))) { - sbcCalls.value += swap.amount; + for (const quote of quotes) { + amount += quote.output.amount; + if (isNativeAddress(convertToEVMAddress(quote.input.token))) { + sbcCalls.value += quote.input.amount; } else { this.options.emitter.emit( - SWAP_STEPS.CREATE_PERMIT_FOR_SOURCE_SWAP(false, swap.input.symbol, chain), + SWAP_STEPS.CREATE_PERMIT_FOR_SOURCE_SWAP(false, quote.input.symbol, chain), ); const allowanceCacheKey = getAllowanceCacheKey({ chainID: chain.id, - contractAddress: convertToEVMAddress(swap.input.token), + contractAddress: convertToEVMAddress(quote.input.token), owner: this.options.address.eoa, spender: this.options.address.ephemeral, }); const txs = await createPermitAndTransferFromTx({ - amount: swap.amount, + amount: quote.input.amount, approval: this.disposableCache[allowanceCacheKey], cache: this.options.cache, chain, - contractAddress: convertToEVMAddress(swap.input.token), + contractAddress: convertToEVMAddress(quote.input.token), owner: this.options.address.eoa, ownerWallet: this.options.wallet.eoa, publicClient, @@ -649,20 +676,20 @@ class SourceSwapsHandler { } this.options.emitter.emit( - SWAP_STEPS.CREATE_PERMIT_FOR_SOURCE_SWAP(true, swap.input.symbol, chain), + SWAP_STEPS.CREATE_PERMIT_FOR_SOURCE_SWAP(true, quote.input.symbol, chain), ); logger.debug('sourceSwap', { chainID, permitCalls: txs, - swap, + quote, }); sbcCalls.calls.push(...txs); } - if (swap.approval) { - sbcCalls.calls.push(swap.approval); + if (quote.swap.approval) { + sbcCalls.calls.push(quote.swap.approval); } - sbcCalls.calls.push(swap.swap); + sbcCalls.calls.push(quote.swap.tx); } } @@ -770,10 +797,10 @@ class SourceSwapsHandler { assets.push({ amount: divDecimals( amount, - getTokenDecimals(Number(chainID), swaps[0].outputToken).decimals, + getTokenDecimals(Number(chainID), quotes[0].output.token).decimals, ), chainID: Number(chainID), - tokenAddress: convertToEVMAddress(swaps[0].outputToken), + tokenAddress: convertToEVMAddress(quotes[0].output.token), }); metadata.src.push(metadataTx); @@ -855,7 +882,7 @@ class SourceSwapsHandler { // if it comes to retry it should be set to 0 oldTotalOutputAmount = 0n; for (const fChain of failedChains) { - const oldQuotes = this.swaps.get(fChain); + const oldQuotes = this.swapsData.get(fChain); if (!oldQuotes) { logger.debug('how can old quote not be there???? we are iterating on it'); continue; @@ -984,7 +1011,7 @@ class Swap { constructor(public input: SwapInput) {} getMetadata() { - const txs = this.getTxsData(); + const txs = this.getParsedQuote(); const { decimals: outputDecimals } = getTokenDecimals( Number(this.input.req.chain.chainID), @@ -995,17 +1022,15 @@ class Swap { input_amt: convertTo32Bytes(this.input.req.inputAmount), input_contract: this.input.req.inputToken, input_decimals: txs.input.decimals, - output_amt: convertTo32Bytes(txs.amount), + output_amt: convertTo32Bytes(txs.input.amount), output_contract: this.input.req.outputToken, output_decimals: outputDecimals, }; } - getTxsData() { - return { - ...getTxsFromQuote(this.input, !bytesEqual(EADDRESS_32_BYTES, this.input.req.inputToken)), - outputToken: this.input.req.outputToken, - }; + getParsedQuote() { + const data = parseQuote(this.input, !bytesEqual(EADDRESS_32_BYTES, this.input.req.inputToken)); + return { ...data, output: { ...data.output, token: this.input.req.outputToken } }; } } diff --git a/src/sdk/ca-base/swap/route.ts b/src/sdk/ca-base/swap/route.ts index f7b289ad..1c1bdb77 100644 --- a/src/sdk/ca-base/swap/route.ts +++ b/src/sdk/ca-base/swap/route.ts @@ -25,7 +25,6 @@ import { SwapParams, } from '../../../commons'; import { - calculateMaxBridgeFees, convertTo32BytesHex, divDecimals, equalFold, @@ -33,15 +32,10 @@ import { getFeeStore, mulDecimals, getBalances, + calculateMaxBridgeFee, } from '../utils'; import { EADDRESS } from './constants'; import { FlatBalance } from './data'; -import { - ErrorChainDataNotFound, - ErrorCOTNotFound, - ErrorInsufficientBalance, - ErrorTokenNotFound, -} from './errors'; import { createIntent } from './rff'; import { calculateValue, convertTo32Bytes, convertToEVMAddress } from './utils'; import { BridgeAsset } from '../../../commons'; @@ -107,14 +101,14 @@ const _exactOutRoute = async ( // ------------------------------ const dstChainDataMap = ChaindataMap.get(dstOmniversalChainID); if (!dstChainDataMap) { - throw ErrorChainDataNotFound; + throw Errors.internal(`chain data not found for chain ${input.toChainId}`); } const cotSymbol = CurrencyID[params.cotCurrencyID]; const dstChainCOT = dstChainDataMap.Currencies.find((c) => c.currencyID === params.cotCurrencyID); if (!dstChainCOT) { - throw ErrorCOTNotFound(input.toChainId); + throw Errors.internal(`COT not found for chain ${input.toChainId}`); } const dstChainCOTAddress = convertToEVMAddress(dstChainCOT.tokenAddress); @@ -161,7 +155,8 @@ const _exactOutRoute = async ( }; } - // Use min but perform everything as max - for buffer of (max - min) + // min is what is actually needed for dst swap, we add 1% for bridge related fees and 1% buffer for source swaps. + // so we are charging min + 2% from the user, we add the buffer so the swap definitely happens and any pending amounts are sent back to the user. const min = destinationSwap.inputAmount; // Apply 2% buffer to destination input amount const max = applyBuffer(destinationSwap.inputAmount, 2).toDP( @@ -317,7 +312,7 @@ const _exactOutRoute = async ( convertToEVMAddress(swap.req.outputToken), ); if (!token) { - throw ErrorTokenNotFound( + throw Errors.tokenNotFound( convertToEVMAddress(swap.req.outputToken), Number(swap.req.chain.chainID), ); @@ -420,6 +415,7 @@ const _exactOutRoute = async ( }, bridge: bridgeInput, destination: { + type: 'EXACT_OUT', swap: destinationSwap, fetchDestinationSwapDetails, }, @@ -467,6 +463,7 @@ export type SwapRoute = { }; bridge: BridgeInput; destination: { + type: 'EXACT_IN' | 'EXACT_OUT'; swap: DestinationSwap; fetchDestinationSwapDetails: () => Promise; }; @@ -539,7 +536,7 @@ const _exactInRoute = async ( }); if (balanceResponse.balances.length === 0) { - throw new Error('no balances returned for user'); + throw Errors.noBalanceForAddress(params.address.eoa); } let { balances } = balanceResponse; @@ -551,7 +548,7 @@ const _exactInRoute = async ( const assetsUsed: AssetUsed = []; let srcBalances: FlatBalance[] = []; - if (input.from && input.from.length > 0) { + if (input.from.length > 0) { // Filter out sources user requested to be used for (const f of input.from) { if (typeof f.amount !== 'bigint') { @@ -560,20 +557,27 @@ const _exactInRoute = async ( const comparison = normalizeToComparisonAddr(f.tokenAddress); - const srcBalance = balances.find( - (b) => equalFold(b.tokenAddress, comparison) && f.chainId === b.chainID, - ); + const srcBalance = balances.find((b) => { + logger.debug('ExactIn: from comparison', { + balanceTokenAddress: b.tokenAddress, + inputTokenAddress: f.tokenAddress, + comparisonTokenAddress: comparison, + }); + return equalFold(b.tokenAddress, comparison) && f.chainId === b.chainID; + }); if (!srcBalance) { logger.error('ExactIN: no src balance found', { token: f.tokenAddress, chainId: f.chainId, }); - throw ErrorInsufficientBalance('0', f.amount.toString()); + throw Errors.insufficientBalance(`available: 0, required: ${f.amount.toString()}`); } const requiredBalance = divDecimals(f.amount, srcBalance.decimals); if (requiredBalance.gt(srcBalance.amount)) { - throw ErrorInsufficientBalance(srcBalance.amount, requiredBalance.toFixed()); + throw Errors.insufficientBalance( + `available: ${srcBalance.amount}, required: ${requiredBalance.toFixed()}`, + ); } srcBalances.push({ @@ -599,13 +603,13 @@ const _exactInRoute = async ( const dstChainDataMap = ChaindataMap.get(dstOmniversalChainID); if (!dstChainDataMap) { - throw new Error(`chaindata map not found for chain ${input.toChainId}`); + throw Errors.internal(`chain data not found for chain ${input.toChainId}`); } const cotSymbol = CurrencyID[params.cotCurrencyID]; const dstChainCOT = dstChainDataMap.Currencies.find((c) => c.currencyID === params.cotCurrencyID); if (!dstChainCOT) { - throw ErrorCOTNotFound(input.toChainId); + throw Errors.internal(`COT not found for chain ${input.toChainId}`); } const dstChainCOTAddress = convertToEVMAddress(dstChainCOT.tokenAddress); @@ -684,7 +688,7 @@ const _exactInRoute = async ( logger.error('ExactIN: failed to map quote originalHolding to balance', { quoteReq: oq.req, }); - throw new Error('internal mapping error: balance for quote input not found'); + throw Errors.internal('mapping error: balance for quote input not found'); } return { ...oq, @@ -706,7 +710,7 @@ const _exactInRoute = async ( outputTokenAddress, ); if (!token) { - throw ErrorTokenNotFound(outputTokenAddress, Number(swap.req.chain.chainID)); + throw Errors.tokenNotFound(outputTokenAddress, Number(swap.req.chain.chainID)); } const bridgeAsset = bridgeAssets.find((b) => equalFold(b.contractAddress, outputTokenAddress)); const outputAmountInDecimal = divDecimals(swap.quote.outputAmountMinimum, token.decimals); @@ -734,8 +738,8 @@ const _exactInRoute = async ( let bridgeInput: BridgeInput = null; if (isBridgeRequired) { - const maxFee = calculateMaxBridgeFees({ - assets: bridgeAssets, + const { fee: maxFee } = calculateMaxBridgeFee({ + assets: bridgeAssets.map((b) => ({ ...b, balance: b.eoaBalance.add(b.ephemeralBalance) })), dst: { chainId: input.toChainId, tokenAddress: dstChainCOTAddress, @@ -851,6 +855,7 @@ const _exactInRoute = async ( }, bridge: bridgeInput, destination: { + type: 'EXACT_IN', swap: destinationSwap, fetchDestinationSwapDetails, }, diff --git a/src/sdk/ca-base/swap/utils.ts b/src/sdk/ca-base/swap/utils.ts index 9c57ae03..5334fcb4 100644 --- a/src/sdk/ca-base/swap/utils.ts +++ b/src/sdk/ca-base/swap/utils.ts @@ -725,7 +725,9 @@ export const toFlatBalance = ( return assets .map((a) => a.breakdown.map((b) => { - const tokenAddress = b.contractAddress === ZERO_ADDRESS ? EADDRESS : b.contractAddress; + const tokenAddress = equalFold(b.contractAddress, ZERO_ADDRESS) + ? EADDRESS + : b.contractAddress; return { amount: b.balance, chainID: b.chain.id, @@ -1080,7 +1082,7 @@ export const getAllowanceCacheKey = ({ export const getSetCodeKey = (input: SetCodeInput) => ('a' + input.chainID + input.address).toLowerCase(); -export const getTxsFromQuote = ( +export const parseQuote = ( input: { agg: Aggregator; originalHolding: Holding & { decimals: number; symbol: string }; @@ -1097,22 +1099,26 @@ export const getTxsFromQuote = ( const originalResponse = (input.quote as LiFiQuote).originalResponse; const tx = originalResponse.transactionRequest; const val = { - amount: input.quote.inputAmount, - approval: null as null | Tx, input: { + amount: input.quote.inputAmount, token: input.req.inputToken, decimals: input.originalHolding.decimals, symbol: input.originalHolding.symbol, }, - outputAmount: input.quote.outputAmountMinimum, + output: { + amount: input.quote.outputAmountMinimum, + }, swap: { - data: tx.data as Hex, - to: tx.to as Hex, - value: BigInt(tx.value), + approval: null as null | Tx, + tx: { + data: tx.data as Hex, + to: tx.to as Hex, + value: BigInt(tx.value), + }, }, }; if (createApproval) { - val.approval = { + val.swap.approval = { data: packERC20Approve( originalResponse.estimate.approvalAddress as Hex, input.quote.inputAmount, @@ -1135,22 +1141,24 @@ export const getTxsFromQuote = ( 'tx.outputAmount': input.quote.outputAmountMinimum, }); const val = { - amount: input.quote.inputAmount, - approval: null as null | Tx, input: { + amount: input.quote.inputAmount, token: input.req.inputToken, decimals: input.originalHolding.decimals, symbol: input.originalHolding.symbol, }, - outputAmount: input.quote.outputAmountMinimum, + output: { amount: input.quote.outputAmountMinimum }, swap: { - data: tx.data, - to: tx.to, - value: BigInt(tx.value), + approval: null as null | Tx, + tx: { + data: tx.data, + to: tx.to, + value: BigInt(tx.value), + }, }, }; if (createApproval) { - val.approval = { + val.swap.approval = { data: packERC20Approve( originalResponse.quote.approvalTarget as Hex, input.quote.inputAmount, diff --git a/src/sdk/ca-base/utils/rff.utils.ts b/src/sdk/ca-base/utils/rff.utils.ts index adb3c4a6..e416d31e 100644 --- a/src/sdk/ca-base/utils/rff.utils.ts +++ b/src/sdk/ca-base/utils/rff.utils.ts @@ -1,6 +1,6 @@ import { MsgCreateRequestForFunds, OmniversalRFF, Universe } from '@avail-project/ca-common'; import { FUEL_BASE_ASSET_ID, INTENT_EXPIRY, isNativeAddress, ZERO_ADDRESS } from '../constants'; -import { getLogger, ChainListType, Intent, IBridgeOptions, BridgeAsset } from '../../../commons'; +import { getLogger, ChainListType, Intent, IBridgeOptions } from '../../../commons'; import { convertTo32Bytes, convertTo32BytesHex, @@ -263,62 +263,6 @@ const createRFFromIntent = async ( }; }; -const calculateMaxBridgeFees = ({ - assets, - feeStore, - dst, -}: { - dst: { - chainId: number; - tokenAddress: Hex; - decimals: number; - }; - assets: BridgeAsset[]; - feeStore: FeeStore; -}) => { - const borrow = assets.reduce((accumulator, asset) => { - return accumulator.add(Decimal.add(asset.eoaBalance, asset.ephemeralBalance)); - }, new Decimal(0)); - - const protocolFee = feeStore.calculateProtocolFee(new Decimal(borrow)); - let borrowWithFee = borrow.add(protocolFee); - - const fulfilmentFee = feeStore.calculateFulfilmentFee({ - decimals: dst.decimals, - destinationChainID: dst.chainId, - destinationTokenAddress: dst.tokenAddress, - }); - borrowWithFee = borrowWithFee.add(fulfilmentFee); - - logger.debug('calculateMaxBridgeFees:1', { - borrow: borrow.toFixed(), - protocolFee: protocolFee.toFixed(), - fulfilmentFee: fulfilmentFee.toFixed(), - borrowWithFee: borrowWithFee.toFixed(), - }); - - for (const asset of assets) { - const solverFee = feeStore.calculateSolverFee({ - borrowAmount: Decimal.add(asset.eoaBalance, asset.ephemeralBalance), - decimals: asset.decimals, - destinationChainID: dst.chainId, - destinationTokenAddress: dst.tokenAddress, - sourceChainID: asset.chainID, - sourceTokenAddress: convertToEVMAddress(asset.contractAddress), - }); - - borrowWithFee = borrowWithFee.add(solverFee); - logger.debug('calculateMaxBridgeFees:2', { - borrow: borrow.toFixed(), - borrowWithFee: borrowWithFee.toFixed(), - solverFee: solverFee.toFixed(), - }); - } - - return borrowWithFee.minus(borrow); -}; - -// FIXME: Remove the above function after updating the usage. const calculateMaxBridgeFee = ({ assets, feeStore, @@ -398,9 +342,4 @@ const calculateMaxBridgeFee = ({ return { fee, maxAmount, sourceChainIds }; }; -export { - createRFFromIntent, - getSourcesAndDestinationsForRFF, - calculateMaxBridgeFee, - calculateMaxBridgeFees, -}; +export { createRFFromIntent, getSourcesAndDestinationsForRFF, calculateMaxBridgeFee }; From e86c4841ccf9c2fcb5d79b4e018a7eb17d2f1692 Mon Sep 17 00:00:00 2001 From: Abhishek Date: Wed, 19 Nov 2025 11:34:00 +0400 Subject: [PATCH 25/51] fix: add networkConfig input to network (#87) --- src/commons/types/index.ts | 10 +--------- src/sdk/ca-base/ca.ts | 8 ++------ src/sdk/ca-base/config.ts | 21 +++++++-------------- src/sdk/ca-base/index.ts | 1 - src/sdk/ca-base/utils/common.utils.ts | 27 --------------------------- 5 files changed, 10 insertions(+), 57 deletions(-) diff --git a/src/commons/types/index.ts b/src/commons/types/index.ts index 44d28be5..7a4d27bb 100644 --- a/src/commons/types/index.ts +++ b/src/commons/types/index.ts @@ -18,7 +18,7 @@ type TokenInfo = { symbol: string; }; -type NexusNetwork = 'mainnet' | 'testnet' | 'devnet'; +type NexusNetwork = 'mainnet' | 'testnet' | 'devnet' | NetworkConfig; export interface BlockTransaction { hash?: string; @@ -414,10 +414,8 @@ type Network = Extract; protected _evm?: { client: Client; provider: EthereumProvider; @@ -126,14 +123,13 @@ export class CA { protected constructor( config: { network?: NexusNetwork; debug?: boolean } = { debug: false, network: 'testnet' }, ) { - this._config = getSDKConfig(config); - this._networkConfig = getNetworkConfig(this._config.network); + this._networkConfig = getNetworkConfig(config.network); this.chainList = new ChainList(this._networkConfig.NETWORK_HINT); this.simulationClient = createBackendSimulationClient({ baseUrl: 'https://nexus-backend.avail.so', }); - if (this._config.debug) { + if (config.debug) { setLogLevel(LOG_LEVEL.DEBUG); } } diff --git a/src/sdk/ca-base/config.ts b/src/sdk/ca-base/config.ts index ca4f286c..68696395 100644 --- a/src/sdk/ca-base/config.ts +++ b/src/sdk/ca-base/config.ts @@ -1,15 +1,13 @@ import { Environment } from '@avail-project/ca-common'; -import { NetworkConfig } from '../../commons'; +import { NetworkConfig, NexusNetwork } from '../../commons'; // Testnet with mainnet tokens const CORAL_CONFIG: NetworkConfig = { COSMOS_URL: 'https://cosmos01-testnet.arcana.network', EXPLORER_URL: 'https://explorer.nexus.availproject.org', - FAUCET_URL: 'https://gateway001-testnet.arcana.network/api/v1/faucet', GRPC_URL: 'https://grpcproxy-testnet.arcana.network', NETWORK_HINT: Environment.CORAL, - SIMULATION_URL: 'https://ca-sim-testnet.arcana.network', VSC_DOMAIN: 'vsc1-testnet.arcana.network', }; @@ -17,10 +15,8 @@ const CORAL_CONFIG: NetworkConfig = { const CERISE_CONFIG: NetworkConfig = { COSMOS_URL: 'https://cosmos01-dev.arcana.network', EXPLORER_URL: 'https://explorer.nexus-cerise.availproject.org', - FAUCET_URL: 'https://gateway-dev.arcana.network/api/v1/faucet', GRPC_URL: 'https://mimosa-dash-grpc.arcana.network', NETWORK_HINT: Environment.CERISE, - SIMULATION_URL: 'https://ca-sim-dev.arcana.network', VSC_DOMAIN: 'mimosa-dash-vsc.arcana.network', }; @@ -28,10 +24,8 @@ const CERISE_CONFIG: NetworkConfig = { const FOLLY_CONFIG: NetworkConfig = { COSMOS_URL: 'https://cosmos04-dev.arcana.network', EXPLORER_URL: 'https://explorer.nexus-folly.availproject.org', - FAUCET_URL: 'https://gateway-dev.arcana.network/api/v1/faucet', GRPC_URL: 'https://grpc-folly.arcana.network', NETWORK_HINT: Environment.FOLLY, - SIMULATION_URL: 'https://ca-sim-dev.arcana.network', VSC_DOMAIN: 'vsc1-folly.arcana.network', }; @@ -43,10 +37,9 @@ const isNetworkConfig = (config?: Environment | NetworkConfig): config is Networ !( config.VSC_DOMAIN && config.COSMOS_URL && - config.SIMULATION_URL && - config.FAUCET_URL && config.EXPLORER_URL && - config.GRPC_URL + config.GRPC_URL && + config.NETWORK_HINT ) ) { return false; @@ -57,14 +50,14 @@ const isNetworkConfig = (config?: Environment | NetworkConfig): config is Networ return true; }; -const getNetworkConfig = (network?: Environment | NetworkConfig): NetworkConfig => { - if (isNetworkConfig(network)) { +const getNetworkConfig = (network?: NexusNetwork): NetworkConfig => { + if (typeof network === 'object' && isNetworkConfig(network)) { return network; } switch (network) { - case Environment.CERISE: + case 'devnet': return CERISE_CONFIG; - case Environment.FOLLY: + case 'testnet': return FOLLY_CONFIG; default: return CORAL_CONFIG; diff --git a/src/sdk/ca-base/index.ts b/src/sdk/ca-base/index.ts index d725b7ba..744fe553 100644 --- a/src/sdk/ca-base/index.ts +++ b/src/sdk/ca-base/index.ts @@ -10,7 +10,6 @@ export type { OnIntentHook, RequestArguments, RFF, - SDKConfig, UserAssetDatum as UserAsset, BridgeStepType, SwapStepType, diff --git a/src/sdk/ca-base/utils/common.utils.ts b/src/sdk/ca-base/utils/common.utils.ts index b662d8d5..cfbc33b3 100644 --- a/src/sdk/ca-base/utils/common.utils.ts +++ b/src/sdk/ca-base/utils/common.utils.ts @@ -39,14 +39,11 @@ import { FUEL_BASE_ASSET_ID, isNativeAddress, ZERO_ADDRESS } from '../constants' import { getLogger, IBridgeOptions, SupportedChainsAndTokensResult } from '../../../commons'; import { Intent, - Network, NetworkConfig, OraclePriceResponse, ReadableIntent, - SDKConfig, TokenInfo, ChainListType, - NexusNetwork, UserAssetDatum, Chain, } from '../../../commons'; @@ -524,29 +521,6 @@ const createDepositDoubleCheckTx = ( }; }; -const getSDKConfig = (c: { network?: NexusNetwork; debug?: boolean }): Required => { - const config = { - debug: c.debug ?? false, - network: Environment.CORAL as Network, - }; - - switch (c.network) { - case 'testnet': { - config.network = Environment.FOLLY; - break; - } - case 'mainnet': { - config.network = Environment.CORAL; - break; - } - case 'devnet': { - config.network = Environment.CERISE; - } - } - - return config; -}; - class UserAsset { get balance() { return this.value.balance; @@ -932,7 +906,6 @@ export { evmWaitForFill, getExpiredIntents, getExplorerURL, - getSDKConfig, getSupportedChains, hexTo0xString, minutesToMs, From 7629da210c551d2467e0240e7f42c1332b09fda2 Mon Sep 17 00:00:00 2001 From: Abhishek Date: Wed, 19 Nov 2025 12:38:08 +0400 Subject: [PATCH 26/51] =?UTF-8?q?fix:=20better=20naming=20for=20balance=20?= =?UTF-8?q?api,=20deprecate=20old=20balance=20api.=20docs:=20=E2=80=A6=20(?= =?UTF-8?q?#88)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix: better naming for balance api, deprecate old balance api. * doc: update changes, update functions tsdoc. * fix: more info of getBalanceForSwap fn. --- README.md | 23 +++++++++++++++++------ package.json | 2 +- src/sdk/ca-base/swap/ob.ts | 15 ++------------- src/sdk/index.ts | 27 +++++++++++++++++++++------ 4 files changed, 41 insertions(+), 26 deletions(-) diff --git a/README.md b/README.md index 04cf32e7..33bff5a6 100644 --- a/README.md +++ b/README.md @@ -239,8 +239,9 @@ All events include `typeID`, `transactionHash`, `explorerURL`, and `error` (if a ## 💰 Balance Operations ```typescript -const balances = await sdk.getUnifiedBalances(); // CA balances -const allBalances = await sdk.getUnifiedBalances(true); // Includes swappable tokens +const unifiedBridgeBalances = await sdk.getBalancesForBridge(); // Returns balances that can be used in bridge operations +--- +const swapBalances = await sdk.getBalancesForSwap(); // Returns balances that can be used in swap operations ``` --- @@ -248,8 +249,19 @@ const allBalances = await sdk.getUnifiedBalances(true); // Includes swappable to ## 🌉 Bridge Operations ```typescript -const result = await sdk.bridge({ token: 'USDC', amount: 83_500_000n, chainId: 137 }); -const simulation = await sdk.simulateBridge({ token: 'USDC', amount: 83_500_000n, chainId: 137 }); +const result = await sdk.bridge({ + token: 'USDC', + amount: 83_500_000n, + chainId: 137, + recipient: '0x....', +}); + +const simulation = await sdk.simulateBridge({ + token: 'USDC', + amount: 83_500_000n, + chainId: 137, + recipient: '0x....', +}); ``` --- @@ -273,7 +285,7 @@ const simulation = await sdk.simulateBridgeAndTransfer({ --- -## ⚙️ Execute & Bridge+Execute +## ⚙️ Execute & Bridge + Execute ```typescript // Direct contract execution @@ -401,7 +413,6 @@ import type { | Base Sepolia | 84532 | ETH | ✅ | | Sepolia | 11155111 | ETH | ✅ | | Monad Testnet | 10143 | MON | ✅ | -| Validium | 567 | VLDM | ✅ | --- diff --git a/package.json b/package.json index a137577c..e7285e61 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@avail-project/nexus-core", - "version": "1.0.0-beta.32", + "version": "1.0.0-beta.33", "description": "Nexus headless SDK for cross-chain transactions", "main": "./dist/index.js", "module": "./dist/index.esm.js", diff --git a/src/sdk/ca-base/swap/ob.ts b/src/sdk/ca-base/swap/ob.ts index 9ac7ddb0..a2d16104 100644 --- a/src/sdk/ca-base/swap/ob.ts +++ b/src/sdk/ca-base/swap/ob.ts @@ -15,7 +15,7 @@ import { DirectSecp256k1Wallet } from '@cosmjs/proto-signing'; import Decimal from 'decimal.js'; import { orderBy, retry } from 'es-toolkit'; import Long from 'long'; -import { Hex, PrivateKeyAccount, toBytes, WalletClient } from 'viem'; +import { Hex, PrivateKeyAccount, WalletClient } from 'viem'; import { getLogger, SWAP_STEPS, SwapStepType } from '../../../commons'; import { divDecimals, equalFold, minutesToMs, waitForTxReceipt } from '../utils'; import { EADDRESS, SWEEPER_ADDRESS } from './constants'; @@ -996,18 +996,6 @@ class SourceSwapsHandler { } class Swap { - txs: { - amount: bigint; - approval: null | Tx; - inputToken: Bytes; - outputAmount: bigint; - outputToken: Bytes; - swap: { - data: Hex; - to: Hex; - value: bigint; - }; - } | null = null; constructor(public input: SwapInput) {} getMetadata() { @@ -1017,6 +1005,7 @@ class Swap { Number(this.input.req.chain.chainID), this.input.req.outputToken, ); + return { agg: 1, input_amt: convertTo32Bytes(this.input.req.inputAmount), diff --git a/src/sdk/index.ts b/src/sdk/index.ts index 2487d6f7..8abac525 100644 --- a/src/sdk/index.ts +++ b/src/sdk/index.ts @@ -28,7 +28,7 @@ import type { } from '../commons'; import { logger } from '../commons'; import { CA } from './ca-base'; -import { AdapterProps } from '@tronweb3/tronwallet-abstract-adapter'; +// import { AdapterProps } from '@tronweb3/tronwallet-abstract-adapter'; export class NexusSDK extends CA { public readonly utils: NexusUtils; @@ -48,7 +48,8 @@ export class NexusSDK extends CA { } /** - * Get unified balances across all chains + * @deprecated use `getBalancesForBridge` for direct replacement. + * @returns unified balances across all chains */ public async getUnifiedBalances(includeSwappableBalances = false): Promise { return this._getUnifiedBalances(includeSwappableBalances); @@ -143,9 +144,9 @@ export class NexusSDK extends CA { this._setOnSwapIntentHook(callback); } - public addTron(adapter: AdapterProps) { - this._setTronAdapter(adapter); - } + // public addTron(adapter: AdapterProps) { + // this._setTronAdapter(adapter); + // } /** * Set callback for allowance approval events @@ -178,7 +179,7 @@ export class NexusSDK extends CA { /** * Enhanced bridge and execute function with optional execute step and improved error handling - * @param params Enhanced bridge and execute parameters + * @param params bridge and execute parameters * @returns Promise resolving to comprehensive operation result */ public async bridgeAndExecute( @@ -200,10 +201,24 @@ export class NexusSDK extends CA { return this._simulateBridgeAndExecute(params); } + /** + * tokens returned here should be used in `input` for exact in swap + * @returns balances that can be used in swap operations + */ public getBalancesForSwap() { return this._getBalancesForSwap(); } + /** + * @returns balances that can be used in bridge operations + */ + public getBalancesForBridge() { + return this._getUnifiedBalances(false); + } + + /** + * @returns list of chains where swap is supported + */ public getSwapSupportedChains(): SupportedChainsResult { return this._getSwapSupportedChains(); } From a4c0d81fa80772b7b57693ad75a930fae10f2319 Mon Sep 17 00:00:00 2001 From: Abhishek Date: Wed, 19 Nov 2025 15:42:11 +0400 Subject: [PATCH 27/51] fix: update ca-common with latest mainnet-c contracts (#89) * fix: update ca-common with latest coral contracts * chore: release rc.1 build * fix: updated to avail multichain rpc * fix: binding error --- package-lock.json | 12 ++++++------ package.json | 6 +++--- src/sdk/ca-base/ca.ts | 14 +++++++------- src/sdk/ca-base/requestHandlers/bridge.ts | 7 +------ src/sdk/ca-base/swap/utils.ts | 23 ++++++++++------------- src/sdk/index.ts | 4 ++-- 6 files changed, 29 insertions(+), 37 deletions(-) diff --git a/package-lock.json b/package-lock.json index 6b113f0e..509fb320 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,15 +1,15 @@ { "name": "@avail-project/nexus-core", - "version": "1.0.0-beta.31", + "version": "1.0.0-beta.34", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@avail-project/nexus-core", - "version": "1.0.0-beta.31", + "version": "1.0.0-beta.34", "license": "MIT", "dependencies": { - "@avail-project/ca-common": "1.0.0-dev.2", + "@avail-project/ca-common": "1.0.0-dev.3", "@cosmjs/proto-signing": "^0.34.0", "@cosmjs/stargate": "^0.34.0", "@metamask/safe-event-emitter": "3.1.2", @@ -49,9 +49,9 @@ "license": "MIT" }, "node_modules/@avail-project/ca-common": { - "version": "1.0.0-dev.2", - "resolved": "https://registry.npmjs.org/@avail-project/ca-common/-/ca-common-1.0.0-dev.2.tgz", - "integrity": "sha512-3e7EcTpDv8uchHAq5xz7a/mKAjG7rgG3fd0ZPR8MDRn8y4biPyy79x6rmS8Qd4hJOXRrQvMUJ48bpVO1dPCAgQ==", + "version": "1.0.0-dev.3", + "resolved": "https://registry.npmjs.org/@avail-project/ca-common/-/ca-common-1.0.0-dev.3.tgz", + "integrity": "sha512-uayZmtX04P99aLy+rGIsDX6BmImOH5HBAajZvf/SKJbIDqz6bG0AFEvybGfvEOCZNpajXA/sFOtTfitTDiQocA==", "license": "MIT", "dependencies": { "@bufbuild/protobuf": "^2.6.0", diff --git a/package.json b/package.json index e7285e61..0e82bc23 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@avail-project/nexus-core", - "version": "1.0.0-beta.33", + "version": "1.0.0-beta.35", "description": "Nexus headless SDK for cross-chain transactions", "main": "./dist/index.js", "module": "./dist/index.esm.js", @@ -39,7 +39,7 @@ "author": "decocereus, makyl", "license": "MIT", "dependencies": { - "@avail-project/ca-common": "1.0.0-dev.2", + "@avail-project/ca-common": "1.0.0-dev.3", "@cosmjs/proto-signing": "^0.34.0", "@cosmjs/stargate": "^0.34.0", "@metamask/safe-event-emitter": "3.1.2", @@ -50,10 +50,10 @@ "@starkware-industries/starkware-crypto-utils": "^0.2.1", "@tronweb3/tronwallet-abstract-adapter": "^1.1.9", "axios": "^1.12.2", + "buffer": "6.0.3", "decimal.js": "^10.6.0", "es-toolkit": "^1.40.0", "fuels": "0.101.1", - "buffer": "6.0.3", "it-ws": "^6.1.5", "long": "^5.3.2", "msgpackr": "^1.11.5", diff --git a/src/sdk/ca-base/ca.ts b/src/sdk/ca-base/ca.ts index 121e9ed3..6975f3f9 100644 --- a/src/sdk/ca-base/ca.ts +++ b/src/sdk/ca-base/ca.ts @@ -134,7 +134,7 @@ export class CA { } } - protected createBridgeHandler = (input: BridgeParams, options?: OnEventParam) => { + protected _createBridgeHandler = (input: BridgeParams, options?: OnEventParam) => { if (!this._evm) { throw Errors.sdkNotInitialized(); } @@ -513,7 +513,7 @@ export class CA { const handler = new BridgeAndExecuteQuery( this.chainList, this._evm.client, - this.createBridgeHandler, + this._createBridgeHandler, this._getUnifiedBalances, this.simulationClient, ); @@ -521,7 +521,7 @@ export class CA { return handler.simulateBridgeAndExecute(params); } - protected _bridgeAndExecute(params: BridgeAndExecuteParams, options?: OnEventParam) { + protected _bridgeAndExecute = (params: BridgeAndExecuteParams, options?: OnEventParam) => { if (!this._evm) { throw Errors.sdkNotInitialized(); } @@ -529,13 +529,13 @@ export class CA { const handler = new BridgeAndExecuteQuery( this.chainList, this._evm.client, - this.createBridgeHandler, + this._createBridgeHandler, this._getUnifiedBalances, this.simulationClient, ); return handler.bridgeAndExecute(params, options); - } + }; protected async _execute(params: ExecuteParams, options?: OnEventParam) { if (!this._evm) { @@ -545,7 +545,7 @@ export class CA { const handler = new BridgeAndExecuteQuery( this.chainList, this._evm.client, - this.createBridgeHandler, + this._createBridgeHandler, this._getUnifiedBalances, this.simulationClient, ); @@ -561,7 +561,7 @@ export class CA { const handler = new BridgeAndExecuteQuery( this.chainList, this._evm.client, - this.createBridgeHandler, + this._createBridgeHandler, this._getUnifiedBalances, this.simulationClient, ); diff --git a/src/sdk/ca-base/requestHandlers/bridge.ts b/src/sdk/ca-base/requestHandlers/bridge.ts index 46eed7de..15eff2a4 100644 --- a/src/sdk/ca-base/requestHandlers/bridge.ts +++ b/src/sdk/ca-base/requestHandlers/bridge.ts @@ -650,12 +650,7 @@ class BridgeHandler { if (currency.permitVariant === PermitVariant.Unsupported || chain.id === 1) { if (chain.universe === Universe.ETHEREUM) { - // await switchChain(this.options.evm.client, chain); - - await this.options.evm.provider.request({ - method: 'wallet_switchEthereumChain', - params: [{ chainId: toHex(chain.id) }], - }); + await switchChain(this.options.evm.client, chain); const h = await this.options.evm.client .writeContract({ diff --git a/src/sdk/ca-base/swap/utils.ts b/src/sdk/ca-base/swap/utils.ts index 5334fcb4..9376d1c9 100644 --- a/src/sdk/ca-base/swap/utils.ts +++ b/src/sdk/ca-base/swap/utils.ts @@ -620,20 +620,17 @@ export const getAnkrBalances = async ( totalBalanceUsd: string; totalCount: number; }; - }>( - 'https://rpc.ankr.com/multichain/269e541dd5773dac3204831e29b9538284dd3e9591d2b7cb2ac47d85eae213b9/', - { - id: Decimal.random(2).mul(100).toNumber(), - jsonrpc: '2.0', - method: 'ankr_getAccountBalance', - params: { - blockchain: chainList.getAnkrNameList(), - onlyWhitelisted: true, - pageSize: 500, - walletAddress: walletAddress, - }, + }>('https://rpcs.avail.so/multichain', { + id: Decimal.random(2).mul(100).toNumber(), + jsonrpc: '2.0', + method: 'ankr_getAccountBalance', + params: { + blockchain: chainList.getAnkrNameList(), + onlyWhitelisted: true, + pageSize: 500, + walletAddress: walletAddress, }, - ); + }); if (!res.data?.result) throw new Error('balances cannot be retrieved'); const filteredAssets = res.data.result.assets.filter( diff --git a/src/sdk/index.ts b/src/sdk/index.ts index 8abac525..dc7a850b 100644 --- a/src/sdk/index.ts +++ b/src/sdk/index.ts @@ -59,7 +59,7 @@ export class NexusSDK extends CA { * Bridge to destination chain from auto-selected or provided source chains */ public async bridge(params: BridgeParams, options?: OnEventParam): Promise { - const result = await this.createBridgeHandler(params, options).execute(); + const result = await this._createBridgeHandler(params, options).execute(); return { explorerUrl: result.explorerURL ?? '', }; @@ -111,7 +111,7 @@ export class NexusSDK extends CA { * Simulate bridge transaction to get costs and fees */ public async simulateBridge(params: BridgeParams): Promise { - return this.createBridgeHandler(params).simulate(); + return this._createBridgeHandler(params).simulate(); } /** From e7d74916661468de2523283a4f97dc689fecbb5a Mon Sep 17 00:00:00 2001 From: Abhishek Date: Thu, 20 Nov 2025 15:09:32 +0400 Subject: [PATCH 28/51] feat: added ability to set chain for siwe (#94) * feat: added ability to set chain for siwe * fix: set siweChain to optional --- src/sdk/ca-base/ca.ts | 38 +++++++++++++++++---------- src/sdk/ca-base/utils/common.utils.ts | 8 +++--- src/sdk/index.ts | 2 +- 3 files changed, 29 insertions(+), 19 deletions(-) diff --git a/src/sdk/ca-base/ca.ts b/src/sdk/ca-base/ca.ts index 6975f3f9..bfd8793e 100644 --- a/src/sdk/ca-base/ca.ts +++ b/src/sdk/ca-base/ca.ts @@ -11,6 +11,7 @@ import { Client, CustomTransport, Hex, + UserRejectedRequestError, } from 'viem'; import { privateKeyToAccount, PrivateKeyAccount } from 'viem/accounts'; import { createSiweMessage } from 'viem/siwe'; @@ -90,6 +91,7 @@ export class CA { }; #ephemeralWallet?: PrivateKeyAccount; public chainList: ChainListType; + private _siweChain = 1; protected _evm?: { client: Client; provider: EthereumProvider; @@ -121,7 +123,11 @@ export class CA { private simulationClient: BackendSimulationClient; protected constructor( - config: { network?: NexusNetwork; debug?: boolean } = { debug: false, network: 'testnet' }, + config: { network?: NexusNetwork; debug?: boolean; siweChain?: number } = { + debug: false, + network: 'testnet', + siweChain: 1, + }, ) { this._networkConfig = getNetworkConfig(config.network); this.chainList = new ChainList(this._networkConfig.NETWORK_HINT); @@ -129,6 +135,10 @@ export class CA { baseUrl: 'https://nexus-backend.avail.so', }); + if (config.siweChain) { + this._siweChain = config.siweChain; + } + if (config.debug) { setLogLevel(LOG_LEVEL.DEBUG); } @@ -427,10 +437,10 @@ export class CA { } protected async _createCosmosWallet() { - let sig = this._getStoredSIWESignature(this._evm!.address); + let sig = retrieveSIWESignatureFromLocalStorage(this._evm!.address, this._siweChain); if (!sig) { sig = await this._signatureForLogin(); - this._storeSIWESignature(this._evm!.address, sig); + storeSIWESignatureToLocalStorage(this._evm!.address, this._siweChain, sig); } const pvtKey = keyDerivation.getPrivateKeyFromEthSignature(sig); @@ -468,13 +478,19 @@ export class CA { if (!this._evm) { throw Errors.sdkNotInitialized(); } + + const chain = this.chainList.getChainByID(this._siweChain); + if (!chain) { + throw Errors.chainNotFound(this._siweChain); + } + const scheme = window.location.protocol.slice(0, -1); const domain = window.location.host; const origin = window.location.origin; const address = await this._getEVMAddress(); const message = createSiweMessage({ address, - chainId: 1, + chainId: chain.id, domain, issuedAt: new Date('2024-12-16T12:17:43.182Z'), // this remains same to arrive at same pvt key nonce: 'iLjYWC6s8frYt4l8w', // maybe this can be shortened hash of address @@ -485,14 +501,16 @@ export class CA { }); const currentChain = await this._evm.client.getChainId(); try { - await this._evm.client.switchChain({ id: 1 }); + await switchChain(this._evm.client, chain); const res = await this._evm.client .signMessage({ account: address, message, }) .catch((e) => { - e.walk(); + if (e instanceof UserRejectedRequestError) { + throw Errors.userRejectedSIWESignature(); + } throw e; }); return res; @@ -579,14 +597,6 @@ export class CA { } }; - private _getStoredSIWESignature(address: Hex) { - return retrieveSIWESignatureFromLocalStorage(address); - } - - private _storeSIWESignature(address: Hex, signature: string) { - return storeSIWESignatureToLocalStorage(address, signature); - } - protected _convertTokenReadableAmountToBigInt = ( amount: string, tokenSymbol: string, diff --git a/src/sdk/ca-base/utils/common.utils.ts b/src/sdk/ca-base/utils/common.utils.ts index cfbc33b3..89b18917 100644 --- a/src/sdk/ca-base/utils/common.utils.ts +++ b/src/sdk/ca-base/utils/common.utils.ts @@ -874,12 +874,12 @@ const retrieveAddress = ( const SIWE_KEY = '_siwe_sig'; -const storeSIWESignatureToLocalStorage = (address: Hex, signature: string) => { - window.localStorage.setItem(`${SIWE_KEY}-${address}`, signature); +const storeSIWESignatureToLocalStorage = (address: Hex, siweChain: number, signature: string) => { + window.localStorage.setItem(`${SIWE_KEY}-${address}-${siweChain}`, signature); }; -const retrieveSIWESignatureFromLocalStorage = (address: Hex) => { - return window.localStorage.getItem(`${SIWE_KEY}-${address}`); +const retrieveSIWESignatureFromLocalStorage = (address: Hex, siweChain: number) => { + return window.localStorage.getItem(`${SIWE_KEY}-${address}-${siweChain}`); }; export { diff --git a/src/sdk/index.ts b/src/sdk/index.ts index dc7a850b..537bfde2 100644 --- a/src/sdk/index.ts +++ b/src/sdk/index.ts @@ -33,7 +33,7 @@ import { CA } from './ca-base'; export class NexusSDK extends CA { public readonly utils: NexusUtils; - constructor(config?: { network?: NexusNetwork; debug?: boolean }) { + constructor(config?: { network?: NexusNetwork; debug?: boolean; siweChain?: number }) { super(config); logger.debug('Nexus SDK initialized with config:', config); this.utils = new NexusUtils(this.chainList); From 2590b406c7f285c751818355d52f4b231259221d Mon Sep 17 00:00:00 2001 From: Abhishek Date: Thu, 20 Nov 2025 15:15:15 +0400 Subject: [PATCH 29/51] fix: swap balances to return same type as bridge balances (#92) * fix: getBalancesForSwap to return UserAsset[] --- package.json | 2 +- src/sdk/ca-base/swap/utils.ts | 4 ++-- src/sdk/ca-base/utils/balance.utils.ts | 2 +- src/sdk/index.ts | 7 +++++-- 4 files changed, 9 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index 0e82bc23..faf48a66 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@avail-project/nexus-core", - "version": "1.0.0-beta.35", + "version": "1.0.0-beta.38", "description": "Nexus headless SDK for cross-chain transactions", "main": "./dist/index.js", "module": "./dist/index.esm.js", diff --git a/src/sdk/ca-base/swap/utils.ts b/src/sdk/ca-base/swap/utils.ts index 9376d1c9..414c337d 100644 --- a/src/sdk/ca-base/swap/utils.ts +++ b/src/sdk/ca-base/swap/utils.ts @@ -61,7 +61,7 @@ import { } from '../utils'; import { SWEEP_ABI } from './abi'; import { CALIBUR_ADDRESS, EADDRESS, SWEEPER_ADDRESS } from './constants'; -import { chainData, getTokenVersion } from './data'; +import { chainData, FlatBalance, getTokenVersion } from './data'; import { createSBCTxFromCalls, waitForSBCTxReceipt } from './sbc'; import { SWAP_STEPS, @@ -715,7 +715,7 @@ export const toFlatBalance = ( convertAddressToBytes32 = true, currentChainID?: number, selectedTokenAddress?: `0x${string}`, -) => { +): FlatBalance[] => { logger.debug('toFlatBalance', { assets, }); diff --git a/src/sdk/ca-base/utils/balance.utils.ts b/src/sdk/ca-base/utils/balance.utils.ts index b3688135..c63b3d28 100644 --- a/src/sdk/ca-base/utils/balance.utils.ts +++ b/src/sdk/ca-base/utils/balance.utils.ts @@ -41,7 +41,7 @@ export const getBalancesForSwap = async (input: { evmAddress: Hex; chainList: Ch input.chainList, ); let balances = toFlatBalance(assets, false); - return balances; + return { assets, balances }; }; export const getBalances = async (input: { diff --git a/src/sdk/index.ts b/src/sdk/index.ts index 537bfde2..96c945bf 100644 --- a/src/sdk/index.ts +++ b/src/sdk/index.ts @@ -28,6 +28,7 @@ import type { } from '../commons'; import { logger } from '../commons'; import { CA } from './ca-base'; +import { FlatBalance } from './ca-base/swap/data'; // import { AdapterProps } from '@tronweb3/tronwallet-abstract-adapter'; export class NexusSDK extends CA { @@ -205,8 +206,10 @@ export class NexusSDK extends CA { * tokens returned here should be used in `input` for exact in swap * @returns balances that can be used in swap operations */ - public getBalancesForSwap() { - return this._getBalancesForSwap(); + public async getBalancesForSwap() { + const result = await this._getBalancesForSwap(); + + return result.assets; } /** From d665e08445b1a180755a8e1ce63f309054a5271c Mon Sep 17 00:00:00 2001 From: Abhishek Date: Thu, 20 Nov 2025 17:36:43 +0400 Subject: [PATCH 30/51] feat: add beforeExecute hook in bridgeAndExecute (#96) * feat: add beforeExecute hook in bridgeAndExecute * fix: removed unused variable preventing builds --- src/commons/types/index.ts | 4 ++++ src/sdk/ca-base/ca.ts | 6 +++++- src/sdk/ca-base/query/bridgeAndExecute.ts | 9 ++++++++- src/sdk/index.ts | 1 - 4 files changed, 17 insertions(+), 3 deletions(-) diff --git a/src/commons/types/index.ts b/src/commons/types/index.ts index 7a4d27bb..a98dff4a 100644 --- a/src/commons/types/index.ts +++ b/src/commons/types/index.ts @@ -654,6 +654,10 @@ export type UserAssetDatum = { symbol: string; }; +export type BeforeExecuteHook = { + beforeExecute?: () => Promise<{ value: bigint; data: Hex }>; +}; + export type { OnIntentHook, OnAllowanceHookData, diff --git a/src/sdk/ca-base/ca.ts b/src/sdk/ca-base/ca.ts index bfd8793e..e83d5ce7 100644 --- a/src/sdk/ca-base/ca.ts +++ b/src/sdk/ca-base/ca.ts @@ -25,6 +25,7 @@ import { Chain, TransferParams, BridgeParams, + BeforeExecuteHook, } from '../../commons'; import { createBridgeParams } from './requestHandlers/helpers'; import { @@ -539,7 +540,10 @@ export class CA { return handler.simulateBridgeAndExecute(params); } - protected _bridgeAndExecute = (params: BridgeAndExecuteParams, options?: OnEventParam) => { + protected _bridgeAndExecute = ( + params: BridgeAndExecuteParams, + options?: OnEventParam & BeforeExecuteHook, + ) => { if (!this._evm) { throw Errors.sdkNotInitialized(); } diff --git a/src/sdk/ca-base/query/bridgeAndExecute.ts b/src/sdk/ca-base/query/bridgeAndExecute.ts index bdf0338e..0e296ac8 100644 --- a/src/sdk/ca-base/query/bridgeAndExecute.ts +++ b/src/sdk/ca-base/query/bridgeAndExecute.ts @@ -16,6 +16,7 @@ import { NEXUS_EVENTS, BRIDGE_STEPS, BridgeStepType, + BeforeExecuteHook, } from '../../../commons'; import { createPublicClient, @@ -208,7 +209,7 @@ class BridgeAndExecuteQuery { */ public async bridgeAndExecute( params: BridgeAndExecuteParams, - options?: OnEventParam, + options?: OnEventParam & BeforeExecuteHook, ): Promise { const { dstPublicClient, @@ -275,6 +276,12 @@ class BridgeAndExecuteQuery { } } + if (options?.beforeExecute) { + const response = await options.beforeExecute(); + tx.data = response.data; + tx.value = response.value; + } + // 8. Execute the transaction const executeResponse = await this.sendTx( { diff --git a/src/sdk/index.ts b/src/sdk/index.ts index 96c945bf..39dade33 100644 --- a/src/sdk/index.ts +++ b/src/sdk/index.ts @@ -28,7 +28,6 @@ import type { } from '../commons'; import { logger } from '../commons'; import { CA } from './ca-base'; -import { FlatBalance } from './ca-base/swap/data'; // import { AdapterProps } from '@tronweb3/tronwallet-abstract-adapter'; export class NexusSDK extends CA { From 6d04bf476de3285cb78ce5684982f0c3d063f463 Mon Sep 17 00:00:00 2001 From: Abhishek Date: Thu, 20 Nov 2025 18:06:41 +0400 Subject: [PATCH 31/51] fix: add bnb and eth chain data (#97) * fix: add bnb and usdc to bnb chain data * fix: add ethereum chain data --- src/sdk/ca-base/swap/data.ts | 72 ++++++++++++++++++++++++++++++++---- 1 file changed, 64 insertions(+), 8 deletions(-) diff --git a/src/sdk/ca-base/swap/data.ts b/src/sdk/ca-base/swap/data.ts index 14b81cc1..84447263 100644 --- a/src/sdk/ca-base/swap/data.ts +++ b/src/sdk/ca-base/swap/data.ts @@ -9,16 +9,17 @@ import { EADDRESS } from './constants'; import { convertToEVMAddress, determinePermitVariantAndVersion } from './utils'; export enum CurrencyID { - AVAX = 5, - DAI = 6, - ETH = 3, + USDC = 0x1, + USDT = 0x2, + ETH = 0x3, + POL = 0x4, + AVAX = 0x5, + BNB = 0x6, + WETH = 0x7, + DAI = 0x8, HYPE = 0x10, KAIA = 0x11, - POL = 4, - USDC = 1, USDS = 99, - USDT = 2, - WETH = 7, } const chainData: Map< @@ -274,6 +275,61 @@ const chainData: Map< }, ], ], + [ + 56, + [ + { + CurrencyID: CurrencyID.USDC, + IsGasToken: false, + Name: CurrencyID[CurrencyID.USDC], + PermitVariant: PermitVariant.Unsupported, + PermitContractVersion: 0, + TokenContractAddress: convertTo32BytesHex('0x8ac76a51cc950d9822d68b83fe1ad97b32cd580d'), + TokenDecimals: 18, + }, + { + CurrencyID: CurrencyID.BNB, + IsGasToken: true, + Name: CurrencyID[CurrencyID.BNB], + PermitVariant: PermitVariant.Unsupported, + PermitContractVersion: 0, + TokenContractAddress: convertTo32BytesHex(EADDRESS), + TokenDecimals: 18, + }, + ], + ], + [ + 1, + [ + { + CurrencyID: CurrencyID.USDC, + IsGasToken: false, + Name: CurrencyID[CurrencyID.USDC], + PermitVariant: PermitVariant.EIP2612Canonical, + PermitContractVersion: 2, + TokenContractAddress: convertTo32BytesHex('0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48'), + TokenDecimals: 6, + }, + { + CurrencyID: CurrencyID.USDT, + IsGasToken: false, + Name: CurrencyID[CurrencyID.USDT], + PermitVariant: PermitVariant.Unsupported, + PermitContractVersion: 0, + TokenContractAddress: convertTo32BytesHex('0xdac17f958d2ee523a2206206994597c13d831ec7'), + TokenDecimals: 6, + }, + { + CurrencyID: CurrencyID.ETH, + IsGasToken: true, + Name: CurrencyID[CurrencyID.ETH], + PermitVariant: PermitVariant.Unsupported, + PermitContractVersion: 0, + TokenContractAddress: convertTo32BytesHex(EADDRESS), + TokenDecimals: 18, + }, + ], + ], ]); const getSwapSupportedChains = (chainList: ChainList) => { @@ -365,7 +421,7 @@ const getTokenVersion = async (tokenAddress: Hex, client: PublicClient) => { export const getTokenDecimals = (chainID: number | string, contractAddress: Bytes) => { const cData = chainData.get(Number(chainID)); if (!cData) { - throw new Error(`chain data not found for chain:${chainID}`); + throw new Error(`chain data not found for chain: ${chainID}`); } const token = cData.find((c) => equalFold(toHex(contractAddress), c.TokenContractAddress)); if (!token) { From 924774e028e91968e7155f9bebfcd88f8bc3a244 Mon Sep 17 00:00:00 2001 From: Abhishek Date: Thu, 20 Nov 2025 18:09:17 +0400 Subject: [PATCH 32/51] feat: add typedoc to create html sdk reference (#95) * feat: add typedoc to create html sdk reference * feat: added github action to deploy typedoc --------- Co-authored-by: decocereus --- .github/workflows/deploy-typedoc.yml | 77 ++++++++ .gitignore | 1 + package-lock.json | 266 ++++++++++++++++++++++++++- package.json | 7 +- typedoc_html.json | 12 ++ 5 files changed, 360 insertions(+), 3 deletions(-) create mode 100644 .github/workflows/deploy-typedoc.yml create mode 100644 typedoc_html.json diff --git a/.github/workflows/deploy-typedoc.yml b/.github/workflows/deploy-typedoc.yml new file mode 100644 index 00000000..30b11462 --- /dev/null +++ b/.github/workflows/deploy-typedoc.yml @@ -0,0 +1,77 @@ +name: Build & Publish TypeDoc + +on: + push: + branches: + - develop + - master + +permissions: + contents: write + +jobs: + build-and-publish: + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Use Node.js + uses: actions/setup-node@v4 + with: + node-version: '18' + + - name: Install dependencies + run: npm ci + + - name: Build TypeDoc (runs your 'docs' script) + run: npm run docs + # typedoc_html.json has "out": "html_docs" so output will be at ./html_docs + + - name: Publish to gh-pages under branch folder + env: + REPO: ${{ github.repository }} + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + BRANCH_NAME: ${{ github.ref_name }} + run: | + set -e + echo "Publishing TypeDoc for branch: ${BRANCH_NAME}" + + REMOTE="https://x-access-token:${GH_TOKEN}@github.com/${REPO}.git" + TMP=tmp-gh-pages + rm -rf $TMP + mkdir -p $TMP + cd $TMP + + # If gh-pages exists, clone it; otherwise init an empty repo + if git ls-remote --heads "${REMOTE}" gh-pages >/dev/null 2>&1; then + git clone --depth 1 --branch gh-pages "${REMOTE}" . + else + git init + git remote add origin "${REMOTE}" + # create an initial .nojekyll so the branch isn't empty after first push + fi + + # Remove old docs for this branch and copy new ones + rm -rf "${BRANCH_NAME}" + mkdir -p "${BRANCH_NAME}" + cp -r ../html_docs/* "${BRANCH_NAME}/" || true + + # Ensure pages with underscores render correctly + touch .nojekyll + + git config user.name "github-actions[bot]" + git config user.email "41898282+github-actions[bot]@users.noreply.github.com" + + # Commit + push + if git rev-parse --verify HEAD >/dev/null 2>&1; then + git add -A + git commit -m "chore(docs): update TypeDoc for ${BRANCH_NAME} (run: ${GITHUB_RUN_ID})" || echo "No changes to commit" + else + git add -A + git commit -m "chore(docs): initialize gh-pages (run: ${GITHUB_RUN_ID})" + fi + + git push --force "${REMOTE}" HEAD:gh-pages diff --git a/.gitignore b/.gitignore index a642f3f6..127f87dc 100644 --- a/.gitignore +++ b/.gitignore @@ -35,3 +35,4 @@ Thumbs.db *.swo /dist-tarballs +html_docs/ \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 509fb320..5307ac72 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@avail-project/nexus-core", - "version": "1.0.0-beta.34", + "version": "1.0.0-beta.38", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@avail-project/nexus-core", - "version": "1.0.0-beta.34", + "version": "1.0.0-beta.38", "license": "MIT", "dependencies": { "@avail-project/ca-common": "1.0.0-dev.3", @@ -39,6 +39,10 @@ "rollup": "^4.52.4", "rollup-plugin-dts": "^6.2.3", "rollup-plugin-typescript2": "0.36.0", + "typedoc": "0.28.14", + "typedoc-plugin-extras": "4.0.1", + "typedoc-plugin-missing-exports": "4.1.2", + "typedoc-plugin-rename-defaults": "0.7.3", "typescript": "^5.9.3" } }, @@ -1048,6 +1052,20 @@ "integrity": "sha512-wkCu63jTGJWpRZQirTaB8S4/gyoebEJLk3AKfnykt/lgWp1U9iHOcCICVHQP547i+y8jEVKwk18+huINFyYVFQ==", "license": "Apache-2.0" }, + "node_modules/@gerrit0/mini-shiki": { + "version": "3.15.0", + "resolved": "https://registry.npmjs.org/@gerrit0/mini-shiki/-/mini-shiki-3.15.0.tgz", + "integrity": "sha512-L5IHdZIDa4bG4yJaOzfasOH/o22MCesY0mx+n6VATbaiCtMeR59pdRqYk4bEiQkIHfxsHPNgdi7VJlZb2FhdMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@shikijs/engine-oniguruma": "^3.15.0", + "@shikijs/langs": "^3.15.0", + "@shikijs/themes": "^3.15.0", + "@shikijs/types": "^3.15.0", + "@shikijs/vscode-textmate": "^10.0.2" + } + }, "node_modules/@graphql-typed-document-node/core": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/@graphql-typed-document-node/core/-/core-3.2.0.tgz", @@ -1882,6 +1900,55 @@ "url": "https://paulmillr.com/funding/" } }, + "node_modules/@shikijs/engine-oniguruma": { + "version": "3.15.0", + "resolved": "https://registry.npmjs.org/@shikijs/engine-oniguruma/-/engine-oniguruma-3.15.0.tgz", + "integrity": "sha512-HnqFsV11skAHvOArMZdLBZZApRSYS4LSztk2K3016Y9VCyZISnlYUYsL2hzlS7tPqKHvNqmI5JSUJZprXloMvA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@shikijs/types": "3.15.0", + "@shikijs/vscode-textmate": "^10.0.2" + } + }, + "node_modules/@shikijs/langs": { + "version": "3.15.0", + "resolved": "https://registry.npmjs.org/@shikijs/langs/-/langs-3.15.0.tgz", + "integrity": "sha512-WpRvEFvkVvO65uKYW4Rzxs+IG0gToyM8SARQMtGGsH4GDMNZrr60qdggXrFOsdfOVssG/QQGEl3FnJ3EZ+8w8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@shikijs/types": "3.15.0" + } + }, + "node_modules/@shikijs/themes": { + "version": "3.15.0", + "resolved": "https://registry.npmjs.org/@shikijs/themes/-/themes-3.15.0.tgz", + "integrity": "sha512-8ow2zWb1IDvCKjYb0KiLNrK4offFdkfNVPXb1OZykpLCzRU6j+efkY+Y7VQjNlNFXonSw+4AOdGYtmqykDbRiQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@shikijs/types": "3.15.0" + } + }, + "node_modules/@shikijs/types": { + "version": "3.15.0", + "resolved": "https://registry.npmjs.org/@shikijs/types/-/types-3.15.0.tgz", + "integrity": "sha512-BnP+y/EQnhihgHy4oIAN+6FFtmfTekwOLsQbRw9hOKwqgNy8Bdsjq8B05oAt/ZgvIWWFrshV71ytOrlPfYjIJw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@shikijs/vscode-textmate": "^10.0.2", + "@types/hast": "^3.0.4" + } + }, + "node_modules/@shikijs/vscode-textmate": { + "version": "10.0.2", + "resolved": "https://registry.npmjs.org/@shikijs/vscode-textmate/-/vscode-textmate-10.0.2.tgz", + "integrity": "sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg==", + "dev": true, + "license": "MIT" + }, "node_modules/@starkware-industries/starkware-crypto-utils": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/@starkware-industries/starkware-crypto-utils/-/starkware-crypto-utils-0.2.1.tgz", @@ -1941,6 +2008,16 @@ "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", "license": "MIT" }, + "node_modules/@types/hast": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz", + "integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/unist": "*" + } + }, "node_modules/@types/node": { "version": "24.10.1", "resolved": "https://registry.npmjs.org/@types/node/-/node-24.10.1.tgz", @@ -1975,6 +2052,13 @@ "@types/node": "*" } }, + "node_modules/@types/unist": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz", + "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/ws": { "version": "8.18.1", "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.18.1.tgz", @@ -2212,6 +2296,13 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true, + "license": "Python-2.0" + }, "node_modules/asn1.js": { "version": "4.10.1", "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.10.1.tgz", @@ -2602,6 +2693,19 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/camelcase": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-8.0.0.tgz", + "integrity": "sha512-8WB3Jcas3swSvjIeA2yvCJ+Miyz5l1ZmB6HFb9R1317dt9LCQoswg/BGrmAmkWVEszSrrg4RwmO46qIm2OEnSA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/chai": { "version": "5.3.3", "resolved": "https://registry.npmjs.org/chai/-/chai-5.3.3.tgz", @@ -3025,6 +3129,19 @@ "typedarray-to-buffer": "3.1.5" } }, + "node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, "node_modules/es-define-property": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", @@ -4269,6 +4386,16 @@ "libsodium-sumo": "^0.7.15" } }, + "node_modules/linkify-it": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.0.tgz", + "integrity": "sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "uc.micro": "^2.0.0" + } + }, "node_modules/load-tsconfig": { "version": "0.2.5", "resolved": "https://registry.npmjs.org/load-tsconfig/-/load-tsconfig-0.2.5.tgz", @@ -4322,6 +4449,13 @@ "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", "license": "ISC" }, + "node_modules/lunr": { + "version": "2.3.9", + "resolved": "https://registry.npmjs.org/lunr/-/lunr-2.3.9.tgz", + "integrity": "sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==", + "dev": true, + "license": "MIT" + }, "node_modules/magic-string": { "version": "0.30.21", "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", @@ -4357,6 +4491,24 @@ "semver": "bin/semver.js" } }, + "node_modules/markdown-it": { + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.1.0.tgz", + "integrity": "sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg==", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1", + "entities": "^4.4.0", + "linkify-it": "^5.0.0", + "mdurl": "^2.0.0", + "punycode.js": "^2.3.1", + "uc.micro": "^2.1.0" + }, + "bin": { + "markdown-it": "bin/markdown-it.mjs" + } + }, "node_modules/math-intrinsics": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", @@ -4377,6 +4529,13 @@ "safe-buffer": "^5.1.2" } }, + "node_modules/mdurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-2.0.0.tgz", + "integrity": "sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==", + "dev": true, + "license": "MIT" + }, "node_modules/miller-rabin": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", @@ -5009,6 +5168,16 @@ "integrity": "sha512-n4DSx829VRTRByMRGdjQ9iqsN0Bh4OolPsFnaZBLcbi8iXcB+kJ9s7EnRt4wILZNV3kPLHkRVfOc/HvhC3ovDw==", "license": "MIT" }, + "node_modules/punycode.js": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode.js/-/punycode.js-2.3.1.tgz", + "integrity": "sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/ramda": { "version": "0.30.1", "resolved": "https://registry.npmjs.org/ramda/-/ramda-0.30.1.tgz", @@ -5953,6 +6122,79 @@ "is-typedarray": "^1.0.0" } }, + "node_modules/typedoc": { + "version": "0.28.14", + "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.28.14.tgz", + "integrity": "sha512-ftJYPvpVfQvFzpkoSfHLkJybdA/geDJ8BGQt/ZnkkhnBYoYW6lBgPQXu6vqLxO4X75dA55hX8Af847H5KXlEFA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@gerrit0/mini-shiki": "^3.12.0", + "lunr": "^2.3.9", + "markdown-it": "^14.1.0", + "minimatch": "^9.0.5", + "yaml": "^2.8.1" + }, + "bin": { + "typedoc": "bin/typedoc" + }, + "engines": { + "node": ">= 18", + "pnpm": ">= 10" + }, + "peerDependencies": { + "typescript": "5.0.x || 5.1.x || 5.2.x || 5.3.x || 5.4.x || 5.5.x || 5.6.x || 5.7.x || 5.8.x || 5.9.x" + } + }, + "node_modules/typedoc-plugin-extras": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/typedoc-plugin-extras/-/typedoc-plugin-extras-4.0.1.tgz", + "integrity": "sha512-ab3T37ukHCwBjwBJpAcWdxy/XAaLdUyy5pwbgF9WDqCRN0DTJmJPLew9Kv6qrx5qnxiyfe6F4Og+PUp15kJWLw==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "typedoc": "0.27.x || 0.28.x" + } + }, + "node_modules/typedoc-plugin-missing-exports": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/typedoc-plugin-missing-exports/-/typedoc-plugin-missing-exports-4.1.2.tgz", + "integrity": "sha512-WNoeWX9+8X3E3riuYPduilUTFefl1K+Z+5bmYqNeH5qcWjtnTRMbRzGdEQ4XXn1WEO4WCIlU0vf46Ca2y/mspg==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "typedoc": "^0.28.1" + } + }, + "node_modules/typedoc-plugin-rename-defaults": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/typedoc-plugin-rename-defaults/-/typedoc-plugin-rename-defaults-0.7.3.tgz", + "integrity": "sha512-fDtrWZ9NcDfdGdlL865GW7uIGQXlthPscURPOhDkKUe4DBQSRRFUf33fhWw41FLlsz8ZTeSxzvvuNmh54MynFA==", + "dev": true, + "license": "MIT", + "dependencies": { + "camelcase": "^8.0.0" + }, + "peerDependencies": { + "typedoc": ">=0.22.x <0.29.x" + } + }, + "node_modules/typedoc/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/typescript": { "version": "5.9.3", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", @@ -5967,6 +6209,13 @@ "node": ">=14.17" } }, + "node_modules/uc.micro": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-2.1.0.tgz", + "integrity": "sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==", + "dev": true, + "license": "MIT" + }, "node_modules/uglify-js": { "version": "3.19.3", "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.19.3.tgz", @@ -6518,6 +6767,19 @@ "symbol-observable": "^2.0.3" } }, + "node_modules/yaml": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.1.tgz", + "integrity": "sha512-lcYcMxX2PO9XMGvAJkJ3OsNMw+/7FKes7/hgerGUYWIoWu5j/+YQqcZr5JnPZWzOsEBgMbSbiSTn/dv/69Mkpw==", + "devOptional": true, + "license": "ISC", + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14.6" + } + }, "node_modules/yup": { "version": "1.6.1", "resolved": "https://registry.npmjs.org/yup/-/yup-1.6.1.tgz", diff --git a/package.json b/package.json index faf48a66..999de998 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,8 @@ "build": "rollup -c", "buildAndPack": "rollup -c && npm pack", "dev": "rollup -c -w", - "clean": "rimraf dist dist-tarballs", + "docs": "typedoc --options typedoc_html.json", + "clean": "rimraf dist dist-tarballs html_docs", "typecheck": "tsc --noEmit", "prepublishOnly": "npm run build" }, @@ -69,6 +70,10 @@ "rollup": "^4.52.4", "rollup-plugin-dts": "^6.2.3", "rollup-plugin-typescript2": "0.36.0", + "typedoc": "0.28.14", + "typedoc-plugin-extras": "4.0.1", + "typedoc-plugin-missing-exports": "4.1.2", + "typedoc-plugin-rename-defaults": "0.7.3", "typescript": "^5.9.3" }, "publishConfig": { diff --git a/typedoc_html.json b/typedoc_html.json new file mode 100644 index 00000000..c69ec8c4 --- /dev/null +++ b/typedoc_html.json @@ -0,0 +1,12 @@ +{ + "entryPoints": ["src/index.ts"], + "entryPointStrategy": "expand", + "tsconfig": "tsconfig.json", + "name": "Nexus core SDK Reference", + "out": "html_docs", + "plugin": [], + "theme": "default", + "excludePrivate": true, + "excludeProtected": false, + "includeVersion": true +} From 33527e1d8882990fac477856250254b6b72e9018 Mon Sep 17 00:00:00 2001 From: Amartya Singh <53113365+decocereus@users.noreply.github.com> Date: Thu, 20 Nov 2025 20:29:36 +0530 Subject: [PATCH 33/51] feat: github pages sdk references (#98) * fix: github action * fix: deploy-typedoc script * feat: added theme for typedoc --- .github/workflows/deploy-typedoc.yml | 52 ++++++++++++++++++---------- package-lock.json | 14 ++++++++ package.json | 3 +- 3 files changed, 49 insertions(+), 20 deletions(-) diff --git a/.github/workflows/deploy-typedoc.yml b/.github/workflows/deploy-typedoc.yml index 30b11462..fccd991b 100644 --- a/.github/workflows/deploy-typedoc.yml +++ b/.github/workflows/deploy-typedoc.yml @@ -1,4 +1,4 @@ -name: Build & Publish TypeDoc +name: Build & Publish TypeDoc (master -> root, develop -> /develop) on: push: @@ -28,50 +28,64 @@ jobs: - name: Build TypeDoc (runs your 'docs' script) run: npm run docs - # typedoc_html.json has "out": "html_docs" so output will be at ./html_docs + # typedoc_html.json should output to ./html_docs - - name: Publish to gh-pages under branch folder + - name: Publish to gh-pages (master -> root, develop -> /develop) env: REPO: ${{ github.repository }} GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} BRANCH_NAME: ${{ github.ref_name }} run: | - set -e + set -euo pipefail echo "Publishing TypeDoc for branch: ${BRANCH_NAME}" REMOTE="https://x-access-token:${GH_TOKEN}@github.com/${REPO}.git" TMP=tmp-gh-pages - rm -rf $TMP - mkdir -p $TMP - cd $TMP + rm -rf "$TMP" + mkdir -p "$TMP" + cd "$TMP" - # If gh-pages exists, clone it; otherwise init an empty repo - if git ls-remote --heads "${REMOTE}" gh-pages >/dev/null 2>&1; then + # If gh-pages exists on remote, clone it; otherwise init an empty repo and add remote + if git ls-remote --heads "${REMOTE}" gh-pages | grep -q 'refs/heads/gh-pages'; then git clone --depth 1 --branch gh-pages "${REMOTE}" . else git init git remote add origin "${REMOTE}" - # create an initial .nojekyll so the branch isn't empty after first push fi - # Remove old docs for this branch and copy new ones - rm -rf "${BRANCH_NAME}" - mkdir -p "${BRANCH_NAME}" - cp -r ../html_docs/* "${BRANCH_NAME}/" || true - - # Ensure pages with underscores render correctly + # Ensure .nojekyll is present touch .nojekyll + # Publish logic: + # - If run on master => publish html_docs to root of gh-pages (overwrites root content but preserves /develop) + # - If run on develop => publish html_docs to gh-pages/develop/ + if [ "${BRANCH_NAME}" = "master" ]; then + echo "Publishing master build to gh-pages root..." + # keep .git and /develop and .nojekyll - remove everything else from root + # enable extglob to use !(pattern) + bash -lc 'shopt -s extglob || true; rm -rf -- !(develop|.nojekyll|.git)' + + # copy the built docs into the root + cp -r ../html_docs/* . || true + else + echo "Publishing develop build to gh-pages/develop/..." + rm -rf "${BRANCH_NAME}" + mkdir -p "${BRANCH_NAME}" + cp -r ../html_docs/* "${BRANCH_NAME}/" || true + fi + + # Configure git user git config user.name "github-actions[bot]" git config user.email "41898282+github-actions[bot]@users.noreply.github.com" - # Commit + push + # Stage changes and commit + git add -A + if git rev-parse --verify HEAD >/dev/null 2>&1; then - git add -A git commit -m "chore(docs): update TypeDoc for ${BRANCH_NAME} (run: ${GITHUB_RUN_ID})" || echo "No changes to commit" else - git add -A git commit -m "chore(docs): initialize gh-pages (run: ${GITHUB_RUN_ID})" fi + # Push to gh-pages (creates branch if needed) git push --force "${REMOTE}" HEAD:gh-pages diff --git a/package-lock.json b/package-lock.json index 5307ac72..e5330f07 100644 --- a/package-lock.json +++ b/package-lock.json @@ -43,6 +43,7 @@ "typedoc-plugin-extras": "4.0.1", "typedoc-plugin-missing-exports": "4.1.2", "typedoc-plugin-rename-defaults": "0.7.3", + "typedoc-theme-fresh": "0.2.1", "typescript": "^5.9.3" } }, @@ -6179,6 +6180,19 @@ "typedoc": ">=0.22.x <0.29.x" } }, + "node_modules/typedoc-theme-fresh": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/typedoc-theme-fresh/-/typedoc-theme-fresh-0.2.1.tgz", + "integrity": "sha512-LQMQka0wrgG+L/Ar/VgZbbq1d0JwzZbDm+N6jaKtMwSUXdWQ4RNBQSmr0y800uJzW4jtqtVGAYjgoDmNhmMPeg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18.0.0" + }, + "peerDependencies": { + "typedoc": "^0.28.14" + } + }, "node_modules/typedoc/node_modules/minimatch": { "version": "9.0.5", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", diff --git a/package.json b/package.json index 999de998..e4f8e1cf 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,7 @@ "build": "rollup -c", "buildAndPack": "rollup -c && npm pack", "dev": "rollup -c -w", - "docs": "typedoc --options typedoc_html.json", + "docs": "typedoc --plugin typedoc-theme-fresh --theme fresh --options typedoc_html.json", "clean": "rimraf dist dist-tarballs html_docs", "typecheck": "tsc --noEmit", "prepublishOnly": "npm run build" @@ -74,6 +74,7 @@ "typedoc-plugin-extras": "4.0.1", "typedoc-plugin-missing-exports": "4.1.2", "typedoc-plugin-rename-defaults": "0.7.3", + "typedoc-theme-fresh": "0.2.1", "typescript": "^5.9.3" }, "publishConfig": { From 142581f9029f6f1fa02b9f1b445b49519afd282b Mon Sep 17 00:00:00 2001 From: Abhishek Date: Thu, 20 Nov 2025 20:44:52 +0400 Subject: [PATCH 34/51] fix: throwing error on simulation failed (#99) * fix: stopped catching error in simulateBridge in bridgeAndExecute * fix: undid accidental removal --- src/sdk/ca-base/query/bridgeAndExecute.ts | 18 +++++++++--------- src/sdk/ca-base/requestHandlers/bridge.ts | 4 +++- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/src/sdk/ca-base/query/bridgeAndExecute.ts b/src/sdk/ca-base/query/bridgeAndExecute.ts index 0e296ac8..b497d898 100644 --- a/src/sdk/ca-base/query/bridgeAndExecute.ts +++ b/src/sdk/ca-base/query/bridgeAndExecute.ts @@ -17,6 +17,8 @@ import { BRIDGE_STEPS, BridgeStepType, BeforeExecuteHook, + ReadableIntent, + TokenInfo, } from '../../../commons'; import { createPublicClient, @@ -176,7 +178,10 @@ class BridgeAndExecuteQuery { gasAmount, }); - let bridgeResult = null; + let bridgeResult: null | { + intent: ReadableIntent; + token: TokenInfo; + } = null; // 7. If bridge is required then simulate bridge if (!skipBridge) { @@ -613,14 +618,9 @@ class BridgeAndExecuteQuery { }; private simulateBridgeWrapper = async (params: BridgeParams) => { - try { - const handler = this.bridge(params); - const result = await handler.simulate(); - return result; - } catch (e) { - logger.debug('simulateBridgeError', { e }); - return null; - } + const handler = this.bridge(params); + const result = await handler.simulate(); + return result; }; } diff --git a/src/sdk/ca-base/requestHandlers/bridge.ts b/src/sdk/ca-base/requestHandlers/bridge.ts index 15eff2a4..4bcbbffd 100644 --- a/src/sdk/ca-base/requestHandlers/bridge.ts +++ b/src/sdk/ca-base/requestHandlers/bridge.ts @@ -1045,7 +1045,9 @@ class BridgeHandler { intent.destination.amount = borrow; if (accountedAmount.lt(borrowWithFee)) { - intent.isAvailableBalanceInsufficient = true; + throw Errors.insufficientBalance( + `required: ${borrowWithFee.toFixed()}, available: ${accountedAmount.toFixed()}`, + ); } if (!gas.equals(0)) { From 41d0bd811e2df7b3e0cf2d80e22c0e02eff4fcc1 Mon Sep 17 00:00:00 2001 From: Amartya Singh <53113365+decocereus@users.noreply.github.com> Date: Thu, 20 Nov 2025 23:23:51 +0530 Subject: [PATCH 35/51] feat: added some code docs and fixed some lints (#100) --- src/commons/constants/index.ts | 19 +++++- src/commons/utils/format.ts | 31 +++++++++ src/sdk/ca-base/ca.ts | 26 ++++---- src/sdk/ca-base/chains.ts | 2 +- src/sdk/ca-base/query/bridgeAndExecute.ts | 14 ++--- src/sdk/ca-base/requestHandlers/bridge.ts | 6 +- src/sdk/ca-base/swap/ob.ts | 18 +++--- src/sdk/ca-base/swap/rff.ts | 8 ++- src/sdk/ca-base/swap/route.ts | 8 ++- src/sdk/ca-base/swap/swap.ts | 2 +- src/sdk/ca-base/swap/utils.ts | 48 +++++++------- src/sdk/ca-base/utils/api.utils.ts | 32 +++++----- src/sdk/ca-base/utils/common.utils.ts | 9 +-- src/sdk/index.ts | 77 +++++++++++++++++++++-- src/sdk/utils.ts | 51 ++++++++++++++- 15 files changed, 255 insertions(+), 96 deletions(-) diff --git a/src/commons/constants/index.ts b/src/commons/constants/index.ts index 246d2ea9..dc24c86c 100644 --- a/src/commons/constants/index.ts +++ b/src/commons/constants/index.ts @@ -64,6 +64,11 @@ export const TESTNET_TOKEN_METADATA: Record = { USDC: { ...BASE_TOKEN_METADATA.USDC, name: 'Test USD Coin' }, } as const; +/** + * Chain metadata + * @returns Chain metadata + */ + export const CHAIN_METADATA: Record = { // Mainnet chains [SUPPORTED_CHAINS.ETHEREUM]: { @@ -226,14 +231,20 @@ export const CHAIN_METADATA: Record = { }, } as const; -// Event name constants to prevent typos +/** + * Event name constants to prevent typos + * @returns Event name constants + */ export const NEXUS_EVENTS = { STEP_COMPLETE: 'STEP_COMPLETE', SWAP_STEP_COMPLETE: 'SWAP_STEP_COMPLETE', STEPS_LIST: 'STEPS_LIST', } as const; -// Helper constants for mainnet and testnet chain categorization +/** + * Mainnet chains + * @returns Mainnet chains + */ export const MAINNET_CHAINS = [ SUPPORTED_CHAINS.ETHEREUM, SUPPORTED_CHAINS.BASE, @@ -249,6 +260,10 @@ export const MAINNET_CHAINS = [ SUPPORTED_CHAINS.TRON, ] as const; +/** + * Testnet chains + * @returns Testnet chains + */ export const TESTNET_CHAINS = [ SUPPORTED_CHAINS.SEPOLIA, SUPPORTED_CHAINS.BASE_SEPOLIA, diff --git a/src/commons/utils/format.ts b/src/commons/utils/format.ts index 350b36c0..1c64976f 100644 --- a/src/commons/utils/format.ts +++ b/src/commons/utils/format.ts @@ -252,6 +252,21 @@ function formatTiny( }; } +/** + * Format a token balance parts + * @param value - The value to format + * @param options - The options to format the balance + * @returns The formatted balance parts + * Examples: + * - 1.234567 -> "1.2346" + * - 0.00008509 -> "~0.0₄8509" (shows 4 leading zeros after decimal) + * - 0.000000000000000123 -> "~0.0₁₅123" + * + * Notes: + * - Uses Unicode subscript digits for the zero count. + * - Returns a structured object with parts of the balance. + */ + export function formatTokenBalanceParts( value: InputValue, { @@ -311,6 +326,22 @@ export function formatTokenBalanceParts( return formatTiny(negative, fracRaw, zeros, tinyOpts); } +/** + * Format a token balance + * @param value - The value to format + * @param options - The options to format the balance + * @returns The formatted balance + * Examples: + * - 1.234567 -> "1.2346" + * - 0.00008509 -> "~0.0₄8509" (shows 4 leading zeros after decimal) + * - 0.000000000000000123 -> "~0.0₁₅123" + * + * Notes: + * - Uses Unicode subscript digits for the zero count. + * - Returns a single string optimized for UI display. + * - If you need richer rendering (e.g., separate parts to style the subscript), + * use `formatTokenBalanceParts` which returns structured parts. + */ export function formatTokenBalance( value: string | number | bigint, options?: FormatTokenBalanceOptions, diff --git a/src/sdk/ca-base/ca.ts b/src/sdk/ca-base/ca.ts index e83d5ce7..1fae87b9 100644 --- a/src/sdk/ca-base/ca.ts +++ b/src/sdk/ca-base/ca.ts @@ -18,16 +18,6 @@ import { createSiweMessage } from 'viem/siwe'; import { ChainList } from './chains'; import { getNetworkConfig } from './config'; import { FUEL_NETWORK_URL } from './constants'; -import { - getLogger, - LOG_LEVEL, - setLogLevel, - Chain, - TransferParams, - BridgeParams, - BeforeExecuteHook, -} from '../../commons'; -import { createBridgeParams } from './requestHandlers/helpers'; import { ChainListType, EthereumProvider, @@ -44,7 +34,15 @@ import { OnEventParam, OnSwapIntentHook, TronAdapter, + getLogger, + LOG_LEVEL, + setLogLevel, + Chain, + TransferParams, + BridgeParams, + BeforeExecuteHook, } from '../../commons'; +import { createBridgeParams } from './requestHandlers/helpers'; import { cosmosFeeGrant, fetchMyIntents, @@ -85,14 +83,14 @@ enum INIT_STATUS { const SIWE_STATEMENT = 'Sign in to enable Nexus'; export class CA { - static getSupportedChains = getSupportedChains; + static readonly getSupportedChains = getSupportedChains; #cosmos?: { wallet: DirectSecp256k1Wallet; address: string; }; #ephemeralWallet?: PrivateKeyAccount; public chainList: ChainListType; - private _siweChain = 1; + private readonly _siweChain: number = 1; protected _evm?: { client: Client; provider: EthereumProvider; @@ -121,7 +119,7 @@ export class CA { protected _networkConfig: NetworkConfig; protected _refundInterval: number | undefined; protected _initPromise: Promise | null = null; - private simulationClient: BackendSimulationClient; + private readonly simulationClient: BackendSimulationClient; protected constructor( config: { network?: NexusNetwork; debug?: boolean; siweChain?: number } = { @@ -591,7 +589,7 @@ export class CA { return handler.simulateExecute(params, this._evm.address); } - private universeCheck = (dstChain: Chain) => { + private readonly universeCheck = (dstChain: Chain) => { if (dstChain.universe === Universe.FUEL && !this._fuel) { throw Errors.walletNotConnected('Fuel'); } diff --git a/src/sdk/ca-base/chains.ts b/src/sdk/ca-base/chains.ts index aa934af0..81bd4487 100644 --- a/src/sdk/ca-base/chains.ts +++ b/src/sdk/ca-base/chains.ts @@ -13,7 +13,7 @@ import { Hex } from 'viem'; class ChainList { public chains: Chain[]; - private vcm: ChainIDKeyedMap>; + private readonly vcm: ChainIDKeyedMap>; constructor(env: Environment) { switch (env) { diff --git a/src/sdk/ca-base/query/bridgeAndExecute.ts b/src/sdk/ca-base/query/bridgeAndExecute.ts index b497d898..5f7ed2f7 100644 --- a/src/sdk/ca-base/query/bridgeAndExecute.ts +++ b/src/sdk/ca-base/query/bridgeAndExecute.ts @@ -47,11 +47,11 @@ import { Errors } from '../errors'; class BridgeAndExecuteQuery { constructor( - private chainList: ChainListType, - private evmClient: WalletClient, - private bridge: (input: BridgeParams, options?: OnEventParam) => BridgeHandler, - private getUnifiedBalances: () => Promise, - private simulationClient: BackendSimulationClient, + private readonly chainList: ChainListType, + private readonly evmClient: WalletClient, + private readonly bridge: (input: BridgeParams, options?: OnEventParam) => BridgeHandler, + private readonly getUnifiedBalances: () => Promise, + private readonly simulationClient: BackendSimulationClient, ) {} private async estimateBridgeAndExecute(params: BridgeAndExecuteParams) { @@ -606,7 +606,7 @@ class BridgeAndExecuteQuery { }; } - private bridgeWrapper = async ( + private readonly bridgeWrapper = async ( params: BridgeParams, options?: OnEventParam, ): Promise => { @@ -617,7 +617,7 @@ class BridgeAndExecuteQuery { }; }; - private simulateBridgeWrapper = async (params: BridgeParams) => { + private readonly simulateBridgeWrapper = async (params: BridgeParams) => { const handler = this.bridge(params); const result = await handler.simulate(); return result; diff --git a/src/sdk/ca-base/requestHandlers/bridge.ts b/src/sdk/ca-base/requestHandlers/bridge.ts index 4bcbbffd..df065c0f 100644 --- a/src/sdk/ca-base/requestHandlers/bridge.ts +++ b/src/sdk/ca-base/requestHandlers/bridge.ts @@ -106,7 +106,7 @@ class BridgeHandler { }; } - private buildIntent = async (sourceChains: number[] = []) => { + private readonly buildIntent = async (sourceChains: number[] = []) => { console.time('process:preIntentSteps'); console.time('preIntentSteps:API'); @@ -701,7 +701,7 @@ class BridgeHandler { signedTx, }); - if (!this.options.tron!.adapter.isMobile) { + if (!this.options.tron.adapter.isMobile) { const txResult = await provider.trx.sendRawTransaction(signedTx); logger.debug('tron tx result', { @@ -1059,7 +1059,7 @@ class BridgeHandler { return intent; } - private markStepDone = (step: BridgeStepType) => { + private readonly markStepDone = (step: BridgeStepType) => { if (this.options.emit) { const s = this.steps.find((s) => s.typeID === step.typeID); if (s) { diff --git a/src/sdk/ca-base/swap/ob.ts b/src/sdk/ca-base/swap/ob.ts index a2d16104..73badb50 100644 --- a/src/sdk/ca-base/swap/ob.ts +++ b/src/sdk/ca-base/swap/ob.ts @@ -16,7 +16,6 @@ import Decimal from 'decimal.js'; import { orderBy, retry } from 'es-toolkit'; import Long from 'long'; import { Hex, PrivateKeyAccount, WalletClient } from 'viem'; -import { getLogger, SWAP_STEPS, SwapStepType } from '../../../commons'; import { divDecimals, equalFold, minutesToMs, waitForTxReceipt } from '../utils'; import { EADDRESS, SWEEPER_ADDRESS } from './constants'; import { getTokenDecimals } from './data'; @@ -42,6 +41,9 @@ import { vscSBCTx, } from './utils'; import { + getLogger, + SWAP_STEPS, + SwapStepType, ChainListType, BridgeAsset, EoaToEphemeralCallMap, @@ -107,14 +109,14 @@ class BridgeHandler { promise: Promise.resolve(), }; constructor( - private input: { + private readonly input: { amount: Decimal; assets: BridgeAsset[]; chainID: number; decimals: number; tokenAddress: `0x${string}`; } | null, - private options: Options, + private readonly options: Options, ) { if (input) { for (const asset of input.assets) { @@ -295,17 +297,17 @@ class DestinationSwapHandler { private eoaToEphCalls: Tx[] = []; constructor( private data: SwapRoute['destination'], - private dstTokenInfo: { + private readonly dstTokenInfo: { contractAddress: `0x${string}`; decimals: number; symbol: string; }, - private dst: { + private readonly dst: { amount?: bigint; chainID: number; token: `0x${string}`; }, - private options: Options, + private readonly options: Options, ) { if (data.swap.dstEOAToEphTx) { options.cache.addAllowanceQuery({ @@ -542,8 +544,8 @@ class DestinationSwapHandler { class SourceSwapsHandler { private disposableCache: { [k: string]: Tx } = {}; - private swapsData: Map; - constructor(data: SwapRoute['source'], private options: Options) { + private readonly swapsData: Map; + constructor(data: SwapRoute['source'], private readonly options: Options) { this.swapsData = this.groupAndOrder(data.swaps); for (const [chainID, swapQuotes] of this.iterate(this.swapsData)) { this.options.cache.addSetCodeQuery({ diff --git a/src/sdk/ca-base/swap/rff.ts b/src/sdk/ca-base/swap/rff.ts index 5bca8e25..8c6b973a 100644 --- a/src/sdk/ca-base/swap/rff.ts +++ b/src/sdk/ca-base/swap/rff.ts @@ -12,9 +12,8 @@ import { webSocket, } from 'viem'; import { Errors } from '../errors'; -import { createRFFromIntent } from '../utils'; -import { getLogger, Intent, NetworkConfig } from '../../../commons'; import { + createRFFromIntent, convertAddressByUniverse, evmWaitForFill, FeeStore, @@ -28,6 +27,9 @@ import { } from '../utils'; import { packERC20Approve } from './utils'; import { + getLogger, + Intent, + NetworkConfig, BridgeAsset, EoaToEphemeralCallMap, RFFDepositCallMap, @@ -286,7 +288,7 @@ export const createBridgeRFF = async ({ const doubleCheckTxMap: Record Promise> = {}; - omniversalRFF.protobufRFF.sources.map((s) => { + omniversalRFF.protobufRFF.sources.forEach((s) => { doubleCheckTxMap[bytesToNumber(s.chainID)] = createDoubleCheckTx( s.chainID, config.cosmos, diff --git a/src/sdk/ca-base/swap/route.ts b/src/sdk/ca-base/swap/route.ts index 1c1bdb77..9149eac8 100644 --- a/src/sdk/ca-base/swap/route.ts +++ b/src/sdk/ca-base/swap/route.ts @@ -16,14 +16,17 @@ import { import Decimal from 'decimal.js'; import { ByteArray, Hex, toBytes } from 'viem'; import { ZERO_ADDRESS } from '../constants'; -import { getLogger, OraclePriceResponse } from '../../../commons'; import { + getLogger, + OraclePriceResponse, ExactInSwapInput, ExactOutSwapInput, SwapData, SwapMode, SwapParams, + BridgeAsset, } from '../../../commons'; + import { convertTo32BytesHex, divDecimals, @@ -38,7 +41,6 @@ import { EADDRESS } from './constants'; import { FlatBalance } from './data'; import { createIntent } from './rff'; import { calculateValue, convertTo32Bytes, convertToEVMAddress } from './utils'; -import { BridgeAsset } from '../../../commons'; import { Errors } from '../errors'; const logger = getLogger(); @@ -552,7 +554,7 @@ const _exactInRoute = async ( // Filter out sources user requested to be used for (const f of input.from) { if (typeof f.amount !== 'bigint') { - throw new Error('input.from.amount must be bigint'); + throw new TypeError('input.from.amount must be bigint'); } const comparison = normalizeToComparisonAddr(f.tokenAddress); diff --git a/src/sdk/ca-base/swap/swap.ts b/src/sdk/ca-base/swap/swap.ts index 8f23b49a..2a428845 100644 --- a/src/sdk/ca-base/swap/swap.ts +++ b/src/sdk/ca-base/swap/swap.ts @@ -254,7 +254,7 @@ const calculatePerformance = () => { const entries = performance.getEntries(); - if (entries.find((entry) => entry.name === 'source-swap-tx-start')) { + if (entries.some((entry) => entry.name === 'source-swap-tx-start')) { measures.push( performance.measure( 'source-swap-tx-duration', diff --git a/src/sdk/ca-base/swap/utils.ts b/src/sdk/ca-base/swap/utils.ts index 414c337d..98320597 100644 --- a/src/sdk/ca-base/swap/utils.ts +++ b/src/sdk/ca-base/swap/utils.ts @@ -43,12 +43,20 @@ import { } from 'viem'; import { ERC20PermitABI, ERC20PermitEIP2612PolygonType, ERC20PermitEIP712Type } from '../abi/erc20'; import { getLogoFromSymbol, ZERO_ADDRESS } from '../constants'; -import { getLogger } from '../../../commons'; import { + getLogger, Chain, SuccessfulSwapResult, UnifiedBalanceResponseData, UserAssetDatum, + SWAP_STEPS, + SwapStepType, + AnkrAsset, + AnkrBalances, + SBCTx, + SwapIntent, + Tx, + ChainListType, } from '../../../commons'; import { convertAddressByUniverse, @@ -63,16 +71,6 @@ import { SWEEP_ABI } from './abi'; import { CALIBUR_ADDRESS, EADDRESS, SWEEPER_ADDRESS } from './constants'; import { chainData, FlatBalance, getTokenVersion } from './data'; import { createSBCTxFromCalls, waitForSBCTxReceipt } from './sbc'; -import { - SWAP_STEPS, - SwapStepType, - AnkrAsset, - AnkrBalances, - SBCTx, - SwapIntent, - Tx, - ChainListType, -} from '../../../commons'; import Long from 'long'; import { Errors } from '../errors'; @@ -686,8 +684,7 @@ export const getAnkrBalances = async ( balance, balanceUSD: asset.balanceUsd, chainID: AnkrChainIdMapping.get(asset.blockchain)!, - tokenAddress: - asset.tokenType === 'ERC20' ? asset.contractAddress : (ZERO_ADDRESS as `0x${string}`), + tokenAddress: asset.tokenType === 'ERC20' ? asset.contractAddress : ZERO_ADDRESS, tokenData: { decimals: asset.tokenDecimals, icon: asset.thumbnail, @@ -720,7 +717,7 @@ export const toFlatBalance = ( assets, }); return assets - .map((a) => + .flatMap((a) => a.breakdown.map((b) => { const tokenAddress = equalFold(b.contractAddress, ZERO_ADDRESS) ? EADDRESS @@ -737,7 +734,6 @@ export const toFlatBalance = ( }; }), ) - .flat() .filter((b) => { return !(b.chainID === currentChainID && equalFold(b.tokenAddress, selectedTokenAddress)); }) @@ -810,8 +806,8 @@ export const balancesToAssets = ( balanceInFiat: new Decimal(currency.value).toDecimalPlaces(2).toNumber(), chain: { id: bytesToNumber(balance.chain_id), - logo: chain.custom.icon as string, - name: chain.name as string, + logo: chain.custom.icon, + name: chain.name, }, contractAddress: tokenAddress, decimals, @@ -851,7 +847,7 @@ export const balancesToAssets = ( const existingAsset = assets.find((a) => equalFold(a.symbol, asset.tokenData.symbol)); if (existingAsset) { if ( - !existingAsset.breakdown.find( + !existingAsset.breakdown.some( (t) => t.chain.id === chain.id && equalFold(t.contractAddress, asset.tokenAddress), ) ) { @@ -884,8 +880,8 @@ export const balancesToAssets = ( balanceInFiat: new Decimal(asset.balanceUSD).toDecimalPlaces(2).toNumber(), chain: { id: chain.id, - logo: chain.custom.icon as string, - name: chain.name as string, + logo: chain.custom.icon, + name: chain.name, }, contractAddress: asset.tokenAddress, decimals: asset.tokenData.decimals, @@ -894,7 +890,7 @@ export const balancesToAssets = ( ], decimals: asset.tokenData.decimals, icon: asset.tokenData.icon, - symbol: asset.tokenData.symbol as string, + symbol: asset.tokenData.symbol, }); } } @@ -926,11 +922,11 @@ export type SetCodeInput = { export class Cache { public allowanceValues: Map = new Map(); public setCodeValues: Map = new Map(); - private allowanceQueries: Set = new Set(); - private nativeAllowanceQueries: Set = new Set(); - private setCodeQueries: Set = new Set(); + private readonly allowanceQueries: Set = new Set(); + private readonly nativeAllowanceQueries: Set = new Set(); + private readonly setCodeQueries: Set = new Set(); - constructor(private publicClientList: PublicClientList) {} + constructor(private readonly publicClientList: PublicClientList) {} addAllowanceQuery(input: AllowanceInput) { this.allowanceQueries.add(input); @@ -1047,7 +1043,7 @@ export class Cache { // To remove duplication of publicClients export class PublicClientList { private list: Record = {}; - constructor(private chainList: ChainListType) {} + constructor(private readonly chainList: ChainListType) {} get(chainID: bigint | number | string) { let client = this.list[Number(chainID)]; diff --git a/src/sdk/ca-base/utils/api.utils.ts b/src/sdk/ca-base/utils/api.utils.ts index db6fca21..e1cfe58c 100644 --- a/src/sdk/ca-base/utils/api.utils.ts +++ b/src/sdk/ca-base/utils/api.utils.ts @@ -106,7 +106,7 @@ export const intentTransform = (input: RequestForFunds[], chainList: ChainListTy const chainId = bytesToNumber(s.chainID); const contractAddress = convertToHexAddressByUniverse(s.contractAddress, s.universe); const result = chainList.getChainAndTokenByAddress(chainId, contractAddress); - if (!result || !result.token) { + if (!result?.token) { throw Errors.tokenNotSupported(contractAddress, chainId); } const valueRaw = bytesToBigInt(s.value); @@ -344,23 +344,21 @@ const getVSCURL = (vscDomain: string, protocol: 'https' | 'wss') => { let vscReq: AxiosInstance | null = null; const getVscReq = (vscDomain: string) => { - if (!vscReq) { - vscReq = axios.create({ - baseURL: new URL('/api/v1', getVSCURL(vscDomain, 'https')).toString(), - headers: { - Accept: 'application/msgpack', + vscReq ??= axios.create({ + baseURL: new URL('/api/v1', getVSCURL(vscDomain, 'https')).toString(), + headers: { + Accept: 'application/msgpack', + }, + responseType: 'arraybuffer', + transformRequest: [ + function (data, headers) { + if (['get', 'head'].includes((this.method as string).toLowerCase())) return; + headers['Content-Type'] = 'application/msgpack'; + return pack(data); }, - responseType: 'arraybuffer', - transformRequest: [ - function (data, headers) { - if (['get', 'head'].includes((this.method as string).toLowerCase())) return; - headers['Content-Type'] = 'application/msgpack'; - return pack(data); - }, - ], - transformResponse: [(data) => unpack(data)], - }); - } + ], + transformResponse: [(data) => unpack(data)], + }); return vscReq; }; diff --git a/src/sdk/ca-base/utils/common.utils.ts b/src/sdk/ca-base/utils/common.utils.ts index 89b18917..b8f38fd1 100644 --- a/src/sdk/ca-base/utils/common.utils.ts +++ b/src/sdk/ca-base/utils/common.utils.ts @@ -33,11 +33,13 @@ import { WalletClient, WebSocketTransport, } from 'viem'; -import { TronWeb } from 'tronweb'; +import { TronWeb, Types, utils } from 'tronweb'; import { ChainList } from '../chains'; import { FUEL_BASE_ASSET_ID, isNativeAddress, ZERO_ADDRESS } from '../constants'; -import { getLogger, IBridgeOptions, SupportedChainsAndTokensResult } from '../../../commons'; import { + getLogger, + IBridgeOptions, + SupportedChainsAndTokensResult, Intent, NetworkConfig, OraclePriceResponse, @@ -51,7 +53,6 @@ import { FeeStore } from './api.utils'; import { requestTimeout, waitForIntentFulfilment } from './contract.utils'; import { cosmosCreateDoubleCheckTx, cosmosFillCheck, cosmosRefundIntent } from './cosmos.utils'; import { AdapterProps } from '@tronweb3/tronwallet-abstract-adapter'; -import { Types, utils } from 'tronweb'; import { Errors } from '../errors'; const logger = getLogger(); @@ -709,7 +710,7 @@ async function waitForTronTxConfirmation( txInfo, }); - if (txInfo && txInfo.receipt) { + if (txInfo?.receipt) { const result = txInfo.receipt.result; if (result === 'FAILED') { throw new Error(`❌ Transaction reverted: ${txid}`); diff --git a/src/sdk/index.ts b/src/sdk/index.ts index 39dade33..f81c8382 100644 --- a/src/sdk/index.ts +++ b/src/sdk/index.ts @@ -41,6 +41,9 @@ export class NexusSDK extends CA { /** * Initialize the SDK with a provider + * @param provider Ethereum provider + * @throws NexusError if the initialize fails + * @returns Promise resolving to void */ public async initialize(provider: EthereumProvider): Promise { await this._setEVMProvider(provider); @@ -48,6 +51,7 @@ export class NexusSDK extends CA { } /** + * Returns unified balance for tokens across all chains * @deprecated use `getBalancesForBridge` for direct replacement. * @returns unified balances across all chains */ @@ -56,7 +60,11 @@ export class NexusSDK extends CA { } /** - * Bridge to destination chain from auto-selected or provided source chains + * Bridge to destination chain from auto-selected sources or provided source chains + * @param params bridge parameters + * @param options event parameters + * @throws NexusError if the bridge fails + * @returns bridge result with explorer URL */ public async bridge(params: BridgeParams, options?: OnEventParam): Promise { const result = await this._createBridgeHandler(params, options).execute(); @@ -65,6 +73,11 @@ export class NexusSDK extends CA { }; } + /** + * Calculates the maximum amount that can be bridged for a given token and destination chain + * @param params + * @returns + */ public async calculateMaxForBridge( params: Omit, ): Promise { @@ -73,6 +86,10 @@ export class NexusSDK extends CA { /** * Bridge & transfer to an address (Attribution) + * @param params transfer parameters + * @param options event parameters + * @throws NexusError if the bridge and transfer fails + * @returns transfer result with transaction hash and explorer URL */ public async bridgeAndTransfer( params: TransferParams, @@ -85,6 +102,14 @@ export class NexusSDK extends CA { }; } + /** + * Swap with exact in + * Useful when trying to swap with fixed sources and destination + * @param input swap input + * @param options event parameters + * @throws NexusError if the swap fails + * @returns swap result with success flag and result + */ public async swapWithExactIn( input: ExactInSwapInput, options?: OnEventParam, @@ -96,6 +121,15 @@ export class NexusSDK extends CA { }; } + /** + * Swap with exact out + * Useful when trying to swap with a fixed destination. + * Sources are calculated automatically. + * @param input swap input + * @param options event parameters + * @throws NexusError if the swap fails + * @returns swap result with success flag and result + */ public async swapWithExactOut( input: ExactOutSwapInput, options?: OnEventParam, @@ -109,13 +143,17 @@ export class NexusSDK extends CA { /** * Simulate bridge transaction to get costs and fees + * @param params bridge parameters + * @returns simulation result with gas estimates */ public async simulateBridge(params: BridgeParams): Promise { return this._createBridgeHandler(params).simulate(); } /** - * Simulate transfer transaction to get costs and fees + * Simulate bridge + transfer transaction to get costs and fees + * @param params transfer parameters + * @returns simulation result with gas estimates */ public async simulateBridgeAndTransfer( params: TransferParams, @@ -124,7 +162,9 @@ export class NexusSDK extends CA { } /** - * Get user's intents with pagination + * Get user's past intents with pagination + * @param page page number + * @returns list of intents */ public async getMyIntents(page: number = 1): Promise { return this._getMyIntents(page); @@ -132,6 +172,9 @@ export class NexusSDK extends CA { /** * Set callback for intent status updates + * Useful for capturing intent and displaying information to the user + * Once set up, data will be automatically emitted, can be stored in a state or a variable for further use. + * @param callback intent status update callback */ public setOnIntentHook(callback: OnIntentHook): void { this._setOnIntentHook(callback); @@ -139,6 +182,9 @@ export class NexusSDK extends CA { /** * Set callback for swap intent details + * Useful for capturing swap intent and displaying information to the user + * Once set up, data will be automatically emitted, can be stored in a state or a variable for further use. + * @param callback swap intent details callback */ public setOnSwapIntentHook(callback: OnSwapIntentHook): void { this._setOnSwapIntentHook(callback); @@ -150,11 +196,18 @@ export class NexusSDK extends CA { /** * Set callback for allowance approval events + * Useful for capturing allowance approval and displaying information to the user + * Once set up, data will be automatically emitted, can be stored in a state or a variable for further use. + * @param callback allowance approval event callback */ public setOnAllowanceHook(callback: OnAllowanceHook): void { this._setOnAllowanceHook(callback); } + /** + * Deinitialize the SDK + * @returns Promise resolving to void + */ public async deinit(): Promise { return this._deinit(); } @@ -162,6 +215,8 @@ export class NexusSDK extends CA { /** * Standalone function to execute funds into a smart contract * @param params execute parameters including contract details and transaction settings + * @param options event parameters + * @throws NexusError if the execute fails * @returns Promise resolving to execute result with transaction hash and explorer URL */ public async execute(params: ExecuteParams, options?: OnEventParam): Promise { @@ -171,6 +226,7 @@ export class NexusSDK extends CA { /** * Simulate a standalone execute to estimate gas costs and validate parameters * @param params execute parameters for simulation + * @throws NexusError if the simulate execute fails * @returns Promise resolving to simulation result with gas estimates */ public async simulateExecute(params: ExecuteParams): Promise { @@ -178,8 +234,12 @@ export class NexusSDK extends CA { } /** - * Enhanced bridge and execute function with optional execute step and improved error handling + * Bridge and execute function + * Starts with an optional bridge transaction if user doesn't have enough funds on the destination chain. + * Then executes the contract call on the destination chain. * @param params bridge and execute parameters + * @param options event parameters + * @throws NexusError if the bridge and execute fails * @returns Promise resolving to comprehensive operation result */ public async bridgeAndExecute( @@ -194,6 +254,9 @@ export class NexusSDK extends CA { * This method provides more accurate gas estimates by using the actual amount that will be * received on the destination chain after bridging (accounting for fees, slippage, etc.) * Includes detailed step-by-step breakdown with approval handling. + * @param params bridge and execute parameters + * @throws NexusError if the simulate bridge and execute fails + * @returns Promise resolving to simulation result with gas estimates */ public async simulateBridgeAndExecute( params: BridgeAndExecuteParams, @@ -202,7 +265,8 @@ export class NexusSDK extends CA { } /** - * tokens returned here should be used in `input` for exact in swap + * Tokens returned here should be used in `input` for exact in swap + * @throws NexusError if the get balances for swap fails * @returns balances that can be used in swap operations */ public async getBalancesForSwap() { @@ -212,6 +276,8 @@ export class NexusSDK extends CA { } /** + * Tokens returned here should be used in bridge, bridgeAndTransfer and bridgeAndExecute operations + * @throws NexusError if the get balances for bridge fails * @returns balances that can be used in bridge operations */ public getBalancesForBridge() { @@ -219,6 +285,7 @@ export class NexusSDK extends CA { } /** + * Get list of chains where swap is supported * @returns list of chains where swap is supported */ public getSwapSupportedChains(): SupportedChainsResult { diff --git a/src/sdk/utils.ts b/src/sdk/utils.ts index 8f44c6db..77a3b551 100644 --- a/src/sdk/utils.ts +++ b/src/sdk/utils.ts @@ -16,30 +16,77 @@ export class NexusUtils { constructor(private readonly chainList: ChainListType) {} formatTokenBalance = formatTokenBalance; formatTokenBalanceParts = formatTokenBalanceParts; + /** + * Parse a value from the smallest unit to the base unit + * @param value - The value to parse + * @param decimals - The number of decimals to parse + * @returns The parsed value + */ parseUnits = parseUnits; + /** + * Format a value from the base unit to the smallest unit + * @param value - The value to format + * @param decimals - The number of decimals to format + * @returns The formatted value + */ formatUnits = formatUnits; + /** + * Check if the address is valid + * @param address - The address to check + * @returns boolean + */ isValidAddress = isAddress; + /** + * Truncate an address + * @param address - The address to truncate + * @param startLength - The number of characters to keep from the start + * @param endLength - The number of characters to keep from the end + * @returns The truncated address + * Examples: + * - 0x1234567890123456789012345678901234567890 -> "0x123456...7890" + */ truncateAddress = utilTruncateAddress; + /** + * Get the coinbase rates for the supported tokens + * @returns Record + */ getCoinbaseRates = async (): Promise> => { return getCoinbasePrices(); }; + /** + * Get the supported chains and tokens for the network + * @param env - The network to get the supported chains and tokens for + * @returns SupportedChainsAndTokensResult + */ getSupportedChains(env?: Network): SupportedChainsAndTokensResult { return getSupportedChains(env); } + /** + * Get the supported chains and tokens for the network + * @returns SupportedChainsResult + */ getSwapSupportedChainsAndTokens(): SupportedChainsResult { return getSwapSupportedChains(this.chainList); } - /* Same for isSupportedChain / isSupportedToken */ + /** + * Check if the chain is supported + * @param chainId - The chain ID to check + * @returns boolean + */ isSupportedChain(chainId: (typeof SUPPORTED_CHAINS)[keyof typeof SUPPORTED_CHAINS]): boolean { return !!this.chainList.getChainByID(chainId); } - // ??? + /** + * Check if the token is supported + * @param token - The token to check + * @returns boolean + */ isSupportedToken(token: string): boolean { const supportedTokens = ['ETH', 'USDC', 'USDT']; return supportedTokens.includes(token.toUpperCase()); From 562486b4d66d7a1578c4bc1f5f58a4d7839271e9 Mon Sep 17 00:00:00 2001 From: Amartya Singh <53113365+decocereus@users.noreply.github.com> Date: Thu, 20 Nov 2025 23:57:25 +0530 Subject: [PATCH 36/51] Released 1.0.0-beta.39 with code docs (#102) * chore: script cleanup * 1.0.0-beta.39 --- package-lock.json | 4 +- package.json | 2 +- scripts/README.md | 117 ---------------- scripts/local-pack.sh | 46 ------ scripts/release-core.sh | 301 ---------------------------------------- 5 files changed, 3 insertions(+), 467 deletions(-) delete mode 100644 scripts/README.md delete mode 100755 scripts/local-pack.sh delete mode 100755 scripts/release-core.sh diff --git a/package-lock.json b/package-lock.json index e5330f07..2fdb0753 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@avail-project/nexus-core", - "version": "1.0.0-beta.38", + "version": "1.0.0-beta.39", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@avail-project/nexus-core", - "version": "1.0.0-beta.38", + "version": "1.0.0-beta.39", "license": "MIT", "dependencies": { "@avail-project/ca-common": "1.0.0-dev.3", diff --git a/package.json b/package.json index e4f8e1cf..4cfde5e0 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@avail-project/nexus-core", - "version": "1.0.0-beta.38", + "version": "1.0.0-beta.39", "description": "Nexus headless SDK for cross-chain transactions", "main": "./dist/index.js", "module": "./dist/index.esm.js", diff --git a/scripts/README.md b/scripts/README.md deleted file mode 100644 index 5c96be0b..00000000 --- a/scripts/README.md +++ /dev/null @@ -1,117 +0,0 @@ -# Release Scripts - -This directory contains release scripts for the Nexus SDK monorepo packages. - -## Available Scripts - -### Individual Package Releases - -#### Core Package (`@avail-project/nexus-core`) - -```bash -# Development release (default) -./scripts/release-core.sh dev [patch|minor|major] -pnpm run release:core:dev - -# Production release -./scripts/release-core.sh prod [patch|minor|major] -pnpm run release:core:prod -``` - -### Local Tarballs (No Publish) - -```bash -# Build and create .tgz files for local installs -./scripts/local-pack.sh - -# In another project -pnpm add /absolute/path/to/dist-tarballs/avail-project-nexus-core-*.tgz -``` - -## Release Types - -### Development Releases (`dev`) - -- Creates SemVer prereleases with your chosen tag (e.g., `beta`, `alpha`, `dev`). -- Prerelease numbering policy: increments 0→9, then rolls to the next patch. - - Example: `0.0.2-beta.0 → 0.0.2-beta.1 … → 0.0.2-beta.9 → 0.0.3-beta.0`. -- Widgets depends on the most recently published Core prerelease for the same tag by publish timestamp (not by semver magnitude). -- No branch restrictions. - -### Production Releases (`prod`) - -- Publishes clean version numbers (e.g., `1.2.3`). -- Tagged with `latest` on npm (default install). -- Checks for `main` branch (can be overridden with `--yes`). -- Creates git tags and pushes to remote. -- Interactive confirmation unless `--yes` is passed. - -## Version Bump Types - -- **patch**: Bug fixes (1.0.0 → 1.0.1) -- **minor**: New features (1.0.0 → 1.1.0) -- **major**: Breaking changes (1.0.0 → 2.0.0) - -## Examples - -```bash -# Core – interactive dev prerelease (choose tag: beta/alpha/dev) -./scripts/release-core.sh - -# Core – non-interactive dev prerelease (beta), dry-run -./scripts/release-core.sh dev patch beta --yes --dry-run - -# Core – non-interactive dev prerelease (beta), publish -./scripts/release-core.sh dev patch beta --yes - -# Core – production release (patch) from current branch -./scripts/release-core.sh prod patch --yes -``` - -## Prerequisites - -- Clean git working directory (no uncommitted changes) -- All dependencies installed (`pnpm install`) -- Valid npm authentication for publishing - -## What the Scripts Do - -1. **Validation**: Check git status, dependencies, and prerequisites -2. **Type Checking**: Run `pnpm run typecheck` to ensure code quality -3. **Building**: Clean and build all necessary packages -4. **Version Bump**: Interactive wizard chooses dev/prod and tag; dev follows 0–9 rollover policy; prod bumps patch/minor/major -5. **Git Operations**: Commit version changes, create tags -6. **Publishing**: Publish to npm with correct tags and access -7. **Cleanup**: Push changes and tags to remote repository - -## Dependency Order - -The widgets package depends on the core package, so: - -- For production releases, core must be published before widgets. -- For dev prereleases, the widgets script resolves the most recently published core prerelease for the same tag by npm publish time. - -## Output - -All scripts provide colored, detailed output showing: - -- Current operation status -- Build results and warnings -- Publication confirmation -- Installation instructions -- Links to published packages - -## Error Handling - -Scripts will exit with error codes if: - -- Git repository has uncommitted changes. -- Type checking fails. -- Build process fails. -- Publication fails. -- Required dependencies are missing. - -## Flags - -- `--yes` or `--ci`: skip interactive prompts (useful in CI; also bypasses the main-branch prompt on prod). -- `--dry-run` or `-n`: simulate publish (runs `npm pack` instead of `npm publish`; skips git push/tag). diff --git a/scripts/local-pack.sh b/scripts/local-pack.sh deleted file mode 100755 index 53307055..00000000 --- a/scripts/local-pack.sh +++ /dev/null @@ -1,46 +0,0 @@ -#!/bin/bash - -# Create a local installable tarball for @avail-project/nexus-core without publishing. -# This script builds packages, rewrites workspace deps for packaging, packs to dist-tarballs/, and restores files. -set -e - -RED='\033[0;31m' -GREEN='\033[0;32m' -YELLOW='\033[1;33m' -BLUE='\033[0;34m' -NC='\033[0m' - -info() { echo -e "${GREEN}[INFO]${NC} $1"; } -warn() { echo -e "${YELLOW}[WARN]${NC} $1"; } -err() { echo -e "${RED}[ERROR]${NC} $1"; } - -ROOT_DIR=$(cd "$(dirname "$0")/.." && pwd) -DEST_DIR="$ROOT_DIR/dist-tarballs" - -cd "$ROOT_DIR" - -info "Cleaning and building packages..." -npm run clean -npm -F run build -mkdir -p "$DEST_DIR" - -# Pack core (already named @avail-project/nexus-core; remove workspace-only deps) -info "Packing core as @avail-project/nexus-core (local tarball)..." -cp package.json package.json.backup - -# Remove @nexus/commons (bundled into dist) -node -e "const fs=require('fs');const p=JSON.parse(fs.readFileSync('package.json','utf8'));if(p.dependencies){delete p.dependencies['@nexus/commons'];}fs.writeFileSync('package.json',JSON.stringify(p,null,2)+'\n');" - -CORE_TARBALL=$(npm pack --pack-destination "$DEST_DIR" --silent) -mv package.json.backup package.json - -info "Created core tarball: $DEST_DIR/$CORE_TARBALL (name: @avail-project/nexus-core)" - -info "Done. Tarballs are in $DEST_DIR" -echo "" -echo "Install in a project with:" -echo " pnpm add $DEST_DIR/$CORE_TARBALL" -echo "or" -echo " npm i $DEST_DIR/$CORE_TARBALL" - - diff --git a/scripts/release-core.sh b/scripts/release-core.sh deleted file mode 100755 index 57a78313..00000000 --- a/scripts/release-core.sh +++ /dev/null @@ -1,301 +0,0 @@ -#!/bin/bash - -# Nexus Core SDK Release Script -set -e - -# Colors for output -RED='\033[0;31m' -GREEN='\033[0;32m' -YELLOW='\033[1;33m' -BLUE='\033[0;34m' -NC='\033[0m' # No Color - -# Function to print colored output -print_status() { - echo -e "${GREEN}[INFO]${NC} $1" -} - -print_warning() { - echo -e "${YELLOW}[WARNING]${NC} $1" -} - -print_error() { - echo -e "${RED}[ERROR]${NC} $1" -} - -print_header() { - echo -e "${BLUE}[CORE RELEASE]${NC} $1" -} - -# Flags -NON_INTERACTIVE=0 -for arg in "$@"; do - if [[ "$arg" == "--yes" || "$arg" == "-y" || "$arg" == "--ci" ]]; then - NON_INTERACTIVE=1 - fi -done -DRY_RUN=0 -for arg in "$@"; do - if [[ "$arg" == "--dry-run" || "$arg" == "-n" ]]; then - DRY_RUN=1 - fi -done - -# Check if we're in a git repository -if ! git rev-parse --git-dir > /dev/null 2>&1; then - print_error "Not in a git repository" - exit 1 -fi - -# Check if we're in the project root directory (single-package repo) -if [[ ! -f "package.json" ]]; then - print_error "Please run this script from the project root directory" - exit 1 -fi - -# Check for uncommitted changes -if ! git diff-index --quiet HEAD --; then - print_header "There are uncommitted changes. Are you sure you want to continue?" - read -p "Continue? (y/N): " _continue - if [[ $_continue != [yY] ]]; then - print_error "Aborting release." - exit 1 - fi -fi - -# Get the release type from command line argument (positional defaults) -RELEASE_TYPE=${1:-"dev"} -VERSION_TYPE=${2:-"patch"} -PRERELEASE_ID=${3:-"dev"} - -# Interactive wizard (skipped with --yes) -if [[ $NON_INTERACTIVE -eq 0 ]]; then - echo "" - print_header "Interactive release wizard" - echo "This script will help you publish @avail-project/nexus-core." - echo "" - echo "Examples:" - echo " dev prerelease: 0.0.2-beta.0 -> 0.0.2-beta.1 ... -> 0.0.2-beta.9 -> 0.0.3-beta.0" - echo " prod release: 0.0.2 -> 0.0.3 (patch), 0.1.0 (minor), 1.0.0 (major)" - echo "" - read -p "Release type [dev|prod] (default: $RELEASE_TYPE): " _rt - if [[ -n "$_rt" ]]; then RELEASE_TYPE="$_rt"; fi - if [[ "$RELEASE_TYPE" != "dev" && "$RELEASE_TYPE" != "prod" ]]; then - print_error "Invalid release type. Use 'dev' or 'prod'" - exit 1 - fi - - # Second prompt: allow custom version override - read -p "Would you like to enter a custom version? (y/N): " _cv - if [[ $_cv == "y" || $_cv == "Y" ]]; then - read -p "Enter custom version (e.g., 1.2.3 or 1.2.3-beta.0): " _custom_version - if [[ -n "$_custom_version" ]]; then - CUSTOM_VERSION="$_custom_version" - print_status "Custom version set to $CUSTOM_VERSION" - fi - fi - - if [[ "$RELEASE_TYPE" == "dev" ]]; then - read -p "Pre-release tag (e.g. beta, alpha, dev) (default: $PRERELEASE_ID): " _pre - if [[ -n "$_pre" ]]; then PRERELEASE_ID="$_pre"; fi - echo "" - echo "Base bump is applied ONLY when starting a new $PRERELEASE_ID series." - echo "Examples: start at 0.0.2-$PRERELEASE_ID.0 (patch), or 0.1.0-$PRERELEASE_ID.0 (minor)." - read -p "Base bump for new series [patch|minor|major] (default: $VERSION_TYPE): " _vt - if [[ -n "$_vt" ]]; then VERSION_TYPE="$_vt"; fi - else - read -p "Version bump [patch|minor|major] (default: $VERSION_TYPE): " _vtp - if [[ -n "$_vtp" ]]; then VERSION_TYPE="$_vtp"; fi - fi -fi - -if [[ "$RELEASE_TYPE" != "dev" && "$RELEASE_TYPE" != "prod" ]]; then - print_error "Invalid release type. Use 'dev' or 'prod'" - echo "Usage: $0 [dev|prod] [patch|minor|major] [prerelease-id]" - echo "Examples:" - echo " $0 dev patch alpha # Creates 1.0.1-alpha.0" - echo " $0 dev minor beta # Creates 1.1.0-beta.0" - echo " $0 dev patch # Creates 1.0.1-dev.0 (default)" - exit 1 -fi - -if [[ "$VERSION_TYPE" != "patch" && "$VERSION_TYPE" != "minor" && "$VERSION_TYPE" != "major" ]]; then - print_error "Invalid version type. Use 'patch', 'minor', or 'major'" - echo "Usage: $0 [dev|prod] [patch|minor|major] [prerelease-id]" - exit 1 -fi - -print_header "Starting @avail-project/nexus-core $RELEASE_TYPE release ($VERSION_TYPE)..." - -# Run type checking -print_status "Running type check..." -npm run typecheck - -# Clean previous builds -print_status "Cleaning previous builds..." -rm -rf dist - -# Build package -print_status "Building @avail-project/nexus-core package (single package repo)..." -npm run build - -if [[ "$RELEASE_TYPE" == "prod" ]]; then - print_header "Creating production release..." - - # Ensure we're on main branch for production releases - CURRENT_BRANCH=$(git branch --show-current) - if [[ "$CURRENT_BRANCH" != "main" ]]; then - print_warning "Not on main branch. Current branch: $CURRENT_BRANCH" - if [[ $NON_INTERACTIVE -eq 0 ]]; then - read -p "Do you want to continue with production release from this branch? (y/N): " confirm - if [[ $confirm != [yY] ]]; then - print_error "Aborting production release. Switch to main branch first." - exit 1 - fi - else - print_status "--yes provided. Continuing from $CURRENT_BRANCH." - fi - fi - - # Version bump (root package.json) - print_status "Bumping version (${CUSTOM_VERSION:+custom $CUSTOM_VERSION}${CUSTOM_VERSION:+, }$VERSION_TYPE)..." - if [[ -n "$CUSTOM_VERSION" ]]; then - npm version "$CUSTOM_VERSION" --no-git-tag-version --allow-same-version - else - npm version $VERSION_TYPE --no-git-tag-version - fi - CORE_VERSION=$(node -p "require('./package.json').version") - - # Commit version changes (skip if no changes) - if [[ $DRY_RUN -eq 1 ]]; then - print_status "DRY RUN: would git add/commit version bumps for v$CORE_VERSION" - else - git add package.json - if git diff --cached --quiet; then - print_status "No version changes to commit (prod)." - else - git commit -m "chore(core): release v$CORE_VERSION" - fi - # Create tag (only if it doesn't exist) - if git tag --list | grep -q "^core-v$CORE_VERSION$"; then - print_warning "Tag core-v$CORE_VERSION already exists, skipping tag creation" - else - git tag "core-v$CORE_VERSION" - fi - fi - # Publish to npm (or pack in dry-run) - if [[ $DRY_RUN -eq 1 ]]; then - print_status "DRY RUN: npm pack (skipping publish) for @avail-project/nexus-core@$CORE_VERSION" - npm pack >/dev/null 2>&1 || true - else - print_status "Publishing @avail-project/nexus-core@$CORE_VERSION to npm..." - npm publish --access public - fi - - # Push changes and tags - if [[ $DRY_RUN -eq 1 ]]; then - print_status "DRY RUN: skipping git push of branch and tag core-v$CORE_VERSION" - else - print_status "Pushing changes to git..." - git push origin $CURRENT_BRANCH - git push origin "core-v$CORE_VERSION" - fi - - print_header "✅ Production release completed!" - print_status "🚀 @avail-project/nexus-core@$CORE_VERSION published successfully!" - print_status "📦 Install with: npm install @avail-project/nexus-core" - -else - print_header "Creating development release..." - - # Compute next prerelease version with 0-9 rollover by publication time (root) - print_status "Computing next $PRERELEASE_ID version with rollover logic..." - if [[ -n "$CUSTOM_VERSION" ]]; then - PRERELEASE_VERSION="$CUSTOM_VERSION" - else - export PRERELEASE_ID - export VERSION_TYPE - export PKG='@avail-project/nexus-core' - PRERELEASE_VERSION=$(node -e ' -const cp=require("child_process"); -const fs=require("fs"); -const pkg=process.env.PKG; -const pre=process.env.PRERELEASE_ID||"dev"; -const bump=process.env.VERSION_TYPE||"patch"; -const current=JSON.parse(fs.readFileSync("package.json","utf8")).version; -function exec(cmd){try{return cp.execSync(cmd,{stdio:["pipe","pipe","ignore"]}).toString().trim();}catch(e){return "";}} -function parse(v){const m=v&&v.match(/^(\d+)\.(\d+)\.(\d+)(?:-([0-9A-Za-z-]+)\.(\d+))?$/);if(!m) return null;return {M:+m[1],m:+m[2],p:+m[3],pre:m[4],n:m[5]?+m[5]:null};} -function cmpBase(a,b){if(a.M!==b.M) return a.M-b.M; if(a.m!==b.m) return a.m-b.m; return a.p-b.p;} -function bumpBase(base,t){if(t==="major") return {M:base.M+1,m:0,p:0}; if(t==="minor") return {M:base.M,m:base.m+1,p:0}; return {M:base.M,m:base.m,p:base.p+1};} -function toStr(b,preid,idx){return `${b.M}.${b.m}.${b.p}-${preid}.${idx}`} -let timesJSON = exec(`npm view ${pkg} time --json`); -let times={};try{times=JSON.parse(timesJSON||"{}");}catch(_){times={};} -let preEntries=Object.entries(times).filter(([v])=>new RegExp(`^\\d+\\.\\d+\\.\\d+-${pre}\\.\\d+$`).test(v)); -preEntries.sort((a,b)=>new Date(a[1]) - new Date(b[1])); -let latestPre = preEntries.length? preEntries[preEntries.length-1][0] : ""; -let latestStable = exec(`npm view ${pkg} version 2>/dev/null`) || ""; -let next; -if(latestPre){ - const lp=parse(latestPre); - if(lp.n<9){ next=toStr({M:lp.M,m:lp.m,p:lp.p},pre,lp.n+1); } - else { next=toStr({M:lp.M,m:lp.m,p:lp.p+1},pre,0); } -}else{ - const curr=parse(current); - const stable=parse(latestStable)||curr; - let base = cmpBase(stable,curr) >= 0 ? stable : curr; - base = bumpBase(base,bump); - next = toStr(base,pre,0); -} -console.log(next); -') - fi - export PRERELEASE_VERSION - npm version "$PRERELEASE_VERSION" --no-git-tag-version --allow-same-version - - # Commit version changes (skip if no changes) - if [[ $DRY_RUN -eq 1 ]]; then - print_status "DRY RUN: would git add/commit dev bump to v$PRERELEASE_VERSION and tag core-v$PRERELEASE_VERSION" - else - git add package.json - if git diff --cached --quiet; then - print_status "No version changes to commit (dev)." - else - git commit -m "chore(core): $PRERELEASE_ID release v$PRERELEASE_VERSION" - fi - # Create tag (only if it doesn't exist) - if git tag --list | grep -q "^core-v$PRERELEASE_VERSION$"; then - print_warning "Tag core-v$PRERELEASE_VERSION already exists, skipping tag creation" - else - git tag "core-v$PRERELEASE_VERSION" - fi - fi - # Publish to npm with prerelease tag (or pack in dry-run) - if [[ $DRY_RUN -eq 1 ]]; then - print_status "DRY RUN: npm pack (skipping publish) for @avail-project/nexus-core@$PRERELEASE_VERSION" - npm pack >/dev/null 2>&1 || true - else - print_status "Publishing @avail-project/nexus-core@$PRERELEASE_VERSION to npm ($PRERELEASE_ID tag)..." - npm publish --access public --tag $PRERELEASE_ID - # Add incremental tag (e.g., alpha-1, beta-2) matching pre-release number - INCREMENTAL_TAG=$(node -e "const v=process.env.PRERELEASE_VERSION||'';const m=v.match(/$PRERELEASE_ID\\.(\\d+)/);console.log(m ? ('$PRERELEASE_ID-' + m[1]) : '$PRERELEASE_ID')") - if [ -n "$INCREMENTAL_TAG" ] && [ "$INCREMENTAL_TAG" != "$PRERELEASE_ID" ]; then - print_status "Adding dist-tag $INCREMENTAL_TAG for @avail-project/nexus-core@$PRERELEASE_VERSION..." - npm dist-tag add @avail-project/nexus-core@$PRERELEASE_VERSION $INCREMENTAL_TAG || true - fi - fi - - # Push changes and tags - if [[ $DRY_RUN -eq 1 ]]; then - print_status "DRY RUN: skipping git push of branch and tag core-v$PRERELEASE_VERSION" - else - print_status "Pushing changes to git..." - git push origin $(git branch --show-current) - git push origin "core-v$PRERELEASE_VERSION" - fi - - print_header "✅ Development release completed!" - print_status "🚀 @avail-project/nexus-core@$PRERELEASE_VERSION published successfully!" - print_status "📦 Install with: npm install @avail-project/nexus-core@$PRERELEASE_ID" -fi - -print_header "🎉 @avail-project/nexus-core release process completed successfully!" From 247b7ad579ae3e1fcb1bc8e3d956523014490c7e Mon Sep 17 00:00:00 2001 From: Abhishek Date: Fri, 21 Nov 2025 13:24:51 +0400 Subject: [PATCH 37/51] fix: audit fixes (#66) * fix: use proper deadlines for batched calls and permits * fix: fix nonce fetching from latest - deterministic nonce --- src/sdk/ca-base/requestHandlers/bridge.ts | 2 ++ src/sdk/ca-base/swap/sbc.ts | 17 +++++++++-------- src/sdk/ca-base/swap/utils.ts | 7 +++++-- src/sdk/ca-base/utils/common.utils.ts | 6 ++++++ src/sdk/ca-base/utils/contract.utils.ts | 3 ++- 5 files changed, 24 insertions(+), 11 deletions(-) diff --git a/src/sdk/ca-base/requestHandlers/bridge.ts b/src/sdk/ca-base/requestHandlers/bridge.ts index df065c0f..11d1769c 100644 --- a/src/sdk/ca-base/requestHandlers/bridge.ts +++ b/src/sdk/ca-base/requestHandlers/bridge.ts @@ -71,6 +71,7 @@ import { createRFFromIntent, retrieveAddress, getBalances, + createDeadlineFromNow, } from '../utils'; import { TronWeb } from 'tronweb'; import { Errors } from '../errors'; @@ -738,6 +739,7 @@ class BridgeHandler { account, vc, source.amount, + createDeadlineFromNow(3n), ).catch((e) => { if (e instanceof ContractFunctionExecutionError) { const isUserRejectedRequestError = diff --git a/src/sdk/ca-base/swap/sbc.ts b/src/sdk/ca-base/swap/sbc.ts index 25e78c22..5da9e6d9 100644 --- a/src/sdk/ca-base/swap/sbc.ts +++ b/src/sdk/ca-base/swap/sbc.ts @@ -4,7 +4,6 @@ import { Chain, encodeAbiParameters, Hex, - maxUint256, PrivateKeyAccount, PublicClient, SignAuthorizationReturnType, @@ -13,7 +12,7 @@ import { WalletClient, } from 'viem'; -import { waitForTxReceipt } from '../utils'; +import { createDeadlineFromNow, waitForTxReceipt } from '../utils'; import CaliburABI from './calibur.abi'; import { CALIBUR_ADDRESS, CALIBUR_EIP712, ZERO_BYTES_20, ZERO_BYTES_32 } from './constants'; import { Cache, convertTo32Bytes, isAuthorizationCodeSet, PublicClientList } from './utils'; @@ -27,6 +26,7 @@ export const createBatchedCallSignature = ( chain: bigint, address: `0x${string}`, account: PrivateKeyAccount, + deadline: bigint, ) => { return account.signTypedData({ domain: { @@ -41,7 +41,7 @@ export const createBatchedCallSignature = ( calls: batchedCalls, revertOnFailure: true, }, - deadline: maxUint256, + deadline, executor: toHex(ZERO_BYTES_20), keyHash: toHex(ZERO_BYTES_32), nonce, @@ -86,20 +86,20 @@ export const createSBCTxFromCalls = async ({ publicClient: PublicClient; }) => { const nonce = bytesToBigInt(window.crypto.getRandomValues(new Uint8Array(24))) << 64n; - + const deadline = createDeadlineFromNow(3n); const signature = await createBatchedCallSignature( calls, nonce, BigInt(chainID), ephemeralAddress, ephemeralWallet, + deadline, ); let authorization: null | SignAuthorizationReturnType = null; if (!(await isAuthorizationCodeSet(chainID, ephemeralAddress, cache))) { const nonce = await publicClient.getTransactionCount({ address: ephemeralAddress, - blockTag: 'pending', }); // create authorization for calibur @@ -119,7 +119,7 @@ export const createSBCTxFromCalls = async ({ value: convertTo32Bytes(c.value), })), chain_id: convertTo32Bytes(chainID), - deadline: toBytes(maxUint256), + deadline: toBytes(deadline), key_hash: ZERO_BYTES_32, nonce: convertTo32Bytes(nonce), revert_on_failure: true, @@ -163,13 +163,14 @@ export const caliburExecute = async ({ value: bigint; }) => { const nonce = bytesToBigInt(window.crypto.getRandomValues(new Uint8Array(24))) << 64n; - + const deadline = createDeadlineFromNow(3n); const signature = await createBatchedCallSignature( calls, nonce, BigInt(chain.id), ephemeralAddress, ephemeralWallet, + deadline, ); return actualWallet.writeContract({ @@ -182,7 +183,7 @@ export const caliburExecute = async ({ calls, revertOnFailure: true, }, - deadline: maxUint256, + deadline, executor: toHex(ZERO_BYTES_20), keyHash: toHex(ZERO_BYTES_32), nonce, diff --git a/src/sdk/ca-base/swap/utils.ts b/src/sdk/ca-base/swap/utils.ts index 98320597..a43ff4ef 100644 --- a/src/sdk/ca-base/swap/utils.ts +++ b/src/sdk/ca-base/swap/utils.ts @@ -61,6 +61,7 @@ import { import { convertAddressByUniverse, convertTo32BytesHex, + createDeadlineFromNow, divDecimals, equalFold, getExplorerURL, @@ -187,6 +188,8 @@ export const createPermitSignature = async ( contract.read.nonces([walletAddress]), ]); + const deadline = createDeadlineFromNow(3n); + logger.debug('createPermitSigParams', { account: walletAddress, domain: { @@ -196,7 +199,7 @@ export const createPermitSignature = async ( version, }, message: { - deadline: maxUint256, + deadline, nonce, owner: walletAddress, spender: spender, @@ -218,7 +221,7 @@ export const createPermitSignature = async ( version: version.toString(), }, message: { - deadline: maxUint256, + deadline, nonce, owner: walletAddress, spender: spender, diff --git a/src/sdk/ca-base/utils/common.utils.ts b/src/sdk/ca-base/utils/common.utils.ts index b8f38fd1..6b8258e0 100644 --- a/src/sdk/ca-base/utils/common.utils.ts +++ b/src/sdk/ca-base/utils/common.utils.ts @@ -883,7 +883,13 @@ const retrieveSIWESignatureFromLocalStorage = (address: Hex, siweChain: number) return window.localStorage.getItem(`${SIWE_KEY}-${address}-${siweChain}`); }; +const createDeadlineFromNow = (minutes: bigint = 3n): bigint => { + const nowInSeconds = BigInt(Math.floor(Date.now() / 1000)); + return nowInSeconds + minutes * 60n; +}; + export { + createDeadlineFromNow, percentageAdditionToBigInt, retrieveSIWESignatureFromLocalStorage, storeSIWESignatureToLocalStorage, diff --git a/src/sdk/ca-base/utils/contract.utils.ts b/src/sdk/ca-base/utils/contract.utils.ts index 978632ac..25a98934 100644 --- a/src/sdk/ca-base/utils/contract.utils.ts +++ b/src/sdk/ca-base/utils/contract.utils.ts @@ -32,7 +32,8 @@ import { GetAllowanceParams, SetAllowanceParams, } from '../../../commons'; -import { equalFold, minutesToMs } from './common.utils'; +import { vscCreateSponsoredApprovals } from './api.utils'; +import { convertTo32Bytes, createDeadlineFromNow, equalFold, minutesToMs } from './common.utils'; const logger = getLogger(); From 8ef0159e89b5381d9a8d1c3d89febccef6267751 Mon Sep 17 00:00:00 2001 From: Jeremias Moraes Date: Fri, 21 Nov 2025 10:12:30 -0300 Subject: [PATCH 38/51] feat: Adds client id for telemetry usage (#77) * feat: Adds client id for telemetry usage * lint * feat: removes crypto lib + adds correct code error to telemetry logger * feat: Switch id to hex formated --- src/sdk/ca-base/nexusError.ts | 2 +- src/sdk/telemetry.ts | 30 ++++++++++++++++++++++++------ 2 files changed, 25 insertions(+), 7 deletions(-) diff --git a/src/sdk/ca-base/nexusError.ts b/src/sdk/ca-base/nexusError.ts index b1966dda..75508042 100644 --- a/src/sdk/ca-base/nexusError.ts +++ b/src/sdk/ca-base/nexusError.ts @@ -63,7 +63,7 @@ export function createError(code: ErrorCode, message: string, data?: NexusErrorD severityText: 'ERROR', attributes: { data: nexusError.data, - cause: nexusError.cause, + cause: code, stackTrace: nexusError.stack, } as AnyValueMap, }); diff --git a/src/sdk/telemetry.ts b/src/sdk/telemetry.ts index 5b9fa51e..54b21f53 100644 --- a/src/sdk/telemetry.ts +++ b/src/sdk/telemetry.ts @@ -2,17 +2,35 @@ import { LoggerProvider, BatchLogRecordProcessor } from '@opentelemetry/sdk-logs import { OTLPLogExporter } from '@opentelemetry/exporter-logs-otlp-http'; import { logs } from '@opentelemetry/api-logs'; import { resourceFromAttributes } from '@opentelemetry/resources'; +import { toHex } from 'viem/utils'; -const resource = resourceFromAttributes({ 'service.name': 'nexus-sdk-internal-logs' }); +function getOrGenerateClientId(): string { + const KEY = 'nexus-client-id'; + let clientId = localStorage.getItem(KEY); + + if (!clientId) { + const bytes = new Uint8Array(32); + clientId = toHex(window.crypto.getRandomValues(bytes)); + localStorage.setItem(KEY, clientId); + } + return clientId; +} + +const resource = resourceFromAttributes({ + 'service.name': 'nexus-sdk-internal-logs', + 'client.id': getOrGenerateClientId(), +}); const loggerProvider = new LoggerProvider({ resource: resource, processors: [ - new BatchLogRecordProcessor(new OTLPLogExporter({ - url: 'https://otel.avail.so/v1/logs', - headers: { 'x-otlp-force-fetch': '1' } - })) - ] + new BatchLogRecordProcessor( + new OTLPLogExporter({ + url: 'https://otel.avail.so/v1/logs', + headers: { 'x-otlp-force-fetch': '1' }, + }), + ), + ], }); logs.setGlobalLoggerProvider(loggerProvider); From 6d6812f632544358cb09245a7c044b0694b9a716 Mon Sep 17 00:00:00 2001 From: Abhishek Date: Sat, 22 Nov 2025 19:17:19 +0400 Subject: [PATCH 39/51] fix: bridge & execute fixes (#90) * fix: add 30% extra gas in bridge and execute * fix: updating to using gasLimit, separated out gas for approval and execute * fix: naming changes, grouping response from estimate fn * fix: deposit gas estimate (#105) * fix: updated gas estimate for deposit to move away from collectionFee * fix: removed unused variables * fix: removed unused code, npm audit to update a dependency * fix: fixed optimal bridge amount calculation in case of native token * chore: update sdk version * fix: buffer to gas & gasPrice to factor in time delay btw estimate & execute, fix: arrow fns in ca class for default binding, extra checks in switch chain * fix: updated response to beforeExecute hook to be optional * fix: bridgeAndExecute params on main class, unused variables build issue --- package-lock.json | 6 +- package.json | 2 +- src/commons/constants/index.ts | 1 + src/commons/types/index.ts | 2 +- src/commons/types/swap-types.ts | 1 - src/integrations/tenderly.ts | 12 +- src/sdk/ca-base/ca.ts | 138 ++++++-------- src/sdk/ca-base/query/bridgeAndExecute.ts | 204 ++++++++++++++------- src/sdk/ca-base/query/bridgeAndTransfer.ts | 2 + src/sdk/ca-base/requestHandlers/bridge.ts | 28 +-- src/sdk/ca-base/utils/common.utils.ts | 93 ++++++---- src/sdk/ca-base/utils/contract.utils.ts | 65 +++---- src/sdk/ca-base/utils/rff.utils.ts | 4 +- src/sdk/index.ts | 3 +- 14 files changed, 303 insertions(+), 258 deletions(-) diff --git a/package-lock.json b/package-lock.json index 2fdb0753..0959346a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5302,9 +5302,9 @@ } }, "node_modules/rimraf/node_modules/glob": { - "version": "10.4.5", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", - "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz", + "integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==", "license": "ISC", "dependencies": { "foreground-child": "^3.1.0", diff --git a/package.json b/package.json index 4cfde5e0..eb141a8f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@avail-project/nexus-core", - "version": "1.0.0-beta.39", + "version": "1.0.0-beta.40", "description": "Nexus headless SDK for cross-chain transactions", "main": "./dist/index.js", "module": "./dist/index.esm.js", diff --git a/src/commons/constants/index.ts b/src/commons/constants/index.ts index dc24c86c..3562d258 100644 --- a/src/commons/constants/index.ts +++ b/src/commons/constants/index.ts @@ -13,6 +13,7 @@ export const MAINNET_CHAIN_IDS = { BNB: 56, HYPEREVM: 999, TRON: 728126428, + MONAD: 143, } as const; export const TESTNET_CHAIN_IDS = { diff --git a/src/commons/types/index.ts b/src/commons/types/index.ts index a98dff4a..8265184f 100644 --- a/src/commons/types/index.ts +++ b/src/commons/types/index.ts @@ -655,7 +655,7 @@ export type UserAssetDatum = { }; export type BeforeExecuteHook = { - beforeExecute?: () => Promise<{ value: bigint; data: Hex }>; + beforeExecute?: () => Promise<{ value?: bigint; data?: Hex; gas?: bigint }>; }; export type { diff --git a/src/commons/types/swap-types.ts b/src/commons/types/swap-types.ts index c24a3f5d..ecd2bcb3 100644 --- a/src/commons/types/swap-types.ts +++ b/src/commons/types/swap-types.ts @@ -281,7 +281,6 @@ export type Tx = { to: Hex; value: bigint; gas?: bigint; - gasPrice?: bigint; }; // export type UserAsset = { diff --git a/src/integrations/tenderly.ts b/src/integrations/tenderly.ts index 851077d4..b00393d9 100644 --- a/src/integrations/tenderly.ts +++ b/src/integrations/tenderly.ts @@ -147,7 +147,7 @@ export class BackendSimulationClient { } async simulateBundleV2(request: BundleSimulationRequest) { - logger.info('DEBUG simulateBundle - request:', JSON.stringify(request, null, 2)); + logger.debug('DEBUG simulateBundle - request:', JSON.stringify(request, null, 2)); const { data } = await axios.post( new URL(`/api/gas-estimation/bundle`, this.baseUrl).href, @@ -158,15 +158,7 @@ export class BackendSimulationClient { throw Errors.simulationError(data.message ?? 'Bundle simulation failed'); } - const gasUsed = data.data.reduce((acc, d) => { - return acc + BigInt(d.gasUsed); - }, 0n); - - const gasLimit = data.data.reduce((acc, d) => { - return acc + BigInt(d.gasLimit); - }, 0n); - - return { gasUsed, gasLimit }; + return { gas: data.data.map((d) => BigInt(d.gasLimit)) }; } } diff --git a/src/sdk/ca-base/ca.ts b/src/sdk/ca-base/ca.ts index 1fae87b9..948a3e5a 100644 --- a/src/sdk/ca-base/ca.ts +++ b/src/sdk/ca-base/ca.ts @@ -2,17 +2,7 @@ import { createCosmosWallet, Universe } from '@avail-project/ca-common'; import { DirectSecp256k1Wallet } from '@cosmjs/proto-signing'; import { keyDerivation } from '@starkware-industries/starkware-crypto-utils'; import { Account, FuelConnector, Provider } from 'fuels'; -import { - createWalletClient, - custom, - WalletActions, - publicActions, - type PublicActions, - Client, - CustomTransport, - Hex, - UserRejectedRequestError, -} from 'viem'; +import { createWalletClient, custom, Hex, UserRejectedRequestError, WalletClient } from 'viem'; import { privateKeyToAccount, PrivateKeyAccount } from 'viem/accounts'; import { createSiweMessage } from 'viem/siwe'; import { ChainList } from './chains'; @@ -92,7 +82,7 @@ export class CA { public chainList: ChainListType; private readonly _siweChain: number = 1; protected _evm?: { - client: Client; + client: WalletClient; provider: EthereumProvider; address: Hex; }; @@ -165,7 +155,7 @@ export class CA { return bridgeHandler; }; - protected async _calculateMaxForBridge(params: Omit) { + protected _calculateMaxForBridge = async (params: Omit) => { if (!this._evm) { throw Errors.sdkNotInitialized(); } @@ -177,12 +167,13 @@ export class CA { tron: this._tron, networkConfig: this._networkConfig, }); - } + }; protected _deinit = () => { this.#cosmos = undefined; + if (this._evm) { - this._evm.provider.removeListener('accountsChanged', this.onAccountsChanged); + this._evm.provider.removeListener('accountsChanged', this._onAccountsChanged); } if (this._refundInterval) { @@ -193,12 +184,12 @@ export class CA { this._initStatus = INIT_STATUS.CREATED; }; - protected async _getMyIntents(page = 1) { + protected _getMyIntents = async (page = 1) => { const { wallet } = await this._getCosmosWallet(); const address = (await wallet.getAccounts())[0].address; const rffList = await fetchMyIntents(address, this._networkConfig.GRPC_URL, page); return intentTransform(rffList, this.chainList); - } + }; protected _getUnifiedBalances = async (includeSwappableBalances = false) => { if (!this._evm || this._initStatus !== INIT_STATUS.DONE) { @@ -230,30 +221,31 @@ export class CA { return balances; }; - protected _isInitialized() { + protected _isInitialized = () => { return this._initStatus === INIT_STATUS.DONE; - } + }; - protected async _swapWithExactIn(input: ExactInSwapInput, options?: OnEventParam) { + protected _swapWithExactIn = async (input: ExactInSwapInput, options?: OnEventParam) => { return swap( { mode: SwapMode.EXACT_IN, data: input, }, - await this.getSwapOptions(options), + await this._getSwapOptions(options), ); - } - protected async _swapWithExactOut(input: ExactOutSwapInput, options?: OnEventParam) { + }; + + protected _swapWithExactOut = async (input: ExactOutSwapInput, options?: OnEventParam) => { return swap( { mode: SwapMode.EXACT_OUT, data: input, }, - await this.getSwapOptions(options), + await this._getSwapOptions(options), ); - } + }; - private async getSwapOptions(options?: OnEventParam): Promise { + private _getSwapOptions = async (options?: OnEventParam): Promise => { return { onSwapIntent: this._hooks.onSwapIntent, onEvent: options?.onEvent, @@ -271,7 +263,7 @@ export class CA { networkConfig: this._networkConfig, ...options, }; - } + }; protected _init = () => { if (!this._evm) { @@ -305,7 +297,7 @@ export class CA { return this._initPromise; }; - protected onAccountsChanged = (accounts: Array<`0x${string}`>) => { + protected _onAccountsChanged = (accounts: Array<`0x${string}`>) => { this._deinit(); if (accounts.length !== 0) { if (this._evm) { @@ -315,13 +307,13 @@ export class CA { } }; - async _setEVMProvider(provider: EthereumProvider) { + protected _setEVMProvider = async (provider: EthereumProvider) => { if (this._evm?.provider === provider) { return; } const client = createWalletClient({ - transport: custom(provider), - }).extend(publicActions); + transport: custom({ ...provider, request: provider.request.bind(provider) }), + }); const address = (await client.getAddresses())[0]; @@ -330,9 +322,9 @@ export class CA { provider, address, }; - } + }; - public async _setTronAdapter(adapter: TronAdapter) { + protected _setTronAdapter = async (adapter: TronAdapter) => { if (this._tron) { logger.debug('Already has tron adapter, so skip', { adapter, @@ -354,9 +346,9 @@ export class CA { adapter, address: tronHexToEvmAddress(utils.address.toHex(adapter.address as string)), }; - } + }; - protected async _setFuelConnector(connector: FuelConnector) { + protected _setFuelConnector = async (connector: FuelConnector) => { if (this._fuel?.connector === connector) { return; } @@ -385,43 +377,31 @@ export class CA { connector, provider, }; - } + }; - protected _setOnAllowanceHook(hook: OnAllowanceHook) { + protected _setOnAllowanceHook = (hook: OnAllowanceHook) => { this._hooks.onAllowance = hook; - } + }; - protected _setOnIntentHook(hook: OnIntentHook) { + protected _setOnIntentHook = (hook: OnIntentHook) => { this._hooks.onIntent = hook; - } + }; - protected _setOnSwapIntentHook(hook: OnSwapIntentHook) { + protected _setOnSwapIntentHook = (hook: OnSwapIntentHook) => { this._hooks.onSwapIntent = hook; - } + }; - protected async _bridgeAndTransfer(input: TransferParams, options?: OnEventParam) { + protected _bridgeAndTransfer = async (input: TransferParams, options?: OnEventParam) => { const params = createBridgeAndTransferParams(input, this.chainList); return this._bridgeAndExecute(params, options); - } + }; - protected async _simulateBridgeAndTransfer(input: TransferParams) { + protected _simulateBridgeAndTransfer = async (input: TransferParams) => { const params = createBridgeAndTransferParams(input, this.chainList); return this._simulateBridgeAndExecute(params); - } - - protected _changeChain(chainID: number) { - if (!this._evm) { - throw Errors.sdkNotInitialized(); - } - const chain = this.chainList.getChainByID(chainID); - if (!chain) { - throw Errors.chainNotFound(chainID); - } - - return switchChain(this._evm.client, chain); - } + }; - protected async _checkPendingRefunds() { + protected _checkPendingRefunds = async () => { await this._init(); const account = await this._getEVMAddress(); try { @@ -433,9 +413,9 @@ export class CA { } catch (e) { logger.error('Error checking pending refunds', e); } - } + }; - protected async _createCosmosWallet() { + protected _createCosmosWallet = async () => { let sig = retrieveSIWESignatureFromLocalStorage(this._evm!.address, this._siweChain); if (!sig) { sig = await this._signatureForLogin(); @@ -448,32 +428,32 @@ export class CA { const address = (await wallet.getAccounts())[0].address; await cosmosFeeGrant(this._networkConfig.COSMOS_URL, this._networkConfig.VSC_DOMAIN, address); return { wallet, address }; - } + }; - protected async _getCosmosWallet() { + protected _getCosmosWallet = async () => { if (!this.#cosmos) { this.#cosmos = await this._createCosmosWallet(); } return this.#cosmos; - } + }; - protected async _getEVMAddress() { + protected _getEVMAddress = async () => { if (!this._evm) { throw Errors.sdkNotInitialized(); } return (await this._evm.client.requestAddresses())[0]; - } + }; - protected async _setProviderHooks() { + protected _setProviderHooks = async () => { if (!this._evm) { throw Errors.sdkNotInitialized(); } if (this._evm.provider) { - this._evm.provider.on('accountsChanged', this.onAccountsChanged); + this._evm.provider.on('accountsChanged', this._onAccountsChanged); } - } + }; - protected async _signatureForLogin() { + protected _signatureForLogin = async () => { if (!this._evm) { throw Errors.sdkNotInitialized(); } @@ -516,13 +496,13 @@ export class CA { } finally { await this._evm.client.switchChain({ id: currentChain }); } - } + }; - protected _getSwapSupportedChains() { + protected _getSwapSupportedChains = () => { return getSwapSupportedChains(this.chainList); - } + }; - protected _simulateBridgeAndExecute(params: BridgeAndExecuteParams) { + protected _simulateBridgeAndExecute = (params: BridgeAndExecuteParams) => { if (!this._evm) { throw Errors.sdkNotInitialized(); } @@ -536,7 +516,7 @@ export class CA { ); return handler.simulateBridgeAndExecute(params); - } + }; protected _bridgeAndExecute = ( params: BridgeAndExecuteParams, @@ -557,7 +537,7 @@ export class CA { return handler.bridgeAndExecute(params, options); }; - protected async _execute(params: ExecuteParams, options?: OnEventParam) { + protected _execute = async (params: ExecuteParams, options?: OnEventParam) => { if (!this._evm) { throw Errors.sdkNotInitialized(); } @@ -571,9 +551,9 @@ export class CA { ); return handler.execute(params, options); - } + }; - protected async _simulateExecute(params: ExecuteParams) { + protected _simulateExecute = (params: ExecuteParams) => { if (!this._evm) { throw Errors.sdkNotInitialized(); } @@ -587,7 +567,7 @@ export class CA { ); return handler.simulateExecute(params, this._evm.address); - } + }; private readonly universeCheck = (dstChain: Chain) => { if (dstChain.universe === Universe.FUEL && !this._fuel) { diff --git a/src/sdk/ca-base/query/bridgeAndExecute.ts b/src/sdk/ca-base/query/bridgeAndExecute.ts index 5f7ed2f7..a6399a4c 100644 --- a/src/sdk/ca-base/query/bridgeAndExecute.ts +++ b/src/sdk/ca-base/query/bridgeAndExecute.ts @@ -24,6 +24,7 @@ import { createPublicClient, Hex, http, + parseGwei, PublicClient, serializeTransaction, toHex, @@ -37,13 +38,17 @@ import { generateStateOverride, switchChain, erc20GetAllowance, - percentageAdditionToBigInt, + pctAdditionToBigInt, getL1Fee, + divideBigInt, + getPctGasBufferByChain, } from '../utils'; import { packERC20Approve } from '../swap/utils'; import { BackendSimulationClient } from '../../../integrations/tenderly'; import BridgeHandler from '../requestHandlers/bridge'; import { Errors } from '../errors'; +import { isNativeAddress } from '../constants'; +import { Universe } from '@avail-project/ca-common'; class BridgeAndExecuteQuery { constructor( @@ -65,8 +70,6 @@ class BridgeAndExecuteQuery { throw Errors.tokenNotFound(tokenSymbol, toChainId); } - await switchChain(this.evmClient, dstChain); - const address = (await this.evmClient.getAddresses())[0]; let txs: Tx[] = []; @@ -87,27 +90,38 @@ class BridgeAndExecuteQuery { txs.push(tx); const determineGasUsed = params.execute.gas - ? Promise.resolve({ gasUsed: params.execute.gas + (approvalTx ? 85_000n : 0n) }) + ? Promise.resolve({ approvalGas: approvalTx ? 70_000n : 0n, txGas: params.execute.gas }) : this.simulateBundle({ txs, - amount: BigInt(execute.tokenApproval?.amount ?? '0'), + amount: params.amount, userAddress: address, chainId: dstChain.id, tokenAddress: token.contractAddress, - tokenSymbol: execute.tokenApproval?.token ?? 'ETH', - }).then(({ gasUsed }) => ({ - gasUsed: percentageAdditionToBigInt(gasUsed, 0.1), - })); + tokenSymbol: params.token ?? 'ETH', + }).then(({ gas }) => { + if (approvalTx) { + return { + approvalGas: gas[0], + txGas: gas[1], + }; + } else { + return { + approvalGas: 0n, + txGas: gas[0], + }; + } + }); const determineGasFee = params.execute.gasPrice ? Promise.resolve({ maxFeePerGas: params.execute.gasPrice, gasPrice: params.execute.gasPrice, + maxPriorityFeePerGas: 0n, }) : dstPublicClient.estimateFeesPerGas(); // 5. simulate approval(?) and execution + fetch gasPrice + fetch unified balance - const [{ gasUsed }, gasFeeEstimate, balances, l1Fee] = await Promise.all([ + const [gasUsed, gasFeeEstimate, balances, l1Fee] = await Promise.all([ determineGasUsed, determineGasFee, this.getUnifiedBalances(), @@ -123,17 +137,32 @@ class BridgeAndExecuteQuery { ), ]); - const gasPrice = gasFeeEstimate.maxFeePerGas ?? gasFeeEstimate.gasPrice ?? 0n; + // gasLimit = 1.3 * gasUsed for each (1.05 for monad) + const pctBuffer = getPctGasBufferByChain(dstChain.id); + const approvalGas = pctAdditionToBigInt(gasUsed.approvalGas, pctBuffer); + const txGas = pctAdditionToBigInt(gasUsed.txGas, pctBuffer); + + let gasPrice = gasFeeEstimate.maxFeePerGas ?? gasFeeEstimate.gasPrice ?? 0n; if (gasPrice === 0n) { throw Errors.gasPriceError({ chainId: dstChain.id, }); } - const gasFee = gasUsed * (gasPrice + l1Fee); + // gasPrice = (maxFeePerGas + 0.5 * maxPriorityFeePerGas) + gasPrice += divideBigInt( + gasFeeEstimate.maxPriorityFeePerGas === 0n + ? parseGwei('2') + : gasFeeEstimate.maxPriorityFeePerGas, + 2, + ); + + const gasFee = (approvalGas + txGas) * gasPrice + l1Fee; logger.debug('BridgeAndExecute:3', { - gasUsed, + increasedGas: approvalGas + txGas, + approvalGas, + txGas, gasFeeEstimate, gasPrice, balances, @@ -151,17 +180,22 @@ class BridgeAndExecuteQuery { ); return { + dstPublicClient, + dstChain, + amount: { + token: tokenAmount, + gas: gasAmount, + }, skipBridge, - tokenAmount, - gasAmount, tx, approvalTx, + gas: { + tx: txGas, + approval: approvalGas, + }, token, - dstChain, address, - dstPublicClient, gasFee, - gasUsed, gasPrice, }; } @@ -169,13 +203,13 @@ class BridgeAndExecuteQuery { public async simulateBridgeAndExecute( params: BridgeAndExecuteParams, ): Promise { - const { gasFee, token, skipBridge, tokenAmount, gasAmount, gasUsed, gasPrice } = + const { gasFee, token, skipBridge, amount, gas, gasPrice } = await this.estimateBridgeAndExecute(params); logger.debug('BridgeAndExecute:4:CalculateOptimalBridgeAmount', { skipBridge, - tokenAmount, - gasAmount, + amount, + gas, }); let bridgeResult: null | { @@ -187,10 +221,10 @@ class BridgeAndExecuteQuery { if (!skipBridge) { bridgeResult = await this.simulateBridgeWrapper({ token: token.symbol, - amount: tokenAmount, + amount: amount.token, toChainId: params.toChainId, sourceChains: params.sourceChains, - gas: gasAmount, + gas: amount.gas, }); } @@ -198,7 +232,7 @@ class BridgeAndExecuteQuery { const result: BridgeAndExecuteSimulationResult = { bridgeSimulation: bridgeResult, executeSimulation: { - gasUsed, + gasUsed: gas.approval + gas.tx, gasPrice, gasFee, }, @@ -218,22 +252,29 @@ class BridgeAndExecuteQuery { ): Promise { const { dstPublicClient, - address, dstChain, + address, token, skipBridge, - tokenAmount, - gasAmount, tx, approvalTx, - gasUsed, + amount, + gas, gasPrice, } = await this.estimateBridgeAndExecute(params); logger.debug('BridgeAndExecute:4:CalculateOptimalBridgeAmount', { skipBridge, - tokenAmount, - gasAmount, + amount, + approval: { + tx: approvalTx, + gas: gas.approval, + }, + tx: { + tx, + gas: gas.tx, + }, + gasPrice, }); const executeSteps: BridgeStepType[] = [ @@ -244,8 +285,11 @@ class BridgeAndExecuteQuery { // Approval and execute if (approvalTx) { executeSteps.unshift(BRIDGE_STEPS.EXECUTE_APPROVAL_STEP); + approvalTx.gas = gas.approval; } + tx.gas = gas.tx; + let bridgeResult: BridgeResult = { explorerUrl: '', }; @@ -255,10 +299,10 @@ class BridgeAndExecuteQuery { bridgeResult = await this.bridgeWrapper( { token: token.symbol, - amount: tokenAmount, + amount: amount.token, toChainId: params.toChainId, sourceChains: params.sourceChains, - gas: gasAmount, + gas: amount.gas, }, { onEvent: (event) => { @@ -283,8 +327,20 @@ class BridgeAndExecuteQuery { if (options?.beforeExecute) { const response = await options.beforeExecute(); - tx.data = response.data; - tx.value = response.value; + logger.debug('BeforeExecuteHook', { + response, + }); + if (response.data) { + tx.data = response.data; + } + + if (response.value) { + tx.value = response.value; + } + + if (response.gas && response.gas !== 0n) { + tx.gas = response.gas; + } } // 8. Execute the transaction @@ -292,7 +348,6 @@ class BridgeAndExecuteQuery { { approvalTx, tx, - gas: gasUsed, gasPrice, }, { @@ -369,7 +424,7 @@ class BridgeAndExecuteQuery { } // 4. Encode execute tx - const tx = { + const tx: Tx = { to: params.to, value: params.value ?? 0n, data: params.data ?? '0x', @@ -457,29 +512,44 @@ class BridgeAndExecuteQuery { requiredGasAmount: bigint, assets: UserAssetDatum[], ): Promise<{ skipBridge: boolean; tokenAmount: bigint; gasAmount: bigint }> { - try { - let skipBridge = true; - let tokenAmount = requiredTokenAmount; - let gasAmount = requiredGasAmount; - const assetList = new UserAssets(assets); - const { destinationAssetBalance, destinationGasBalance } = assetList.getAssetDetails( - chain, - tokenAddress, - ); + let skipBridge = true; + let tokenAmount = requiredTokenAmount; + let gasAmount = requiredGasAmount; + const assetList = new UserAssets(assets); + const { destinationAssetBalance, destinationGasBalance } = assetList.getAssetDetails( + chain, + tokenAddress, + ); - const destinationTokenAmount = mulDecimals(destinationAssetBalance, tokenDecimals); - const destinationGasAmount = mulDecimals( - destinationGasBalance, - chain.nativeCurrency.decimals, - ); + const destinationTokenAmount = mulDecimals(destinationAssetBalance, tokenDecimals); + const destinationGasAmount = mulDecimals(destinationGasBalance, chain.nativeCurrency.decimals); - logger.debug('calculateOptimalBridgeAmount', { - destinationTokenAmount, - requiredTokenAmount, - destinationGasAmount, - requiredGasAmount, - }); + logger.debug('calculateOptimalBridgeAmount', { + destinationTokenAmount, + requiredTokenAmount, + destinationGasAmount, + requiredGasAmount, + }); + if (isNativeAddress(Universe.ETHEREUM, tokenAddress)) { + const totalRequired = requiredGasAmount + requiredTokenAmount; + if (destinationGasAmount < totalRequired) { + skipBridge = false; + // Total missing native amount + const difference = totalRequired - destinationGasAmount; + + // First cover missing TOKEN + const missingToken = + requiredTokenAmount > destinationTokenAmount + ? requiredTokenAmount - destinationTokenAmount + : 0n; + // Then cover missing GAS out of the remaining deficit + const gasPart = difference > missingToken ? difference - missingToken : 0n; + + tokenAmount = missingToken; + gasAmount = gasPart; + } + } else { const isGasBridgeRequired = destinationGasAmount < requiredGasAmount; const isTokenBridgeRequired = destinationTokenAmount < requiredTokenAmount; @@ -494,17 +564,12 @@ class BridgeAndExecuteQuery { gasAmount = destinationGasAmount < requiredGasAmount ? requiredGasAmount - destinationGasAmount : 0n; } - - return { - skipBridge, - tokenAmount, - gasAmount, - }; - } catch (error) { - logger.warn(`Failed to calculate optimal bridge amount: ${error}`); - // Default to bridging full amount on error - return { skipBridge: false, tokenAmount: requiredTokenAmount, gasAmount: requiredGasAmount }; } + return { + skipBridge, + tokenAmount, + gasAmount, + }; } private async simulateBundle(input: { @@ -525,6 +590,7 @@ class BridgeAndExecuteQuery { data: tx.data, value: toHex(tx.value), stepId: `sim_${i}`, + enableStateOverride: true, // ???????? stateOverride: overrides, })), }); @@ -534,7 +600,6 @@ class BridgeAndExecuteQuery { params: { tx: Tx; approvalTx: Tx | null; - gas?: bigint; gasPrice?: bigint; }, options: { @@ -549,6 +614,7 @@ class BridgeAndExecuteQuery { }, ) { const { waitForReceipt = true, receiptTimeout = 300000, requiredConfirmations = 1 } = options; + await switchChain(options.client, options.chain); let approvalHash; if (params.approvalTx) { @@ -571,8 +637,6 @@ class BridgeAndExecuteQuery { ...params.tx, account: options.address, chain: options.chain, - gas: params.gas, - gasPrice: params.gasPrice, }); if (options.emit) { @@ -613,7 +677,7 @@ class BridgeAndExecuteQuery { const handler = this.bridge(params, options); const result = await handler.execute(); return { - explorerUrl: result?.explorerURL ?? '', + explorerUrl: result.explorerURL, }; }; diff --git a/src/sdk/ca-base/query/bridgeAndTransfer.ts b/src/sdk/ca-base/query/bridgeAndTransfer.ts index 4b879fe3..3672cb31 100644 --- a/src/sdk/ca-base/query/bridgeAndTransfer.ts +++ b/src/sdk/ca-base/query/bridgeAndTransfer.ts @@ -17,6 +17,7 @@ const createBridgeAndTransferParams = ( to: input.recipient, value: input.amount, data: '0x', + gas: 21_000n, } : { to: token.contractAddress, @@ -26,6 +27,7 @@ const createBridgeAndTransferParams = ( functionName: 'transfer', args: [input.recipient, input.amount], }), + gas: 63_000n, }; return { diff --git a/src/sdk/ca-base/requestHandlers/bridge.ts b/src/sdk/ca-base/requestHandlers/bridge.ts index 11d1769c..94cb0700 100644 --- a/src/sdk/ca-base/requestHandlers/bridge.ts +++ b/src/sdk/ca-base/requestHandlers/bridge.ts @@ -174,7 +174,7 @@ class BridgeHandler { // Step 4: create intent console.time('preIntentSteps: CreateIntent'); - const intent = this.createIntent({ + const intent = await this.createIntent({ amount: tokenAmountInDecimal, assets: userAssets, feeStore, @@ -649,10 +649,14 @@ class BridgeHandler { }); } + if (chain.universe == Universe.ETHEREUM) { + logger.debug(`Switching chain to ${chain.id}`); + + await switchChain(this.options.evm.client, chain); + } + if (currency.permitVariant === PermitVariant.Unsupported || chain.id === 1) { if (chain.universe === Universe.ETHEREUM) { - await switchChain(this.options.evm.client, chain); - const h = await this.options.evm.client .writeContract({ abi: ERC20ABI, @@ -729,8 +733,6 @@ class BridgeHandler { type: 'json-rpc', }; - await switchChain(this.options.evm.client, chain); - const signed = parseSignature( await signPermitForAddressAndValue( currency, @@ -875,7 +877,7 @@ class BridgeHandler { logger.debug('BridgeSteps', this.steps); } - private createIntent(input: { + private async createIntent(input: { amount: Decimal; assets: UserAssets; feeStore: FeeStore; @@ -913,7 +915,7 @@ class BridgeHandler { throw new Error(`Asset ${token.symbol} not found in UserAssets`); } - const allSources = asset.iterate(feeStore).map((v) => { + const allSources = (await asset.iterate(this.options.chainList)).map((v) => { const chain = this.options.chainList.getChainByID(v.chainID); if (!chain) { throw Errors.chainNotFound(v.chainID); @@ -975,18 +977,6 @@ class BridgeHandler { continue; } - // if (assetC.chainID === CHAIN_IDS.fuel.mainnet) { - // const fuelChain = this.options.chainList.getChainByID(CHAIN_IDS.fuel.mainnet); - // const baseAssetBalanceOnFuel = assets.getNativeBalance(fuelChain!); - // if (new Decimal(baseAssetBalanceOnFuel).lessThan('0.000_003')) { - // logger.debug('fuel base asset balance is lesser than min expected deposit fee, so skip', { - // current: baseAssetBalanceOnFuel, - // minimum: '0.000_003', - // }); - // continue; - // } - // } - // Now collectionFee is a fixed amount - applicable to all const collectionFee = feeStore.calculateCollectionFee({ decimals: assetC.decimals, diff --git a/src/sdk/ca-base/utils/common.utils.ts b/src/sdk/ca-base/utils/common.utils.ts index 6b8258e0..8a391237 100644 --- a/src/sdk/ca-base/utils/common.utils.ts +++ b/src/sdk/ca-base/utils/common.utils.ts @@ -11,7 +11,7 @@ import { } from '@avail-project/ca-common'; import { DirectSecp256k1Wallet } from '@cosmjs/proto-signing'; import Decimal from 'decimal.js'; -import { arrayify, CHAIN_IDS, FuelConnector, hexlify, Provider } from 'fuels'; +import { arrayify, FuelConnector, hexlify, Provider } from 'fuels'; import Long from 'long'; import { ByteArray, @@ -49,8 +49,11 @@ import { UserAssetDatum, Chain, } from '../../../commons'; -import { FeeStore } from './api.utils'; -import { requestTimeout, waitForIntentFulfilment } from './contract.utils'; +import { + createPublicClientWithFallback, + requestTimeout, + waitForIntentFulfilment, +} from './contract.utils'; import { cosmosCreateDoubleCheckTx, cosmosFillCheck, cosmosRefundIntent } from './cosmos.utils'; import { AdapterProps } from '@tronweb3/tronwallet-abstract-adapter'; import { Errors } from '../errors'; @@ -565,8 +568,8 @@ class UserAsset { return false; } - iterate(feeStore: FeeStore) { - return this.value.breakdown + async iterate(chainList: ChainListType) { + const values = this.value.breakdown .filter((b) => new Decimal(b.balance).gt(0)) .sort((a, b) => { if (a.chain.id === 1) { @@ -576,37 +579,46 @@ class UserAsset { return -1; } return Decimal.sub(b.balance, a.balance).toNumber(); - }) - .map((b) => { - let balance = new Decimal(b.balance); - if (this.isDeposit(b.contractAddress, b.universe)) { - const collectionFee = feeStore.calculateCollectionFee({ - decimals: b.decimals, - sourceChainID: b.chain.id, - sourceTokenAddress: b.contractAddress, - }); - - let estimatedGasForDeposit = collectionFee.mul(b.chain.id === 1 ? 2 : 4); - - if (b.contractAddress === FUEL_BASE_ASSET_ID && b.chain.id === CHAIN_IDS.fuel.mainnet) { - // Estimating this amount of gas is required for fuel -> vault - estimatedGasForDeposit = new Decimal('0.000_003'); - } - - if (new Decimal(b.balance).lessThan(estimatedGasForDeposit)) { - balance = new Decimal(0); - } else { - balance = new Decimal(b.balance).minus(estimatedGasForDeposit); - } + }); + + const balances = []; + + for (const b of values) { + let balance = new Decimal(b.balance); + if (this.isDeposit(b.contractAddress, b.universe)) { + const ESTIMATED_DEPOSIT_GAS = 200_000n; + + const chain = chainList.getChainByID(b.chain.id); + if (!chain) { + throw Errors.chainNotFound(b.chain.id); } - return { - balance, - chainID: b.chain.id, - decimals: b.decimals, - tokenContract: b.contractAddress, - universe: b.universe, - }; + + const publicClient = createPublicClientWithFallback(chain); + const gasEstimate = await publicClient.estimateFeesPerGas(); + const gasUnitPrice = gasEstimate.maxFeePerGas ?? gasEstimate.gasPrice; + + const estimatedGasForDeposit = divDecimals( + ESTIMATED_DEPOSIT_GAS * gasUnitPrice, + chain.nativeCurrency.decimals, + ); + + if (new Decimal(b.balance).lessThan(estimatedGasForDeposit)) { + balance = new Decimal(0); + } else { + balance = new Decimal(b.balance).minus(estimatedGasForDeposit); + } + } + + balances.push({ + balance, + chainID: b.chain.id, + decimals: b.decimals, + tokenContract: b.contractAddress, + universe: b.universe, }); + } + + return balances; } } class UserAssets { @@ -785,10 +797,18 @@ async function waitForTronDepositTxConfirmation( throw new Error(`⏰ Timeout: Transaction not confirmed within ${timeout / 1000}s`); } -function percentageAdditionToBigInt(base: bigint, percentage: number) { +function pctAdditionToBigInt(base: bigint, percentage: number) { return base + BigInt(new Decimal(base).mul(percentage).toFixed(0)); } +function divideBigInt(base: bigint, divisor: number) { + if (base === 0n) { + return base; + } + + return BigInt(new Decimal(base).div(divisor).toFixed(0)); +} + async function waitForTronApprovalTxConfirmation( amount: bigint, owner: Hex, @@ -889,8 +909,9 @@ const createDeadlineFromNow = (minutes: bigint = 3n): bigint => { }; export { + divideBigInt, createDeadlineFromNow, - percentageAdditionToBigInt, + pctAdditionToBigInt, retrieveSIWESignatureFromLocalStorage, storeSIWESignatureToLocalStorage, retrieveAddress, diff --git a/src/sdk/ca-base/utils/contract.utils.ts b/src/sdk/ca-base/utils/contract.utils.ts index 25a98934..b55ab717 100644 --- a/src/sdk/ca-base/utils/contract.utils.ts +++ b/src/sdk/ca-base/utils/contract.utils.ts @@ -24,36 +24,12 @@ import gasOracleABI from '../abi/gasOracle'; import { FillEvent } from '../abi/vault'; import { ZERO_ADDRESS } from '../constants'; import { Errors } from '../errors'; -import { getLogger } from '../../../commons'; -import { - ChainListType, - Chain, - EVMTransaction, - GetAllowanceParams, - SetAllowanceParams, -} from '../../../commons'; -import { vscCreateSponsoredApprovals } from './api.utils'; -import { convertTo32Bytes, createDeadlineFromNow, equalFold, minutesToMs } from './common.utils'; +import { getLogger, MAINNET_CHAIN_IDS, TESTNET_CHAIN_IDS } from '../../../commons'; +import { ChainListType, Chain, GetAllowanceParams, SetAllowanceParams } from '../../../commons'; +import { equalFold, minutesToMs } from './common.utils'; const logger = getLogger(); -const isEVMTx = (tx: unknown): tx is EVMTransaction => { - logger.debug('isEVMTx', tx); - if (typeof tx !== 'object') { - return false; - } - if (!tx) { - return false; - } - if (!('to' in tx)) { - return false; - } - if (!('data' in tx || 'value' in tx)) { - return false; - } - return true; -}; - const getAllowance = async ( chain: Chain, address: `0x${string}`, @@ -248,15 +224,26 @@ const waitForTxReceipt = async ( }; const switchChain = async (client: WalletClient, chain: Chain) => { + const current = await client.getChainId(); + if (current === chain.id) return; + try { await client.switchChain({ id: chain.id }); - } catch (e) { - logger.debug('error during switching chain', e); - await client.addChain({ - chain, - }); - await client.switchChain({ id: chain.id }); - return; + } catch (outerErr) { + logger.error(`switchChain failed, trying addChain`, outerErr); + try { + await client.addChain({ chain }); + await client.switchChain({ id: chain.id }); + } catch (inner) { + logger.error('Unable to add/switch chain', inner); + throw inner; + } + } + + const after = await client.getChainId(); + if (after !== chain.id) { + logger.error(`Wallet did not switch chains even though no error was thrown`); + throw Errors.internal('wallet did not switch chain - no error thrown'); } }; @@ -461,7 +448,16 @@ const createPublicClientWithFallback = (chain: Chain): PublicClient => { }); }; +const getPctGasBufferByChain = (chainId: number) => { + if (chainId === TESTNET_CHAIN_IDS.MONAD_TESTNET || chainId === MAINNET_CHAIN_IDS.MONAD) { + return 0.05; + } + + return 0.3; +}; + export { + getPctGasBufferByChain, erc20GetAllowance, erc20SetAllowance, createPublicClientWithFallback, @@ -469,7 +465,6 @@ export { getAllowances, getL1Fee, getTokenTxFunction, - isEVMTx, requestTimeout, signPermitForAddressAndValue, switchChain, diff --git a/src/sdk/ca-base/utils/rff.utils.ts b/src/sdk/ca-base/utils/rff.utils.ts index e416d31e..6fec0f63 100644 --- a/src/sdk/ca-base/utils/rff.utils.ts +++ b/src/sdk/ca-base/utils/rff.utils.ts @@ -20,14 +20,14 @@ import Decimal from 'decimal.js'; import { FeeStore } from './api.utils'; type Destination = { - tokenAddress: `0x${string}`; + tokenAddress: Hex; universe: Universe; value: bigint; }; type Source = { chainID: bigint; - tokenAddress: `0x${string}`; + tokenAddress: Hex; universe: Universe; valueRaw: bigint; value: Decimal; diff --git a/src/sdk/index.ts b/src/sdk/index.ts index f81c8382..fc9aa13f 100644 --- a/src/sdk/index.ts +++ b/src/sdk/index.ts @@ -25,6 +25,7 @@ import type { OnEventParam, BridgeMaxResult, OnSwapIntentHook, + BeforeExecuteHook, } from '../commons'; import { logger } from '../commons'; import { CA } from './ca-base'; @@ -244,7 +245,7 @@ export class NexusSDK extends CA { */ public async bridgeAndExecute( params: BridgeAndExecuteParams, - options?: OnEventParam, + options?: OnEventParam & BeforeExecuteHook, ): Promise { return this._bridgeAndExecute(params, options); } From 02be113324700e75fcc9d8a2093218ca247aed3d Mon Sep 17 00:00:00 2001 From: Abhishek Date: Mon, 24 Nov 2025 13:55:31 +0400 Subject: [PATCH 40/51] fix: regression errors (#107) * fix: removed telemetry for now, fix: deadline removed from approval for now, fixed approval deadline usage in SBC * fix: update logger to be lazy initialized on init, fix: deadline to bytes32 regression issue --- package.json | 2 +- src/sdk/ca-base/ca.ts | 2 ++ src/sdk/ca-base/nexusError.ts | 25 ++++++++------ src/sdk/ca-base/requestHandlers/bridge.ts | 3 +- src/sdk/ca-base/swap/sbc.ts | 2 +- src/sdk/ca-base/swap/utils.ts | 7 ++-- src/sdk/ca-base/telemetry.ts | 42 +++++++++++++++++++++++ src/sdk/telemetry.ts | 39 --------------------- 8 files changed, 65 insertions(+), 57 deletions(-) create mode 100644 src/sdk/ca-base/telemetry.ts delete mode 100644 src/sdk/telemetry.ts diff --git a/package.json b/package.json index eb141a8f..fe326a55 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@avail-project/nexus-core", - "version": "1.0.0-beta.40", + "version": "1.0.0-beta.44", "description": "Nexus headless SDK for cross-chain transactions", "main": "./dist/index.js", "module": "./dist/index.esm.js", diff --git a/src/sdk/ca-base/ca.ts b/src/sdk/ca-base/ca.ts index 948a3e5a..96124b15 100644 --- a/src/sdk/ca-base/ca.ts +++ b/src/sdk/ca-base/ca.ts @@ -60,6 +60,7 @@ import { import { createBridgeAndTransferParams } from './query/bridgeAndTransfer'; import getMaxValueForBridge from './requestHandlers/bridgeMax'; import { Errors } from './errors'; +import { setLoggerProvider } from './telemetry'; setLogLevel(LOG_LEVEL.NOLOGS); const logger = getLogger(); @@ -283,6 +284,7 @@ export class CA { this._initPromise = (async () => { try { + setLoggerProvider(); this._setProviderHooks(); this.#cosmos = await this._createCosmosWallet(); this._checkPendingRefunds(); diff --git a/src/sdk/ca-base/nexusError.ts b/src/sdk/ca-base/nexusError.ts index 75508042..ca74399d 100644 --- a/src/sdk/ca-base/nexusError.ts +++ b/src/sdk/ca-base/nexusError.ts @@ -1,5 +1,6 @@ import { AnyValueMap, SeverityNumber } from '@opentelemetry/api-logs'; -import telemetryLogger from '../telemetry'; +import { telemetryLogger } from './telemetry'; + export interface NexusErrorData { context?: string; // Where or why it happened cause?: unknown; // Optional nested error @@ -57,16 +58,18 @@ export type ErrorCode = (typeof ERROR_CODES)[keyof typeof ERROR_CODES]; export function createError(code: ErrorCode, message: string, data?: NexusErrorData): NexusError { const nexusError = new NexusError(code, message, data); - telemetryLogger.emit({ - body: message, - severityNumber: SeverityNumber.ERROR, - severityText: 'ERROR', - attributes: { - data: nexusError.data, - cause: code, - stackTrace: nexusError.stack, - } as AnyValueMap, - }); + try { + telemetryLogger?.emit({ + body: message, + severityNumber: SeverityNumber.ERROR, + severityText: 'ERROR', + attributes: { + data: nexusError.data, + cause: code, + stackTrace: nexusError.stack, + } as AnyValueMap, + }); + } catch {} return nexusError; } diff --git a/src/sdk/ca-base/requestHandlers/bridge.ts b/src/sdk/ca-base/requestHandlers/bridge.ts index 94cb0700..38766553 100644 --- a/src/sdk/ca-base/requestHandlers/bridge.ts +++ b/src/sdk/ca-base/requestHandlers/bridge.ts @@ -71,7 +71,7 @@ import { createRFFromIntent, retrieveAddress, getBalances, - createDeadlineFromNow, + // createDeadlineFromNow, } from '../utils'; import { TronWeb } from 'tronweb'; import { Errors } from '../errors'; @@ -741,7 +741,6 @@ class BridgeHandler { account, vc, source.amount, - createDeadlineFromNow(3n), ).catch((e) => { if (e instanceof ContractFunctionExecutionError) { const isUserRejectedRequestError = diff --git a/src/sdk/ca-base/swap/sbc.ts b/src/sdk/ca-base/swap/sbc.ts index 5da9e6d9..a068d53d 100644 --- a/src/sdk/ca-base/swap/sbc.ts +++ b/src/sdk/ca-base/swap/sbc.ts @@ -119,7 +119,7 @@ export const createSBCTxFromCalls = async ({ value: convertTo32Bytes(c.value), })), chain_id: convertTo32Bytes(chainID), - deadline: toBytes(deadline), + deadline: convertTo32Bytes(deadline), key_hash: ZERO_BYTES_32, nonce: convertTo32Bytes(nonce), revert_on_failure: true, diff --git a/src/sdk/ca-base/swap/utils.ts b/src/sdk/ca-base/swap/utils.ts index a43ff4ef..caf77262 100644 --- a/src/sdk/ca-base/swap/utils.ts +++ b/src/sdk/ca-base/swap/utils.ts @@ -175,6 +175,7 @@ export const createPermitSignature = async ( walletAddress: Hex, variant: PermitVariant, version: number, + deadline: bigint, ) => { const contract = getContract({ abi: ERC20ABI, @@ -188,8 +189,6 @@ export const createPermitSignature = async ( contract.read.nonces([walletAddress]), ]); - const deadline = createDeadlineFromNow(3n); - logger.debug('createPermitSigParams', { account: walletAddress, domain: { @@ -558,6 +557,7 @@ export const createPermitApprovalTx = async ({ variant: PermitVariant; version: number; }) => { + const deadline = createDeadlineFromNow(3n); const { signature } = await createPermitSignature( contractAddress, ownerWallet, @@ -565,6 +565,7 @@ export const createPermitApprovalTx = async ({ owner, variant, version, + deadline, ); const { r, s, v } = parseSignature(signature); @@ -582,7 +583,7 @@ export const createPermitApprovalTx = async ({ }) : encodeFunctionData({ abi: ERC20PermitABI, - args: [owner, spender, maxUint256, maxUint256, Number(v), r, s], + args: [owner, spender, maxUint256, deadline, Number(v), r, s], functionName: 'permit', }), to: contractAddress, diff --git a/src/sdk/ca-base/telemetry.ts b/src/sdk/ca-base/telemetry.ts new file mode 100644 index 00000000..5a6b5e66 --- /dev/null +++ b/src/sdk/ca-base/telemetry.ts @@ -0,0 +1,42 @@ +import { LoggerProvider, BatchLogRecordProcessor } from '@opentelemetry/sdk-logs'; +import { OTLPLogExporter } from '@opentelemetry/exporter-logs-otlp-http'; +import { Logger, logs } from '@opentelemetry/api-logs'; +import { resourceFromAttributes } from '@opentelemetry/resources'; +import { toHex } from 'viem/utils'; + +let telemetryLogger: Logger | null = null; + +function getOrGenerateClientId(): string { + const KEY = 'nexus-client-id'; + let clientId = window.localStorage.getItem(KEY); + + if (!clientId) { + const bytes = new Uint8Array(32); + clientId = toHex(window.crypto.getRandomValues(bytes)); + window.localStorage.setItem(KEY, clientId); + } + return clientId; +} + +const setLoggerProvider = () => { + if (!telemetryLogger) { + const loggerProvider = new LoggerProvider({ + resource: resourceFromAttributes({ + 'service.name': 'nexus-sdk-internal-logs', + 'client.id': getOrGenerateClientId(), + }), + processors: [ + new BatchLogRecordProcessor( + new OTLPLogExporter({ + url: 'https://otel.avail.so/v1/logs', + headers: { 'x-otlp-force-fetch': '1' }, + }), + ), + ], + }); + logs.setGlobalLoggerProvider(loggerProvider); + telemetryLogger = logs.getLogger('nexus-telemetry-logger'); + } +}; + +export { setLoggerProvider, telemetryLogger }; diff --git a/src/sdk/telemetry.ts b/src/sdk/telemetry.ts deleted file mode 100644 index 54b21f53..00000000 --- a/src/sdk/telemetry.ts +++ /dev/null @@ -1,39 +0,0 @@ -import { LoggerProvider, BatchLogRecordProcessor } from '@opentelemetry/sdk-logs'; -import { OTLPLogExporter } from '@opentelemetry/exporter-logs-otlp-http'; -import { logs } from '@opentelemetry/api-logs'; -import { resourceFromAttributes } from '@opentelemetry/resources'; -import { toHex } from 'viem/utils'; - -function getOrGenerateClientId(): string { - const KEY = 'nexus-client-id'; - let clientId = localStorage.getItem(KEY); - - if (!clientId) { - const bytes = new Uint8Array(32); - clientId = toHex(window.crypto.getRandomValues(bytes)); - localStorage.setItem(KEY, clientId); - } - return clientId; -} - -const resource = resourceFromAttributes({ - 'service.name': 'nexus-sdk-internal-logs', - 'client.id': getOrGenerateClientId(), -}); - -const loggerProvider = new LoggerProvider({ - resource: resource, - processors: [ - new BatchLogRecordProcessor( - new OTLPLogExporter({ - url: 'https://otel.avail.so/v1/logs', - headers: { 'x-otlp-force-fetch': '1' }, - }), - ), - ], -}); - -logs.setGlobalLoggerProvider(loggerProvider); -const telemetryLogger = logs.getLogger('nexus-telemetry-logger'); - -export default telemetryLogger; From 3ca071f97566568d425cd521b6ef13aeffc988ca Mon Sep 17 00:00:00 2001 From: Abhishek Date: Mon, 24 Nov 2025 15:56:40 +0400 Subject: [PATCH 41/51] fix: remove ethereum from swap list for the meantime (#109) --- package.json | 2 +- src/sdk/ca-base/chains.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index fe326a55..577090b5 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@avail-project/nexus-core", - "version": "1.0.0-beta.44", + "version": "1.0.0-beta.46", "description": "Nexus headless SDK for cross-chain transactions", "main": "./dist/index.js", "module": "./dist/index.esm.js", diff --git a/src/sdk/ca-base/chains.ts b/src/sdk/ca-base/chains.ts index 81bd4487..a30e6d28 100644 --- a/src/sdk/ca-base/chains.ts +++ b/src/sdk/ca-base/chains.ts @@ -636,7 +636,7 @@ const MAINNET_CHAINS: Chain[] = [ }, id: SUPPORTED_CHAINS.ETHEREUM, name: 'Ethereum Mainnet', - ankrName: 'eth', + ankrName: '', nativeCurrency: { decimals: 18, name: 'Ether', From 57e7b97f3f8bcd16f3f4e80e41e7cd1a973a53a0 Mon Sep 17 00:00:00 2001 From: Jeremias Moraes Date: Mon, 24 Nov 2025 09:03:39 -0300 Subject: [PATCH 42/51] feat: Add custom SDK errors (#104) * feat: Adds account,sdk and env errors * feat: Adds error map for generic errors * feat: Enhance error map for generic errors * feat: Add telemetry logging on default logger * feat: Adds lazy telemetry init on default logger --- package-lock.json | 4 +- src/commons/types/swap-steps.ts | 8 +-- src/commons/utils/logger.ts | 32 +++++++++++- src/sdk/ca-base/ca.ts | 8 +-- src/sdk/ca-base/chains.ts | 6 +-- src/sdk/ca-base/errors.ts | 59 ++++++++++++++++++++--- src/sdk/ca-base/nexusError.ts | 21 ++++++++ src/sdk/ca-base/requestHandlers/bridge.ts | 6 +-- src/sdk/ca-base/swap/data.ts | 5 +- src/sdk/ca-base/swap/ob.ts | 22 +++++---- src/sdk/ca-base/swap/rff.ts | 6 +-- src/sdk/ca-base/swap/route.ts | 6 +-- src/sdk/ca-base/swap/swap.ts | 2 +- src/sdk/ca-base/swap/utils.ts | 18 +++---- src/sdk/ca-base/utils/api.utils.ts | 14 +++--- src/sdk/ca-base/utils/common.utils.ts | 40 +++++++-------- src/sdk/ca-base/utils/contract.utils.ts | 2 +- src/sdk/ca-base/utils/cosmos.utils.ts | 6 +-- src/sdk/ca-base/utils/tron.utils.ts | 3 +- 19 files changed, 185 insertions(+), 83 deletions(-) diff --git a/package-lock.json b/package-lock.json index 0959346a..77ef7eb8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@avail-project/nexus-core", - "version": "1.0.0-beta.39", + "version": "1.0.0-beta.44", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@avail-project/nexus-core", - "version": "1.0.0-beta.39", + "version": "1.0.0-beta.44", "license": "MIT", "dependencies": { "@avail-project/ca-common": "1.0.0-dev.3", diff --git a/src/commons/types/swap-steps.ts b/src/commons/types/swap-steps.ts index 11e1865c..dfd3a303 100644 --- a/src/commons/types/swap-steps.ts +++ b/src/commons/types/swap-steps.ts @@ -1,5 +1,6 @@ import { ChainListType } from '.'; import { Hex } from 'viem'; +import { Errors } from '../../sdk/ca-base/errors'; const SWAP_START = { completed: true, @@ -57,7 +58,7 @@ const SOURCE_SWAP_HASH = (ops: [bigint, Hex], chainList: ChainListType) => { const chainID = ops[0]; const chain = chainList.getChainByID(Number(ops[0])); if (!chain) { - throw new Error(`Unknown chain: ${ops[0]}`); + throw Errors.chainNotFound(chainID); } return { @@ -94,9 +95,10 @@ const SWAP_COMPLETE = { } as const; const DESTINATION_SWAP_HASH = (op: [bigint, Hex], chainList: ChainListType) => { - const chain = chainList.getChainByID(Number(op[0])); + const chainID = Number(op[0]) + const chain = chainList.getChainByID(chainID); if (!chain) { - throw new Error(`Unknown chain: ${op[0]}`); + throw Errors.chainNotFound(chainID); } return { chain: { diff --git a/src/commons/utils/logger.ts b/src/commons/utils/logger.ts index 044a4644..18edab7e 100644 --- a/src/commons/utils/logger.ts +++ b/src/commons/utils/logger.ts @@ -1,3 +1,5 @@ +import { telemetryLogger } from '../../sdk/ca-base/telemetry'; + export const LOG_LEVEL = { DEBUG: 1, ERROR: 4, @@ -6,6 +8,14 @@ export const LOG_LEVEL = { WARNING: 3, } as const; +export const LOG_LEVEL_NAME: Record = { + [LOG_LEVEL.DEBUG]: 'DEBUG', + [LOG_LEVEL.ERROR]: 'ERROR', + [LOG_LEVEL.INFO]: 'INFO', + [LOG_LEVEL.NOLOGS]: 'NOLOGS', + [LOG_LEVEL.WARNING]: 'WARNING', +}; + type LogLevel = (typeof LOG_LEVEL)[keyof typeof LOG_LEVEL]; type ExceptionReporter = (message: string) => void; @@ -66,9 +76,9 @@ class Logger { this.internalLog(LOG_LEVEL.DEBUG, message, params); } - error(message: string, err?: unknown) { + error(message: string, err?: unknown, params: unknown = {}) { if (err instanceof Error) { - this.internalLog(LOG_LEVEL.ERROR, message, err.message); + this.internalLog(LOG_LEVEL.ERROR, message, params); sendException(JSON.stringify({ error: err.message, message })); return; } @@ -87,6 +97,24 @@ class Logger { internalLog(level: LogLevel, message: string, params?: unknown) { const logMessage = `[${this.prefix}] Msg: ${message}\n`; + if (level == LOG_LEVEL.ERROR || level == LOG_LEVEL.WARNING) { + const cause = + params && typeof params === 'object' && 'cause' in params + ? (params as any).cause + : 'unknown|not_mapped'; + try { + telemetryLogger?.emit({ + body: message, + severityNumber: level, + severityText: LOG_LEVEL_NAME[level], + attributes: { + cause: cause, + }, + }); + } catch (error) { + console.error('Failed to send telemetry logs: ', error); + } + } this.consoleLog(level, logMessage, params); } diff --git a/src/sdk/ca-base/ca.ts b/src/sdk/ca-base/ca.ts index 96124b15..9fd57c93 100644 --- a/src/sdk/ca-base/ca.ts +++ b/src/sdk/ca-base/ca.ts @@ -277,7 +277,7 @@ export class CA { // Prevent concurrent initializations if (this._initStatus !== INIT_STATUS.CREATED) { - throw new Error(`Unexpected init state: ${this._initStatus}`); + throw Errors.sdkInitStateNotExpected(this._initStatus); } this._initStatus = INIT_STATUS.RUNNING; @@ -291,7 +291,7 @@ export class CA { this._initStatus = INIT_STATUS.DONE; } catch (e) { this._initStatus = INIT_STATUS.CREATED; - logger.error('Error initializing CA', e); + logger.error('Error initializing CA', e, {cause: 'SDK_NOT_INITIALIZED'}); throw e; } })(); @@ -366,7 +366,7 @@ export class CA { const address = await connector.currentAccount(); if (!address) { - throw new Error('could not get current account from connector'); + throw Errors.accountConnectionFailed(); } const provider = new Provider(FUEL_NETWORK_URL, { @@ -413,7 +413,7 @@ export class CA { await refundExpiredIntents(account, this._networkConfig.COSMOS_URL, this.#cosmos!.wallet); }, minutesToMs(10)); } catch (e) { - logger.error('Error checking pending refunds', e); + logger.error('Error checking pending refunds', e, {cause: 'REFUND_CHECK_ERROR'}); } }; diff --git a/src/sdk/ca-base/chains.ts b/src/sdk/ca-base/chains.ts index a30e6d28..df9aff36 100644 --- a/src/sdk/ca-base/chains.ts +++ b/src/sdk/ca-base/chains.ts @@ -25,9 +25,9 @@ class ChainList { this.chains = TESTNET_CHAINS; break; case Environment.JADE: - throw new Error('Jade environment not supported yet'); + throw Errors.environmentNotSupported('Jade'); default: - throw new Error('Unknown environment'); + throw Errors.environmentNotKnown(); } this.vcm = getVaultContractMap(env); } @@ -133,7 +133,7 @@ class ChainList { const vc = this.vcm.get(omniversalChainID); if (!vc) { - throw new Error(`vault contract not found for chain: ${chainID}`); + throw Errors.vaultContractNotFound(chainID); } return convertToHexAddressByUniverse(vc, chain.universe); diff --git a/src/sdk/ca-base/errors.ts b/src/sdk/ca-base/errors.ts index da4f67f8..0798a6a9 100644 --- a/src/sdk/ca-base/errors.ts +++ b/src/sdk/ca-base/errors.ts @@ -3,6 +3,18 @@ import { ERROR_CODES, createError } from './nexusError'; export const Errors = { sdkNotInitialized: () => createError(ERROR_CODES.SDK_NOT_INITIALIZED, 'SDK is not initialized()'), + sdkInitStateNotExpected: (state: string) => + createError(ERROR_CODES.SDK_INIT_STATE_NOT_EXPECTED, 'Unexpected init SDK state', { + details: { state }, + }), + accountConnectionFailed: () => + createError(ERROR_CODES.CONNECT_ACCOUNT_FAILED, 'Account failed to connect from connector'), + environmentNotSupported: (environment: string) => + createError(ERROR_CODES.ENVIRONMENT_NOT_SUPPORTED, 'Environment not supported yet', { + details: { environment }, + }), + environmentNotKnown: () => + createError(ERROR_CODES.ENVIRONMENT_NOT_KNOWN, 'Environment not known/mapped'), invalidAllowance: (expected: number, got: number) => createError( ERROR_CODES.INVALID_VALUES_ALLOWANCE_HOOK, @@ -12,26 +24,32 @@ export const Errors = { details: { expectedLength: expected, receivedLength: got }, }, ), - chainNotFound: (chainId: number | bigint) => createError(ERROR_CODES.CHAIN_NOT_FOUND, `Chain not found: ${chainId}`, { details: { chainId }, }), - + chainDataNotFound: (chainId: number | bigint) => + createError(ERROR_CODES.CHAIN_DATA_NOT_FOUND, `Chain data not found for chain: ${chainId}`, { + details: { chainId }, + }), + assetNotFound: (tokenSymbol: string) => + createError(ERROR_CODES.ASSET_NOT_FOUND, `Asset not found in UserAssets: ${tokenSymbol}`, { + details: { tokenSymbol }, + }), internal: (msg: string, details?: Record) => createError(ERROR_CODES.INTERNAL_ERROR, `Internal error: ${msg}`, { details, }), - - tokenNotSupported: (address: string, chainId: number) => + tokenNotSupported: (address?: string, chainId?: number, additionalMessage?: string) => createError( ERROR_CODES.TOKEN_NOT_SUPPORTED, - `Token with address ${address} is not supported on chain ${chainId}`, + `Token/Asset with address ${address} is not supported on chain ${chainId}.\n${additionalMessage}`, { details: { address, chainId }, }, ), - + universeNotSupported: () => + createError(ERROR_CODES.UNIVERSE_NOT_SUPPORTED, 'Universe not supported'), tokenNotFound: (symbol: string, chainId: number) => createError( ERROR_CODES.TOKEN_NOT_SUPPORTED, @@ -83,13 +101,22 @@ export const Errors = { }, }), - cosmosError: (msg: string) => createError(ERROR_CODES.INTERNAL_ERROR, `COSMOS: ${msg}`), + cosmosError: (msg: string) => createError(ERROR_CODES.COSMOS_ERROR, `COSMOS: ${msg}`), gasPriceError: (result: unknown) => createError(ERROR_CODES.FETCH_GAS_PRICE_FAILED, `rpc: estimateMaxFeePerGas failed`, { details: { result, }, }), + unknownSignatureType: () => createError(ERROR_CODES.UNKNOWN_SIGNATURE, 'Unknown signature type'), + quoteFailed: (message: string) => + createError(ERROR_CODES.QUOTE_FAILED, `Quote failed: ${message}`), + swapFailed: (message: string) => createError(ERROR_CODES.SWAP_FAILED, `Swap failed: ${message}`), + ratesChangedBeyondTolerance: (rate: number | bigint, tolerance: number | bigint) => + createError( + ERROR_CODES.RATES_CHANGED_BEYOND_TOLERANCE, + `Rates changed beyond tolerance. Rate: ${rate}\nTolerance:${tolerance}`, + ), slippageError: (msg: string) => createError(ERROR_CODES.SLIPPAGE_EXCEEDED_ALLOWANCE, `rpc: slippage exceeded - ${msg}`), vaultContractNotFound: (chainId: number | bigint) => @@ -100,7 +127,25 @@ export const Errors = { simulationError: (msg: string) => createError(ERROR_CODES.SIMULATION_FAILED, `tenderly simulation failed: ${msg}`), rFFFeeExpired: () => createError(ERROR_CODES.RFF_FEE_EXPIRED, `fee is not adequate`), + destinationRequestHashNotFound: () => + createError( + ERROR_CODES.DESTINATION_REQUEST_HASH_NOT_FOUND, + 'requestHash not found for destination', + ), + transactionTimeout: (timeout: number) => + createError( + ERROR_CODES.TRANSACTION_TIMEOUT, + `⏰ Timeout: Transaction not confirmed within ${timeout}s`, + ), + transactionReverted: (txHash: string) => + createError(ERROR_CODES.TRANSACTION_REVERTED, `Transaction reverted: ${txHash}`), invalidInput: (msg: string) => createError(ERROR_CODES.INVALID_INPUT, `input invalid: ${msg}`), + invalidAddressLength: (addressType: string, additionalMessage?: string) => + createError( + ERROR_CODES.INVALID_ADDRESS_LENGTH, + `Invalid ${addressType} address length: ${additionalMessage}`, + { details: { type: addressType } }, + ), noBalanceForAddress: (address: Hex) => { createError(ERROR_CODES.NO_BALANCE_FOR_ADDRESS, `no balance found for user: ${address}`); }, diff --git a/src/sdk/ca-base/nexusError.ts b/src/sdk/ca-base/nexusError.ts index ca74399d..4092b90f 100644 --- a/src/sdk/ca-base/nexusError.ts +++ b/src/sdk/ca-base/nexusError.ts @@ -31,9 +31,18 @@ export class NexusError extends Error { export const ERROR_CODES = { INVALID_VALUES_ALLOWANCE_HOOK: 'INVALID_VALUES_ALLOWANCE_HOOK', SDK_NOT_INITIALIZED: 'SDK_NOT_INITIALIZED', + SDK_INIT_STATE_NOT_EXPECTED: 'SDK_INIT_STATE_NOT_EXPECTED', CHAIN_NOT_FOUND: 'CHAIN_NOT_FOUND', + CHAIN_DATA_NOT_FOUND: 'CHAIN_DATA_NOT_FOUND', + RATES_CHANGED_BEYOND_TOLERANCE: 'RATES_CHANGED_BEYOND_TOLERANCE', + ASSET_NOT_FOUND: 'ASSET_NOT_FOUND', + COSMOS_ERROR: 'COSMOS_ERROR', INTERNAL_ERROR: 'INTERNAL_ERROR', TOKEN_NOT_SUPPORTED: 'TOKEN_NOT_SUPPORTED', + UNIVERSE_NOT_SUPPORTED: 'UNIVERSE_NOT_SUPPORTED', + ENVIRONMENT_NOT_SUPPORTED: 'ENVIRONMENT_NOT_SUPPORTED', + ENVIRONMENT_NOT_KNOWN: 'ENVIRONMENT_NOT_KNOWN', + UNKNOWN_SIGNATURE: 'UNKNOWN_SIGNATURE', TRON_DEPOSIT_FAIL: 'TRON_DEPOSIT_FAIL', TRON_APPROVAL_FAIL: 'TRON_APPROVAL_FAIL', FUEL_DEPOSIT_FAIL: 'FUEL_DEPOSIT_FAIL', @@ -42,16 +51,28 @@ export const ERROR_CODES = { USER_DENIED_ALLOWANCE: 'USER_DENIED_ALLOWANCE', USER_DENIED_INTENT_SIGNATURE: 'USER_DENIED_INTENT_SIGNATURE', INSUFFICIENT_BALANCE: 'INSUFFICIENT_BALANCE', + REFUND_FAILED: 'REFUND_FAILED', WALLET_NOT_CONNECTED: 'WALLET_NOT_CONNECTED', USER_DENIED_SIWE_SIGNATURE: 'USER_DENIED_SIWE_SIGNATURE', FETCH_GAS_PRICE_FAILED: 'FETCH_GAS_PRICE_FAILED', SIMULATION_FAILED: 'SIMULATION_FAILED', + QUOTE_FAILED: 'QUOTE_FAILED', + SWAP_FAILED: 'SWAP_FAILED', CONNECT_ACCOUNT_FAILED: 'CONNECT_ACCOUNT_FAILED', VAULT_CONTRACT_NOT_FOUND: 'VAULT_CONTRACT_NOT_FOUND', SLIPPAGE_EXCEEDED_ALLOWANCE: 'SLIPPAGE_EXCEEDED_ALLOWANCE', + ALLOWANCE_SETTING_ERROR: 'ALLOWANCE_SETTING_ERROR', + REFUND_CHECK_ERROR: 'REFUND_CHECK_ERROR', + DESTINATION_REQUEST_HASH_NOT_FOUND: 'DESTINATION_REQUEST_HASH_NOT_FOUND', + DESTINATION_SWEEP_ERROR: 'DESTINATION_SWEEP_ERROR', RFF_FEE_EXPIRED: 'RFF_FEE_EXPIRED', + FEE_GRANT_REQUESTED: 'FEE_GRANT_REQUESTED', INVALID_INPUT: 'INVALID_INPUT', + INVALID_ADDRESS_LENGTH: 'INVALID_ADDRESS_LENGTH', NO_BALANCE_FOR_ADDRESS: 'NO_BALANCE_FOR_ADDRESS', + TRANSACTION_TIMEOUT: 'TRANSACTION_TIMEOUT', + TRANSACTION_REVERTED: 'TRANSACTION_REVERTED', + TRANSACTION_CHECK_ERROR: 'TRANSACTION_CHECK_ERROR', } as const; export type ErrorCode = (typeof ERROR_CODES)[keyof typeof ERROR_CODES]; diff --git a/src/sdk/ca-base/requestHandlers/bridge.ts b/src/sdk/ca-base/requestHandlers/bridge.ts index 38766553..8cbedebb 100644 --- a/src/sdk/ca-base/requestHandlers/bridge.ts +++ b/src/sdk/ca-base/requestHandlers/bridge.ts @@ -603,7 +603,7 @@ class BridgeHandler { ); if (!destinationSigData) { - throw new Error('requestHash not found for destination'); + throw Errors.destinationRequestHashNotFound(); } return { @@ -804,7 +804,7 @@ class BridgeHandler { } this.markStepDone(BRIDGE_STEPS.ALLOWANCE_COMPLETE); } catch (e) { - logger.error('Error setting allowances', e); + logger.error('Error setting allowances', e, {cause: 'ALLOWANCE_SETTING_ERROR'}); throw e; } finally { if (this.params.dstChain.universe === Universe.ETHEREUM) { @@ -911,7 +911,7 @@ class BridgeHandler { const asset = assets.find(token.symbol); if (!asset) { - throw new Error(`Asset ${token.symbol} not found in UserAssets`); + throw Errors.assetNotFound(token.symbol); } const allSources = (await asset.iterate(this.options.chainList)).map((v) => { diff --git a/src/sdk/ca-base/swap/data.ts b/src/sdk/ca-base/swap/data.ts index 84447263..59b1a19c 100644 --- a/src/sdk/ca-base/swap/data.ts +++ b/src/sdk/ca-base/swap/data.ts @@ -7,6 +7,7 @@ import { TokenInfo } from '../../../commons'; import { convertTo32BytesHex, equalFold } from '../utils'; import { EADDRESS } from './constants'; import { convertToEVMAddress, determinePermitVariantAndVersion } from './utils'; +import { Errors } from '../errors'; export enum CurrencyID { USDC = 0x1, @@ -421,11 +422,11 @@ const getTokenVersion = async (tokenAddress: Hex, client: PublicClient) => { export const getTokenDecimals = (chainID: number | string, contractAddress: Bytes) => { const cData = chainData.get(Number(chainID)); if (!cData) { - throw new Error(`chain data not found for chain: ${chainID}`); + throw Errors.chainDataNotFound(Number(chainID)); } const token = cData.find((c) => equalFold(toHex(contractAddress), c.TokenContractAddress)); if (!token) { - throw new Error(`token not found: ${toHex(contractAddress)}`); + throw Errors.assetNotFound(toHex(contractAddress)); } return { decimals: token.TokenDecimals, diff --git a/src/sdk/ca-base/swap/ob.ts b/src/sdk/ca-base/swap/ob.ts index 73badb50..3c638bac 100644 --- a/src/sdk/ca-base/swap/ob.ts +++ b/src/sdk/ca-base/swap/ob.ts @@ -378,9 +378,13 @@ class DestinationSwapHandler { try { await this.executeSwap(metadata); } catch (retryError) { - logger.error('Destination swap failed even after retry.', { - error: (retryError as Error)?.message ?? retryError, - }); + logger.error( + 'Destination swap failed even after retry.', + { + error: (retryError as Error)?.message ?? retryError, + }, + { cause: 'SWAP_FAILED' }, + ); throw retryError; } } @@ -501,7 +505,7 @@ class DestinationSwapHandler { logger.debug('Requoting destination swap...'); const newSwap = await this.data.fetchDestinationSwapDetails(); if (!newSwap.quote) { - throw new Error('Failed to requote destination swap.'); + throw Errors.quoteFailed('Failed to requote destination swap.'); } const isExactIn = this.data.type === 'EXACT_IN'; @@ -524,9 +528,9 @@ class DestinationSwapHandler { newSwap.inputAmount.min.lte(swap.inputAmount.max) ) ) { - throw new Error( - `Rates changed beyond tolerance. Tolerance: ${swap.inputAmount.min.toFixed()}-${swap.inputAmount.max.toFixed()}, After: ${newSwap.inputAmount.min.toFixed()}`, - ); + const rate = swap.inputAmount.min.toNumber(); + const tolerance = swap.inputAmount.min.toNumber() - swap.inputAmount.max.toNumber(); + throw Errors.ratesChangedBeyondTolerance(rate, tolerance); } this.data = { @@ -861,10 +865,10 @@ class SourceSwapsHandler { } catch { // TODO: What to do here? Store it or something? } - throw new Error('source swap failed'); + throw Errors.swapFailed('source swap failed'); } } else { - throw new Error('some source swap failed even after retry'); + throw Errors.swapFailed('some source swap failed even after retry'); } } diff --git a/src/sdk/ca-base/swap/rff.ts b/src/sdk/ca-base/swap/rff.ts index 8c6b973a..3c4b1534 100644 --- a/src/sdk/ca-base/swap/rff.ts +++ b/src/sdk/ca-base/swap/rff.ts @@ -324,7 +324,7 @@ export const createBridgeRFF = async ({ for (const [index, source] of sources.entries()) { const evmSignatureData = signatureData.find((s) => s.universe === Universe.ETHEREUM); if (!evmSignatureData) { - throw new Error('Unknown signature type'); + throw Errors.unknownSignatureType(); } const chain = config.chainList.getChainByID(Number(source.chainID)); @@ -335,7 +335,7 @@ export const createBridgeRFF = async ({ const allowance = allowances[Number(source.chainID)]; logger.debug('allowances', { allowance, chainID: Number(source.chainID) }); if (allowance == null) { - throw new Error('Allowance not applicable'); + throw Errors.internal('Allowance not applicable'); } const tx: Tx[] = []; @@ -387,7 +387,7 @@ export const createBridgeRFF = async ({ const waitForFill = () => { const s = signatureData.find((s) => s.universe === Universe.ETHEREUM); if (!s) { - throw new Error('Unknown signature type'); + throw Errors.unknownSignatureType(); } logger.debug(`Waiting for fill: ${intentID}`); diff --git a/src/sdk/ca-base/swap/route.ts b/src/sdk/ca-base/swap/route.ts index 9149eac8..4f9cda1a 100644 --- a/src/sdk/ca-base/swap/route.ts +++ b/src/sdk/ca-base/swap/route.ts @@ -534,7 +534,7 @@ const _exactInRoute = async ( }), fetchPriceOracle(params.networkConfig.GRPC_URL), ]).catch((e) => { - throw new Error('Error fetching fee, balance or oracle', { cause: e }); + throw Errors.internal('Error fetching fee, balance or oracle', { cause: e }); }); if (balanceResponse.balances.length === 0) { @@ -679,7 +679,7 @@ const _exactInRoute = async ( ); if (!response.quotes.length) { - throw new Error('source swap returned no quotes'); + throw Errors.quoteFailed('source swap returned no quotes'); } sourceSwaps = response.quotes.map((oq) => { @@ -756,7 +756,7 @@ const _exactInRoute = async ( maxFee: maxFee.toFixed(), }); if (dstSwapInputAmountInDecimal.isNegative()) { - throw new Error('bridge fees exceeds source amount'); + throw Errors.internal('bridge fees exceeds source amount'); } bridgeInput = { diff --git a/src/sdk/ca-base/swap/swap.ts b/src/sdk/ca-base/swap/swap.ts index 2a428845..67ac5c36 100644 --- a/src/sdk/ca-base/swap/swap.ts +++ b/src/sdk/ca-base/swap/swap.ts @@ -226,7 +226,7 @@ export const swap = async ( }); logger.debug('SwapID', { id }); } catch (e) { - logger.error('postSwap', e); + logger.error('postSwap', e, {cause: 'SWAP_FAILED'}); } calculatePerformance(); diff --git a/src/sdk/ca-base/swap/utils.ts b/src/sdk/ca-base/swap/utils.ts index caf77262..6fa434df 100644 --- a/src/sdk/ca-base/swap/utils.ts +++ b/src/sdk/ca-base/swap/utils.ts @@ -108,7 +108,7 @@ export const convertToEVMAddress = (address: Hex | Uint8Array) => { return toHex(address.subarray(12)); } - throw new Error('Invalid address'); + throw Errors.invalidAddressLength('evm'); }; export const bytesEqual = (bytes1: Uint8Array, bytes2: Uint8Array): boolean => { @@ -257,7 +257,7 @@ export const createPermitSignature = async ( }; } default: { - throw new Error('Token Not supported: (2612 details not found)'); + throw Errors.tokenNotSupported(undefined, undefined, '(2612 details not found)'); } } }; @@ -282,7 +282,7 @@ export const vscSBCTx = async (input: SBCTx[], vscDomain: string) => { logger.debug('vscSBCTx', { data }); if (data.errored) { - throw new Error('Error in VSC SBC Tx'); + throw Errors.internal('Error in VSC SBC Tx'); } ops.push([bytesToBigInt(input[data.part_idx].chain_id), toHex(data.tx_hash)]); @@ -570,7 +570,7 @@ export const createPermitApprovalTx = async ({ const { r, s, v } = parseSignature(signature); if (!v) { - throw new Error('invalid signature: v is not present'); + throw Errors.internal('invalid signature: v is not present'); } return { @@ -633,7 +633,7 @@ export const getAnkrBalances = async ( walletAddress: walletAddress, }, }); - if (!res.data?.result) throw new Error('balances cannot be retrieved'); + if (!res.data?.result) throw Errors.internal('balances cannot be retrieved'); const filteredAssets = res.data.result.assets.filter( (asset) => @@ -1168,7 +1168,7 @@ export const parseQuote = ( return val; } - throw new Error('Unknown aggregator'); + throw Errors.internal('Unknown aggregator'); }; /** @@ -1484,7 +1484,7 @@ export const createSweeperTxs = ({ )!.Currencies.find((c) => c.currencyID === COTCurrencyID); if (!currency) { - throw new Error(`cot not found on chain ${chainID}`); + throw Errors.internal(`cot not found on chain ${chainID}`); } tokenAddress = convertToEVMAddress(currency.tokenAddress); @@ -1615,7 +1615,7 @@ export const performDestinationSwap = async ({ }, 2); return hash; } catch (e) { - logger.error('destination swap failed twice, sweeping to eoa', e); + logger.error('destination swap failed twice, sweeping to eoa', e, {cause: 'SWAP_FAILED'}); await vscSBCTx( [ await createSBCTxFromCalls({ @@ -1635,7 +1635,7 @@ export const performDestinationSwap = async ({ ], vscDomain, ).catch((e) => { - logger.error('error during destination sweep', e); + logger.error('error during destination sweep', e, {cause: 'DESTINATION_SWEEP_ERROR'}); }); throw e; } diff --git a/src/sdk/ca-base/utils/api.utils.ts b/src/sdk/ca-base/utils/api.utils.ts index e1cfe58c..830ec5ab 100644 --- a/src/sdk/ca-base/utils/api.utils.ts +++ b/src/sdk/ca-base/utils/api.utils.ts @@ -59,7 +59,7 @@ async function fetchMyIntents(address: string, grpcURL: string, page = 1) { return response.requestForFunds; } catch (error) { logger.error('Failed to fetch intents', error); - throw new Error('Failed to fetch intents'); + throw Errors.cosmosError('Failed to fetch intents'); } } @@ -138,7 +138,7 @@ async function fetchProtocolFees(grpcURL: string) { return response; } catch (error) { logger.error('Failed to fetch protocol fees', error); - throw new Error('Failed to fetch protocol fees'); + throw Errors.cosmosError('Failed to fetch protocol fees'); } } @@ -148,7 +148,7 @@ async function fetchSolverData(grpcURL: string) { return response; } catch (error) { logger.error('Failed to fetch solver data', error); - throw new Error('Failed to fetch solver data'); + throw Errors.cosmosError('Failed to fetch solver data'); } } @@ -165,7 +165,7 @@ const fetchPriceOracle = async (grpcURL: string) => { })); return oracleRates; } - throw new Error('InternalError: No price data found.'); + throw Errors.internal('No price data found.'); }; const coinbasePrices = { @@ -184,10 +184,10 @@ const getCoinbasePrices = async () => { coinbasePrices.rates = exchange.data.data.rates; coinbasePrices.lastUpdatedAt = Date.now(); } catch (error) { - logger.error('Failed to fetch Coinbase prices', error); + logger.error('Failed to fetch Coinbase prices', error, {cause: 'INTERNAL_ERROR'}); // Return cached rates if available, otherwise throw if (Object.keys(coinbasePrices.rates).length === 0) { - throw new Error('Failed to fetch exchange rates and no cache available'); + throw Errors.internal('Failed to fetch exchange rates and no cache available'); } } } @@ -584,7 +584,7 @@ const checkIntentFilled = async (intentID: Long, grpcURL: string) => { return 'ok'; } - throw new Error('not filled yet'); + throw Errors.internal('not filled yet'); }; export { diff --git a/src/sdk/ca-base/utils/common.utils.ts b/src/sdk/ca-base/utils/common.utils.ts index 8a391237..7ad33b4c 100644 --- a/src/sdk/ca-base/utils/common.utils.ts +++ b/src/sdk/ca-base/utils/common.utils.ts @@ -75,7 +75,7 @@ function convertAddressByUniverse(input: ByteArray | Hex, universe: Universe) { return inputIsString ? toHex(bytes.subarray(12)) : bytes.subarray(12); } - throw new Error('invalid length of input'); + throw Errors.invalidAddressLength('evm|tron'); } if (universe === Universe.FUEL) { @@ -90,7 +90,7 @@ function convertAddressByUniverse(input: ByteArray | Hex, universe: Universe) { return inputIsString ? toHex(padded) : padded; } - throw new Error('invalid length of input'); + throw Errors.invalidAddressLength('fuel'); } return toHex(input); @@ -197,7 +197,7 @@ const createRequestFuelSignature = async ( ) => { const account = await connector.currentAccount(); if (!account) { - throw new Error('Fuel connector is not connected.'); + throw Errors.internal('Fuel connector is not connected.'); } const vault = new ArcanaVault(hexlify(fuelVaultAddress), provider); @@ -422,7 +422,7 @@ const convertGasToToken = ( ?.priceUsd.toFixed(); if (!transferTokenInUSD) { - throw new Error('could not find token in price oracle'); + throw Errors.internal('could not find token in price oracle'); } const usdValue = gas.mul(gasTokenInUSD); @@ -475,21 +475,21 @@ const convertToHexAddressByUniverse = (address: Uint8Array, universe: Universe) if (address.length === 32) { return bytesToHex(address); } else { - throw new Error('fuel: invalid address length'); + throw Errors.invalidAddressLength('fuel'); } } else if (universe === Universe.ETHEREUM || universe === Universe.TRON) { if (address.length === 20) { return bytesToHex(address); } else if (address.length === 32) { if (!address.subarray(0, 12).every((b) => b === 0)) { - throw new Error('evm: non-zero-padded 32-byte address'); + throw Errors.invalidAddressLength('evm', 'non-zero-padded 32-byte address'); } return bytesToHex(address.subarray(12)); } else { - throw new Error('evm: invalid address length'); + throw Errors.invalidAddressLength('evm'); } } else { - throw new Error('unsupported universe'); + throw Errors.universeNotSupported(); } }; @@ -634,7 +634,7 @@ class UserAssets { return new UserAsset(asset); } } - throw new Error('Asset is not supported.'); + throw Errors.tokenNotSupported(); } findOnChain(chainID: number, address: `0x${string}`) { @@ -725,13 +725,13 @@ async function waitForTronTxConfirmation( if (txInfo?.receipt) { const result = txInfo.receipt.result; if (result === 'FAILED') { - throw new Error(`❌ Transaction reverted: ${txid}`); + throw Errors.transactionReverted(txid); } else { return txInfo; } } } catch (err) { - logger.error(`⚠️ Error while checking transaction:`, err); + logger.error(`⚠️ Error while checking transaction:`, err, {cause: 'TRANSACTION_CHECK_ERROR'}); // Don’t throw yet; continue polling } @@ -739,7 +739,7 @@ async function waitForTronTxConfirmation( await new Promise((resolve) => setTimeout(resolve, interval)); } - throw new Error(`⏰ Timeout: Transaction not confirmed within ${timeout / 1000}s`); + throw Errors.transactionTimeout((timeout / 1000)); } async function waitForTronDepositTxConfirmation( @@ -776,17 +776,17 @@ async function waitForTronDepositTxConfirmation( result, }); if (result.Error) { - throw new Error(result.Error); + throw Errors.internal(result.Error); } const requestState = bytesToNumber(result.constant_result[0]); if (requestState === 0) { - throw new Error('Request not witnessed yet.'); + throw Errors.internal('Request not witnessed yet.'); } return; } catch (err) { - logger.error(`⚠️ Error while checking transaction:`, err); + logger.error(`⚠️ Error while checking transaction:`, err, {cause: 'TRANSACTION_CHECK_ERROR'}); // Don’t throw yet; continue polling } @@ -794,7 +794,7 @@ async function waitForTronDepositTxConfirmation( await new Promise((resolve) => setTimeout(resolve, interval)); } - throw new Error(`⏰ Timeout: Transaction not confirmed within ${timeout / 1000}s`); + throw Errors.transactionTimeout((timeout / 1000)); } function pctAdditionToBigInt(base: bigint, percentage: number) { @@ -846,17 +846,17 @@ async function waitForTronApprovalTxConfirmation( }); if (result.Error) { - throw new Error(result.Error); + throw Errors.internal(result.Error); } const allowance = hexToBigInt(`0x${result.constant_result[0]}`); if (allowance < amount) { - throw new Error('Allowance not set yet.'); + throw Errors.internal('Allowance not set yet.'); } return; } catch (err) { - logger.error(`⚠️ Error while checking transaction:`, err); + logger.error(`⚠️ Error while checking transaction:`, err, {cause: 'TRANSACTION_CHECK_ERROR'}); // Don’t throw yet; continue polling } @@ -864,7 +864,7 @@ async function waitForTronApprovalTxConfirmation( await new Promise((resolve) => setTimeout(resolve, interval)); } - throw new Error(`⏰ Timeout: Transaction not confirmed within ${timeout / 1000}s`); + throw Errors.transactionTimeout((timeout / 1000)); } const createExplorerTxURL = (txHash: Hex, explorerURL: string) => { diff --git a/src/sdk/ca-base/utils/contract.utils.ts b/src/sdk/ca-base/utils/contract.utils.ts index b55ab717..0ff38feb 100644 --- a/src/sdk/ca-base/utils/contract.utils.ts +++ b/src/sdk/ca-base/utils/contract.utils.ts @@ -217,7 +217,7 @@ const waitForTxReceipt = async ( timeout, }); if (r.status === 'reverted') { - throw new Error(`Transaction reverted: ${hash}`); + throw Errors.transactionReverted(hash); } return r; diff --git a/src/sdk/ca-base/utils/cosmos.utils.ts b/src/sdk/ca-base/utils/cosmos.utils.ts index 0a98a5fa..c6aca9ff 100644 --- a/src/sdk/ca-base/utils/cosmos.utils.ts +++ b/src/sdk/ca-base/utils/cosmos.utils.ts @@ -31,7 +31,7 @@ const cosmosFeeGrant = async (cosmosURL: string, vscDomain: string, address: str baseURL: getCosmosURL(cosmosURL, 'rest'), }); } catch (e) { - logger.error('Requesting a fee grant', e); + logger.error('Requesting a fee grant', e, {cause: 'FEE_GRANT_REQUESTED'}); const response = await vscCreateFeeGrant(vscDomain, address); logger.debug('Fee grant response', response.data); return; @@ -122,7 +122,7 @@ const cosmosRefundIntent = async ( throw Errors.cosmosError(`unknown error: ${JSON.stringify(resp)}`); } } catch (e) { - logger.error('Refund failed', e); + logger.error('Refund failed', e, {cause: 'REFUND_FAILED'}); throw e; } } finally { @@ -232,7 +232,7 @@ const waitForCosmosFillEvent = async (intentID: Long, cosmosURL: string, ac: Abo } } - throw new Error('waitForCosmosFillEvent: out of loop but no events'); + throw Errors.cosmosError('waitForCosmosFillEvent: out of loop but no events'); } finally { connection.close(); } diff --git a/src/sdk/ca-base/utils/tron.utils.ts b/src/sdk/ca-base/utils/tron.utils.ts index c2b95ac3..420225c1 100644 --- a/src/sdk/ca-base/utils/tron.utils.ts +++ b/src/sdk/ca-base/utils/tron.utils.ts @@ -1,11 +1,12 @@ import { Hex } from 'viem'; +import { Errors } from '../errors'; function tronHexToEvmAddress(tronHex: string): Hex { const normalized = tronHex.toLowerCase().replace(/^0x/, ''); // Validate length and prefix if (!/^41[a-f0-9]{40}$/.test(normalized)) { - throw new Error(`Invalid TRON hex address: ${tronHex}`); + throw Errors.internal(`Invalid TRON hex address: ${tronHex}`); } // Extract last 20 bytes (40 hex chars) and return as EVM address From 6990cc6d705ea6ff3cedb003f28efc15854cf27e Mon Sep 17 00:00:00 2001 From: Abhishek Date: Tue, 25 Nov 2025 09:18:04 +0400 Subject: [PATCH 43/51] feat: add monad mainnet chain & token details (#110) * feat: add monad mainnet chain & token details * fix: updated ca-common version * fix: buffer for gas changed for monad to 30%, removed balance caching for now, updated gas set for transfer * feat: added monad metadata * fix: updated gasPrice to be baseFee + 5*maxPriorityFee --------- Co-authored-by: decocereus --- package-lock.json | 12 ++-- package.json | 4 +- src/commons/constants/index.ts | 12 +++- src/sdk/ca-base/chains.ts | 36 ++++++++++ src/sdk/ca-base/query/bridgeAndExecute.ts | 15 ++--- src/sdk/ca-base/query/bridgeAndTransfer.ts | 2 +- src/sdk/ca-base/utils/balance.utils.ts | 77 ++++++---------------- src/sdk/ca-base/utils/contract.utils.ts | 10 +-- 8 files changed, 89 insertions(+), 79 deletions(-) diff --git a/package-lock.json b/package-lock.json index 77ef7eb8..362e9654 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,15 +1,15 @@ { "name": "@avail-project/nexus-core", - "version": "1.0.0-beta.44", + "version": "1.0.0-beta.46", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@avail-project/nexus-core", - "version": "1.0.0-beta.44", + "version": "1.0.0-beta.46", "license": "MIT", "dependencies": { - "@avail-project/ca-common": "1.0.0-dev.3", + "@avail-project/ca-common": "1.0.0-dev.4", "@cosmjs/proto-signing": "^0.34.0", "@cosmjs/stargate": "^0.34.0", "@metamask/safe-event-emitter": "3.1.2", @@ -54,9 +54,9 @@ "license": "MIT" }, "node_modules/@avail-project/ca-common": { - "version": "1.0.0-dev.3", - "resolved": "https://registry.npmjs.org/@avail-project/ca-common/-/ca-common-1.0.0-dev.3.tgz", - "integrity": "sha512-uayZmtX04P99aLy+rGIsDX6BmImOH5HBAajZvf/SKJbIDqz6bG0AFEvybGfvEOCZNpajXA/sFOtTfitTDiQocA==", + "version": "1.0.0-dev.4", + "resolved": "https://registry.npmjs.org/@avail-project/ca-common/-/ca-common-1.0.0-dev.4.tgz", + "integrity": "sha512-EG7BP4o6f1juSHIzxOO/X4AzWO+pnvI177gg0hbfyYV8eSFsWOm5L/PPKk7FCE20YGinS/R21R/F8r2q3Tgcdg==", "license": "MIT", "dependencies": { "@bufbuild/protobuf": "^2.6.0", diff --git a/package.json b/package.json index 577090b5..460982c7 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@avail-project/nexus-core", - "version": "1.0.0-beta.46", + "version": "1.0.0-beta.50", "description": "Nexus headless SDK for cross-chain transactions", "main": "./dist/index.js", "module": "./dist/index.esm.js", @@ -40,7 +40,7 @@ "author": "decocereus, makyl", "license": "MIT", "dependencies": { - "@avail-project/ca-common": "1.0.0-dev.3", + "@avail-project/ca-common": "1.0.0-dev.4", "@cosmjs/proto-signing": "^0.34.0", "@cosmjs/stargate": "^0.34.0", "@metamask/safe-event-emitter": "3.1.2", diff --git a/src/commons/constants/index.ts b/src/commons/constants/index.ts index 3562d258..bccb9b0b 100644 --- a/src/commons/constants/index.ts +++ b/src/commons/constants/index.ts @@ -81,6 +81,15 @@ export const CHAIN_METADATA: Record = { rpcUrls: ['https://eth.merkle.io'], blockExplorerUrls: ['https://etherscan.io'], }, + [SUPPORTED_CHAINS.MONAD]: { + id: SUPPORTED_CHAINS.MONAD, + name: 'Monad', + shortName: 'monad', + logo: 'https://assets.coingecko.com/coins/images/38927/large/monad.jpg', + nativeCurrency: { name: 'Monad', symbol: 'MON', decimals: 18 }, + rpcUrls: ['https://rpcs.avail.so/monad'], + blockExplorerUrls: ['https://monadvision.com'], + }, [SUPPORTED_CHAINS.BASE]: { id: SUPPORTED_CHAINS.BASE, name: 'Base', @@ -291,7 +300,8 @@ export const TOKEN_CONTRACT_ADDRESSES = { [SUPPORTED_CHAINS.AVALANCHE]: '0xb97ef9ef8734c71904d8002f8b6bc66dd9c48a6e', [SUPPORTED_CHAINS.BNB]: '0x8AC76a51cc950d9822D68b83fE1Ad97B32Cd580d', [SUPPORTED_CHAINS.HYPEREVM]: '0xb88339CB7199b77E23DB6E890353E22632Ba630f', - // testnet chains + [SUPPORTED_CHAINS.MONAD]: '0x754704Bc059F8C67012fEd69BC8A327a5aafb603', + // Testnet chains [SUPPORTED_CHAINS.SEPOLIA]: '0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238', // [SUPPORTED_CHAINS.VALIDIUM_TESTNET]: '0x8Cf5f629Bb26FC3F92144e72bC4A3719A7DF07F3', [SUPPORTED_CHAINS.BASE_SEPOLIA]: '0x036CbD53842c5426634e7929541eC2318f3dCF7e', diff --git a/src/sdk/ca-base/chains.ts b/src/sdk/ca-base/chains.ts index df9aff36..58dc00dc 100644 --- a/src/sdk/ca-base/chains.ts +++ b/src/sdk/ca-base/chains.ts @@ -651,6 +651,42 @@ const MAINNET_CHAINS: Chain[] = [ }, universe: Universe.ETHEREUM, }, + { + blockExplorers: { + default: { + name: 'Monad Vision', + url: 'https://monadvision.com', + }, + }, + custom: { + icon: 'https://assets.coingecko.com/coins/images/38927/large/monad.jpg', + knownTokens: [ + { + contractAddress: TOKEN_CONTRACT_ADDRESSES['USDC'][SUPPORTED_CHAINS.MONAD], + decimals: 6, + logo: getLogoFromSymbol('USDC'), + name: 'USD Coin', + symbol: 'USDC', + }, + ], + }, + id: SUPPORTED_CHAINS.MONAD, + name: 'Monad', + ankrName: '', + nativeCurrency: { + decimals: 18, + name: 'Monad', + symbol: 'MON', + }, + rpcUrls: { + default: { + http: ['https://rpcs.avail.so/monad'], + publicHttp: [], + webSocket: ['wss://rpcs.avail.so/monad'], + }, + }, + universe: Universe.ETHEREUM, + }, { blockExplorers: { default: { diff --git a/src/sdk/ca-base/query/bridgeAndExecute.ts b/src/sdk/ca-base/query/bridgeAndExecute.ts index a6399a4c..d343cf97 100644 --- a/src/sdk/ca-base/query/bridgeAndExecute.ts +++ b/src/sdk/ca-base/query/bridgeAndExecute.ts @@ -40,7 +40,7 @@ import { erc20GetAllowance, pctAdditionToBigInt, getL1Fee, - divideBigInt, + // divideBigInt, getPctGasBufferByChain, } from '../utils'; import { packERC20Approve } from '../swap/utils'; @@ -137,7 +137,7 @@ class BridgeAndExecuteQuery { ), ]); - // gasLimit = 1.3 * gasUsed for each (1.05 for monad) + // gasLimit = 1.3 * gasUsed (30% buffer) const pctBuffer = getPctGasBufferByChain(dstChain.id); const approvalGas = pctAdditionToBigInt(gasUsed.approvalGas, pctBuffer); const txGas = pctAdditionToBigInt(gasUsed.txGas, pctBuffer); @@ -149,13 +149,12 @@ class BridgeAndExecuteQuery { }); } - // gasPrice = (maxFeePerGas + 0.5 * maxPriorityFeePerGas) - gasPrice += divideBigInt( - gasFeeEstimate.maxPriorityFeePerGas === 0n + // Giving more is not an issue since it will be refunded - other than monad + // gasPrice = (baseFee + 5 * maxPriorityFeePerGas) + gasPrice += + (gasFeeEstimate.maxPriorityFeePerGas === 0n ? parseGwei('2') - : gasFeeEstimate.maxPriorityFeePerGas, - 2, - ); + : gasFeeEstimate.maxPriorityFeePerGas) * 4n; const gasFee = (approvalGas + txGas) * gasPrice + l1Fee; diff --git a/src/sdk/ca-base/query/bridgeAndTransfer.ts b/src/sdk/ca-base/query/bridgeAndTransfer.ts index 3672cb31..7c86876d 100644 --- a/src/sdk/ca-base/query/bridgeAndTransfer.ts +++ b/src/sdk/ca-base/query/bridgeAndTransfer.ts @@ -27,7 +27,7 @@ const createBridgeAndTransferParams = ( functionName: 'transfer', args: [input.recipient, input.amount], }), - gas: 63_000n, + gas: 80_000n, }; return { diff --git a/src/sdk/ca-base/utils/balance.utils.ts b/src/sdk/ca-base/utils/balance.utils.ts index c63b3d28..514f19c9 100644 --- a/src/sdk/ca-base/utils/balance.utils.ts +++ b/src/sdk/ca-base/utils/balance.utils.ts @@ -1,39 +1,15 @@ import { Environment } from '@avail-project/ca-common'; -import { ChainListType, logger, SUPPORTED_CHAINS, UserAssetDatum } from '../../../commons'; +import { ChainListType, logger, SUPPORTED_CHAINS } from '../../../commons'; import { equalFold, getEVMBalancesForAddress, getFuelBalancesForAddress, getTronBalancesForAddress, - minutesToMs, } from '.'; import { encodePacked, Hex, keccak256, pad, toHex } from 'viem'; import { balancesToAssets, getAnkrBalances, toFlatBalance } from '../swap/utils'; import { filterSupportedTokens } from '../swap/data'; -const getKeyForStorage = ({ - evmAddress, - fuelAddress, - tronAddress, -}: { - evmAddress: Hex; - fuelAddress?: string; - tronAddress?: string; -}) => { - let key = evmAddress; - if (fuelAddress) { - key += `:${fuelAddress}`; - } - if (tronAddress) { - key += `:${tronAddress}`; - } - return key; -}; - -let balanceCache = { - value: {} as { [k: string]: { data: UserAssetDatum[]; lastUpdatedAt: number } }, -}; - export const getBalancesForSwap = async (input: { evmAddress: Hex; chainList: ChainListType }) => { const assets = balancesToAssets( false, @@ -59,38 +35,27 @@ export const getBalances = async (input: { const removeTransferFee = input.removeTransferFee ?? false; const filter = input.filter ?? true; - const cacheKey = getKeyForStorage(input); - console.log({ balanceCache }); - - let cacheValue = balanceCache.value[cacheKey]; - if (!cacheValue || cacheValue.lastUpdatedAt + minutesToMs(0.5) < Date.now()) { - const [ankrBalances, evmBalances, fuelBalances, tronBalances] = await Promise.all([ - input.networkHint === Environment.FOLLY || isCA - ? Promise.resolve([]) - : getAnkrBalances(input.evmAddress, input.chainList, removeTransferFee), - getEVMBalancesForAddress(input.vscDomain, input.evmAddress), - input.fuelAddress - ? getFuelBalancesForAddress(input.vscDomain, input.fuelAddress as `0x${string}`) - : Promise.resolve([]), - input.tronAddress - ? getTronBalancesForAddress(input.vscDomain, input.tronAddress as Hex) - : Promise.resolve([]), - ]); - - balanceCache.value[cacheKey] = { - data: balancesToAssets( - isCA, - ankrBalances, - input.chainList, - evmBalances, - fuelBalances, - tronBalances, - ), - lastUpdatedAt: Date.now(), - }; - } + const [ankrBalances, evmBalances, fuelBalances, tronBalances] = await Promise.all([ + input.networkHint === Environment.FOLLY || isCA + ? Promise.resolve([]) + : getAnkrBalances(input.evmAddress, input.chainList, removeTransferFee), + getEVMBalancesForAddress(input.vscDomain, input.evmAddress), + input.fuelAddress + ? getFuelBalancesForAddress(input.vscDomain, input.fuelAddress as `0x${string}`) + : Promise.resolve([]), + input.tronAddress + ? getTronBalancesForAddress(input.vscDomain, input.tronAddress as Hex) + : Promise.resolve([]), + ]); - const assets = balanceCache.value[cacheKey].data; + const assets = balancesToAssets( + isCA, + ankrBalances, + input.chainList, + evmBalances, + fuelBalances, + tronBalances, + ); let balances = toFlatBalance(assets); if (filter) { diff --git a/src/sdk/ca-base/utils/contract.utils.ts b/src/sdk/ca-base/utils/contract.utils.ts index 0ff38feb..35f145c4 100644 --- a/src/sdk/ca-base/utils/contract.utils.ts +++ b/src/sdk/ca-base/utils/contract.utils.ts @@ -24,7 +24,7 @@ import gasOracleABI from '../abi/gasOracle'; import { FillEvent } from '../abi/vault'; import { ZERO_ADDRESS } from '../constants'; import { Errors } from '../errors'; -import { getLogger, MAINNET_CHAIN_IDS, TESTNET_CHAIN_IDS } from '../../../commons'; +import { getLogger } from '../../../commons'; import { ChainListType, Chain, GetAllowanceParams, SetAllowanceParams } from '../../../commons'; import { equalFold, minutesToMs } from './common.utils'; @@ -448,10 +448,10 @@ const createPublicClientWithFallback = (chain: Chain): PublicClient => { }); }; -const getPctGasBufferByChain = (chainId: number) => { - if (chainId === TESTNET_CHAIN_IDS.MONAD_TESTNET || chainId === MAINNET_CHAIN_IDS.MONAD) { - return 0.05; - } +const getPctGasBufferByChain = (_: number) => { + // if (chainId === TESTNET_CHAIN_IDS.MONAD_TESTNET || chainId === MAINNET_CHAIN_IDS.MONAD) { + // return 0.05; + // } return 0.3; }; From 50352fbf3ba889c81eed2c2c009531844ade8075 Mon Sep 17 00:00:00 2001 From: Abhishek Date: Wed, 26 Nov 2025 14:54:03 +0400 Subject: [PATCH 44/51] feat: add mainnet (#112) * feat: start with adding jade * fix: remove fuel * fix: added public urls as fallback, fix: updated urls for vsc and explorer for jade, updated ca-common --- package-lock.json | 2757 +----------------- package.json | 7 +- rollup.config.mjs | 2 - src/commons/types/index.ts | 10 +- src/sdk/ca-base/ca.ts | 52 +- src/sdk/ca-base/chains.ts | 53 +- src/sdk/ca-base/config.ts | 30 +- src/sdk/ca-base/constants.ts | 21 +- src/sdk/ca-base/errors.ts | 5 - src/sdk/ca-base/nexusError.ts | 2 - src/sdk/ca-base/requestHandlers/bridge.ts | 62 +- src/sdk/ca-base/requestHandlers/bridgeMax.ts | 1 - src/sdk/ca-base/swap/utils.ts | 8 +- src/sdk/ca-base/utils/api.utils.ts | 12 +- src/sdk/ca-base/utils/balance.utils.ts | 22 +- src/sdk/ca-base/utils/common.utils.ts | 85 +- src/sdk/ca-base/utils/contract.utils.ts | 22 +- src/sdk/ca-base/utils/cosmos.utils.ts | 4 +- src/sdk/ca-base/utils/rff.utils.ts | 45 +- 19 files changed, 173 insertions(+), 3027 deletions(-) diff --git a/package-lock.json b/package-lock.json index 362e9654..5c10ad02 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,17 +1,17 @@ { "name": "@avail-project/nexus-core", - "version": "1.0.0-beta.46", + "version": "1.0.0-beta.50", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@avail-project/nexus-core", - "version": "1.0.0-beta.46", + "version": "1.0.0-beta.50", "license": "MIT", "dependencies": { - "@avail-project/ca-common": "1.0.0-dev.4", - "@cosmjs/proto-signing": "^0.34.0", - "@cosmjs/stargate": "^0.34.0", + "@avail-project/ca-common": "1.0.0-rc.1", + "@cosmjs/proto-signing": "0.34.0", + "@cosmjs/stargate": "0.34.0", "@metamask/safe-event-emitter": "3.1.2", "@opentelemetry/api-logs": "0.208.0", "@opentelemetry/exporter-logs-otlp-http": "0.208.0", @@ -23,7 +23,6 @@ "buffer": "6.0.3", "decimal.js": "^10.6.0", "es-toolkit": "^1.40.0", - "fuels": "0.101.1", "it-ws": "^6.1.5", "long": "^5.3.2", "msgpackr": "^1.11.5", @@ -54,9 +53,9 @@ "license": "MIT" }, "node_modules/@avail-project/ca-common": { - "version": "1.0.0-dev.4", - "resolved": "https://registry.npmjs.org/@avail-project/ca-common/-/ca-common-1.0.0-dev.4.tgz", - "integrity": "sha512-EG7BP4o6f1juSHIzxOO/X4AzWO+pnvI177gg0hbfyYV8eSFsWOm5L/PPKk7FCE20YGinS/R21R/F8r2q3Tgcdg==", + "version": "1.0.0-rc.1", + "resolved": "https://registry.npmjs.org/@avail-project/ca-common/-/ca-common-1.0.0-rc.1.tgz", + "integrity": "sha512-6qOnrqFDa3HG1DYxdjUHoA9FKHKfUdhOdLdYISY3mI4PDI88L3dl1HRoQrmdL4RKHUrPXbnaVxawYtX+RU2jOw==", "license": "MIT", "dependencies": { "@bufbuild/protobuf": "^2.6.0", @@ -70,7 +69,6 @@ "@cosmjs/stargate": "^0.34.0", "axios": "^1.10.0", "decimal.js": "^10.6.0", - "fuels": "^0.101.1", "long": "^5.3.2", "msgpackr": "^1.11.4", "viem": "^2.31.7" @@ -179,16 +177,16 @@ } }, "node_modules/@cosmjs/proto-signing": { - "version": "0.34.1", - "resolved": "https://registry.npmjs.org/@cosmjs/proto-signing/-/proto-signing-0.34.1.tgz", - "integrity": "sha512-7oeU2QyVwAWoeGXtsrQ8e6eCjWR4essYDegFA4a/1eXFnIvAb8oPMxoVshZfUmDhhhtmyHQvuqxFm3zMO0R6aA==", + "version": "0.34.0", + "resolved": "https://registry.npmjs.org/@cosmjs/proto-signing/-/proto-signing-0.34.0.tgz", + "integrity": "sha512-1/f4JNSAhsP5lr7fdCJxT+qkWqeDq8vViwCilqMIkqvxLAcf6FxEkvmTOpYBAdOT5fVe3+5nZ5GX5FYMq1tdfA==", "license": "Apache-2.0", "dependencies": { - "@cosmjs/amino": "^0.34.1", - "@cosmjs/crypto": "^0.34.1", - "@cosmjs/encoding": "^0.34.1", - "@cosmjs/math": "^0.34.1", - "@cosmjs/utils": "^0.34.1", + "@cosmjs/amino": "^0.34.0", + "@cosmjs/crypto": "^0.34.0", + "@cosmjs/encoding": "^0.34.0", + "@cosmjs/math": "^0.34.0", + "@cosmjs/utils": "^0.34.0", "cosmjs-types": "^0.9.0" } }, @@ -205,18 +203,18 @@ } }, "node_modules/@cosmjs/stargate": { - "version": "0.34.1", - "resolved": "https://registry.npmjs.org/@cosmjs/stargate/-/stargate-0.34.1.tgz", - "integrity": "sha512-BOaSEmHnThtpKft7jFwFKOKptRoVNq01vmaDKoTISgmS5qi9JgVwiogjL679Aclmmy/xO+GoRfQvWsFrR7f1KA==", + "version": "0.34.0", + "resolved": "https://registry.npmjs.org/@cosmjs/stargate/-/stargate-0.34.0.tgz", + "integrity": "sha512-FU/A0OdkNKfqQ4d7CC8KceTVGoCy3BemFgVjbXL/K5FnAafEjqqWInQ531oNvBejpMdm1NSkfbp97CfILeTW7A==", "license": "Apache-2.0", "dependencies": { - "@cosmjs/amino": "^0.34.1", - "@cosmjs/encoding": "^0.34.1", - "@cosmjs/math": "^0.34.1", - "@cosmjs/proto-signing": "^0.34.1", - "@cosmjs/stream": "^0.34.1", - "@cosmjs/tendermint-rpc": "^0.34.1", - "@cosmjs/utils": "^0.34.1", + "@cosmjs/amino": "^0.34.0", + "@cosmjs/encoding": "^0.34.0", + "@cosmjs/math": "^0.34.0", + "@cosmjs/proto-signing": "^0.34.0", + "@cosmjs/stream": "^0.34.0", + "@cosmjs/tendermint-rpc": "^0.34.0", + "@cosmjs/utils": "^0.34.0", "cosmjs-types": "^0.9.0" } }, @@ -239,818 +237,18 @@ "@cosmjs/encoding": "^0.34.1", "@cosmjs/json-rpc": "^0.34.1", "@cosmjs/math": "^0.34.1", - "@cosmjs/socket": "^0.34.1", - "@cosmjs/stream": "^0.34.1", - "@cosmjs/utils": "^0.34.1", - "cross-fetch": "^4.1.0", - "readonly-date": "^1.0.0", - "xstream": "^11.14.0" - } - }, - "node_modules/@cosmjs/utils": { - "version": "0.34.1", - "resolved": "https://registry.npmjs.org/@cosmjs/utils/-/utils-0.34.1.tgz", - "integrity": "sha512-OjevgFwbVN7t8afmFF8A3rj80jQnOXqwdGEzfv7jbYxTvhUGPa8SvpeaulhWQYQ49K3zlIuB9a2PJWdf1H9Udw==", - "license": "Apache-2.0" - }, - "node_modules/@esbuild/aix-ppc64": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.1.tgz", - "integrity": "sha512-kfYGy8IdzTGy+z0vFGvExZtxkFlA4zAxgKEahG9KE1ScBjpQnFsNOX8KTU5ojNru5ed5CVoJYXFtoxaq5nFbjQ==", - "cpu": [ - "ppc64" - ], - "license": "MIT", - "optional": true, - "os": [ - "aix" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-arm": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.1.tgz", - "integrity": "sha512-dp+MshLYux6j/JjdqVLnMglQlFu+MuVeNrmT5nk6q07wNhCdSnB7QZj+7G8VMUGh1q+vj2Bq8kRsuyA00I/k+Q==", - "cpu": [ - "arm" - ], - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-arm64": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.1.tgz", - "integrity": "sha512-50tM0zCJW5kGqgG7fQ7IHvQOcAn9TKiVRuQ/lN0xR+T2lzEFvAi1ZcS8DiksFcEpf1t/GYOeOfCAgDHFpkiSmA==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-x64": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.1.tgz", - "integrity": "sha512-GCj6WfUtNldqUzYkN/ITtlhwQqGWu9S45vUXs7EIYf+7rCiiqH9bCloatO9VhxsL0Pji+PF4Lz2XXCES+Q8hDw==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/darwin-arm64": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.1.tgz", - "integrity": "sha512-5hEZKPf+nQjYoSr/elb62U19/l1mZDdqidGfmFutVUjjUZrOazAtwK+Kr+3y0C/oeJfLlxo9fXb1w7L+P7E4FQ==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/darwin-x64": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.1.tgz", - "integrity": "sha512-hxVnwL2Dqs3fM1IWq8Iezh0cX7ZGdVhbTfnOy5uURtao5OIVCEyj9xIzemDi7sRvKsuSdtCAhMKarxqtlyVyfA==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/freebsd-arm64": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.1.tgz", - "integrity": "sha512-1MrCZs0fZa2g8E+FUo2ipw6jw5qqQiH+tERoS5fAfKnRx6NXH31tXBKI3VpmLijLH6yriMZsxJtaXUyFt/8Y4A==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/freebsd-x64": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.1.tgz", - "integrity": "sha512-0IZWLiTyz7nm0xuIs0q1Y3QWJC52R8aSXxe40VUxm6BB1RNmkODtW6LHvWRrGiICulcX7ZvyH6h5fqdLu4gkww==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-arm": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.1.tgz", - "integrity": "sha512-NdKOhS4u7JhDKw9G3cY6sWqFcnLITn6SqivVArbzIaf3cemShqfLGHYMx8Xlm/lBit3/5d7kXvriTUGa5YViuQ==", - "cpu": [ - "arm" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-arm64": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.1.tgz", - "integrity": "sha512-jaN3dHi0/DDPelk0nLcXRm1q7DNJpjXy7yWaWvbfkPvI+7XNSc/lDOnCLN7gzsyzgu6qSAmgSvP9oXAhP973uQ==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-ia32": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.1.tgz", - "integrity": "sha512-OJykPaF4v8JidKNGz8c/q1lBO44sQNUQtq1KktJXdBLn1hPod5rE/Hko5ugKKZd+D2+o1a9MFGUEIUwO2YfgkQ==", - "cpu": [ - "ia32" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-loong64": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.1.tgz", - "integrity": "sha512-nGfornQj4dzcq5Vp835oM/o21UMlXzn79KobKlcs3Wz9smwiifknLy4xDCLUU0BWp7b/houtdrgUz7nOGnfIYg==", - "cpu": [ - "loong64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-mips64el": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.1.tgz", - "integrity": "sha512-1osBbPEFYwIE5IVB/0g2X6i1qInZa1aIoj1TdL4AaAb55xIIgbg8Doq6a5BzYWgr+tEcDzYH67XVnTmUzL+nXg==", - "cpu": [ - "mips64el" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-ppc64": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.1.tgz", - "integrity": "sha512-/6VBJOwUf3TdTvJZ82qF3tbLuWsscd7/1w+D9LH0W/SqUgM5/JJD0lrJ1fVIfZsqB6RFmLCe0Xz3fmZc3WtyVg==", - "cpu": [ - "ppc64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-riscv64": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.1.tgz", - "integrity": "sha512-nSut/Mx5gnilhcq2yIMLMe3Wl4FK5wx/o0QuuCLMtmJn+WeWYoEGDN1ipcN72g1WHsnIbxGXd4i/MF0gTcuAjQ==", - "cpu": [ - "riscv64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-s390x": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.1.tgz", - "integrity": "sha512-cEECeLlJNfT8kZHqLarDBQso9a27o2Zd2AQ8USAEoGtejOrCYHNtKP8XQhMDJMtthdF4GBmjR2au3x1udADQQQ==", - "cpu": [ - "s390x" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-x64": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.1.tgz", - "integrity": "sha512-xbfUhu/gnvSEg+EGovRc+kjBAkrvtk38RlerAzQxvMzlB4fXpCFCeUAYzJvrnhFtdeyVCDANSjJvOvGYoeKzFA==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/netbsd-arm64": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.1.tgz", - "integrity": "sha512-O96poM2XGhLtpTh+s4+nP7YCCAfb4tJNRVZHfIE7dgmax+yMP2WgMd2OecBuaATHKTHsLWHQeuaxMRnCsH8+5g==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/netbsd-x64": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.1.tgz", - "integrity": "sha512-X53z6uXip6KFXBQ+Krbx25XHV/NCbzryM6ehOAeAil7X7oa4XIq+394PWGnwaSQ2WRA0KI6PUO6hTO5zeF5ijA==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openbsd-arm64": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.1.tgz", - "integrity": "sha512-Na9T3szbXezdzM/Kfs3GcRQNjHzM6GzFBeU1/6IV/npKP5ORtp9zbQjvkDJ47s6BCgaAZnnnu/cY1x342+MvZg==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openbsd-x64": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.1.tgz", - "integrity": "sha512-T3H78X2h1tszfRSf+txbt5aOp/e7TAz3ptVKu9Oyir3IAOFPGV6O9c2naym5TOriy1l0nNf6a4X5UXRZSGX/dw==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/sunos-x64": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.1.tgz", - "integrity": "sha512-2H3RUvcmULO7dIE5EWJH8eubZAI4xw54H1ilJnRNZdeo8dTADEZ21w6J22XBkXqGJbe0+wnNJtw3UXRoLJnFEg==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-arm64": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.1.tgz", - "integrity": "sha512-GE7XvrdOzrb+yVKB9KsRMq+7a2U/K5Cf/8grVFRAGJmfADr/e/ODQ134RK2/eeHqYV5eQRFxb1hY7Nr15fv1NQ==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-ia32": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.1.tgz", - "integrity": "sha512-uOxSJCIcavSiT6UnBhBzE8wy3n0hOkJsBOzy7HDAuTDE++1DJMRRVCPGisULScHL+a/ZwdXPpXD3IyFKjA7K8A==", - "cpu": [ - "ia32" - ], - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-x64": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.1.tgz", - "integrity": "sha512-Y1EQdcfwMSeQN/ujR5VayLOJ1BHaK+ssyk0AEzPjC+t1lITgsnccPqFjb6V+LsTp/9Iov4ysfjxLaGJ9RPtkVg==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@fuel-ts/abi-coder": { - "version": "0.101.1", - "resolved": "https://registry.npmjs.org/@fuel-ts/abi-coder/-/abi-coder-0.101.1.tgz", - "integrity": "sha512-PgKO4BLo8dzwdJqHIMmOtoOiV/a8OIqPju9h3maOLXMDwgVXxL/NLku33iLP8CDuFu91AssAOg5XURTHDfQ1aQ==", - "license": "Apache-2.0", - "dependencies": { - "@fuel-ts/crypto": "0.101.1", - "@fuel-ts/errors": "0.101.1", - "@fuel-ts/hasher": "0.101.1", - "@fuel-ts/math": "0.101.1", - "@fuel-ts/utils": "0.101.1", - "type-fest": "4.34.1" - }, - "engines": { - "node": "^18.20.3 || ^20.0.0 || ^22.0.0" - } - }, - "node_modules/@fuel-ts/abi-typegen": { - "version": "0.101.1", - "resolved": "https://registry.npmjs.org/@fuel-ts/abi-typegen/-/abi-typegen-0.101.1.tgz", - "integrity": "sha512-4s4Zf+5Ohdym9bl/Cebl7kwufaKJ9C2nJNt5EB+0bXmVArl8zOpP67U+cQSVXawMUVryBVM3mY7Ay2p/WD9wDg==", - "license": "Apache-2.0", - "dependencies": { - "@fuel-ts/errors": "0.101.1", - "@fuel-ts/utils": "0.101.1", - "@fuel-ts/versions": "0.101.1", - "commander": "13.1.0", - "glob": "10.4.5", - "handlebars": "4.7.8", - "mkdirp": "3.0.1", - "ramda": "0.30.1", - "rimraf": "5.0.10" - }, - "bin": { - "fuels-typegen": "typegen.js" - }, - "engines": { - "node": "^18.20.3 || ^20.0.0 || ^22.0.0" - } - }, - "node_modules/@fuel-ts/abi-typegen/node_modules/glob": { - "version": "10.4.5", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", - "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", - "license": "ISC", - "dependencies": { - "foreground-child": "^3.1.0", - "jackspeak": "^3.1.2", - "minimatch": "^9.0.4", - "minipass": "^7.1.2", - "package-json-from-dist": "^1.0.0", - "path-scurry": "^1.11.1" - }, - "bin": { - "glob": "dist/esm/bin.mjs" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/@fuel-ts/abi-typegen/node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/@fuel-ts/account": { - "version": "0.101.1", - "resolved": "https://registry.npmjs.org/@fuel-ts/account/-/account-0.101.1.tgz", - "integrity": "sha512-x+UfuBaCvb9KYT+wIJba3RL21nR4JH0qZevDs/jzw9cLMsLl8AYLKMg2wS9rhR5OCoa9PbsOe9DDrDI+y3BpVA==", - "license": "Apache-2.0", - "dependencies": { - "@fuel-ts/abi-coder": "0.101.1", - "@fuel-ts/address": "0.101.1", - "@fuel-ts/crypto": "0.101.1", - "@fuel-ts/errors": "0.101.1", - "@fuel-ts/hasher": "0.101.1", - "@fuel-ts/math": "0.101.1", - "@fuel-ts/merkle": "0.101.1", - "@fuel-ts/transactions": "0.101.1", - "@fuel-ts/utils": "0.101.1", - "@fuel-ts/versions": "0.101.1", - "@fuels/vm-asm": "0.60.2", - "@noble/curves": "1.8.1", - "events": "3.3.0", - "graphql": "16.10.0", - "graphql-request": "6.1.0", - "graphql-tag": "2.12.6", - "ramda": "0.30.1" - }, - "engines": { - "node": "^18.20.3 || ^20.0.0 || ^22.0.0" - } - }, - "node_modules/@fuel-ts/account/node_modules/@noble/curves": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.8.1.tgz", - "integrity": "sha512-warwspo+UYUPep0Q+vtdVB4Ugn8GGQj8iyB3gnRWsztmUHTI3S1nhdiWNsPUGL0vud7JlRRk1XEu7Lq1KGTnMQ==", - "license": "MIT", - "dependencies": { - "@noble/hashes": "1.7.1" - }, - "engines": { - "node": "^14.21.3 || >=16" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/@fuel-ts/account/node_modules/@noble/hashes": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.7.1.tgz", - "integrity": "sha512-B8XBPsn4vT/KJAGqDzbwztd+6Yte3P4V7iafm24bxgDe/mlRuK6xmWPuCNrKt2vDafZ8MfJLlchDG/vYafQEjQ==", - "license": "MIT", - "engines": { - "node": "^14.21.3 || >=16" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/@fuel-ts/address": { - "version": "0.101.1", - "resolved": "https://registry.npmjs.org/@fuel-ts/address/-/address-0.101.1.tgz", - "integrity": "sha512-l+PvQ2kB/zS/TW7S3/UjjaJ95UNflWizmKr97M13gkOdP99UuI2InYu9zjH72Azbt3LR/RMilHMTyZeWRSV42w==", - "license": "Apache-2.0", - "dependencies": { - "@fuel-ts/crypto": "0.101.1", - "@fuel-ts/errors": "0.101.1", - "@fuel-ts/utils": "0.101.1", - "@noble/hashes": "1.7.1" - }, - "engines": { - "node": "^18.20.3 || ^20.0.0 || ^22.0.0" - } - }, - "node_modules/@fuel-ts/address/node_modules/@noble/hashes": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.7.1.tgz", - "integrity": "sha512-B8XBPsn4vT/KJAGqDzbwztd+6Yte3P4V7iafm24bxgDe/mlRuK6xmWPuCNrKt2vDafZ8MfJLlchDG/vYafQEjQ==", - "license": "MIT", - "engines": { - "node": "^14.21.3 || >=16" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/@fuel-ts/contract": { - "version": "0.101.1", - "resolved": "https://registry.npmjs.org/@fuel-ts/contract/-/contract-0.101.1.tgz", - "integrity": "sha512-UBOjDIYqO1EY8qirjxpEUsW0K2+fR8mC0xDI8k0c1Aes3YVAZyMmpf6ZWvjF5BVElu4kO8pFXr6xcQoDn6TuMw==", - "license": "Apache-2.0", - "dependencies": { - "@fuel-ts/abi-coder": "0.101.1", - "@fuel-ts/account": "0.101.1", - "@fuel-ts/crypto": "0.101.1", - "@fuel-ts/errors": "0.101.1", - "@fuel-ts/hasher": "0.101.1", - "@fuel-ts/math": "0.101.1", - "@fuel-ts/merkle": "0.101.1", - "@fuel-ts/program": "0.101.1", - "@fuel-ts/transactions": "0.101.1", - "@fuel-ts/utils": "0.101.1", - "@fuels/vm-asm": "0.60.2", - "ramda": "0.30.1" - }, - "engines": { - "node": "^18.20.3 || ^20.0.0 || ^22.0.0" - } - }, - "node_modules/@fuel-ts/crypto": { - "version": "0.101.1", - "resolved": "https://registry.npmjs.org/@fuel-ts/crypto/-/crypto-0.101.1.tgz", - "integrity": "sha512-Dy6Q1NbdGojyT0q3mrZu72hSTlXfNprKA6A6vJHKkwRcwFphnrZHAubVfjzus4ZeQf9fdcqZrfWLUG76/F6r9g==", - "license": "Apache-2.0", - "dependencies": { - "@fuel-ts/errors": "0.101.1", - "@fuel-ts/utils": "0.101.1", - "@noble/hashes": "1.7.1" - }, - "engines": { - "node": "^18.20.3 || ^20.0.0 || ^22.0.0" - } - }, - "node_modules/@fuel-ts/crypto/node_modules/@noble/hashes": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.7.1.tgz", - "integrity": "sha512-B8XBPsn4vT/KJAGqDzbwztd+6Yte3P4V7iafm24bxgDe/mlRuK6xmWPuCNrKt2vDafZ8MfJLlchDG/vYafQEjQ==", - "license": "MIT", - "engines": { - "node": "^14.21.3 || >=16" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/@fuel-ts/errors": { - "version": "0.101.1", - "resolved": "https://registry.npmjs.org/@fuel-ts/errors/-/errors-0.101.1.tgz", - "integrity": "sha512-BPp3/tD3YyxbV/qGujwrUOluyB4abEHOD1GIgvUGKiLy9S3TNjBzIPLYG0ARVcswvYTEh8r7/hoZcRKtpNpcEQ==", - "license": "Apache-2.0", - "dependencies": { - "@fuel-ts/versions": "0.101.1" - }, - "engines": { - "node": "^18.20.3 || ^20.0.0 || ^22.0.0" - } - }, - "node_modules/@fuel-ts/hasher": { - "version": "0.101.1", - "resolved": "https://registry.npmjs.org/@fuel-ts/hasher/-/hasher-0.101.1.tgz", - "integrity": "sha512-diLLZbMvwy6ivkZEBDzh6HXkqPzxCVJov29A4A+ILwvKcXHultJ/36bxj3S415cj5DtgVj8KBoqeo1Sw7cg+rg==", - "license": "Apache-2.0", - "dependencies": { - "@fuel-ts/crypto": "0.101.1", - "@fuel-ts/utils": "0.101.1", - "@noble/hashes": "1.7.1" - }, - "engines": { - "node": "^18.20.3 || ^20.0.0 || ^22.0.0" - } - }, - "node_modules/@fuel-ts/hasher/node_modules/@noble/hashes": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.7.1.tgz", - "integrity": "sha512-B8XBPsn4vT/KJAGqDzbwztd+6Yte3P4V7iafm24bxgDe/mlRuK6xmWPuCNrKt2vDafZ8MfJLlchDG/vYafQEjQ==", - "license": "MIT", - "engines": { - "node": "^14.21.3 || >=16" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/@fuel-ts/math": { - "version": "0.101.1", - "resolved": "https://registry.npmjs.org/@fuel-ts/math/-/math-0.101.1.tgz", - "integrity": "sha512-F1bGLZN71DmL5h1/znlXgWahL8A28RMur4B2MscTp/sFyqQ9tHlpEDjdF2ajr3lSxlMWohDJbElCNramLqE/Tg==", - "license": "Apache-2.0", - "dependencies": { - "@fuel-ts/errors": "0.101.1", - "@types/bn.js": "5.1.6", - "bn.js": "5.2.1" - }, - "engines": { - "node": "^18.20.3 || ^20.0.0 || ^22.0.0" - } - }, - "node_modules/@fuel-ts/math/node_modules/@types/bn.js": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-5.1.6.tgz", - "integrity": "sha512-Xh8vSwUeMKeYYrj3cX4lGQgFSF/N03r+tv4AiLl1SucqV+uTQpxRcnM8AkXKHwYP9ZPXOYXRr2KPXpVlIvqh9w==", - "license": "MIT", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@fuel-ts/math/node_modules/bn.js": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.1.tgz", - "integrity": "sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ==", - "license": "MIT" - }, - "node_modules/@fuel-ts/merkle": { - "version": "0.101.1", - "resolved": "https://registry.npmjs.org/@fuel-ts/merkle/-/merkle-0.101.1.tgz", - "integrity": "sha512-JJEdTQ2BxWHjX09caf42Ebfc32J0dHx/dv9pXfvpxc3BUgdRE8gM0Wvrqq/cu6S2XD/Y6vQp/qhOq9PXWJUuKg==", - "license": "Apache-2.0", - "dependencies": { - "@fuel-ts/hasher": "0.101.1", - "@fuel-ts/math": "0.101.1" - }, - "engines": { - "node": "^18.20.3 || ^20.0.0 || ^22.0.0" - } - }, - "node_modules/@fuel-ts/program": { - "version": "0.101.1", - "resolved": "https://registry.npmjs.org/@fuel-ts/program/-/program-0.101.1.tgz", - "integrity": "sha512-6ManClwCW7NI4jE3BoaNWStHyGEWcrD7hkK+9T5+hESY0ckGiBGMuKvR3VhVaTsTRVfqMx/m1kPSu2O5BY/vrA==", - "license": "Apache-2.0", - "dependencies": { - "@fuel-ts/abi-coder": "0.101.1", - "@fuel-ts/account": "0.101.1", - "@fuel-ts/address": "0.101.1", - "@fuel-ts/errors": "0.101.1", - "@fuel-ts/math": "0.101.1", - "@fuel-ts/transactions": "0.101.1", - "@fuel-ts/utils": "0.101.1", - "@fuels/vm-asm": "0.60.2", - "ramda": "0.30.1" - }, - "engines": { - "node": "^18.20.3 || ^20.0.0 || ^22.0.0" - } - }, - "node_modules/@fuel-ts/recipes": { - "version": "0.101.1", - "resolved": "https://registry.npmjs.org/@fuel-ts/recipes/-/recipes-0.101.1.tgz", - "integrity": "sha512-DVQfE7pnoFBmTNwBPrL2qN5jlp8w9rCD9aQKwvBaPwvi4UYiTg1elcWlX5/mEhUAnGlDIYOQ4XFuxLZAgmDUww==", - "license": "Apache-2.0", - "dependencies": { - "@fuel-ts/abi-coder": "0.101.1", - "@fuel-ts/abi-typegen": "0.101.1", - "@fuel-ts/account": "0.101.1", - "@fuel-ts/address": "0.101.1", - "@fuel-ts/contract": "0.101.1", - "@fuel-ts/program": "0.101.1", - "@fuel-ts/transactions": "0.101.1", - "@fuel-ts/utils": "0.101.1" - }, - "engines": { - "node": "^18.20.3 || ^20.0.0 || ^22.0.0" - } - }, - "node_modules/@fuel-ts/script": { - "version": "0.101.1", - "resolved": "https://registry.npmjs.org/@fuel-ts/script/-/script-0.101.1.tgz", - "integrity": "sha512-6s6SKciwOYM/MK1DAE7Cd19hTL5FOG+FtPP9IvZ+UwmNz7zydD2LXHdTcOjTPZnhmzvhBrlfH2CUAsOqhMHGpg==", - "license": "Apache-2.0", - "dependencies": { - "@fuel-ts/abi-coder": "0.101.1", - "@fuel-ts/account": "0.101.1", - "@fuel-ts/errors": "0.101.1", - "@fuel-ts/math": "0.101.1", - "@fuel-ts/program": "0.101.1", - "@fuel-ts/transactions": "0.101.1", - "@fuel-ts/utils": "0.101.1" - }, - "engines": { - "node": "^18.20.3 || ^20.0.0 || ^22.0.0" - } - }, - "node_modules/@fuel-ts/transactions": { - "version": "0.101.1", - "resolved": "https://registry.npmjs.org/@fuel-ts/transactions/-/transactions-0.101.1.tgz", - "integrity": "sha512-VLCtwOO5PD31rxSnGbBaJuQO8AwvqUwwRfXrE3fLzrreJKyUM5K2XZHsfQq9dtd/RWaaOUPNMp7ztVQzKebfUQ==", - "license": "Apache-2.0", - "dependencies": { - "@fuel-ts/abi-coder": "0.101.1", - "@fuel-ts/address": "0.101.1", - "@fuel-ts/errors": "0.101.1", - "@fuel-ts/hasher": "0.101.1", - "@fuel-ts/math": "0.101.1", - "@fuel-ts/utils": "0.101.1" - }, - "engines": { - "node": "^18.20.3 || ^20.0.0 || ^22.0.0" - } - }, - "node_modules/@fuel-ts/utils": { - "version": "0.101.1", - "resolved": "https://registry.npmjs.org/@fuel-ts/utils/-/utils-0.101.1.tgz", - "integrity": "sha512-H7j38/quroMccPrjFrnn+Cuui6iPpyH15NKdBT2XVv96rk9XX2DG5aBIGn+nYqPTA8+W+a7sp3U65sgckyZ4Rg==", - "license": "Apache-2.0", - "dependencies": { - "@fuel-ts/errors": "0.101.1", - "@fuel-ts/math": "0.101.1", - "@fuel-ts/versions": "0.101.1", - "fflate": "0.8.2" - }, - "engines": { - "node": "^18.20.3 || ^20.0.0 || ^22.0.0" - }, - "peerDependencies": { - "vitest": "3.0.9" - } - }, - "node_modules/@fuel-ts/versions": { - "version": "0.101.1", - "resolved": "https://registry.npmjs.org/@fuel-ts/versions/-/versions-0.101.1.tgz", - "integrity": "sha512-3/tYZBbCaShkzfrVEBulm83f3MJaUpOCK4q3BpAxvbhWHsKS9AxbLhHWQ0RZUXII5OJmGnSpWfy0Bhe7FYo93A==", - "license": "Apache-2.0", - "dependencies": { - "chalk": "4", - "cli-table": "0.3.11" - }, - "bin": { - "fuels-versions": "versions.js" - }, - "engines": { - "node": "^18.20.3 || ^20.0.0 || ^22.0.0" + "@cosmjs/socket": "^0.34.1", + "@cosmjs/stream": "^0.34.1", + "@cosmjs/utils": "^0.34.1", + "cross-fetch": "^4.1.0", + "readonly-date": "^1.0.0", + "xstream": "^11.14.0" } }, - "node_modules/@fuels/vm-asm": { - "version": "0.60.2", - "resolved": "https://registry.npmjs.org/@fuels/vm-asm/-/vm-asm-0.60.2.tgz", - "integrity": "sha512-wkCu63jTGJWpRZQirTaB8S4/gyoebEJLk3AKfnykt/lgWp1U9iHOcCICVHQP547i+y8jEVKwk18+huINFyYVFQ==", + "node_modules/@cosmjs/utils": { + "version": "0.34.1", + "resolved": "https://registry.npmjs.org/@cosmjs/utils/-/utils-0.34.1.tgz", + "integrity": "sha512-OjevgFwbVN7t8afmFF8A3rj80jQnOXqwdGEzfv7jbYxTvhUGPa8SvpeaulhWQYQ49K3zlIuB9a2PJWdf1H9Udw==", "license": "Apache-2.0" }, "node_modules/@gerrit0/mini-shiki": { @@ -1067,15 +265,6 @@ "@shikijs/vscode-textmate": "^10.0.2" } }, - "node_modules/@graphql-typed-document-node/core": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/@graphql-typed-document-node/core/-/core-3.2.0.tgz", - "integrity": "sha512-mB9oAsNCm9aM3/SOv4YtBMqZbYj10R7dkq8byBqxGY/ncFwhf2oQzMV+LCRlWoDSEBJ3COiR1yeDvMtsoOsuFQ==", - "license": "MIT", - "peerDependencies": { - "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" - } - }, "node_modules/@improbable-eng/grpc-web": { "version": "0.15.0", "resolved": "https://registry.npmjs.org/@improbable-eng/grpc-web/-/grpc-web-0.15.0.tgz", @@ -1088,27 +277,11 @@ "google-protobuf": "^3.14.0" } }, - "node_modules/@isaacs/cliui": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", - "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", - "license": "ISC", - "dependencies": { - "string-width": "^5.1.2", - "string-width-cjs": "npm:string-width@^4.2.0", - "strip-ansi": "^7.0.1", - "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", - "wrap-ansi": "^8.1.0", - "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, "node_modules/@jridgewell/sourcemap-codec": { "version": "1.5.5", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "dev": true, "license": "MIT" }, "node_modules/@metamask/safe-event-emitter": { @@ -1393,16 +566,6 @@ "node": ">=14" } }, - "node_modules/@pkgjs/parseargs": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", - "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", - "license": "MIT", - "optional": true, - "engines": { - "node": ">=14" - } - }, "node_modules/@protobufjs/aspromise": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", @@ -1586,6 +749,7 @@ "cpu": [ "arm" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1599,6 +763,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1612,6 +777,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1625,6 +791,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1638,6 +805,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1651,6 +819,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1664,6 +833,7 @@ "cpu": [ "arm" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1677,6 +847,7 @@ "cpu": [ "arm" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1690,6 +861,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1703,6 +875,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1716,6 +889,7 @@ "cpu": [ "loong64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1729,6 +903,7 @@ "cpu": [ "ppc64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1742,6 +917,7 @@ "cpu": [ "riscv64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1755,6 +931,7 @@ "cpu": [ "riscv64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1768,6 +945,7 @@ "cpu": [ "s390x" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1781,6 +959,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1794,6 +973,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1807,6 +987,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1820,6 +1001,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1833,6 +1015,7 @@ "cpu": [ "ia32" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1846,6 +1029,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1859,6 +1043,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -2007,6 +1192,7 @@ "version": "1.0.8", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", + "dev": true, "license": "MIT" }, "node_modules/@types/hast": { @@ -2069,155 +1255,6 @@ "@types/node": "*" } }, - "node_modules/@vitest/expect": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-3.0.9.tgz", - "integrity": "sha512-5eCqRItYgIML7NNVgJj6TVCmdzE7ZVgJhruW0ziSQV4V7PvLkDL1bBkBdcTs/VuIz0IxPb5da1IDSqc1TR9eig==", - "license": "MIT", - "peer": true, - "dependencies": { - "@vitest/spy": "3.0.9", - "@vitest/utils": "3.0.9", - "chai": "^5.2.0", - "tinyrainbow": "^2.0.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/@vitest/mocker": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-3.0.9.tgz", - "integrity": "sha512-ryERPIBOnvevAkTq+L1lD+DTFBRcjueL9lOUfXsLfwP92h4e+Heb+PjiqS3/OURWPtywfafK0kj++yDFjWUmrA==", - "license": "MIT", - "peer": true, - "dependencies": { - "@vitest/spy": "3.0.9", - "estree-walker": "^3.0.3", - "magic-string": "^0.30.17" - }, - "funding": { - "url": "https://opencollective.com/vitest" - }, - "peerDependencies": { - "msw": "^2.4.9", - "vite": "^5.0.0 || ^6.0.0" - }, - "peerDependenciesMeta": { - "msw": { - "optional": true - }, - "vite": { - "optional": true - } - } - }, - "node_modules/@vitest/mocker/node_modules/estree-walker": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", - "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", - "license": "MIT", - "peer": true, - "dependencies": { - "@types/estree": "^1.0.0" - } - }, - "node_modules/@vitest/pretty-format": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-3.2.4.tgz", - "integrity": "sha512-IVNZik8IVRJRTr9fxlitMKeJeXFFFN0JaB9PHPGQ8NKQbGpfjlTx9zO4RefN8gp7eqjNy8nyK3NZmBzOPeIxtA==", - "license": "MIT", - "peer": true, - "dependencies": { - "tinyrainbow": "^2.0.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/@vitest/runner": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-3.0.9.tgz", - "integrity": "sha512-NX9oUXgF9HPfJSwl8tUZCMP1oGx2+Sf+ru6d05QjzQz4OwWg0psEzwY6VexP2tTHWdOkhKHUIZH+fS6nA7jfOw==", - "license": "MIT", - "peer": true, - "dependencies": { - "@vitest/utils": "3.0.9", - "pathe": "^2.0.3" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/@vitest/snapshot": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-3.0.9.tgz", - "integrity": "sha512-AiLUiuZ0FuA+/8i19mTYd+re5jqjEc2jZbgJ2up0VY0Ddyyxg/uUtBDpIFAy4uzKaQxOW8gMgBdAJJ2ydhu39A==", - "license": "MIT", - "peer": true, - "dependencies": { - "@vitest/pretty-format": "3.0.9", - "magic-string": "^0.30.17", - "pathe": "^2.0.3" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/@vitest/snapshot/node_modules/@vitest/pretty-format": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-3.0.9.tgz", - "integrity": "sha512-OW9F8t2J3AwFEwENg3yMyKWweF7oRJlMyHOMIhO5F3n0+cgQAJZBjNgrF8dLwFTEXl5jUqBLXd9QyyKv8zEcmA==", - "license": "MIT", - "peer": true, - "dependencies": { - "tinyrainbow": "^2.0.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/@vitest/spy": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-3.0.9.tgz", - "integrity": "sha512-/CcK2UDl0aQ2wtkp3YVWldrpLRNCfVcIOFGlVGKO4R5eajsH393Z1yiXLVQ7vWsj26JOEjeZI0x5sm5P4OGUNQ==", - "license": "MIT", - "peer": true, - "dependencies": { - "tinyspy": "^3.0.2" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/@vitest/utils": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-3.0.9.tgz", - "integrity": "sha512-ilHM5fHhZ89MCp5aAaM9uhfl1c2JdxVxl3McqsdVyVNN6JffnEen8UMCdRTzOhGXNQGo5GNL9QugHrz727Wnng==", - "license": "MIT", - "peer": true, - "dependencies": { - "@vitest/pretty-format": "3.0.9", - "loupe": "^3.1.3", - "tinyrainbow": "^2.0.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/@vitest/utils/node_modules/@vitest/pretty-format": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-3.0.9.tgz", - "integrity": "sha512-OW9F8t2J3AwFEwENg3yMyKWweF7oRJlMyHOMIhO5F3n0+cgQAJZBjNgrF8dLwFTEXl5jUqBLXd9QyyKv8zEcmA==", - "license": "MIT", - "peer": true, - "dependencies": { - "tinyrainbow": "^2.0.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, "node_modules/abitype": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/abitype/-/abitype-1.1.0.tgz", @@ -2245,58 +1282,6 @@ "integrity": "sha512-e5pEa2kBnBOgR4Y/p20pskXI74UEz7de8ZGVo58asOtvSVG5YAbJeELPZxOmt+Bnz3rX753YKhfIn4X4l1PPRQ==", "license": "MIT" }, - "node_modules/ansi-regex": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", - "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/anymatch": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", - "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", - "license": "ISC", - "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/anymatch/node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "license": "MIT", - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, "node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", @@ -2334,25 +1319,6 @@ "util": "^0.12.5" } }, - "node_modules/assertion-error": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz", - "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==", - "license": "MIT", - "peer": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/async": { - "version": "2.6.4", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz", - "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==", - "license": "MIT", - "dependencies": { - "lodash": "^4.17.14" - } - }, "node_modules/asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", @@ -2389,6 +1355,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, "license": "MIT" }, "node_modules/base-x": { @@ -2435,18 +1402,6 @@ "node": "*" } }, - "node_modules/binary-extensions": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", - "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", - "license": "MIT", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/bip39": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/bip39/-/bip39-3.1.0.tgz", @@ -2472,23 +1427,12 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "dev": true, "license": "MIT", "dependencies": { "balanced-match": "^1.0.0" } }, - "node_modules/braces": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", - "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", - "license": "MIT", - "dependencies": { - "fill-range": "^7.1.1" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/brorand": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", @@ -2622,31 +1566,6 @@ "integrity": "sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ==", "license": "MIT" }, - "node_modules/bundle-require": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/bundle-require/-/bundle-require-5.1.0.tgz", - "integrity": "sha512-3WrrOuZiyaaZPWiEt4G3+IffISVC9HYlWueJEBWED4ZH4aIAC2PnkdnuRrR94M+w6yGWn4AglWtJtBI8YqvgoA==", - "license": "MIT", - "dependencies": { - "load-tsconfig": "^0.2.3" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "peerDependencies": { - "esbuild": ">=0.18" - } - }, - "node_modules/cac": { - "version": "6.7.14", - "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz", - "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==", - "license": "MIT", - "peer": true, - "engines": { - "node": ">=8" - } - }, "node_modules/call-bind": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz", @@ -2703,127 +1622,22 @@ "engines": { "node": ">=16" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/chai": { - "version": "5.3.3", - "resolved": "https://registry.npmjs.org/chai/-/chai-5.3.3.tgz", - "integrity": "sha512-4zNhdJD/iOjSH0A05ea+Ke6MU5mmpQcbQsSOkgdaUMJ9zTlDTD/GYlwohmIE2u0gaxHYiVHEn1Fw9mZ/ktJWgw==", - "license": "MIT", - "peer": true, - "dependencies": { - "assertion-error": "^2.0.1", - "check-error": "^2.1.1", - "deep-eql": "^5.0.1", - "loupe": "^3.1.0", - "pathval": "^2.0.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/check-error": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/check-error/-/check-error-2.1.1.tgz", - "integrity": "sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==", - "license": "MIT", - "peer": true, - "engines": { - "node": ">= 16" - } - }, - "node_modules/chokidar": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", - "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", - "license": "MIT", - "dependencies": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - }, - "engines": { - "node": ">= 8.10.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - } - }, - "node_modules/cipher-base": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.7.tgz", - "integrity": "sha512-Mz9QMT5fJe7bKI7MH31UilT5cEK5EHHRCccw/YRFsRY47AuNgaV6HY3rscp0/I4Q+tTW/5zoqpSeRRI54TkDWA==", - "license": "MIT", - "dependencies": { - "inherits": "^2.0.4", - "safe-buffer": "^5.2.1", - "to-buffer": "^1.2.2" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/cli-table": { - "version": "0.3.11", - "resolved": "https://registry.npmjs.org/cli-table/-/cli-table-0.3.11.tgz", - "integrity": "sha512-IqLQi4lO0nIB4tcdTpN4LCB9FI3uqrJZK7RC515EnhZ6qBaglkIgICb1wjeAqpdoOabm1+SuQtkXIPdYC93jhQ==", - "dependencies": { - "colors": "1.0.3" - }, - "engines": { - "node": ">= 0.2.0" - } - }, - "node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "license": "MIT", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "license": "MIT" - }, - "node_modules/colors": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/colors/-/colors-1.0.3.tgz", - "integrity": "sha512-pFGrxThWcWQ2MsAz6RtgeWe4NK2kUE1WfsrvvlctdII745EW9I0yflqhe7++M5LEc7bV2c/9/5zc8sFcpL0Drw==", + "node_modules/cipher-base": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.7.tgz", + "integrity": "sha512-Mz9QMT5fJe7bKI7MH31UilT5cEK5EHHRCccw/YRFsRY47AuNgaV6HY3rscp0/I4Q+tTW/5zoqpSeRRI54TkDWA==", "license": "MIT", + "dependencies": { + "inherits": "^2.0.4", + "safe-buffer": "^5.2.1", + "to-buffer": "^1.2.2" + }, "engines": { - "node": ">=0.1.90" + "node": ">= 0.10" } }, "node_modules/combined-stream": { @@ -2838,15 +1652,6 @@ "node": ">= 0.8" } }, - "node_modules/commander": { - "version": "13.1.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-13.1.0.tgz", - "integrity": "sha512-/rFeCpNJQbhSZjGVwO9RFV3xPqbnERS8MmIQzCtD/zl6gpJuV/bMLuN92oG3F7d8oDEHHRrujSXNUr8fpjntKw==", - "license": "MIT", - "engines": { - "node": ">=18" - } - }, "node_modules/commondir": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", @@ -2918,20 +1723,6 @@ "node-fetch": "^2.7.0" } }, - "node_modules/cross-spawn": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", - "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", - "license": "MIT", - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" - } - }, "node_modules/crypto-browserify": { "version": "3.12.1", "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.1.tgz", @@ -2958,31 +1749,12 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "license": "MIT", - "dependencies": { - "ms": "^2.1.1" - } - }, "node_modules/decimal.js": { "version": "10.6.0", "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.6.0.tgz", "integrity": "sha512-YpgQiITW3JXGntzdUmyUR1V812Hn8T1YVXhCu+wO3OpS4eU9l4YdD3qjyiKdV6mvV29zapkMeD390UVEf2lkUg==", "license": "MIT" }, - "node_modules/deep-eql": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-5.0.2.tgz", - "integrity": "sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==", - "license": "MIT", - "peer": true, - "engines": { - "node": ">=6" - } - }, "node_modules/deepmerge": { "version": "4.3.1", "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", @@ -3087,12 +1859,6 @@ "node": ">= 0.4" } }, - "node_modules/eastasianwidth": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", - "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", - "license": "MIT" - }, "node_modules/elliptic": { "version": "6.6.1", "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.6.1.tgz", @@ -3114,12 +1880,6 @@ "integrity": "sha512-n4DSx829VRTRByMRGdjQ9iqsN0Bh4OolPsFnaZBLcbi8iXcB+kJ9s7EnRt4wILZNV3kPLHkRVfOc/HvhC3ovDw==", "license": "MIT" }, - "node_modules/emoji-regex": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", - "license": "MIT" - }, "node_modules/enc-utils": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/enc-utils/-/enc-utils-3.0.0.tgz", @@ -3161,13 +1921,6 @@ "node": ">= 0.4" } }, - "node_modules/es-module-lexer": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.7.0.tgz", - "integrity": "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==", - "license": "MIT", - "peer": true - }, "node_modules/es-object-atoms": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", @@ -3205,46 +1958,6 @@ "benchmarks" ] }, - "node_modules/esbuild": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.1.tgz", - "integrity": "sha512-BGO5LtrGC7vxnqucAe/rmvKdJllfGaYWdyABvyMoXQlfYMb2bbRuReWR5tEGE//4LcNJj9XrkovTqNYRFZHAMQ==", - "hasInstallScript": true, - "license": "MIT", - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=18" - }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.25.1", - "@esbuild/android-arm": "0.25.1", - "@esbuild/android-arm64": "0.25.1", - "@esbuild/android-x64": "0.25.1", - "@esbuild/darwin-arm64": "0.25.1", - "@esbuild/darwin-x64": "0.25.1", - "@esbuild/freebsd-arm64": "0.25.1", - "@esbuild/freebsd-x64": "0.25.1", - "@esbuild/linux-arm": "0.25.1", - "@esbuild/linux-arm64": "0.25.1", - "@esbuild/linux-ia32": "0.25.1", - "@esbuild/linux-loong64": "0.25.1", - "@esbuild/linux-mips64el": "0.25.1", - "@esbuild/linux-ppc64": "0.25.1", - "@esbuild/linux-riscv64": "0.25.1", - "@esbuild/linux-s390x": "0.25.1", - "@esbuild/linux-x64": "0.25.1", - "@esbuild/netbsd-arm64": "0.25.1", - "@esbuild/netbsd-x64": "0.25.1", - "@esbuild/openbsd-arm64": "0.25.1", - "@esbuild/openbsd-x64": "0.25.1", - "@esbuild/sunos-x64": "0.25.1", - "@esbuild/win32-arm64": "0.25.1", - "@esbuild/win32-ia32": "0.25.1", - "@esbuild/win32-x64": "0.25.1" - } - }, "node_modules/estree-walker": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", @@ -3420,15 +2133,6 @@ "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", "license": "MIT" }, - "node_modules/events": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", - "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", - "license": "MIT", - "engines": { - "node": ">=0.8.x" - } - }, "node_modules/evp_bytestokey": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", @@ -3439,52 +2143,6 @@ "safe-buffer": "^5.1.1" } }, - "node_modules/expect-type": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.2.2.tgz", - "integrity": "sha512-JhFGDVJ7tmDJItKhYgJCGLOWjuK9vPxiXoUFLwLDc99NlmklilbiQJwoctZtt13+xMw91MCk/REan6MWHqDjyA==", - "license": "Apache-2.0", - "peer": true, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/fdir": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", - "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", - "license": "MIT", - "peer": true, - "engines": { - "node": ">=12.0.0" - }, - "peerDependencies": { - "picomatch": "^3 || ^4" - }, - "peerDependenciesMeta": { - "picomatch": { - "optional": true - } - } - }, - "node_modules/fflate": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/fflate/-/fflate-0.8.2.tgz", - "integrity": "sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A==", - "license": "MIT" - }, - "node_modules/fill-range": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", - "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", - "license": "MIT", - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/find-cache-dir": { "version": "3.3.2", "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.2.tgz", @@ -3552,22 +2210,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/foreground-child": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", - "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", - "license": "ISC", - "dependencies": { - "cross-spawn": "^7.0.6", - "signal-exit": "^4.0.1" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/form-data": { "version": "4.0.4", "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.4.tgz", @@ -3610,6 +2252,7 @@ "version": "2.3.3", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, "hasInstallScript": true, "license": "MIT", "optional": true, @@ -3620,84 +2263,6 @@ "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } }, - "node_modules/fuels": { - "version": "0.101.1", - "resolved": "https://registry.npmjs.org/fuels/-/fuels-0.101.1.tgz", - "integrity": "sha512-/0LwAynHrKZZn4aw7QkyVc+Af+MIwlg82eCVSdAUVDJ+/pQ6Oma+aZyqjynmsKEuOlvkzw+jhUReGoWqexF4tg==", - "license": "Apache-2.0", - "dependencies": { - "@fuel-ts/abi-coder": "0.101.1", - "@fuel-ts/abi-typegen": "0.101.1", - "@fuel-ts/account": "0.101.1", - "@fuel-ts/address": "0.101.1", - "@fuel-ts/contract": "0.101.1", - "@fuel-ts/crypto": "0.101.1", - "@fuel-ts/errors": "0.101.1", - "@fuel-ts/hasher": "0.101.1", - "@fuel-ts/math": "0.101.1", - "@fuel-ts/program": "0.101.1", - "@fuel-ts/recipes": "0.101.1", - "@fuel-ts/script": "0.101.1", - "@fuel-ts/transactions": "0.101.1", - "@fuel-ts/utils": "0.101.1", - "@fuel-ts/versions": "0.101.1", - "@fuels/vm-asm": "0.60.2", - "bundle-require": "5.1.0", - "chalk": "4", - "chokidar": "3.6.0", - "commander": "13.1.0", - "esbuild": "0.25.1", - "glob": "10.4.5", - "handlebars": "4.7.8", - "joycon": "3.1.1", - "lodash.camelcase": "4.3.0", - "portfinder": "1.0.32", - "toml": "3.0.0", - "uglify-js": "3.19.3", - "yup": "1.6.1" - }, - "bin": { - "fuels": "fuels.js" - }, - "engines": { - "node": "^18.20.3 || ^20.0.0 || ^22.0.0" - } - }, - "node_modules/fuels/node_modules/glob": { - "version": "10.4.5", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", - "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", - "license": "ISC", - "dependencies": { - "foreground-child": "^3.1.0", - "jackspeak": "^3.1.2", - "minimatch": "^9.0.4", - "minipass": "^7.1.2", - "package-json-from-dist": "^1.0.0", - "path-scurry": "^1.11.1" - }, - "bin": { - "glob": "dist/esm/bin.mjs" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/fuels/node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/function-bind": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", @@ -3774,18 +2339,6 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "license": "ISC", - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, "node_modules/globalthis": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", @@ -3827,82 +2380,6 @@ "dev": true, "license": "ISC" }, - "node_modules/graphql": { - "version": "16.10.0", - "resolved": "https://registry.npmjs.org/graphql/-/graphql-16.10.0.tgz", - "integrity": "sha512-AjqGKbDGUFRKIRCP9tCKiIGHyriz2oHEbPIbEtcSLSs4YjReZOIPQQWek4+6hjw62H9QShXHyaGivGiYVLeYFQ==", - "license": "MIT", - "engines": { - "node": "^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0" - } - }, - "node_modules/graphql-request": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/graphql-request/-/graphql-request-6.1.0.tgz", - "integrity": "sha512-p+XPfS4q7aIpKVcgmnZKhMNqhltk20hfXtkaIkTfjjmiKMJ5xrt5c743cL03y/K7y1rg3WrIC49xGiEQ4mxdNw==", - "license": "MIT", - "dependencies": { - "@graphql-typed-document-node/core": "^3.2.0", - "cross-fetch": "^3.1.5" - }, - "peerDependencies": { - "graphql": "14 - 16" - } - }, - "node_modules/graphql-request/node_modules/cross-fetch": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.2.0.tgz", - "integrity": "sha512-Q+xVJLoGOeIMXZmbUK4HYk+69cQH6LudR0Vu/pRm2YlU/hDV9CiS0gKUMaWY5f2NeUH9C1nV3bsTlCo0FsTV1Q==", - "license": "MIT", - "dependencies": { - "node-fetch": "^2.7.0" - } - }, - "node_modules/graphql-tag": { - "version": "2.12.6", - "resolved": "https://registry.npmjs.org/graphql-tag/-/graphql-tag-2.12.6.tgz", - "integrity": "sha512-FdSNcu2QQcWnM2VNvSCCDCVS5PpPqpzgFT8+GXzqJuoDd0CBncxCY278u4mhRO7tMgo2JjgJA5aZ+nWSQ/Z+xg==", - "license": "MIT", - "dependencies": { - "tslib": "^2.1.0" - }, - "engines": { - "node": ">=10" - }, - "peerDependencies": { - "graphql": "^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0" - } - }, - "node_modules/handlebars": { - "version": "4.7.8", - "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.8.tgz", - "integrity": "sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==", - "license": "MIT", - "dependencies": { - "minimist": "^1.2.5", - "neo-async": "^2.6.2", - "source-map": "^0.6.1", - "wordwrap": "^1.0.0" - }, - "bin": { - "handlebars": "bin/handlebars" - }, - "engines": { - "node": ">=0.4.7" - }, - "optionalDependencies": { - "uglify-js": "^3.1.4" - } - }, - "node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, "node_modules/has-property-descriptors": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", @@ -4042,18 +2519,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "license": "MIT", - "dependencies": { - "binary-extensions": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/is-callable": { "version": "1.2.7", "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", @@ -4082,24 +2547,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, "node_modules/is-generator-function": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.2.tgz", @@ -4119,18 +2566,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "license": "MIT", - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/is-module": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz", @@ -4154,15 +2589,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "license": "MIT", - "engines": { - "node": ">=0.12.0" - } - }, "node_modules/is-reference": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/is-reference/-/is-reference-1.2.1.tgz", @@ -4218,12 +2644,6 @@ "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", "license": "MIT" }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "license": "ISC" - }, "node_modules/isomorphic-ws": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/isomorphic-ws/-/isomorphic-ws-4.0.1.tgz", @@ -4292,30 +2712,6 @@ } } }, - "node_modules/jackspeak": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", - "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", - "license": "BlueOak-1.0.0", - "dependencies": { - "@isaacs/cliui": "^8.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - }, - "optionalDependencies": { - "@pkgjs/parseargs": "^0.11.0" - } - }, - "node_modules/joycon": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/joycon/-/joycon-3.1.1.tgz", - "integrity": "sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==", - "license": "MIT", - "engines": { - "node": ">=10" - } - }, "node_modules/js-sha3": { "version": "0.8.0", "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.8.0.tgz", @@ -4397,15 +2793,6 @@ "uc.micro": "^2.0.0" } }, - "node_modules/load-tsconfig": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/load-tsconfig/-/load-tsconfig-0.2.5.tgz", - "integrity": "sha512-IXO6OCs9yg8tMKzfPZ1YmheJbZCiEsnBdcB03l0OcfK9prKnJb96siuHCr5Fl37/yo9DnKU+TLpxzTUspw9shg==", - "license": "MIT", - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - } - }, "node_modules/locate-path": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", @@ -4419,37 +2806,12 @@ "node": ">=8" } }, - "node_modules/lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", - "license": "MIT" - }, - "node_modules/lodash.camelcase": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", - "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==", - "license": "MIT" - }, "node_modules/long": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/long/-/long-5.3.2.tgz", "integrity": "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==", "license": "Apache-2.0" }, - "node_modules/loupe": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/loupe/-/loupe-3.2.1.tgz", - "integrity": "sha512-CdzqowRJCeLU72bHvWqwRBBlLcMEtIvGrlvef74kMnV2AolS9Y8xUv1I0U/MNAWMhBlKIoyuEgoJ0t/bbwHbLQ==", - "license": "MIT", - "peer": true - }, - "node_modules/lru-cache": { - "version": "10.4.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", - "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", - "license": "ISC" - }, "node_modules/lunr": { "version": "2.3.9", "resolved": "https://registry.npmjs.org/lunr/-/lunr-2.3.9.tgz", @@ -4461,6 +2823,7 @@ "version": "0.30.21", "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", + "dev": true, "license": "MIT", "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.5" @@ -4591,56 +2954,17 @@ }, "node_modules/minimatch": { "version": "5.1.6", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", - "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/minimist": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", - "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/minipass": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", - "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", - "license": "ISC", - "engines": { - "node": ">=16 || 14 >=14.17" - } - }, - "node_modules/mkdirp": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-3.0.1.tgz", - "integrity": "sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==", - "license": "MIT", - "bin": { - "mkdirp": "dist/cjs/src/bin.js" + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" }, "engines": { "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "license": "MIT" - }, "node_modules/msgpackr": { "version": "1.11.5", "resolved": "https://registry.npmjs.org/msgpackr/-/msgpackr-1.11.5.tgz", @@ -4678,31 +3002,6 @@ "integrity": "sha512-VqO6OSvLrFVAYYjgsr8tyv62/rCQhPgsZUXLTqoFLSgdkgiUYKYeArbt1uWLlEpkjxQe+P0+sHlbPEte1Bi06Q==", "license": "Apache-2.0 OR MIT" }, - "node_modules/nanoid": { - "version": "3.3.11", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", - "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "peer": true, - "bin": { - "nanoid": "bin/nanoid.cjs" - }, - "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" - } - }, - "node_modules/neo-async": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", - "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", - "license": "MIT" - }, "node_modules/node-addon-api": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-2.0.2.tgz", @@ -4755,15 +3054,6 @@ "node-gyp-build-optional-packages-test": "build-test.js" } }, - "node_modules/normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/object-is": { "version": "1.1.6", "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.6.tgz", @@ -4915,12 +3205,6 @@ "node": ">=6" } }, - "node_modules/package-json-from-dist": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", - "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", - "license": "BlueOak-1.0.0" - }, "node_modules/parse-asn1": { "version": "5.1.9", "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.9.tgz", @@ -4947,15 +3231,6 @@ "node": ">=8" } }, - "node_modules/path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, "node_modules/path-parse": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", @@ -4963,39 +3238,6 @@ "dev": true, "license": "MIT" }, - "node_modules/path-scurry": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", - "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", - "license": "BlueOak-1.0.0", - "dependencies": { - "lru-cache": "^10.2.0", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" - }, - "engines": { - "node": ">=16 || 14 >=14.18" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/pathe": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", - "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", - "license": "MIT", - "peer": true - }, - "node_modules/pathval": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pathval/-/pathval-2.0.1.tgz", - "integrity": "sha512-//nshmD55c46FuFw26xV/xFAaB5HF9Xdap7HJBBnrKdAd6/GxDBaNA1870O79+9ueg61cZLSVc+OaFlfmObYVQ==", - "license": "MIT", - "peer": true, - "engines": { - "node": ">= 14.16" - } - }, "node_modules/pbkdf2": { "version": "3.1.5", "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.5.tgz", @@ -5017,12 +3259,15 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", - "license": "ISC" + "dev": true, + "license": "ISC", + "optional": true }, "node_modules/picomatch": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "dev": true, "license": "MIT", "engines": { "node": ">=12" @@ -5044,32 +3289,6 @@ "node": ">=8" } }, - "node_modules/portfinder": { - "version": "1.0.32", - "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.32.tgz", - "integrity": "sha512-on2ZJVVDXRADWE6jnQaX0ioEylzgBpQk8r55NE4wjXW1ZxO+BgDlY6DXwj20i0V8eB4SenDQ00WEaxfiIQPcxg==", - "license": "MIT", - "dependencies": { - "async": "^2.6.4", - "debug": "^3.2.7", - "mkdirp": "^0.5.6" - }, - "engines": { - "node": ">= 0.12.0" - } - }, - "node_modules/portfinder/node_modules/mkdirp": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", - "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", - "license": "MIT", - "dependencies": { - "minimist": "^1.2.6" - }, - "bin": { - "mkdirp": "bin/cmd.js" - } - }, "node_modules/possible-typed-array-names": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz", @@ -5079,47 +3298,12 @@ "node": ">= 0.4" } }, - "node_modules/postcss": { - "version": "8.5.6", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", - "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/postcss" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "peer": true, - "dependencies": { - "nanoid": "^3.3.11", - "picocolors": "^1.1.1", - "source-map-js": "^1.2.1" - }, - "engines": { - "node": "^10 || ^12 || >=14" - } - }, "node_modules/process-nextick-args": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", "license": "MIT" }, - "node_modules/property-expr": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/property-expr/-/property-expr-2.0.6.tgz", - "integrity": "sha512-SVtmxhRE/CGkn3eZY1T6pC8Nln6Fr/lu1mKSgRud0eC73whjGfoAogbn78LkD8aFL0zz3bAFerKSnOl7NlErBA==", - "license": "MIT" - }, "node_modules/protobufjs": { "version": "7.5.4", "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.5.4.tgz", @@ -5179,16 +3363,6 @@ "node": ">=6" } }, - "node_modules/ramda": { - "version": "0.30.1", - "resolved": "https://registry.npmjs.org/ramda/-/ramda-0.30.1.tgz", - "integrity": "sha512-tEF5I22zJnuclswcZMc8bDIrwRHRzf+NqVEmqg50ShAZMP7MWeR/RGDthfM/p+BlqvF2fXAzpn8i+SJcYD3alw==", - "license": "MIT", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/ramda" - } - }, "node_modules/randombytes": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", @@ -5229,30 +3403,6 @@ "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", "license": "MIT" }, - "node_modules/readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "license": "MIT", - "dependencies": { - "picomatch": "^2.2.1" - }, - "engines": { - "node": ">=8.10.0" - } - }, - "node_modules/readdirp/node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "license": "MIT", - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, "node_modules/readonly-date": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/readonly-date/-/readonly-date-1.0.0.tgz", @@ -5286,56 +3436,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/rimraf": { - "version": "5.0.10", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.10.tgz", - "integrity": "sha512-l0OE8wL34P4nJH/H2ffoaniAokM2qSmrtXHmlpvYr5AVVX8msAyW0l8NVJFDxlSK4u3Uh/f41cQheDVdnYijwQ==", - "license": "ISC", - "dependencies": { - "glob": "^10.3.7" - }, - "bin": { - "rimraf": "dist/esm/bin.mjs" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/rimraf/node_modules/glob": { - "version": "10.5.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz", - "integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==", - "license": "ISC", - "dependencies": { - "foreground-child": "^3.1.0", - "jackspeak": "^3.1.2", - "minimatch": "^9.0.4", - "minipass": "^7.1.2", - "package-json-from-dist": "^1.0.0", - "path-scurry": "^1.11.1" - }, - "bin": { - "glob": "dist/esm/bin.mjs" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/rimraf/node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/ripemd160": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.3.tgz", @@ -5380,6 +3480,7 @@ "version": "4.53.2", "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.53.2.tgz", "integrity": "sha512-MHngMYwGJVi6Fmnk6ISmnk7JAHRNF0UkuucA0CUW3N3a4KnONPEZz+vUanQP/ZC/iY1Qkf3bwPWzyY84wEks1g==", + "dev": true, "license": "MIT", "dependencies": { "@types/estree": "1.0.8" @@ -5605,79 +3706,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "license": "MIT", - "dependencies": { - "shebang-regex": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/siginfo": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz", - "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==", - "license": "ISC", - "peer": true - }, - "node_modules/signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", - "license": "ISC", - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/source-map-js": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", - "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", - "license": "BSD-3-Clause", - "peer": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/stackback": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", - "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==", - "license": "MIT", - "peer": true - }, - "node_modules/std-env": { - "version": "3.10.0", - "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.10.0.tgz", - "integrity": "sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==", - "license": "MIT", - "peer": true - }, "node_modules/stream-browserify": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-3.0.0.tgz", @@ -5694,137 +3722,29 @@ "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", "license": "MIT", "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "license": "MIT", - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, - "node_modules/string_decoder/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "license": "MIT" - }, - "node_modules/string-width": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", - "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", - "license": "MIT", - "dependencies": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/string-width-cjs": { - "name": "string-width", - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/string-width-cjs/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/string-width-cjs/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "license": "MIT" - }, - "node_modules/string-width-cjs/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-ansi": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz", - "integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==", - "license": "MIT", - "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, - "node_modules/strip-ansi-cjs": { - "name": "strip-ansi", - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-ansi-cjs/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "license": "MIT", + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, "engines": { - "node": ">=8" + "node": ">= 6" } }, - "node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "license": "MIT", "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" + "safe-buffer": "~5.1.0" } }, + "node_modules/string_decoder/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "license": "MIT" + }, "node_modules/supports-preserve-symlinks-flag": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", @@ -5847,73 +3767,6 @@ "node": ">=0.10" } }, - "node_modules/tiny-case": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/tiny-case/-/tiny-case-1.0.3.tgz", - "integrity": "sha512-Eet/eeMhkO6TX8mnUteS9zgPbUMQa4I6Kkp5ORiBD5476/m+PIRiumP5tmh5ioJpH7k51Kehawy2UDfsnxxY8Q==", - "license": "MIT" - }, - "node_modules/tinybench": { - "version": "2.9.0", - "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz", - "integrity": "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==", - "license": "MIT", - "peer": true - }, - "node_modules/tinyexec": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-0.3.2.tgz", - "integrity": "sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==", - "license": "MIT", - "peer": true - }, - "node_modules/tinyglobby": { - "version": "0.2.15", - "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", - "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", - "license": "MIT", - "peer": true, - "dependencies": { - "fdir": "^6.5.0", - "picomatch": "^4.0.3" - }, - "engines": { - "node": ">=12.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/SuperchupuDev" - } - }, - "node_modules/tinypool": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-1.1.1.tgz", - "integrity": "sha512-Zba82s87IFq9A9XmjiX5uZA/ARWDrB03OHlq+Vw1fSdt0I+4/Kutwy8BP4Y/y/aORMo61FQ0vIb5j44vSo5Pkg==", - "license": "MIT", - "peer": true, - "engines": { - "node": "^18.0.0 || >=20.0.0" - } - }, - "node_modules/tinyrainbow": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-2.0.0.tgz", - "integrity": "sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw==", - "license": "MIT", - "peer": true, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/tinyspy": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-3.0.2.tgz", - "integrity": "sha512-n1cw8k1k0x4pgA2+9XrOkFydTerNcJ1zWCO5Nn9scWHTD+5tp8dghT2x1uduQePZTZgd3Tupf+x9BxJjeJi77Q==", - "license": "MIT", - "peer": true, - "engines": { - "node": ">=14.0.0" - } - }, "node_modules/to-buffer": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.2.2.tgz", @@ -5934,30 +3787,6 @@ "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", "license": "MIT" }, - "node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "license": "MIT", - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/toml": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/toml/-/toml-3.0.0.tgz", - "integrity": "sha512-y/mWCZinnvxjTKYhJ+pYxwD0mRLVvOtdS2Awbgxln6iEnt4rk0yBxeSBHkGJcPucRiG0e55mwWp+g/05rsrd6w==", - "license": "MIT" - }, - "node_modules/toposort": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/toposort/-/toposort-2.0.2.tgz", - "integrity": "sha512-0a5EOkAUp8D4moMi2W8ZF8jcga7BgZd91O/yabJCFY8az+XSzeGyTKs0Aoo897iV1Nj6guFq8orWDS96z91oGg==", - "license": "MIT" - }, "node_modules/tr46": { "version": "0.0.3", "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", @@ -6088,18 +3917,6 @@ "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", "license": "0BSD" }, - "node_modules/type-fest": { - "version": "4.34.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.34.1.tgz", - "integrity": "sha512-6kSc32kT0rbwxD6QL1CYe8IqdzN/J/ILMrNK+HMQCKH3insCDRY/3ITb0vcBss0a3t72fzh2YSzj8ko1HgwT3g==", - "license": "(MIT OR CC0-1.0)", - "engines": { - "node": ">=16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/typed-array-buffer": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz", @@ -6230,18 +4047,6 @@ "dev": true, "license": "MIT" }, - "node_modules/uglify-js": { - "version": "3.19.3", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.19.3.tgz", - "integrity": "sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ==", - "license": "BSD-2-Clause", - "bin": { - "uglifyjs": "bin/uglifyjs" - }, - "engines": { - "node": ">=0.8.0" - } - }, "node_modules/uint8arrays": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/uint8arrays/-/uint8arrays-5.1.0.tgz", @@ -6376,210 +4181,6 @@ } } }, - "node_modules/vite": { - "version": "6.4.1", - "resolved": "https://registry.npmjs.org/vite/-/vite-6.4.1.tgz", - "integrity": "sha512-+Oxm7q9hDoLMyJOYfUYBuHQo+dkAloi33apOPP56pzj+vsdJDzr+j1NISE5pyaAuKL4A3UD34qd0lx5+kfKp2g==", - "license": "MIT", - "peer": true, - "dependencies": { - "esbuild": "^0.25.0", - "fdir": "^6.4.4", - "picomatch": "^4.0.2", - "postcss": "^8.5.3", - "rollup": "^4.34.9", - "tinyglobby": "^0.2.13" - }, - "bin": { - "vite": "bin/vite.js" - }, - "engines": { - "node": "^18.0.0 || ^20.0.0 || >=22.0.0" - }, - "funding": { - "url": "https://github.com/vitejs/vite?sponsor=1" - }, - "optionalDependencies": { - "fsevents": "~2.3.3" - }, - "peerDependencies": { - "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", - "jiti": ">=1.21.0", - "less": "*", - "lightningcss": "^1.21.0", - "sass": "*", - "sass-embedded": "*", - "stylus": "*", - "sugarss": "*", - "terser": "^5.16.0", - "tsx": "^4.8.1", - "yaml": "^2.4.2" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - }, - "jiti": { - "optional": true - }, - "less": { - "optional": true - }, - "lightningcss": { - "optional": true - }, - "sass": { - "optional": true - }, - "sass-embedded": { - "optional": true - }, - "stylus": { - "optional": true - }, - "sugarss": { - "optional": true - }, - "terser": { - "optional": true - }, - "tsx": { - "optional": true - }, - "yaml": { - "optional": true - } - } - }, - "node_modules/vite-node": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-3.0.9.tgz", - "integrity": "sha512-w3Gdx7jDcuT9cNn9jExXgOyKmf5UOTb6WMHz8LGAm54eS1Elf5OuBhCxl6zJxGhEeIkgsE1WbHuoL0mj/UXqXg==", - "license": "MIT", - "peer": true, - "dependencies": { - "cac": "^6.7.14", - "debug": "^4.4.0", - "es-module-lexer": "^1.6.0", - "pathe": "^2.0.3", - "vite": "^5.0.0 || ^6.0.0" - }, - "bin": { - "vite-node": "vite-node.mjs" - }, - "engines": { - "node": "^18.0.0 || ^20.0.0 || >=22.0.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/vite-node/node_modules/debug": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", - "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", - "license": "MIT", - "peer": true, - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/vitest": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/vitest/-/vitest-3.0.9.tgz", - "integrity": "sha512-BbcFDqNyBlfSpATmTtXOAOj71RNKDDvjBM/uPfnxxVGrG+FSH2RQIwgeEngTaTkuU/h0ScFvf+tRcKfYXzBybQ==", - "license": "MIT", - "peer": true, - "dependencies": { - "@vitest/expect": "3.0.9", - "@vitest/mocker": "3.0.9", - "@vitest/pretty-format": "^3.0.9", - "@vitest/runner": "3.0.9", - "@vitest/snapshot": "3.0.9", - "@vitest/spy": "3.0.9", - "@vitest/utils": "3.0.9", - "chai": "^5.2.0", - "debug": "^4.4.0", - "expect-type": "^1.1.0", - "magic-string": "^0.30.17", - "pathe": "^2.0.3", - "std-env": "^3.8.0", - "tinybench": "^2.9.0", - "tinyexec": "^0.3.2", - "tinypool": "^1.0.2", - "tinyrainbow": "^2.0.0", - "vite": "^5.0.0 || ^6.0.0", - "vite-node": "3.0.9", - "why-is-node-running": "^2.3.0" - }, - "bin": { - "vitest": "vitest.mjs" - }, - "engines": { - "node": "^18.0.0 || ^20.0.0 || >=22.0.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" - }, - "peerDependencies": { - "@edge-runtime/vm": "*", - "@types/debug": "^4.1.12", - "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", - "@vitest/browser": "3.0.9", - "@vitest/ui": "3.0.9", - "happy-dom": "*", - "jsdom": "*" - }, - "peerDependenciesMeta": { - "@edge-runtime/vm": { - "optional": true - }, - "@types/debug": { - "optional": true - }, - "@types/node": { - "optional": true - }, - "@vitest/browser": { - "optional": true - }, - "@vitest/ui": { - "optional": true - }, - "happy-dom": { - "optional": true - }, - "jsdom": { - "optional": true - } - } - }, - "node_modules/vitest/node_modules/debug": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", - "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", - "license": "MIT", - "peer": true, - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, "node_modules/webidl-conversions": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", @@ -6596,21 +4197,6 @@ "webidl-conversions": "^3.0.0" } }, - "node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "license": "ISC", - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, "node_modules/which-typed-array": { "version": "1.1.19", "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.19.tgz", @@ -6632,117 +4218,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/why-is-node-running": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.3.0.tgz", - "integrity": "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==", - "license": "MIT", - "peer": true, - "dependencies": { - "siginfo": "^2.0.0", - "stackback": "0.0.2" - }, - "bin": { - "why-is-node-running": "cli.js" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/wordwrap": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", - "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==", - "license": "MIT" - }, - "node_modules/wrap-ansi": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", - "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", - "license": "MIT", - "dependencies": { - "ansi-styles": "^6.1.0", - "string-width": "^5.0.1", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/wrap-ansi-cjs": { - "name": "wrap-ansi", - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/wrap-ansi-cjs/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "license": "MIT" - }, - "node_modules/wrap-ansi-cjs/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/wrap-ansi-cjs/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/wrap-ansi/node_modules/ansi-styles": { - "version": "6.2.3", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", - "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", @@ -6785,7 +4260,7 @@ "version": "2.8.1", "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.1.tgz", "integrity": "sha512-lcYcMxX2PO9XMGvAJkJ3OsNMw+/7FKes7/hgerGUYWIoWu5j/+YQqcZr5JnPZWzOsEBgMbSbiSTn/dv/69Mkpw==", - "devOptional": true, + "dev": true, "license": "ISC", "bin": { "yaml": "bin.mjs" @@ -6793,30 +4268,6 @@ "engines": { "node": ">= 14.6" } - }, - "node_modules/yup": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/yup/-/yup-1.6.1.tgz", - "integrity": "sha512-JED8pB50qbA4FOkDol0bYF/p60qSEDQqBD0/qeIrUCG1KbPBIQ776fCUNb9ldbPcSTxA69g/47XTo4TqWiuXOA==", - "license": "MIT", - "dependencies": { - "property-expr": "^2.0.5", - "tiny-case": "^1.0.3", - "toposort": "^2.0.2", - "type-fest": "^2.19.0" - } - }, - "node_modules/yup/node_modules/type-fest": { - "version": "2.19.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", - "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", - "license": "(MIT OR CC0-1.0)", - "engines": { - "node": ">=12.20" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } } } } diff --git a/package.json b/package.json index 460982c7..ede28ed9 100644 --- a/package.json +++ b/package.json @@ -40,9 +40,9 @@ "author": "decocereus, makyl", "license": "MIT", "dependencies": { - "@avail-project/ca-common": "1.0.0-dev.4", - "@cosmjs/proto-signing": "^0.34.0", - "@cosmjs/stargate": "^0.34.0", + "@avail-project/ca-common": "1.0.0-rc.1", + "@cosmjs/proto-signing": "0.34.0", + "@cosmjs/stargate": "0.34.0", "@metamask/safe-event-emitter": "3.1.2", "@opentelemetry/api-logs": "0.208.0", "@opentelemetry/exporter-logs-otlp-http": "0.208.0", @@ -54,7 +54,6 @@ "buffer": "6.0.3", "decimal.js": "^10.6.0", "es-toolkit": "^1.40.0", - "fuels": "0.101.1", "it-ws": "^6.1.5", "long": "^5.3.2", "msgpackr": "^1.11.5", diff --git a/rollup.config.mjs b/rollup.config.mjs index 4beb091d..bcf95809 100644 --- a/rollup.config.mjs +++ b/rollup.config.mjs @@ -46,7 +46,6 @@ const baseConfig = { '@starkware-industries/starkware-crypto-utils', '@metamask/safe-event-emitter', 'decimal.js', - 'fuels', 'long', 'msgpackr', 'tslib', @@ -97,7 +96,6 @@ export default defineConfig([ '@tronweb3/tronwallet-abstract-adapter', 'tronweb', 'decimal.js', - 'fuels', 'long', 'msgpackr', 'tslib', diff --git a/src/commons/types/index.ts b/src/commons/types/index.ts index 8265184f..6b939a11 100644 --- a/src/commons/types/index.ts +++ b/src/commons/types/index.ts @@ -3,7 +3,6 @@ import { TransactionReceipt, ByteArray, Hex, WalletClient } from 'viem'; import { ChainDatum, Environment, PermitVariant, Universe } from '@avail-project/ca-common'; import Decimal from 'decimal.js'; import { SwapIntent } from './swap-types'; -import { FuelConnector, Provider } from 'fuels'; import { DirectSecp256k1Wallet } from '@cosmjs/proto-signing'; import { AdapterProps } from '@tronweb3/tronwallet-abstract-adapter'; import { SwapStepType } from './swap-steps'; @@ -18,7 +17,7 @@ type TokenInfo = { symbol: string; }; -type NexusNetwork = 'mainnet' | 'testnet' | 'devnet' | NetworkConfig; +type NexusNetwork = 'mainnet' | 'canary' | 'testnet' | NetworkConfig; export interface BlockTransaction { hash?: string; @@ -264,11 +263,6 @@ export type IBridgeOptions = { client: WalletClient; provider: EthereumProvider; }; - fuel?: { - address: string; - connector: FuelConnector; - provider: Provider; - }; tron?: { address: string; adapter: TronAdapter; @@ -368,8 +362,6 @@ export type FeeStoreData = { }[]; }; -export type FeeUniverse = 'ETHEREUM' | 'FUEL'; - export type Intent = { allSources: IntentSource[]; destination: IntentDestination; diff --git a/src/sdk/ca-base/ca.ts b/src/sdk/ca-base/ca.ts index 9fd57c93..335aefd9 100644 --- a/src/sdk/ca-base/ca.ts +++ b/src/sdk/ca-base/ca.ts @@ -1,13 +1,11 @@ import { createCosmosWallet, Universe } from '@avail-project/ca-common'; import { DirectSecp256k1Wallet } from '@cosmjs/proto-signing'; import { keyDerivation } from '@starkware-industries/starkware-crypto-utils'; -import { Account, FuelConnector, Provider } from 'fuels'; import { createWalletClient, custom, Hex, UserRejectedRequestError, WalletClient } from 'viem'; import { privateKeyToAccount, PrivateKeyAccount } from 'viem/accounts'; import { createSiweMessage } from 'viem/siwe'; import { ChainList } from './chains'; import { getNetworkConfig } from './config'; -import { FUEL_NETWORK_URL } from './constants'; import { ChainListType, EthereumProvider, @@ -87,12 +85,6 @@ export class CA { provider: EthereumProvider; address: Hex; }; - protected _fuel?: { - account: Account; - address: string; - connector: FuelConnector; - provider: Provider; - }; protected _tron?: { address: string; adapter: TronAdapter; @@ -145,7 +137,6 @@ export class CA { const bridgeHandler = new BridgeHandler(params, { chainList: this.chainList, cosmos: this.#cosmos!, - fuel: this._fuel, evm: this._evm, hooks: this._hooks, tron: this._tron, @@ -163,7 +154,6 @@ export class CA { return getMaxValueForBridge(params, { chainList: this.chainList, - fuel: this._fuel, evm: this._evm, tron: this._tron, networkConfig: this._networkConfig, @@ -204,7 +194,6 @@ export class CA { filter: false, isCA: includeSwappableBalances === false, vscDomain: this._networkConfig.VSC_DOMAIN, - fuelAddress: this._fuel?.address, tronAddress: this._tron?.address, }); return assets; @@ -277,7 +266,7 @@ export class CA { // Prevent concurrent initializations if (this._initStatus !== INIT_STATUS.CREATED) { - throw Errors.sdkInitStateNotExpected(this._initStatus); + throw Errors.sdkInitStateNotExpected(this._initStatus); } this._initStatus = INIT_STATUS.RUNNING; @@ -291,7 +280,7 @@ export class CA { this._initStatus = INIT_STATUS.DONE; } catch (e) { this._initStatus = INIT_STATUS.CREATED; - logger.error('Error initializing CA', e, {cause: 'SDK_NOT_INITIALIZED'}); + logger.error('Error initializing CA', e, { cause: 'SDK_NOT_INITIALIZED' }); throw e; } })(); @@ -350,37 +339,6 @@ export class CA { }; }; - protected _setFuelConnector = async (connector: FuelConnector) => { - if (this._fuel?.connector === connector) { - return; - } - - logger.debug('setFuelConnector', { - connected: connector.connected, - connector: connector, - }); - - if (!(await connector.isConnected())) { - await connector.connect(); - } - - const address = await connector.currentAccount(); - if (!address) { - throw Errors.accountConnectionFailed(); - } - - const provider = new Provider(FUEL_NETWORK_URL, { - resourceCacheTTL: -1, - }); - - this._fuel = { - account: new Account(address, provider, connector), - address, - connector, - provider, - }; - }; - protected _setOnAllowanceHook = (hook: OnAllowanceHook) => { this._hooks.onAllowance = hook; }; @@ -413,7 +371,7 @@ export class CA { await refundExpiredIntents(account, this._networkConfig.COSMOS_URL, this.#cosmos!.wallet); }, minutesToMs(10)); } catch (e) { - logger.error('Error checking pending refunds', e, {cause: 'REFUND_CHECK_ERROR'}); + logger.error('Error checking pending refunds', e, { cause: 'REFUND_CHECK_ERROR' }); } }; @@ -572,10 +530,6 @@ export class CA { }; private readonly universeCheck = (dstChain: Chain) => { - if (dstChain.universe === Universe.FUEL && !this._fuel) { - throw Errors.walletNotConnected('Fuel'); - } - if (dstChain.universe === Universe.TRON && !this._tron) { throw Errors.walletNotConnected('Tron'); } diff --git a/src/sdk/ca-base/chains.ts b/src/sdk/ca-base/chains.ts index 58dc00dc..486c6e94 100644 --- a/src/sdk/ca-base/chains.ts +++ b/src/sdk/ca-base/chains.ts @@ -17,14 +17,14 @@ class ChainList { constructor(env: Environment) { switch (env) { - case Environment.CERISE: + case Environment.JADE: case Environment.CORAL: this.chains = MAINNET_CHAINS; break; case Environment.FOLLY: this.chains = TESTNET_CHAINS; break; - case Environment.JADE: + case Environment.CERISE: throw Errors.environmentNotSupported('Jade'); default: throw Errors.environmentNotKnown(); @@ -473,55 +473,6 @@ const TESTNET_CHAINS: Chain[] = [ ]; const MAINNET_CHAINS: Chain[] = [ - // { - // blockExplorers: { - // default: { - // name: 'Fuel Network Explorer', - // url: 'https://app.fuel.network/', - // }, - // }, - // custom: { - // icon: 'https://avatars.githubusercontent.com/u/55993183', - // knownTokens: [ - // { - // contractAddress: FUEL_BASE_ASSET_ID, - // decimals: 9, - // logo: getLogoFromSymbol('ETH'), - // name: 'Ether', - // symbol: 'ETH', - // }, - // { - // contractAddress: '0x286c479da40dc953bddc3bb4c453b608bba2e0ac483b077bd475174115395e6b', - // decimals: 6, - // logo: getLogoFromSymbol('USDC'), - // name: 'USD Coin', - // symbol: 'USDC', - // }, - // { - // contractAddress: '0xa0265fb5c32f6e8db3197af3c7eb05c48ae373605b8165b6f4a51c5b0ba4812e', - // decimals: 6, - // logo: getLogoFromSymbol('USDT'), - // name: 'Tether USD', - // symbol: 'USDT', - // }, - // ], - // }, - // id: CHAIN_IDS.fuel.mainnet, - // name: 'Fuel Network', - // ankrName: '', - // nativeCurrency: { - // decimals: 9, - // name: 'Ether', - // symbol: 'ETH', - // }, - // rpcUrls: { - // default: { - // http: [FUEL_NETWORK_URL], - // webSocket: [], - // }, - // }, - // universe: Universe.FUEL, - // }, { blockExplorers: { default: { diff --git a/src/sdk/ca-base/config.ts b/src/sdk/ca-base/config.ts index 68696395..9f1f7b44 100644 --- a/src/sdk/ca-base/config.ts +++ b/src/sdk/ca-base/config.ts @@ -2,7 +2,16 @@ import { Environment } from '@avail-project/ca-common'; import { NetworkConfig, NexusNetwork } from '../../commons'; -// Testnet with mainnet tokens +// Mainnet +const JADE_CONFIG: NetworkConfig = { + COSMOS_URL: 'https://cosmos-mainnet.availproject.org', + EXPLORER_URL: 'https://nexus-explorer.availproject.org', + GRPC_URL: 'https://grpcproxy-mainnet.availproject.org', + NETWORK_HINT: Environment.JADE, + VSC_DOMAIN: 'vsc-mainnet.availproject.org', +}; + +// Canary const CORAL_CONFIG: NetworkConfig = { COSMOS_URL: 'https://cosmos01-testnet.arcana.network', EXPLORER_URL: 'https://explorer.nexus.availproject.org', @@ -11,16 +20,7 @@ const CORAL_CONFIG: NetworkConfig = { VSC_DOMAIN: 'vsc1-testnet.arcana.network', }; -// Dev with mainnet tokens -const CERISE_CONFIG: NetworkConfig = { - COSMOS_URL: 'https://cosmos01-dev.arcana.network', - EXPLORER_URL: 'https://explorer.nexus-cerise.availproject.org', - GRPC_URL: 'https://mimosa-dash-grpc.arcana.network', - NETWORK_HINT: Environment.CERISE, - VSC_DOMAIN: 'mimosa-dash-vsc.arcana.network', -}; - -// Dev with testnet tokens +// Testnet const FOLLY_CONFIG: NetworkConfig = { COSMOS_URL: 'https://cosmos04-dev.arcana.network', EXPLORER_URL: 'https://explorer.nexus-folly.availproject.org', @@ -55,13 +55,13 @@ const getNetworkConfig = (network?: NexusNetwork): NetworkConfig => { return network; } switch (network) { - case 'devnet': - return CERISE_CONFIG; + case 'canary': + return CORAL_CONFIG; case 'testnet': return FOLLY_CONFIG; default: - return CORAL_CONFIG; + return JADE_CONFIG; } }; -export { CERISE_CONFIG, CORAL_CONFIG, getNetworkConfig }; +export { getNetworkConfig }; diff --git a/src/sdk/ca-base/constants.ts b/src/sdk/ca-base/constants.ts index 371583ec..9742e229 100644 --- a/src/sdk/ca-base/constants.ts +++ b/src/sdk/ca-base/constants.ts @@ -1,7 +1,5 @@ import { Universe } from '@avail-project/ca-common'; -const FUEL_NETWORK_URL = 'https://mainnet.fuel.network/v1/graphql'; - const SymbolToLogo: { [k: string]: string } = { BNB: 'https://assets.coingecko.com/coins/images/825/large/bnb-icon2_2x.png', AVAX: 'https://assets.coingecko.com/coins/images/12559/standard/Avalanche_Circle_RedWhite_Trans.png', @@ -17,8 +15,6 @@ const SymbolToLogo: { [k: string]: string } = { HYPE: 'https://assets.coingecko.com/coins/images/50882/large/hyperliquid.jpg', }; -const FUEL_BASE_ASSET_ID = '0xf8f8b6283d7fa5b672b530cbb84fcccb4ff8dc40f8176ef4544ddb1f1952ad07'; - const getLogoFromSymbol = (symbol: string) => { const logo = SymbolToLogo[symbol]; if (!logo) { @@ -30,11 +26,7 @@ const getLogoFromSymbol = (symbol: string) => { const isNativeAddress = (universe: Universe, address: `0x${string}`) => { if (universe === Universe.ETHEREUM || universe === Universe.TRON) { - return address === ZERO_ADDRESS || address === ZERO_ADDRESS_FUEL; - } - - if (universe === Universe.FUEL) { - return address === FUEL_BASE_ASSET_ID; + return address === ZERO_ADDRESS || address === ZERO_ADDRESS_BYTES_32; } // Handle other universes or return false by default @@ -45,13 +37,6 @@ const INTENT_EXPIRY = 15 * 60 * 1000; const ZERO_ADDRESS: `0x${string}` = '0x0000000000000000000000000000000000000000'; -const ZERO_ADDRESS_FUEL = '0x0000000000000000000000000000000000000000000000000000000000000000'; +const ZERO_ADDRESS_BYTES_32 = '0x0000000000000000000000000000000000000000000000000000000000000000'; -export { - FUEL_BASE_ASSET_ID, - FUEL_NETWORK_URL, - getLogoFromSymbol, - INTENT_EXPIRY, - isNativeAddress, - ZERO_ADDRESS, -}; +export { getLogoFromSymbol, INTENT_EXPIRY, isNativeAddress, ZERO_ADDRESS }; diff --git a/src/sdk/ca-base/errors.ts b/src/sdk/ca-base/errors.ts index 0798a6a9..64e73e4e 100644 --- a/src/sdk/ca-base/errors.ts +++ b/src/sdk/ca-base/errors.ts @@ -69,11 +69,6 @@ export const Errors = { details: { result }, }), - fuelDepositFailed: (result: unknown) => - createError(ERROR_CODES.FUEL_DEPOSIT_FAIL, 'Fuel deposit transaction failed.', { - details: { result }, - }), - liquidityTimeout: () => createError(ERROR_CODES.LIQUIDITY_TIMEOUT, 'Timed out waiting for fulfilment.'), diff --git a/src/sdk/ca-base/nexusError.ts b/src/sdk/ca-base/nexusError.ts index 4092b90f..3afc23bb 100644 --- a/src/sdk/ca-base/nexusError.ts +++ b/src/sdk/ca-base/nexusError.ts @@ -45,7 +45,6 @@ export const ERROR_CODES = { UNKNOWN_SIGNATURE: 'UNKNOWN_SIGNATURE', TRON_DEPOSIT_FAIL: 'TRON_DEPOSIT_FAIL', TRON_APPROVAL_FAIL: 'TRON_APPROVAL_FAIL', - FUEL_DEPOSIT_FAIL: 'FUEL_DEPOSIT_FAIL', LIQUIDITY_TIMEOUT: 'LIQUIDITY_TIMEOUT', USER_DENIED_INTENT: 'USER_DENIED_INTENT', USER_DENIED_ALLOWANCE: 'USER_DENIED_ALLOWANCE', @@ -119,7 +118,6 @@ function handleNexusError(err: unknown) { break; case ERROR_CODES.TRON_DEPOSIT_FAIL: - case ERROR_CODES.FUEL_DEPOSIT_FAIL: console.warn('Deposit failed'); // Possibly ask user to retry break; diff --git a/src/sdk/ca-base/requestHandlers/bridge.ts b/src/sdk/ca-base/requestHandlers/bridge.ts index 8cbedebb..1b2eac32 100644 --- a/src/sdk/ca-base/requestHandlers/bridge.ts +++ b/src/sdk/ca-base/requestHandlers/bridge.ts @@ -1,5 +1,4 @@ import { - ArcanaVault, ChaindataMap, ERC20ABI, EVMVaultABI, @@ -8,7 +7,6 @@ import { Universe, } from '@avail-project/ca-common'; import Decimal from 'decimal.js'; -import { Account, BN, CHAIN_IDS, hexlify } from 'fuels'; import Long from 'long'; import { ContractFunctionExecutionError, @@ -117,7 +115,6 @@ class BridgeHandler { vscDomain: this.options.networkConfig.VSC_DOMAIN, evmAddress: this.options.evm.address, chainList: this.options.chainList, - fuelAddress: this.options.fuel?.address, tronAddress: this.options.tron?.address, isCA: true, }), @@ -407,7 +404,6 @@ class BridgeHandler { } const evmDeposits: Promise[] = []; - const fuelDeposits: Promise[] = []; const tronDeposits: Promise[] = []; const evmSignatureData = signatureData.find((d) => d.universe === Universe.ETHEREUM); @@ -416,12 +412,6 @@ class BridgeHandler { throw Errors.internal('ethereum in universe list but no signature data present'); } - const fuelSignatureData = signatureData.find((d) => d.universe === Universe.FUEL); - - if (!fuelSignatureData && universes.has(Universe.FUEL)) { - throw Errors.internal('fuel in universe list but no signature data present'); - } - const tronSignatureData = signatureData.find((d) => d.universe === Universe.TRON); if (!tronSignatureData && universes.has(Universe.TRON)) { @@ -436,47 +426,7 @@ class BridgeHandler { throw Errors.chainNotFound(s.chainID); } - if (s.universe === Universe.FUEL) { - if (!this.options.fuel) { - throw Errors.internal('fuel is involved but no associated data'); - } - - const account = new Account( - this.options.fuel.address, - this.options.fuel.provider, - this.options.fuel.connector, - ); - - const vault = new ArcanaVault( - this.options.chainList.getVaultContractAddress(CHAIN_IDS.fuel.mainnet), - account, - ); - - const tx = await vault.functions - .deposit(omniversalRFF.asFuelRFF(), hexlify(fuelSignatureData!.signature), i) - .callParams({ - forward: { - amount: new BN(s.valueRaw.toString()), - assetId: s.tokenAddress, - }, - }) - .call(); - - this.markStepDone(BRIDGE_STEPS.INTENT_DEPOSIT_REQUEST(i + 1, s.value, chain)); - - fuelDeposits.push( - (async function () { - const result = await tx.waitForResult(); - logger.debug('PostIntentSubmission: Fuel deposit result', { - result, - }); - - if (result.transactionResult.isStatusFailure) { - throw Errors.fuelDepositFailed(result.transactionResult); - } - })(), - ); - } else if (s.universe === Universe.ETHEREUM && isNativeAddress(s.universe, s.tokenAddress)) { + if (s.universe === Universe.ETHEREUM && isNativeAddress(s.universe, s.tokenAddress)) { await switchChain(this.options.evm.client, chain); const publicClient = createPublicClientWithFallback(chain); @@ -554,12 +504,8 @@ class BridgeHandler { ); } - if (evmDeposits.length || fuelDeposits.length || tronDeposits.length) { - await Promise.all([ - Promise.all(evmDeposits), - Promise.all(tronDeposits), - Promise.all(fuelDeposits), - ]); + if (evmDeposits.length || tronDeposits.length) { + await Promise.all([Promise.all(evmDeposits), Promise.all(tronDeposits)]); this.markStepDone(BRIDGE_STEPS.INTENT_DEPOSITS_CONFIRMED); } @@ -804,7 +750,7 @@ class BridgeHandler { } this.markStepDone(BRIDGE_STEPS.ALLOWANCE_COMPLETE); } catch (e) { - logger.error('Error setting allowances', e, {cause: 'ALLOWANCE_SETTING_ERROR'}); + logger.error('Error setting allowances', e, { cause: 'ALLOWANCE_SETTING_ERROR' }); throw e; } finally { if (this.params.dstChain.universe === Universe.ETHEREUM) { diff --git a/src/sdk/ca-base/requestHandlers/bridgeMax.ts b/src/sdk/ca-base/requestHandlers/bridgeMax.ts index 5d7edacd..f25312dc 100644 --- a/src/sdk/ca-base/requestHandlers/bridgeMax.ts +++ b/src/sdk/ca-base/requestHandlers/bridgeMax.ts @@ -17,7 +17,6 @@ const getMaxValueForBridge = async ( vscDomain: options.networkConfig.VSC_DOMAIN, evmAddress: options.evm.address, chainList: options.chainList, - fuelAddress: options.fuel?.address, tronAddress: options.tron?.address, isCA: true, }), diff --git a/src/sdk/ca-base/swap/utils.ts b/src/sdk/ca-base/swap/utils.ts index 6fa434df..d808d410 100644 --- a/src/sdk/ca-base/swap/utils.ts +++ b/src/sdk/ca-base/swap/utils.ts @@ -754,16 +754,14 @@ export const balancesToAssets = ( ankrBalances: AnkrBalances, chainList: ChainListType, evmBalances: UnifiedBalanceResponseData[] = [], - fuelBalances: UnifiedBalanceResponseData[] = [], tronBalances: UnifiedBalanceResponseData[] = [], ) => { const assets: UserAssetDatum[] = []; - const vscBalances = evmBalances.concat(fuelBalances).concat(tronBalances); + const vscBalances = evmBalances.concat(tronBalances); logger.debug('balanceToAssets', { ankrBalances, evmBalances, - fuelBalances, tronBalances, }); for (const balance of vscBalances) { @@ -1615,7 +1613,7 @@ export const performDestinationSwap = async ({ }, 2); return hash; } catch (e) { - logger.error('destination swap failed twice, sweeping to eoa', e, {cause: 'SWAP_FAILED'}); + logger.error('destination swap failed twice, sweeping to eoa', e, { cause: 'SWAP_FAILED' }); await vscSBCTx( [ await createSBCTxFromCalls({ @@ -1635,7 +1633,7 @@ export const performDestinationSwap = async ({ ], vscDomain, ).catch((e) => { - logger.error('error during destination sweep', e, {cause: 'DESTINATION_SWEEP_ERROR'}); + logger.error('error during destination sweep', e, { cause: 'DESTINATION_SWEEP_ERROR' }); }); throw e; } diff --git a/src/sdk/ca-base/utils/api.utils.ts b/src/sdk/ca-base/utils/api.utils.ts index 830ec5ab..c7965042 100644 --- a/src/sdk/ca-base/utils/api.utils.ts +++ b/src/sdk/ca-base/utils/api.utils.ts @@ -132,9 +132,7 @@ export const intentTransform = (input: RequestForFunds[], chainList: ChainListTy async function fetchProtocolFees(grpcURL: string) { try { - const response = await getCosmosQueryClient(grpcURL).ProtocolFees({ - Universe: Universe.FUEL, - }); + const response = await getCosmosQueryClient(grpcURL).ProtocolFees({}); return response; } catch (error) { logger.error('Failed to fetch protocol fees', error); @@ -184,7 +182,7 @@ const getCoinbasePrices = async () => { coinbasePrices.rates = exchange.data.data.rates; coinbasePrices.lastUpdatedAt = Date.now(); } catch (error) { - logger.error('Failed to fetch Coinbase prices', error, {cause: 'INTERNAL_ERROR'}); + logger.error('Failed to fetch Coinbase prices', error, { cause: 'INTERNAL_ERROR' }); // Return cached rates if available, otherwise throw if (Object.keys(coinbasePrices.rates).length === 0) { throw Errors.internal('Failed to fetch exchange rates and no cache available'); @@ -365,7 +363,7 @@ const getVscReq = (vscDomain: string) => { export const getBalancesFromVSC = async ( vscDomain: string, address: `0x${string}`, - namespace: 'ETHEREUM' | 'FUEL' | 'TRON' = 'ETHEREUM', + namespace: 'ETHEREUM' | 'TRON' = 'ETHEREUM', ) => { const response = await getVscReq(vscDomain).get<{ balances: UnifiedBalanceResponseData[]; @@ -378,10 +376,6 @@ export const getEVMBalancesForAddress = async (vscDomain: string, address: `0x${ return getBalancesFromVSC(vscDomain, address); }; -export const getFuelBalancesForAddress = async (vscDomain: string, address: `0x${string}`) => { - return getBalancesFromVSC(vscDomain, address, 'FUEL'); -}; - export const getTronBalancesForAddress = async (vscDomain: string, address: `0x${string}`) => { return getBalancesFromVSC(vscDomain, address, 'TRON'); }; diff --git a/src/sdk/ca-base/utils/balance.utils.ts b/src/sdk/ca-base/utils/balance.utils.ts index 514f19c9..14c77b02 100644 --- a/src/sdk/ca-base/utils/balance.utils.ts +++ b/src/sdk/ca-base/utils/balance.utils.ts @@ -1,11 +1,6 @@ import { Environment } from '@avail-project/ca-common'; import { ChainListType, logger, SUPPORTED_CHAINS } from '../../../commons'; -import { - equalFold, - getEVMBalancesForAddress, - getFuelBalancesForAddress, - getTronBalancesForAddress, -} from '.'; +import { equalFold, getEVMBalancesForAddress, getTronBalancesForAddress } from '.'; import { encodePacked, Hex, keccak256, pad, toHex } from 'viem'; import { balancesToAssets, getAnkrBalances, toFlatBalance } from '../swap/utils'; import { filterSupportedTokens } from '../swap/data'; @@ -25,7 +20,6 @@ export const getBalances = async (input: { chainList: ChainListType; removeTransferFee?: boolean; filter?: boolean; - fuelAddress?: string; tronAddress?: string; isCA?: boolean; vscDomain: string; @@ -35,27 +29,17 @@ export const getBalances = async (input: { const removeTransferFee = input.removeTransferFee ?? false; const filter = input.filter ?? true; - const [ankrBalances, evmBalances, fuelBalances, tronBalances] = await Promise.all([ + const [ankrBalances, evmBalances, tronBalances] = await Promise.all([ input.networkHint === Environment.FOLLY || isCA ? Promise.resolve([]) : getAnkrBalances(input.evmAddress, input.chainList, removeTransferFee), getEVMBalancesForAddress(input.vscDomain, input.evmAddress), - input.fuelAddress - ? getFuelBalancesForAddress(input.vscDomain, input.fuelAddress as `0x${string}`) - : Promise.resolve([]), input.tronAddress ? getTronBalancesForAddress(input.vscDomain, input.tronAddress as Hex) : Promise.resolve([]), ]); - const assets = balancesToAssets( - isCA, - ankrBalances, - input.chainList, - evmBalances, - fuelBalances, - tronBalances, - ); + const assets = balancesToAssets(isCA, ankrBalances, input.chainList, evmBalances, tronBalances); let balances = toFlatBalance(assets); if (filter) { diff --git a/src/sdk/ca-base/utils/common.utils.ts b/src/sdk/ca-base/utils/common.utils.ts index 7ad33b4c..c444b145 100644 --- a/src/sdk/ca-base/utils/common.utils.ts +++ b/src/sdk/ca-base/utils/common.utils.ts @@ -1,5 +1,4 @@ import { - ArcanaVault, Bytes, DepositVEPacket, Environment, @@ -11,7 +10,6 @@ import { } from '@avail-project/ca-common'; import { DirectSecp256k1Wallet } from '@cosmjs/proto-signing'; import Decimal from 'decimal.js'; -import { arrayify, FuelConnector, hexlify, Provider } from 'fuels'; import Long from 'long'; import { ByteArray, @@ -35,7 +33,7 @@ import { } from 'viem'; import { TronWeb, Types, utils } from 'tronweb'; import { ChainList } from '../chains'; -import { FUEL_BASE_ASSET_ID, isNativeAddress, ZERO_ADDRESS } from '../constants'; +import { isNativeAddress, ZERO_ADDRESS } from '../constants'; import { getLogger, IBridgeOptions, @@ -78,21 +76,6 @@ function convertAddressByUniverse(input: ByteArray | Hex, universe: Universe) { throw Errors.invalidAddressLength('evm|tron'); } - if (universe === Universe.FUEL) { - if (bytes.length === 32) { - return inputIsString ? input : bytes; - } - if (bytes.length === 20) { - const padded = pad(bytes, { - dir: 'left', - size: 32, - }); - return inputIsString ? toHex(padded) : padded; - } - - throw Errors.invalidAddressLength('fuel'); - } - return toHex(input); } @@ -189,26 +172,6 @@ const equalFold = (a?: string, b?: string) => { return a.toLowerCase() === b.toLowerCase(); }; -const createRequestFuelSignature = async ( - fuelVaultAddress: string, - provider: Provider, - connector: FuelConnector, - fuelRFF: Parameters[0], -) => { - const account = await connector.currentAccount(); - if (!account) { - throw Errors.internal('Fuel connector is not connected.'); - } - - const vault = new ArcanaVault(hexlify(fuelVaultAddress), provider); - const { value: hash } = await vault.functions.hash_request(fuelRFF).get(); - const signature = await connector.signMessage(account, { - personalSign: arrayify(hash), - }); - - return { requestHash: hash as Hex, signature: arrayify(signature) }; -}; - const getExplorerURL = (baseURL: string, id: Long) => { return new URL(`/intent/${id.toNumber()}`, baseURL).toString(); }; @@ -407,10 +370,7 @@ const convertGasToToken = ( const gasTokenInUSD = oraclePrices .find( - (rate) => - rate.chainId === destinationChainID && - (equalFold(rate.tokenAddress, ZERO_ADDRESS) || - equalFold(rate.tokenAddress, FUEL_BASE_ASSET_ID)), + (rate) => rate.chainId === destinationChainID && equalFold(rate.tokenAddress, ZERO_ADDRESS), ) ?.priceUsd.toFixed() ?? '0'; @@ -471,13 +431,7 @@ const convertTo32BytesHex = (value: Hex | Bytes) => { }; const convertToHexAddressByUniverse = (address: Uint8Array, universe: Universe) => { - if (universe === Universe.FUEL) { - if (address.length === 32) { - return bytesToHex(address); - } else { - throw Errors.invalidAddressLength('fuel'); - } - } else if (universe === Universe.ETHEREUM || universe === Universe.TRON) { + if (universe === Universe.ETHEREUM || universe === Universe.TRON) { if (address.length === 20) { return bytesToHex(address); } else if (address.length === 32) { @@ -561,10 +515,6 @@ class UserAsset { return equalFold(tokenAddress, ZERO_ADDRESS); } - if (universe === Universe.FUEL) { - return true; - } - return false; } @@ -731,7 +681,9 @@ async function waitForTronTxConfirmation( } } } catch (err) { - logger.error(`⚠️ Error while checking transaction:`, err, {cause: 'TRANSACTION_CHECK_ERROR'}); + logger.error(`⚠️ Error while checking transaction:`, err, { + cause: 'TRANSACTION_CHECK_ERROR', + }); // Don’t throw yet; continue polling } @@ -739,7 +691,7 @@ async function waitForTronTxConfirmation( await new Promise((resolve) => setTimeout(resolve, interval)); } - throw Errors.transactionTimeout((timeout / 1000)); + throw Errors.transactionTimeout(timeout / 1000); } async function waitForTronDepositTxConfirmation( @@ -786,7 +738,9 @@ async function waitForTronDepositTxConfirmation( return; } catch (err) { - logger.error(`⚠️ Error while checking transaction:`, err, {cause: 'TRANSACTION_CHECK_ERROR'}); + logger.error(`⚠️ Error while checking transaction:`, err, { + cause: 'TRANSACTION_CHECK_ERROR', + }); // Don’t throw yet; continue polling } @@ -794,7 +748,7 @@ async function waitForTronDepositTxConfirmation( await new Promise((resolve) => setTimeout(resolve, interval)); } - throw Errors.transactionTimeout((timeout / 1000)); + throw Errors.transactionTimeout(timeout / 1000); } function pctAdditionToBigInt(base: bigint, percentage: number) { @@ -856,7 +810,9 @@ async function waitForTronApprovalTxConfirmation( return; } catch (err) { - logger.error(`⚠️ Error while checking transaction:`, err, {cause: 'TRANSACTION_CHECK_ERROR'}); + logger.error(`⚠️ Error while checking transaction:`, err, { + cause: 'TRANSACTION_CHECK_ERROR', + }); // Don’t throw yet; continue polling } @@ -864,24 +820,16 @@ async function waitForTronApprovalTxConfirmation( await new Promise((resolve) => setTimeout(resolve, interval)); } - throw Errors.transactionTimeout((timeout / 1000)); + throw Errors.transactionTimeout(timeout / 1000); } const createExplorerTxURL = (txHash: Hex, explorerURL: string) => { return new URL(`/tx/${txHash}`, explorerURL).href; }; -const retrieveAddress = ( - universe: Universe, - input: Pick, -): Hex => { +const retrieveAddress = (universe: Universe, input: Pick): Hex => { if (universe === Universe.ETHEREUM) { return input.evm.address; - } else if (universe === Universe.FUEL) { - if (!input.fuel) { - throw Errors.internal('fuel source but no fuel input'); - } - return input.fuel.address as Hex; } else if (universe === Universe.TRON) { if (!input.tron) { throw Errors.internal('tron source but no tron input'); @@ -928,7 +876,6 @@ export { convertToHexAddressByUniverse, createDepositDoubleCheckTx, createRequestEVMSignature, - createRequestFuelSignature, divDecimals, equalFold, evmWaitForFill, diff --git a/src/sdk/ca-base/utils/contract.utils.ts b/src/sdk/ca-base/utils/contract.utils.ts index 35f145c4..05bfa378 100644 --- a/src/sdk/ca-base/utils/contract.utils.ts +++ b/src/sdk/ca-base/utils/contract.utils.ts @@ -1,6 +1,5 @@ import { Currency, PermitCreationError, PermitVariant } from '@avail-project/ca-common'; import { ERC20ABI as ERC20ABIC } from '@avail-project/ca-common'; -import { CHAIN_IDS } from 'fuels'; import { Account, Address, @@ -95,15 +94,11 @@ const getAllowances = async ( const values: { [k: number]: bigint } = {}; const promises = []; for (const i of input) { - if (i.chainID === CHAIN_IDS.fuel.mainnet) { - promises.push(Promise.resolve(0n)); - } else { - const chain = chainList.getChainByID(i.chainID); - if (!chain) { - throw Errors.chainNotFound(i.chainID); - } - promises.push(getAllowance(chain, i.holderAddress, i.tokenContract, chainList)); + const chain = chainList.getChainByID(i.chainID); + if (!chain) { + throw Errors.chainNotFound(i.chainID); } + promises.push(getAllowance(chain, i.holderAddress, i.tokenContract, chainList)); } const result = await Promise.all(promises); for (const i in result) { @@ -438,13 +433,10 @@ async function signPermitForAddressAndValue( } const createPublicClientWithFallback = (chain: Chain): PublicClient => { - if (chain.rpcUrls.default.http.length === 1) { - return createPublicClient({ - transport: http(chain.rpcUrls.default.http[0]), - }); - } return createPublicClient({ - transport: fallback(chain.rpcUrls.default.http.map((s) => http(s))), + transport: fallback( + chain.rpcUrls.default.http.concat(chain.rpcUrls.default.publicHttp ?? []).map((s) => http(s)), + ), }); }; diff --git a/src/sdk/ca-base/utils/cosmos.utils.ts b/src/sdk/ca-base/utils/cosmos.utils.ts index c6aca9ff..bb19a290 100644 --- a/src/sdk/ca-base/utils/cosmos.utils.ts +++ b/src/sdk/ca-base/utils/cosmos.utils.ts @@ -31,7 +31,7 @@ const cosmosFeeGrant = async (cosmosURL: string, vscDomain: string, address: str baseURL: getCosmosURL(cosmosURL, 'rest'), }); } catch (e) { - logger.error('Requesting a fee grant', e, {cause: 'FEE_GRANT_REQUESTED'}); + logger.error('Requesting a fee grant', e, { cause: 'FEE_GRANT_REQUESTED' }); const response = await vscCreateFeeGrant(vscDomain, address); logger.debug('Fee grant response', response.data); return; @@ -122,7 +122,7 @@ const cosmosRefundIntent = async ( throw Errors.cosmosError(`unknown error: ${JSON.stringify(resp)}`); } } catch (e) { - logger.error('Refund failed', e, {cause: 'REFUND_FAILED'}); + logger.error('Refund failed', e, { cause: 'REFUND_FAILED' }); throw e; } } finally { diff --git a/src/sdk/ca-base/utils/rff.utils.ts b/src/sdk/ca-base/utils/rff.utils.ts index 6fec0f63..cfe01073 100644 --- a/src/sdk/ca-base/utils/rff.utils.ts +++ b/src/sdk/ca-base/utils/rff.utils.ts @@ -1,16 +1,14 @@ import { MsgCreateRequestForFunds, OmniversalRFF, Universe } from '@avail-project/ca-common'; -import { FUEL_BASE_ASSET_ID, INTENT_EXPIRY, isNativeAddress, ZERO_ADDRESS } from '../constants'; +import { INTENT_EXPIRY, isNativeAddress, ZERO_ADDRESS } from '../constants'; import { getLogger, ChainListType, Intent, IBridgeOptions } from '../../../commons'; import { convertTo32Bytes, convertTo32BytesHex, createRequestEVMSignature, - createRequestFuelSignature, createRequestTronSignature, mulDecimals, } from './common.utils'; import { Hex, PrivateKeyAccount, toBytes, WalletClient } from 'viem'; -import { CHAIN_IDS } from 'fuels'; import Long from 'long'; import { TronWeb } from 'tronweb'; import { tronHexToEvmAddress } from './tron.utils'; @@ -35,11 +33,7 @@ type Source = { const logger = getLogger(); -const getSourcesAndDestinationsForRFF = ( - intent: Intent, - chainList: ChainListType, - destinationUniverse: Universe, -) => { +const getSourcesAndDestinationsForRFF = (intent: Intent, chainList: ChainListType, _: Universe) => { const sources: Source[] = []; const universes = new Set(); @@ -80,9 +74,7 @@ const getSourcesAndDestinationsForRFF = ( destinations[0].value = destinations[0].value + intent.destination.gas; } else { destinations.push({ - tokenAddress: convertTo32BytesHex( - destinationUniverse === Universe.FUEL ? FUEL_BASE_ASSET_ID : ZERO_ADDRESS, - ), + tokenAddress: convertTo32BytesHex(ZERO_ADDRESS), universe: intent.destination.universe, value: intent.destination.gas, }); @@ -94,7 +86,7 @@ const getSourcesAndDestinationsForRFF = ( const createRFFromIntent = async ( intent: Intent, - options: Pick & { + options: Pick & { evm: { address: `0x${string}`; client: WalletClient | PrivateKeyAccount; @@ -117,13 +109,6 @@ const createRFFromIntent = async ( }); } - if (universe === Universe.FUEL) { - parties.push({ - address: convertTo32BytesHex(options.fuel!.address as Hex), - universe, - }); - } - if (universe === Universe.TRON) { console.log({ tronAddress: TronWeb.address.toHex(options.tron!.address) }); parties.push({ @@ -189,28 +174,6 @@ const createRFFromIntent = async ( }); } - if (universe === Universe.FUEL) { - if (!options.fuel?.address || !options.fuel?.provider || !options.fuel?.connector) { - logger.error('universe has fuel but not expected input', { - fuelInput: options.fuel, - }); - throw Errors.internal('universe list includes fuel but not expected input'); - } - - const { requestHash, signature } = await createRequestFuelSignature( - options.chainList.getVaultContractAddress(CHAIN_IDS.fuel.mainnet), - options.fuel.provider, - options.fuel.connector, - omniversalRFF.asFuelRFF(), - ); - signatureData.push({ - address: toBytes(options.fuel.address), - requestHash, - signature, - universe: Universe.FUEL, - }); - } - if (universe === Universe.TRON) { if (!options.tron) { logger.error('universe has tron but not expected input', { From 2423e924050127cfb51bc6e9a12b27ca1a3b6594 Mon Sep 17 00:00:00 2001 From: Abhishek Date: Wed, 26 Nov 2025 15:51:24 +0400 Subject: [PATCH 45/51] fix: deduplicated cosmos signing client to prevent nonce issues (#113) --- src/commons/types/index.ts | 12 ++++--- src/commons/types/swap-types.ts | 3 +- src/sdk/ca-base/ca.ts | 21 +++++++---- src/sdk/ca-base/requestHandlers/bridge.ts | 10 ++---- src/sdk/ca-base/swap/ob.ts | 6 ++-- src/sdk/ca-base/swap/rff.ts | 34 ++++-------------- src/sdk/ca-base/utils/common.utils.ts | 24 +++---------- src/sdk/ca-base/utils/cosmos.utils.ts | 43 +++++++---------------- 8 files changed, 52 insertions(+), 101 deletions(-) diff --git a/src/commons/types/index.ts b/src/commons/types/index.ts index 6b939a11..4f3d2e18 100644 --- a/src/commons/types/index.ts +++ b/src/commons/types/index.ts @@ -3,11 +3,11 @@ import { TransactionReceipt, ByteArray, Hex, WalletClient } from 'viem'; import { ChainDatum, Environment, PermitVariant, Universe } from '@avail-project/ca-common'; import Decimal from 'decimal.js'; import { SwapIntent } from './swap-types'; -import { DirectSecp256k1Wallet } from '@cosmjs/proto-signing'; import { AdapterProps } from '@tronweb3/tronwallet-abstract-adapter'; import { SwapStepType } from './swap-steps'; import { BridgeStepType } from './bridge-steps'; import { FormatTokenBalanceOptions, FormattedParts } from '../utils/format'; +import { SigningStargateClient } from '@cosmjs/stargate'; type TokenInfo = { contractAddress: `0x${string}`; @@ -253,11 +253,13 @@ export interface BridgeAndExecuteParams { recentApprovalTxHash?: string; } +export type CosmosOptions = { + address: string; + client: SigningStargateClient; +}; + export type IBridgeOptions = { - cosmos: { - wallet: DirectSecp256k1Wallet; - address: string; - }; + cosmos: CosmosOptions; evm: { address: `0x${string}`; client: WalletClient; diff --git a/src/commons/types/swap-types.ts b/src/commons/types/swap-types.ts index ecd2bcb3..3a2d940d 100644 --- a/src/commons/types/swap-types.ts +++ b/src/commons/types/swap-types.ts @@ -4,6 +4,7 @@ import Decimal from 'decimal.js'; import { type Hex, PrivateKeyAccount, WalletClient } from 'viem'; import { NetworkConfig, ChainListType, OnEventParam, TokenInfo } from '../index'; +import { SigningStargateClient } from '@cosmjs/stargate'; export type AuthorizationList = { address: Uint8Array; @@ -128,7 +129,7 @@ export type SwapParams = { ephemeral: Hex; }; wallet: { - cosmos: DirectSecp256k1Wallet; + cosmos: SigningStargateClient; ephemeral: PrivateKeyAccount; eoa: WalletClient; }; diff --git a/src/sdk/ca-base/ca.ts b/src/sdk/ca-base/ca.ts index 335aefd9..323660e4 100644 --- a/src/sdk/ca-base/ca.ts +++ b/src/sdk/ca-base/ca.ts @@ -1,4 +1,4 @@ -import { createCosmosWallet, Universe } from '@avail-project/ca-common'; +import { createCosmosClient, createCosmosWallet, Universe } from '@avail-project/ca-common'; import { DirectSecp256k1Wallet } from '@cosmjs/proto-signing'; import { keyDerivation } from '@starkware-industries/starkware-crypto-utils'; import { createWalletClient, custom, Hex, UserRejectedRequestError, WalletClient } from 'viem'; @@ -29,6 +29,7 @@ import { TransferParams, BridgeParams, BeforeExecuteHook, + CosmosOptions, } from '../../commons'; import { createBridgeParams } from './requestHandlers/helpers'; import { @@ -45,6 +46,7 @@ import { switchChain, intentTransform, mulDecimals, + getCosmosURL, } from './utils'; import { swap } from './swap/swap'; import { getSwapSupportedChains } from './swap/utils'; @@ -73,9 +75,8 @@ const SIWE_STATEMENT = 'Sign in to enable Nexus'; export class CA { static readonly getSupportedChains = getSupportedChains; - #cosmos?: { + #cosmos?: CosmosOptions & { wallet: DirectSecp256k1Wallet; - address: string; }; #ephemeralWallet?: PrivateKeyAccount; public chainList: ChainListType; @@ -246,7 +247,7 @@ export class CA { ephemeral: this.#ephemeralWallet!.address, }, wallet: { - cosmos: this.#cosmos!.wallet, + cosmos: this.#cosmos!.client, ephemeral: this.#ephemeralWallet!, eoa: this._evm!.client, }, @@ -365,10 +366,10 @@ export class CA { await this._init(); const account = await this._getEVMAddress(); try { - await refundExpiredIntents(account, this._networkConfig.COSMOS_URL, this.#cosmos!.wallet); + await refundExpiredIntents({ address: account, client: this.#cosmos!.client }); this._refundInterval = window.setInterval(async () => { - await refundExpiredIntents(account, this._networkConfig.COSMOS_URL, this.#cosmos!.wallet); + await refundExpiredIntents({ address: account, client: this.#cosmos!.client }); }, minutesToMs(10)); } catch (e) { logger.error('Error checking pending refunds', e, { cause: 'REFUND_CHECK_ERROR' }); @@ -386,8 +387,14 @@ export class CA { const wallet = await createCosmosWallet(`0x${pvtKey.padStart(64, '0')}`); this.#ephemeralWallet = privateKeyToAccount(`0x${pvtKey.padStart(64, '0')}`); const address = (await wallet.getAccounts())[0].address; + const client = await createCosmosClient( + wallet, + getCosmosURL(this._networkConfig.COSMOS_URL, 'rpc'), + { broadcastPollIntervalMs: 250 }, + ); await cosmosFeeGrant(this._networkConfig.COSMOS_URL, this._networkConfig.VSC_DOMAIN, address); - return { wallet, address }; + + return { wallet, address, client }; }; protected _getCosmosWallet = async () => { diff --git a/src/sdk/ca-base/requestHandlers/bridge.ts b/src/sdk/ca-base/requestHandlers/bridge.ts index 1b2eac32..ca08897c 100644 --- a/src/sdk/ca-base/requestHandlers/bridge.ts +++ b/src/sdk/ca-base/requestHandlers/bridge.ts @@ -388,9 +388,8 @@ class BridgeHandler { const intentID = await cosmosCreateRFF({ address: this.options.cosmos.address, - cosmosURL: this.options.networkConfig.COSMOS_URL, msg: msgBasicCosmos, - wallet: this.options.cosmos.wallet, + client: this.options.cosmos.client, }); const explorerURL = getExplorerURL(this.options.networkConfig.EXPLORER_URL, intentID); @@ -495,12 +494,7 @@ class BridgeHandler { ); } doubleCheckTxs.push( - createDepositDoubleCheckTx( - convertTo32Bytes(chain.id), - this.options.cosmos, - intentID, - this.options.networkConfig, - ), + createDepositDoubleCheckTx(convertTo32Bytes(chain.id), this.options.cosmos, intentID), ); } diff --git a/src/sdk/ca-base/swap/ob.ts b/src/sdk/ca-base/swap/ob.ts index 3c638bac..42902ec1 100644 --- a/src/sdk/ca-base/swap/ob.ts +++ b/src/sdk/ca-base/swap/ob.ts @@ -11,7 +11,6 @@ import { QuoteRequestExactInput, Universe, } from '@avail-project/ca-common'; -import { DirectSecp256k1Wallet } from '@cosmjs/proto-signing'; import Decimal from 'decimal.js'; import { orderBy, retry } from 'es-toolkit'; import Long from 'long'; @@ -53,6 +52,7 @@ import { } from '../../../commons'; import { SwapRoute } from './route'; import { Errors } from '../errors'; +import { SigningStargateClient } from '@cosmjs/stargate'; type Options = { address: { @@ -79,7 +79,7 @@ type Options = { publicClientList: PublicClientList; slippage: number; wallet: { - cosmos: DirectSecp256k1Wallet; + cosmos: SigningStargateClient; eoa: WalletClient; ephemeral: PrivateKeyAccount; }; @@ -228,7 +228,7 @@ class BridgeHandler { chainList: this.options.chainList, cosmos: { address: this.options.address.cosmos, - wallet: this.options.wallet.cosmos, + client: this.options.wallet.cosmos, }, evm: { address: this.options.address.ephemeral, diff --git a/src/sdk/ca-base/swap/rff.ts b/src/sdk/ca-base/swap/rff.ts index 3c4b1534..48472942 100644 --- a/src/sdk/ca-base/swap/rff.ts +++ b/src/sdk/ca-base/swap/rff.ts @@ -1,5 +1,4 @@ import { DepositVEPacket, EVMVaultABI, MsgDoubleCheckTx, Universe } from '@avail-project/ca-common'; -import { DirectSecp256k1Wallet } from '@cosmjs/proto-signing'; import Decimal from 'decimal.js'; import Long from 'long'; import { @@ -35,6 +34,7 @@ import { RFFDepositCallMap, Tx, ChainListType, + CosmosOptions, } from '../../../commons'; const logger = getLogger(); @@ -219,10 +219,7 @@ export const createBridgeRFF = async ({ }: { config: { chainList: ChainListType; - cosmos: { - address: string; - wallet: DirectSecp256k1Wallet; - }; + cosmos: CosmosOptions; evm: { address: `0x${string}`; client: PrivateKeyAccount; @@ -260,14 +257,8 @@ export const createBridgeRFF = async ({ intent, { chainList: config.chainList, - cosmos: { - address: config.cosmos.address, - wallet: config.cosmos.wallet, - }, - evm: { - address: config.evm.address, - client: config.evm.client, - }, + cosmos: config.cosmos, + evm: config.evm, }, Universe.ETHEREUM, ); @@ -279,9 +270,8 @@ export const createBridgeRFF = async ({ const createRFF = async () => { intentID = await cosmosCreateRFF({ address: config.cosmos.address, - cosmosURL: config.network.COSMOS_URL, + client: config.cosmos.client, msg: msgBasicCosmos, - wallet: config.cosmos.wallet, }); storeIntentHashToStore(config.evm.address, intentID.toNumber()); @@ -293,7 +283,6 @@ export const createBridgeRFF = async ({ s.chainID, config.cosmos, intentID, - config.network.COSMOS_URL, ); }); @@ -420,15 +409,7 @@ export const createBridgeRFF = async ({ }; }; -export const createDoubleCheckTx = ( - chainID: Uint8Array, - cosmos: { - address: string; - wallet: DirectSecp256k1Wallet; - }, - intentID: Long, - cosmosURL: string, -) => { +export const createDoubleCheckTx = (chainID: Uint8Array, cosmos: CosmosOptions, intentID: Long) => { const msg = MsgDoubleCheckTx.create({ creator: cosmos.address, packet: { @@ -445,9 +426,8 @@ export const createDoubleCheckTx = ( return () => { return cosmosCreateDoubleCheckTx({ address: cosmos.address, - cosmosURL, msg, - wallet: cosmos.wallet, + client: cosmos.client, }); }; }; diff --git a/src/sdk/ca-base/utils/common.utils.ts b/src/sdk/ca-base/utils/common.utils.ts index c444b145..8a45a942 100644 --- a/src/sdk/ca-base/utils/common.utils.ts +++ b/src/sdk/ca-base/utils/common.utils.ts @@ -8,7 +8,6 @@ import { MsgDoubleCheckTx, Universe, } from '@avail-project/ca-common'; -import { DirectSecp256k1Wallet } from '@cosmjs/proto-signing'; import Decimal from 'decimal.js'; import Long from 'long'; import { @@ -39,13 +38,13 @@ import { IBridgeOptions, SupportedChainsAndTokensResult, Intent, - NetworkConfig, OraclePriceResponse, ReadableIntent, TokenInfo, ChainListType, UserAssetDatum, Chain, + CosmosOptions, } from '../../../commons'; import { createPublicClientWithFallback, @@ -136,11 +135,7 @@ const getExpiredIntents = (address: string) => { return expiredIntents; }; -const refundExpiredIntents = async ( - address: string, - cosmosURL: string, - wallet: DirectSecp256k1Wallet, -) => { +const refundExpiredIntents = async ({ address, client }: CosmosOptions) => { logger.debug('Starting check for expired intents at ', new Date()); const expIntents = getExpiredIntents(address); const failedRefunds: IntentD[] = []; @@ -148,7 +143,7 @@ const refundExpiredIntents = async ( for (const intent of expIntents) { logger.debug(`Starting refund for: ${intent.id}`); try { - await cosmosRefundIntent(cosmosURL, intent.id, wallet); + await cosmosRefundIntent({ client, intentID: intent.id, address }); } catch (e) { logger.debug('Refund failed', e); failedRefunds.push({ @@ -447,15 +442,7 @@ const convertToHexAddressByUniverse = (address: Uint8Array, universe: Universe) } }; -const createDepositDoubleCheckTx = ( - chainID: Uint8Array, - cosmos: { - address: string; - wallet: DirectSecp256k1Wallet; - }, - intentID: Long, - network: NetworkConfig, -) => { +const createDepositDoubleCheckTx = (chainID: Uint8Array, cosmos: CosmosOptions, intentID: Long) => { const msg = MsgDoubleCheckTx.create({ creator: cosmos.address, packet: { @@ -472,9 +459,8 @@ const createDepositDoubleCheckTx = ( return () => { return cosmosCreateDoubleCheckTx({ address: cosmos.address, - cosmosURL: network.COSMOS_URL, + client: cosmos.client, msg, - wallet: cosmos.wallet, }); }; }; diff --git a/src/sdk/ca-base/utils/cosmos.utils.ts b/src/sdk/ca-base/utils/cosmos.utils.ts index bb19a290..2bd4421f 100644 --- a/src/sdk/ca-base/utils/cosmos.utils.ts +++ b/src/sdk/ca-base/utils/cosmos.utils.ts @@ -1,17 +1,15 @@ import { - createCosmosClient, MsgCreateRequestForFunds, MsgCreateRequestForFundsResponse, MsgDoubleCheckTx, MsgRefundReq, MsgRefundReqResponse, } from '@avail-project/ca-common'; -import { DirectSecp256k1Wallet } from '@cosmjs/proto-signing'; import { isDeliverTxFailure, isDeliverTxSuccess } from '@cosmjs/stargate'; import axios from 'axios'; import { connect } from 'it-ws/client'; import Long from 'long'; -import { getLogger } from '../../../commons'; +import { CosmosOptions, getLogger } from '../../../commons'; import { checkIntentFilled, vscCreateFeeGrant } from './api.utils'; import { Errors } from '../errors'; @@ -40,18 +38,11 @@ const cosmosFeeGrant = async (cosmosURL: string, vscDomain: string, address: str const cosmosCreateRFF = async ({ address, - cosmosURL, + client, msg, - wallet, -}: { - address: string; - cosmosURL: string; +}: CosmosOptions & { msg: MsgCreateRequestForFunds; - wallet: DirectSecp256k1Wallet; }) => { - const client = await createCosmosClient(wallet, getCosmosURL(cosmosURL, 'rpc'), { - broadcastPollIntervalMs: 250, - }); try { const res = await client.signAndBroadcast( address, @@ -78,15 +69,13 @@ const cosmosCreateRFF = async ({ } }; -const cosmosRefundIntent = async ( - cosmosURL: string, - intentID: number, - wallet: DirectSecp256k1Wallet, -) => { - const address = (await wallet.getAccounts())[0].address; - const client = await createCosmosClient(wallet, getCosmosURL(cosmosURL, 'rpc'), { - broadcastPollIntervalMs: 250, - }); +const cosmosRefundIntent = async ({ + address, + client, + intentID, +}: CosmosOptions & { + intentID: number; +}) => { try { const resp = await client.signAndBroadcast( address, @@ -132,19 +121,11 @@ const cosmosRefundIntent = async ( const cosmosCreateDoubleCheckTx = async ({ address, - cosmosURL, + client, msg, - wallet, -}: { - address: string; - cosmosURL: string; +}: CosmosOptions & { msg: MsgDoubleCheckTx; - wallet: DirectSecp256k1Wallet; }) => { - const client = await createCosmosClient(wallet, getCosmosURL(cosmosURL, 'rpc'), { - broadcastPollIntervalMs: 250, - }); - try { logger.debug('cosmosCreateDoubleCheckTx', { doubleCheckMsg: msg }); From ee64c7ca6d1d2af7b12355055aaa4b253003b4d3 Mon Sep 17 00:00:00 2001 From: Abhishek Date: Wed, 26 Nov 2025 15:59:22 +0400 Subject: [PATCH 46/51] fix: siwe chain to sepolia for testnet (#114) --- src/sdk/ca-base/ca.ts | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/src/sdk/ca-base/ca.ts b/src/sdk/ca-base/ca.ts index 323660e4..e4a7f817 100644 --- a/src/sdk/ca-base/ca.ts +++ b/src/sdk/ca-base/ca.ts @@ -1,4 +1,9 @@ -import { createCosmosClient, createCosmosWallet, Universe } from '@avail-project/ca-common'; +import { + createCosmosClient, + createCosmosWallet, + Environment, + Universe, +} from '@avail-project/ca-common'; import { DirectSecp256k1Wallet } from '@cosmjs/proto-signing'; import { keyDerivation } from '@starkware-industries/starkware-crypto-utils'; import { createWalletClient, custom, Hex, UserRejectedRequestError, WalletClient } from 'viem'; @@ -30,6 +35,7 @@ import { BridgeParams, BeforeExecuteHook, CosmosOptions, + SUPPORTED_CHAINS, } from '../../commons'; import { createBridgeParams } from './requestHandlers/helpers'; import { @@ -80,7 +86,7 @@ export class CA { }; #ephemeralWallet?: PrivateKeyAccount; public chainList: ChainListType; - private readonly _siweChain: number = 1; + private readonly _siweChain; protected _evm?: { client: WalletClient; provider: EthereumProvider; @@ -118,9 +124,10 @@ export class CA { baseUrl: 'https://nexus-backend.avail.so', }); - if (config.siweChain) { - this._siweChain = config.siweChain; - } + this._siweChain = + config?.siweChain ?? this._networkConfig.NETWORK_HINT === Environment.FOLLY + ? SUPPORTED_CHAINS.SEPOLIA + : SUPPORTED_CHAINS.ETHEREUM; if (config.debug) { setLogLevel(LOG_LEVEL.DEBUG); From 8eafc8fd34eceae73cd28377c59b50a09b1839b8 Mon Sep 17 00:00:00 2001 From: Jeremias Moraes Date: Wed, 26 Nov 2025 09:09:30 -0300 Subject: [PATCH 47/51] feat: Enhances telemetry labels: host, origin and network (#111) * feat: Enhances telemetry labels: host, origin and network * feat: Adds func return type --- src/sdk/ca-base/ca.ts | 2 +- src/sdk/ca-base/telemetry.ts | 13 ++++++++++++- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/src/sdk/ca-base/ca.ts b/src/sdk/ca-base/ca.ts index e4a7f817..f7110bad 100644 --- a/src/sdk/ca-base/ca.ts +++ b/src/sdk/ca-base/ca.ts @@ -281,7 +281,7 @@ export class CA { this._initPromise = (async () => { try { - setLoggerProvider(); + setLoggerProvider(this._networkConfig); this._setProviderHooks(); this.#cosmos = await this._createCosmosWallet(); this._checkPendingRefunds(); diff --git a/src/sdk/ca-base/telemetry.ts b/src/sdk/ca-base/telemetry.ts index 5a6b5e66..7ee7b9fb 100644 --- a/src/sdk/ca-base/telemetry.ts +++ b/src/sdk/ca-base/telemetry.ts @@ -2,7 +2,10 @@ import { LoggerProvider, BatchLogRecordProcessor } from '@opentelemetry/sdk-logs import { OTLPLogExporter } from '@opentelemetry/exporter-logs-otlp-http'; import { Logger, logs } from '@opentelemetry/api-logs'; import { resourceFromAttributes } from '@opentelemetry/resources'; +import { Environment } from '@avail-project/ca-common'; import { toHex } from 'viem/utils'; +import { NetworkConfig } from '../../commons'; + let telemetryLogger: Logger | null = null; @@ -18,12 +21,20 @@ function getOrGenerateClientId(): string { return clientId; } -const setLoggerProvider = () => { +function getNetworkName(networkConfig: NetworkConfig): string { + return Environment[networkConfig.NETWORK_HINT]; +} + +const setLoggerProvider = (networkConfig: NetworkConfig) => { if (!telemetryLogger) { const loggerProvider = new LoggerProvider({ resource: resourceFromAttributes({ 'service.name': 'nexus-sdk-internal-logs', 'client.id': getOrGenerateClientId(), + 'origin': window.origin, + 'host': window.location.host, + 'hostname': window.location.hostname, + 'network': getNetworkName(networkConfig), }), processors: [ new BatchLogRecordProcessor( From 02e841868f11f00b9da0c2d30c5a387b36924ad3 Mon Sep 17 00:00:00 2001 From: Amartya Singh <53113365+decocereus@users.noreply.github.com> Date: Wed, 26 Nov 2025 23:02:10 +0530 Subject: [PATCH 48/51] Chore/disable tron (#115) --- src/commons/constants/index.ts | 12 +++--- src/sdk/ca-base/chains.ts | 74 +++++++++++++++++----------------- 2 files changed, 43 insertions(+), 43 deletions(-) diff --git a/src/commons/constants/index.ts b/src/commons/constants/index.ts index bccb9b0b..3aef378b 100644 --- a/src/commons/constants/index.ts +++ b/src/commons/constants/index.ts @@ -12,7 +12,7 @@ export const MAINNET_CHAIN_IDS = { KAIA: 8217, BNB: 56, HYPEREVM: 999, - TRON: 728126428, + // TRON: 728126428, MONAD: 143, } as const; @@ -23,7 +23,7 @@ export const TESTNET_CHAIN_IDS = { OPTIMISM_SEPOLIA: 11155420, POLYGON_AMOY: 80002, MONAD_TESTNET: 10143, - TRON_SHASTA: 2494104990, + // TRON_SHASTA: 2494104990, // VALIDIUM_TESTNET: 567, } as const; @@ -267,7 +267,7 @@ export const MAINNET_CHAINS = [ SUPPORTED_CHAINS.KAIA, SUPPORTED_CHAINS.BNB, SUPPORTED_CHAINS.HYPEREVM, - SUPPORTED_CHAINS.TRON, + // SUPPORTED_CHAINS.TRON, ] as const; /** @@ -281,7 +281,7 @@ export const TESTNET_CHAINS = [ SUPPORTED_CHAINS.OPTIMISM_SEPOLIA, SUPPORTED_CHAINS.POLYGON_AMOY, SUPPORTED_CHAINS.MONAD_TESTNET, - SUPPORTED_CHAINS.TRON_SHASTA, + // SUPPORTED_CHAINS.TRON_SHASTA, ] as const; /** @@ -321,9 +321,9 @@ export const TOKEN_CONTRACT_ADDRESSES = { [SUPPORTED_CHAINS.AVALANCHE]: '0x9702230a8ea53601f5cd2dc00fdbc13d4df4a8c7', [SUPPORTED_CHAINS.BNB]: '0x55d398326f99059fF775485246999027B3197955', [SUPPORTED_CHAINS.HYPEREVM]: '0xB8CE59FC3717ada4C02eaDF9682A9e934F625ebb', - [SUPPORTED_CHAINS.TRON]: '0xa614f803B6FD780986A42c78Ec9c7f77e6DeD13C', + // [SUPPORTED_CHAINS.TRON]: '0xa614f803B6FD780986A42c78Ec9c7f77e6DeD13C', // testnet chains - [SUPPORTED_CHAINS.TRON_SHASTA]: '0x42a1e39aefA49290F2B3F9ed688D7cecf86CD6E0', + // [SUPPORTED_CHAINS.TRON_SHASTA]: '0x42a1e39aefA49290F2B3F9ed688D7cecf86CD6E0', [SUPPORTED_CHAINS.ARBITRUM_SEPOLIA]: '0xF954d4A5859b37De88a91bdbb8Ad309056FB04B1', [SUPPORTED_CHAINS.OPTIMISM_SEPOLIA]: '0x6462693c2F21AC0E517f12641D404895030F7426', [SUPPORTED_CHAINS.MONAD_TESTNET]: '0x1c56F176D6735888fbB6f8bD9ADAd8Ad7a023a0b', diff --git a/src/sdk/ca-base/chains.ts b/src/sdk/ca-base/chains.ts index 486c6e94..8fff5a09 100644 --- a/src/sdk/ca-base/chains.ts +++ b/src/sdk/ca-base/chains.ts @@ -982,43 +982,43 @@ const MAINNET_CHAINS: Chain[] = [ }, universe: Universe.ETHEREUM, }, - { - blockExplorers: { - default: { - name: 'TronScan', - url: 'https://tronscan.org', - }, - }, - custom: { - icon: 'https://assets.coingecko.com/asset_platforms/images/1094/large/TRON_LOGO.png', - knownTokens: [ - { - contractAddress: TOKEN_CONTRACT_ADDRESSES['USDT'][SUPPORTED_CHAINS.TRON], - decimals: 6, - logo: getLogoFromSymbol('USDT'), - name: 'Tether USD', - symbol: 'USDT', - }, - ], - }, - id: SUPPORTED_CHAINS.TRON, - ankrName: '', - name: 'Tron mainnet', - nativeCurrency: { - decimals: 6, - name: 'TRX', - symbol: 'TRX', - }, - rpcUrls: { - default: { - http: ['https://api.trongrid.io/jsonrpc'], - grpc: ['https://api.trongrid.io'], - publicHttp: ['https://api.trongrid.io/jsonrpc', 'https://tron.therpc.io/jsonrpc'], - webSocket: ['wss://tron.drpc.org'], - }, - }, - universe: Universe.TRON, - }, + // { + // blockExplorers: { + // default: { + // name: 'TronScan', + // url: 'https://tronscan.org', + // }, + // }, + // custom: { + // icon: 'https://assets.coingecko.com/asset_platforms/images/1094/large/TRON_LOGO.png', + // knownTokens: [ + // { + // contractAddress: TOKEN_CONTRACT_ADDRESSES['USDT'][SUPPORTED_CHAINS.TRON], + // decimals: 6, + // logo: getLogoFromSymbol('USDT'), + // name: 'Tether USD', + // symbol: 'USDT', + // }, + // ], + // }, + // id: SUPPORTED_CHAINS.TRON, + // ankrName: '', + // name: 'Tron mainnet', + // nativeCurrency: { + // decimals: 6, + // name: 'TRX', + // symbol: 'TRX', + // }, + // rpcUrls: { + // default: { + // http: ['https://api.trongrid.io/jsonrpc'], + // grpc: ['https://api.trongrid.io'], + // publicHttp: ['https://api.trongrid.io/jsonrpc', 'https://tron.therpc.io/jsonrpc'], + // webSocket: ['wss://tron.drpc.org'], + // }, + // }, + // universe: Universe.TRON, + // }, ]; export { ChainList }; From b48f3510f083469f6d509a6287387029d645dcc2 Mon Sep 17 00:00:00 2001 From: Abhishek Date: Wed, 26 Nov 2025 23:51:54 +0400 Subject: [PATCH 49/51] fix: fix evm address usage in refunds (#117) * fix: fix evm address usage in refunds * fix: remove console.log --- package.json | 2 +- src/sdk/ca-base/ca.ts | 19 +++++++++++++++---- src/sdk/ca-base/utils/common.utils.ts | 10 +++++++--- 3 files changed, 23 insertions(+), 8 deletions(-) diff --git a/package.json b/package.json index ede28ed9..6bfc0eab 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@avail-project/nexus-core", - "version": "1.0.0-beta.50", + "version": "1.0.0-beta.53", "description": "Nexus headless SDK for cross-chain transactions", "main": "./dist/index.js", "module": "./dist/index.esm.js", diff --git a/src/sdk/ca-base/ca.ts b/src/sdk/ca-base/ca.ts index f7110bad..ff2f0209 100644 --- a/src/sdk/ca-base/ca.ts +++ b/src/sdk/ca-base/ca.ts @@ -371,12 +371,20 @@ export class CA { protected _checkPendingRefunds = async () => { await this._init(); - const account = await this._getEVMAddress(); + const evmAddress = await this._getEVMAddress(); try { - await refundExpiredIntents({ address: account, client: this.#cosmos!.client }); + await refundExpiredIntents({ + evmAddress, + address: this.#cosmos!.address, + client: this.#cosmos!.client, + }); this._refundInterval = window.setInterval(async () => { - await refundExpiredIntents({ address: account, client: this.#cosmos!.client }); + await refundExpiredIntents({ + evmAddress, + address: this.#cosmos!.address, + client: this.#cosmos!.client, + }); }, minutesToMs(10)); } catch (e) { logger.error('Error checking pending refunds', e, { cause: 'REFUND_CHECK_ERROR' }); @@ -392,14 +400,17 @@ export class CA { const pvtKey = keyDerivation.getPrivateKeyFromEthSignature(sig); const wallet = await createCosmosWallet(`0x${pvtKey.padStart(64, '0')}`); + this.#ephemeralWallet = privateKeyToAccount(`0x${pvtKey.padStart(64, '0')}`); + const address = (await wallet.getAccounts())[0].address; + await cosmosFeeGrant(this._networkConfig.COSMOS_URL, this._networkConfig.VSC_DOMAIN, address); + const client = await createCosmosClient( wallet, getCosmosURL(this._networkConfig.COSMOS_URL, 'rpc'), { broadcastPollIntervalMs: 250 }, ); - await cosmosFeeGrant(this._networkConfig.COSMOS_URL, this._networkConfig.VSC_DOMAIN, address); return { wallet, address, client }; }; diff --git a/src/sdk/ca-base/utils/common.utils.ts b/src/sdk/ca-base/utils/common.utils.ts index 8a45a942..d1bde9c6 100644 --- a/src/sdk/ca-base/utils/common.utils.ts +++ b/src/sdk/ca-base/utils/common.utils.ts @@ -135,9 +135,13 @@ const getExpiredIntents = (address: string) => { return expiredIntents; }; -const refundExpiredIntents = async ({ address, client }: CosmosOptions) => { +const refundExpiredIntents = async ({ + address, + evmAddress, + client, +}: CosmosOptions & { evmAddress: string }) => { logger.debug('Starting check for expired intents at ', new Date()); - const expIntents = getExpiredIntents(address); + const expIntents = getExpiredIntents(evmAddress); const failedRefunds: IntentD[] = []; for (const intent of expIntents) { @@ -155,7 +159,7 @@ const refundExpiredIntents = async ({ address, client }: CosmosOptions) => { if (failedRefunds.length > 0) { for (const failed of failedRefunds) { - storeIntentHashToStore(address, failed.id, failed.createdAt); + storeIntentHashToStore(evmAddress, failed.id, failed.createdAt); } } }; From 0eeae838e8d1680b5a3efd29d5e0eef247964a40 Mon Sep 17 00:00:00 2001 From: Abhishek Date: Wed, 26 Nov 2025 23:58:43 +0400 Subject: [PATCH 50/51] fix: added explorerUrl and fulfilledAt to intent list (#118) --- src/commons/types/index.ts | 1 + src/sdk/ca-base/ca.ts | 2 +- src/sdk/ca-base/utils/api.utils.ts | 9 ++++++++- 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/commons/types/index.ts b/src/commons/types/index.ts index 4f3d2e18..46550a23 100644 --- a/src/commons/types/index.ts +++ b/src/commons/types/index.ts @@ -538,6 +538,7 @@ export type OnEventParam = { }; export type RFF = { + explorerUrl: string; deposited: boolean; destinationChain: { id: number; name: string; logo: string; universe: string }; destinations: { diff --git a/src/sdk/ca-base/ca.ts b/src/sdk/ca-base/ca.ts index ff2f0209..480de06d 100644 --- a/src/sdk/ca-base/ca.ts +++ b/src/sdk/ca-base/ca.ts @@ -187,7 +187,7 @@ export class CA { const { wallet } = await this._getCosmosWallet(); const address = (await wallet.getAccounts())[0].address; const rffList = await fetchMyIntents(address, this._networkConfig.GRPC_URL, page); - return intentTransform(rffList, this.chainList); + return intentTransform(rffList, this._networkConfig.EXPLORER_URL, this.chainList); }; protected _getUnifiedBalances = async (includeSwappableBalances = false) => { diff --git a/src/sdk/ca-base/utils/api.utils.ts b/src/sdk/ca-base/utils/api.utils.ts index c7965042..3249a67d 100644 --- a/src/sdk/ca-base/utils/api.utils.ts +++ b/src/sdk/ca-base/utils/api.utils.ts @@ -27,6 +27,7 @@ import { convertToHexAddressByUniverse, divDecimals, equalFold, + getExplorerURL, minutesToMs, } from './common.utils'; import { Errors } from '../errors'; @@ -63,7 +64,11 @@ async function fetchMyIntents(address: string, grpcURL: string, page = 1) { } } -export const intentTransform = (input: RequestForFunds[], chainList: ChainListType): RFF[] => { +export const intentTransform = ( + input: RequestForFunds[], + explorerBaseURL: string, + chainList: ChainListType, +): RFF[] => { return input.map((rff) => { const dstChainId = bytesToNumber(rff.destinationChainID); const dstChain = chainList.getChainByID(dstChainId); @@ -71,6 +76,7 @@ export const intentTransform = (input: RequestForFunds[], chainList: ChainListTy throw Errors.chainNotFound(dstChainId); } return { + explorerUrl: getExplorerURL(explorerBaseURL, rff.id), deposited: rff.deposited, destinationChain: { id: dstChain.id, @@ -98,6 +104,7 @@ export const intentTransform = (input: RequestForFunds[], chainList: ChainListTy value: divDecimals(valueRaw, token.decimals).toFixed(token.decimals), }; }), + fulfilledAt: rff.fulfilledAt.toNumber(), expiry: rff.expiry.toNumber(), fulfilled: rff.fulfilled, id: rff.id.toNumber(), From b4f807c1a3f43f7ca027d57c6c69229ccabbe112 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20Petrli=C4=87?= Date: Wed, 26 Nov 2025 21:01:10 +0100 Subject: [PATCH 51/51] doc: readme fix (#108) * Readme update * fix: formatTokenBalance example --------- Co-authored-by: decocereus --- README.md | 32 +++++++++++++++++++------------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index 33bff5a6..74404474 100644 --- a/README.md +++ b/README.md @@ -41,7 +41,7 @@ const bridgeResult = await sdk.bridge( token: 'USDC', amount: 1_500_000n, recipient: '0x...' // Optional - chainId: 137, // Polygon + toChainId: 137, // Polygon }, { onEvent: (event) => { @@ -58,7 +58,7 @@ const transferResult = await sdk.bridgeAndTransfer( { token: 'ETH', amount: 1_500_000n, - chainId: 1, // Ethereum + toChainId: 1, // Ethereum recipient: '0x742d35Cc6634C0532925a3b8D4C9db96c4b4Db45', }, { @@ -77,7 +77,8 @@ const executeResult = await sdk.execute( to: '0x...', value: 0n, data: '0x...', - tokenApproval: { token: 'USDC', amount: 10000n }, + toChainId: 1, + tokenApproval: { token: 'USDC', amount: 10000n, spender: "0x..." }, }, { onEvent: (event) => { @@ -99,7 +100,7 @@ const bridgeAndExecuteResult = await sdk.bridgeAndExecute( execute: { to: '0x...', data: '0x...', - tokenApproval: { token: 'USDC', amount: 100_000_000n }, + tokenApproval: { token: 'USDC', amount: 100_000_000n, spender: "0x..." }, }, }, { @@ -252,14 +253,14 @@ const swapBalances = await sdk.getBalancesForSwap(); // Returns balances that ca const result = await sdk.bridge({ token: 'USDC', amount: 83_500_000n, - chainId: 137, + toChainId: 137, recipient: '0x....', }); const simulation = await sdk.simulateBridge({ token: 'USDC', amount: 83_500_000n, - chainId: 137, + toChainId: 137, recipient: '0x....', }); ``` @@ -272,13 +273,13 @@ const simulation = await sdk.simulateBridge({ const result = await sdk.bridgeAndTransfer({ token: 'USDC', amount: 1_530_000n, - chainId: 42161, + toChainId: 42161, recipient: '0x...', }); const simulation = await sdk.simulateBridgeAndTransfer({ token: 'USDC', amount: 1_530_000n, // = 1.53 USDC - chainId: 42161, + toChainId: 42161, recipient: '0x...', }); ``` @@ -293,7 +294,7 @@ const result = await sdk.execute({ toChainId: 1, to: '0xc3d688B66703497DAA19211EEdff47f25384cdc3', data: '0x...', - tokenApproval: { token: 'USDC', amount: 1000000n }, + tokenApproval: { token: 'USDC', amount: 1000000n, spender: '0x...' }, }); // Bridge and execute @@ -305,7 +306,7 @@ const result2 = await sdk.bridgeAndExecute({ execute: { to: '0xa354F35829Ae975e850e23e9615b11Da1B3dC4DE', data: '0x...', - tokenApproval: { token: 'USDC', amount: 100_000_000n }, + tokenApproval: { token: 'USDC', amount: 100_000_000n, spender: '0x...' }, }, }); ``` @@ -346,9 +347,14 @@ console.log('Active intents:', intents); ## 🛠️ Utilities ```typescript +import { CHAIN_METADATA } from '@avail-project/nexus-core'; + const isValid = sdk.utils.isValidAddress('0x...'); -const chainMeta = sdk.utils.getChainMetadata(137); -const formatted = sdk.utils.formatTokenAmount('1000000', 'USDC'); // "1.0 USDC" +const chainMeta = CHAIN_METADATA[137]; +const formatted = sdk.utils.formatTokenBalance('0.000294700412452583', { + symbol: 'ETH', + decimals: 18, +}); // "~0.0₄2552 ETH" ``` --- @@ -357,7 +363,7 @@ const formatted = sdk.utils.formatTokenAmount('1000000', 'USDC'); // "1.0 USDC" ```typescript try { - await sdk.bridge({ token: 'USDC', amount: 1.53, chainId: 137 }); + await sdk.bridge({ token: 'USDC', amount: 1_530_000n, toChainId: 137 }); } catch (err) { if (err instanceof NexusError) { console.error(`[${err.code}] ${err.message}`);