@avalabs/fusion-sdk 0.23.0 → 0.24.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,2 +1,2 @@
1
- let e=function(e){return e.DEV=`dev`,e.PROD=`production`,e.TEST=`test`,e}({}),t=function(e){return e.NATIVE=`native`,e.ERC20=`erc20`,e.SPL=`spl`,e}({}),n=function(e){return e.AVALANCHE_CCT=`avalanche-cct`,e.AVALANCHE_EVM=`avalanche-evm`,e.LOMBARD_BTC_TO_BTCB=`lombard-btc-to-btcb`,e.LOMBARD_BTCB_TO_BTC=`lombard-btcb-to-btc`,e.MARKR=`markr`,e.WRAP_UNWRAP=`wrap-unwrap`,e}({});const r=[n.LOMBARD_BTCB_TO_BTC,n.LOMBARD_BTC_TO_BTCB],i=[n.AVALANCHE_EVM,n.WRAP_UNWRAP];let a=function(e){return e.AddressOwnership=`address-ownership`,e.AllowanceApproval=`allowance-approval`,e.AvalancheCrossChainExport=`avalanche-cross-chain-export`,e.AvalancheCrossChainImport=`avalanche-cross-chain-import`,e.TokensTransfer=`tokens-transfer`,e.WrapToken=`wrap-token`,e.HyperliquidAuthorize=`hyperliquid-authorize`,e.HyperliquidSendAsset=`hyperliquid-send-asset`,e.ScheduleRecurringSwap=`schedule-recurring-swap`,e.PauseRecurringSwap=`pause-recurring-swap`,e.ResumeRecurringSwap=`resume-recurring-swap`,e.CancelRecurringSwap=`cancel-recurring-swap`,e}({}),o=function(e){return e.FUJI=`eip155:43113`,e.MAINNET=`eip155:43114`,e}({}),s=function(e){return e.MAINNET=`eip155:1`,e.SEPOLIA=`eip155:11155111`,e}({}),c=function(e){return e.MAINNET=`bip122:000000000019d6689c085ae165831e93`,e.TESTNET=`bip122:000000000933ea01ad0ee984209779ba`,e}({}),l=function(e){return e.MAINNET=`solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp`,e.DEVNET=`solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1`,e}({}),u=function(e){return e.MAINNET=`eip155:1337`,e}({});const d={C:o.MAINNET,P:`avax:Rr9hnPVPxuUvrdCul-vjEsU1zmqKqRDo`,X:`avax:imji8papUf2EhV3le337w1vgFauqkJg-`},f={C:o.FUJI,P:`avax:Sj7NVE3jXTbJvwFAiu7OEUo_8g8ctXMG`,X:`avax:8AJTpRj3SAqv1e80Mtl9em08LhvKEbkl`},p={C:`2q9e4r6Mu3U68nU1fYjgbR6JvwrRx36CohpAX5UQxse55x1Q5`,P:`11111111111111111111111111111111LpoYY`,X:`2oYMBNV4eNHyqk2fjjV5nVQLDbtmNJzq5s3qs3Lo6ftnC6FByM`},m={C:`yH8D7ThNJkxmtkuv2jgBa4P1Rn3Qpr4pPr7QYNfcdoS6k6HWp`,P:`11111111111111111111111111111111LpoYY`,X:`2JVSBoinj9C2J33VntvzYtVJNZdN2NKiwwKjcumHUWEb5DbBrm`},h={mainnet:{[d.C]:p.C,[d.P]:p.P,[d.X]:p.X},fuji:{[f.C]:m.C,[f.P]:m.P,[f.X]:m.X}},g={chainId:o.FUJI,chainName:`Avalanche Fuji (C-Chain)`,networkToken:{type:t.NATIVE,name:`AVAX`,symbol:`AVAX`,decimals:18},rpcUrl:`https://api.avax-test.network/ext/bc/C/rpc`},_={chainId:o.MAINNET,chainName:`Avalanche Mainnet (C-Chain)`,rpcUrl:`https://api.avax.network/ext/bc/C/rpc`,networkToken:{type:t.NATIVE,name:`AVAX`,symbol:`AVAX`,decimals:18}},v={chainId:d.P,chainName:`Avalanche Mainnet (P-Chain)`,rpcUrl:`https://api.avax.network/ext/bc/P`,networkToken:{type:t.NATIVE,name:`AVAX`,symbol:`AVAX`,decimals:9}},y={chainId:f.P,chainName:`Avalanche Fuji (P-Chain)`,rpcUrl:`https://api.avax-test.network/ext/bc/P`,networkToken:{type:t.NATIVE,name:`AVAX`,symbol:`AVAX`,decimals:9}},b={chainId:d.X,chainName:`Avalanche Mainnet (X-Chain)`,rpcUrl:`https://api.avax.network/ext/bc/X`,networkToken:{type:t.NATIVE,name:`AVAX`,symbol:`AVAX`,decimals:9}},x={chainId:f.X,chainName:`Avalanche Fuji (X-Chain)`,rpcUrl:`https://api.avax-test.network/ext/bc/X`,networkToken:{type:t.NATIVE,name:`AVAX`,symbol:`AVAX`,decimals:9}},S={chainId:s.SEPOLIA,chainName:`Ethereum Sepolia`,rpcUrl:`https://proxy-api.avax.network/proxy/infura/sepolia`,networkToken:{type:t.NATIVE,name:`ETH`,symbol:`ETH`,decimals:18}},C={chainId:s.MAINNET,chainName:`Ethereum Mainnet`,rpcUrl:`https://proxy-api.avax.network/proxy/infura/mainnet`,networkToken:{type:t.NATIVE,name:`ETH`,symbol:`ETH`,decimals:18}},w={chainId:c.TESTNET,chainName:`Bitcoin Testnet`,rpcUrl:``,networkToken:{type:t.NATIVE,name:`Bitcoin`,symbol:`BTC`,decimals:8}},T={chainId:c.MAINNET,chainName:`Bitcoin Mainnet`,rpcUrl:``,networkToken:{type:t.NATIVE,name:`Bitcoin`,symbol:`BTC`,decimals:8}},E={chainId:l.MAINNET,chainName:`Solana`,rpcUrl:`https://proxy-api.avax.network/proxy/nownodes/sol`,networkToken:{type:t.NATIVE,name:`SOL`,symbol:`SOL`,decimals:9}},D={chainId:l.DEVNET,chainName:`Solana (Devnet)`,rpcUrl:`https://api.devnet.solana.com`,networkToken:{type:t.NATIVE,name:`SOL`,symbol:`SOL`,decimals:9}},O={type:t.NATIVE,name:`Avalanche`,symbol:`AVAX`,decimals:18,logoUri:`https://images.ctfassets.net/gcj8jwzm6086/5VHupNKwnDYJvqMENeV7iJ/fdd6326b7a82c8388e4ee9d4be7062d4/avalanche-avax-logo.svg`},k={type:t.NATIVE,name:`Ether`,symbol:`ETH`,decimals:18,logoUri:`https://images.ctfassets.net/gcj8jwzm6086/6l56QLVZmvacuBfjHBTThP/791d743dd2c526692562780c2325fedf/eth-circle__1_.svg`};let A=function(e){return e.AVALANCHE=`avalanche`,e.BITCOIN=`bitcoin`,e.ETHEREUM=`ethereum`,e.SOLANA=`solana`,e.UNKNOWN=`_unknown`,e}({}),j=function(e){return e[e.AVALANCHE_MAINNET=43114]=`AVALANCHE_MAINNET`,e[e.AVALANCHE_TESTNET=43113]=`AVALANCHE_TESTNET`,e[e.ETHEREUM_HOMESTEAD=1]=`ETHEREUM_HOMESTEAD`,e[e.ETHEREUM_TEST_SEPOLIA=11155111]=`ETHEREUM_TEST_SEPOLIA`,e[e.BITCOIN=0xfffffffffffeb]=`BITCOIN`,e[e.BITCOIN_TESTNET=0xfffffffffffea]=`BITCOIN_TESTNET`,e}({});const M={slow:`low`,normal:`medium`,fast:`high`};exports.AVALANCHE_CAIP2_TO_BLOCKCHAIN_ID_BY_NETWORK=h,exports.AVALANCHE_FUJI_CHAIN=g,exports.AVALANCHE_FUJI_P_CHAIN=y,exports.AVALANCHE_FUJI_X_CHAIN=x,exports.AVALANCHE_MAINNET_CHAIN=_,exports.AVALANCHE_MAINNET_P_CHAIN=v,exports.AVALANCHE_MAINNET_X_CHAIN=b,exports.AvalancheChainIds=o,exports.AvalancheFujiBlockchainChainIds=f,exports.AvalancheFujiBlockchainIds=m,exports.AvalancheMainnetBlockchainChainIds=d,exports.AvalancheMainnetBlockchainIds=p,exports.BITCOIN_MAINNET_CHAIN=T,exports.BITCOIN_TESTNET_CHAIN=w,exports.BTC_SERVICE_TYPES=r,exports.BitcoinChainIds=c,exports.Blockchain=A,exports.ERC_ZERO_ADDRESS=`0x0000000000000000000000000000000000000000`,exports.ETHEREUM_MAINNET_CHAIN=C,exports.ETHEREUM_SEPOLIA_CHAIN=S,exports.EVM_SERVICE_TYPES=i,exports.Environment=e,exports.EthereumChainIds=s,exports.EvmChainId=j,exports.FEE_RATE_TIER_TO_BITCOIN=M,exports.HyperliquidChainIds=u,exports.NATIVE_AVAX=O,exports.NATIVE_ETH=k,exports.NATIVE_SOL_ADDRESS=`11111111111111111111111111111111`,exports.SOLANA_DEVNET_CHAIN=D,exports.SOLANA_MAINNET_CHAIN=E,exports.ServiceType=n,exports.SolanaChainIds=l,exports.TokenType=t,exports.TransferSignatureReason=a;
1
+ let e=function(e){return e.DEV=`dev`,e.PROD=`production`,e.TEST=`test`,e}({}),t=function(e){return e.NATIVE=`native`,e.ERC20=`erc20`,e.SPL=`spl`,e}({}),n=function(e){return e.AVALANCHE_CCT=`avalanche-cct`,e.AVALANCHE_EVM=`avalanche-evm`,e.LOMBARD_BTC_TO_BTCB=`lombard-btc-to-btcb`,e.LOMBARD_BTCB_TO_BTC=`lombard-btcb-to-btc`,e.MARKR=`markr`,e.WRAP_UNWRAP=`wrap-unwrap`,e}({});const r=[n.LOMBARD_BTCB_TO_BTC,n.LOMBARD_BTC_TO_BTCB],i=[n.AVALANCHE_EVM,n.WRAP_UNWRAP];let a=function(e){return e.AddressOwnership=`address-ownership`,e.AllowanceApproval=`allowance-approval`,e.AvalancheCrossChainExport=`avalanche-cross-chain-export`,e.AvalancheCrossChainImport=`avalanche-cross-chain-import`,e.TokensTransfer=`tokens-transfer`,e.WrapToken=`wrap-token`,e.HyperliquidAuthorize=`hyperliquid-authorize`,e.HyperliquidSendAsset=`hyperliquid-send-asset`,e.ScheduleRecurringSwap=`schedule-recurring-swap`,e.PauseRecurringSwap=`pause-recurring-swap`,e.ResumeRecurringSwap=`resume-recurring-swap`,e.CancelRecurringSwap=`cancel-recurring-swap`,e}({}),o=function(e){return e.FUJI=`eip155:43113`,e.MAINNET=`eip155:43114`,e}({}),s=function(e){return e.MAINNET=`eip155:1`,e.SEPOLIA=`eip155:11155111`,e}({}),c=function(e){return e.MAINNET=`bip122:000000000019d6689c085ae165831e93`,e.TESTNET=`bip122:000000000933ea01ad0ee984209779ba`,e}({}),l=function(e){return e.MAINNET=`solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp`,e.DEVNET=`solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1`,e}({}),u=function(e){return e.MAINNET=`eip155:1337`,e}({}),d=function(e){return e.MAINNET=`eip155:8453`,e.SEPOLIA=`eip155:84532`,e}({}),f=function(e){return e.MAINNET=`eip155:137`,e.AMOY=`eip155:80002`,e}({});const p={C:o.MAINNET,P:`avax:Rr9hnPVPxuUvrdCul-vjEsU1zmqKqRDo`,X:`avax:imji8papUf2EhV3le337w1vgFauqkJg-`},m={C:o.FUJI,P:`avax:Sj7NVE3jXTbJvwFAiu7OEUo_8g8ctXMG`,X:`avax:8AJTpRj3SAqv1e80Mtl9em08LhvKEbkl`},h={C:`2q9e4r6Mu3U68nU1fYjgbR6JvwrRx36CohpAX5UQxse55x1Q5`,P:`11111111111111111111111111111111LpoYY`,X:`2oYMBNV4eNHyqk2fjjV5nVQLDbtmNJzq5s3qs3Lo6ftnC6FByM`},g={C:`yH8D7ThNJkxmtkuv2jgBa4P1Rn3Qpr4pPr7QYNfcdoS6k6HWp`,P:`11111111111111111111111111111111LpoYY`,X:`2JVSBoinj9C2J33VntvzYtVJNZdN2NKiwwKjcumHUWEb5DbBrm`},_={mainnet:{[p.C]:h.C,[p.P]:h.P,[p.X]:h.X},fuji:{[m.C]:g.C,[m.P]:g.P,[m.X]:g.X}},v={chainId:o.FUJI,chainName:`Avalanche Fuji (C-Chain)`,networkToken:{type:t.NATIVE,name:`AVAX`,symbol:`AVAX`,decimals:18},rpcUrl:`https://api.avax-test.network/ext/bc/C/rpc`},y={chainId:o.MAINNET,chainName:`Avalanche Mainnet (C-Chain)`,rpcUrl:`https://api.avax.network/ext/bc/C/rpc`,networkToken:{type:t.NATIVE,name:`AVAX`,symbol:`AVAX`,decimals:18}},b={chainId:p.P,chainName:`Avalanche Mainnet (P-Chain)`,rpcUrl:`https://api.avax.network/ext/bc/P`,networkToken:{type:t.NATIVE,name:`AVAX`,symbol:`AVAX`,decimals:9}},x={chainId:m.P,chainName:`Avalanche Fuji (P-Chain)`,rpcUrl:`https://api.avax-test.network/ext/bc/P`,networkToken:{type:t.NATIVE,name:`AVAX`,symbol:`AVAX`,decimals:9}},S={chainId:p.X,chainName:`Avalanche Mainnet (X-Chain)`,rpcUrl:`https://api.avax.network/ext/bc/X`,networkToken:{type:t.NATIVE,name:`AVAX`,symbol:`AVAX`,decimals:9}},C={chainId:m.X,chainName:`Avalanche Fuji (X-Chain)`,rpcUrl:`https://api.avax-test.network/ext/bc/X`,networkToken:{type:t.NATIVE,name:`AVAX`,symbol:`AVAX`,decimals:9}},w={chainId:s.SEPOLIA,chainName:`Ethereum Sepolia`,rpcUrl:`https://proxy-api.avax.network/proxy/infura/sepolia`,networkToken:{type:t.NATIVE,name:`ETH`,symbol:`ETH`,decimals:18}},T={chainId:s.MAINNET,chainName:`Ethereum Mainnet`,rpcUrl:`https://proxy-api.avax.network/proxy/infura/mainnet`,networkToken:{type:t.NATIVE,name:`ETH`,symbol:`ETH`,decimals:18}},E={chainId:c.TESTNET,chainName:`Bitcoin Testnet`,rpcUrl:``,networkToken:{type:t.NATIVE,name:`Bitcoin`,symbol:`BTC`,decimals:8}},D={chainId:c.MAINNET,chainName:`Bitcoin Mainnet`,rpcUrl:``,networkToken:{type:t.NATIVE,name:`Bitcoin`,symbol:`BTC`,decimals:8}},O={chainId:l.MAINNET,chainName:`Solana`,rpcUrl:`https://proxy-api.avax.network/proxy/nownodes/sol`,networkToken:{type:t.NATIVE,name:`SOL`,symbol:`SOL`,decimals:9}},k={chainId:l.DEVNET,chainName:`Solana (Devnet)`,rpcUrl:`https://api.devnet.solana.com`,networkToken:{type:t.NATIVE,name:`SOL`,symbol:`SOL`,decimals:9}},A={type:t.NATIVE,name:`Avalanche`,symbol:`AVAX`,decimals:18,logoUri:`https://images.ctfassets.net/gcj8jwzm6086/5VHupNKwnDYJvqMENeV7iJ/fdd6326b7a82c8388e4ee9d4be7062d4/avalanche-avax-logo.svg`},j={type:t.NATIVE,name:`Ether`,symbol:`ETH`,decimals:18,logoUri:`https://images.ctfassets.net/gcj8jwzm6086/6l56QLVZmvacuBfjHBTThP/791d743dd2c526692562780c2325fedf/eth-circle__1_.svg`};let M=function(e){return e.AVALANCHE=`avalanche`,e.BITCOIN=`bitcoin`,e.ETHEREUM=`ethereum`,e.SOLANA=`solana`,e.UNKNOWN=`_unknown`,e}({}),N=function(e){return e[e.AVALANCHE_MAINNET=43114]=`AVALANCHE_MAINNET`,e[e.AVALANCHE_TESTNET=43113]=`AVALANCHE_TESTNET`,e[e.ETHEREUM_HOMESTEAD=1]=`ETHEREUM_HOMESTEAD`,e[e.ETHEREUM_TEST_SEPOLIA=11155111]=`ETHEREUM_TEST_SEPOLIA`,e[e.BITCOIN=0xfffffffffffeb]=`BITCOIN`,e[e.BITCOIN_TESTNET=0xfffffffffffea]=`BITCOIN_TESTNET`,e}({});const P={slow:`low`,normal:`medium`,fast:`high`};exports.AVALANCHE_CAIP2_TO_BLOCKCHAIN_ID_BY_NETWORK=_,exports.AVALANCHE_FUJI_CHAIN=v,exports.AVALANCHE_FUJI_P_CHAIN=x,exports.AVALANCHE_FUJI_X_CHAIN=C,exports.AVALANCHE_MAINNET_CHAIN=y,exports.AVALANCHE_MAINNET_P_CHAIN=b,exports.AVALANCHE_MAINNET_X_CHAIN=S,exports.AvalancheChainIds=o,exports.AvalancheFujiBlockchainChainIds=m,exports.AvalancheFujiBlockchainIds=g,exports.AvalancheMainnetBlockchainChainIds=p,exports.AvalancheMainnetBlockchainIds=h,exports.BITCOIN_MAINNET_CHAIN=D,exports.BITCOIN_TESTNET_CHAIN=E,exports.BTC_SERVICE_TYPES=r,exports.BaseChainIds=d,exports.BitcoinChainIds=c,exports.Blockchain=M,exports.ERC_ZERO_ADDRESS=`0x0000000000000000000000000000000000000000`,exports.ETHEREUM_MAINNET_CHAIN=T,exports.ETHEREUM_SEPOLIA_CHAIN=w,exports.EVM_SERVICE_TYPES=i,exports.Environment=e,exports.EthereumChainIds=s,exports.EvmChainId=N,exports.FEE_RATE_TIER_TO_BITCOIN=P,exports.HyperliquidChainIds=u,exports.NATIVE_AVAX=A,exports.NATIVE_ETH=j,exports.NATIVE_SOL_ADDRESS=`11111111111111111111111111111111`,exports.PolygonChainIds=f,exports.SOLANA_DEVNET_CHAIN=k,exports.SOLANA_MAINNET_CHAIN=O,exports.ServiceType=n,exports.SolanaChainIds=l,exports.TokenType=t,exports.TransferSignatureReason=a;
2
2
  //# sourceMappingURL=constants.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"constants.cjs","names":[],"sources":["../src/constants.ts"],"sourcesContent":["import type { Address as SolAddress } from '@solana/kit';\nimport type { Address as EvmAddress } from 'viem';\nimport type { NativeAsset } from './types/asset';\nimport type { BitcoinFeeRateTier } from './types/bitcoin';\nimport type { Caip2ChainId } from './types/caip';\nimport type { Chain } from './types/chain';\nimport type { FeeRateTier } from './types/fee';\n\nexport enum Environment {\n DEV = 'dev',\n PROD = 'production',\n TEST = 'test',\n}\n\nexport enum TokenType {\n NATIVE = 'native',\n ERC20 = 'erc20',\n SPL = 'spl',\n}\n\nexport enum ServiceType {\n /** Avalanche Cross-chain transfer service. Export/import between C/P/X Avalanche chains. */\n AVALANCHE_CCT = 'avalanche-cct',\n /** Bridge between EVM chains within Avalanche (or EVM-compatible flows). */\n AVALANCHE_EVM = 'avalanche-evm',\n /** Bitcoin → Avalanche. */\n LOMBARD_BTC_TO_BTCB = 'lombard-btc-to-btcb',\n /** Avalanche → Bitcoin. */\n LOMBARD_BTCB_TO_BTC = 'lombard-btcb-to-btc',\n MARKR = 'markr',\n /** Same-chain wrap/unwrap of native ETH ↔ WETH and AVAX ↔ WAVAX. */\n WRAP_UNWRAP = 'wrap-unwrap',\n}\n\nexport const BTC_SERVICE_TYPES: readonly [ServiceType.LOMBARD_BTCB_TO_BTC, ServiceType.LOMBARD_BTC_TO_BTCB] = [\n ServiceType.LOMBARD_BTCB_TO_BTC,\n ServiceType.LOMBARD_BTC_TO_BTCB,\n];\n\nexport const EVM_SERVICE_TYPES: readonly [ServiceType.AVALANCHE_EVM, ServiceType.WRAP_UNWRAP] = [\n ServiceType.AVALANCHE_EVM,\n ServiceType.WRAP_UNWRAP,\n];\n\n/** Reasons for user signatures during execution. */\nexport enum TransferSignatureReason {\n AddressOwnership = 'address-ownership',\n /** ERC-20 allowance approval for router/bridge. */\n AllowanceApproval = 'allowance-approval',\n /** Primary signature for cross-chain export transaction. */\n AvalancheCrossChainExport = 'avalanche-cross-chain-export',\n /** Primary signature for cross-chain import transaction. */\n AvalancheCrossChainImport = 'avalanche-cross-chain-import',\n /** The primary token movement call (swap or bridge submit). */\n TokensTransfer = 'tokens-transfer',\n /** Optional wrap/unwrap step for native token handling. */\n WrapToken = 'wrap-token',\n /** Hyperliquid 2-phase withdrawal: step 1, nonce-mapping authorization (Relay protocol). */\n HyperliquidAuthorize = 'hyperliquid-authorize',\n /** Hyperliquid 2-phase withdrawal: step 2, the `sendAsset` transfer. */\n HyperliquidSendAsset = 'hyperliquid-send-asset',\n /** Markr recurring: first-fill swap that schedules the recurring order on-chain. */\n ScheduleRecurringSwap = 'schedule-recurring-swap',\n /** Markr recurring: pause an active schedule (preserves allowance). */\n PauseRecurringSwap = 'pause-recurring-swap',\n /** Markr recurring: resume (unpause) a paused schedule. */\n ResumeRecurringSwap = 'resume-recurring-swap',\n /** Markr recurring: cancel an active or paused schedule. */\n CancelRecurringSwap = 'cancel-recurring-swap',\n}\n\nexport const ERC_ZERO_ADDRESS: EvmAddress = '0x0000000000000000000000000000000000000000';\nexport const NATIVE_SOL_ADDRESS: SolAddress = '11111111111111111111111111111111' as SolAddress;\n\nexport enum AvalancheChainIds {\n FUJI = 'eip155:43113',\n MAINNET = 'eip155:43114',\n}\n\nexport enum EthereumChainIds {\n MAINNET = 'eip155:1',\n SEPOLIA = 'eip155:11155111',\n}\n\nexport enum BitcoinChainIds {\n MAINNET = 'bip122:000000000019d6689c085ae165831e93',\n TESTNET = 'bip122:000000000933ea01ad0ee984209779ba',\n}\n\nexport enum SolanaChainIds {\n MAINNET = 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp',\n DEVNET = 'solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1',\n}\n\n/**\n * Hyperliquid is identified by CAIP-2 `eip155:1337` per Relay's convention.\n * It's an EVM-namespaced chain ID but has no real EVM execution — withdrawals\n * use a two-signature EIP-712 flow against Hyperliquid's `/exchange` API.\n */\nexport enum HyperliquidChainIds {\n MAINNET = 'eip155:1337',\n}\n\nexport type AvalancheBlockchainAlias = 'C' | 'P' | 'X';\n\nexport const AvalancheMainnetBlockchainChainIds: Readonly<Record<AvalancheBlockchainAlias, Caip2ChainId>> = {\n C: AvalancheChainIds.MAINNET,\n P: 'avax:Rr9hnPVPxuUvrdCul-vjEsU1zmqKqRDo',\n X: 'avax:imji8papUf2EhV3le337w1vgFauqkJg-',\n};\n\nexport const AvalancheFujiBlockchainChainIds: Readonly<Record<AvalancheBlockchainAlias, Caip2ChainId>> = {\n C: AvalancheChainIds.FUJI,\n P: 'avax:Sj7NVE3jXTbJvwFAiu7OEUo_8g8ctXMG',\n X: 'avax:8AJTpRj3SAqv1e80Mtl9em08LhvKEbkl',\n};\n\nexport const AvalancheMainnetBlockchainIds: Readonly<Record<AvalancheBlockchainAlias, string>> = {\n C: '2q9e4r6Mu3U68nU1fYjgbR6JvwrRx36CohpAX5UQxse55x1Q5',\n P: '11111111111111111111111111111111LpoYY',\n X: '2oYMBNV4eNHyqk2fjjV5nVQLDbtmNJzq5s3qs3Lo6ftnC6FByM',\n};\n\nexport const AvalancheFujiBlockchainIds: Readonly<Record<AvalancheBlockchainAlias, string>> = {\n C: 'yH8D7ThNJkxmtkuv2jgBa4P1Rn3Qpr4pPr7QYNfcdoS6k6HWp',\n P: '11111111111111111111111111111111LpoYY',\n X: '2JVSBoinj9C2J33VntvzYtVJNZdN2NKiwwKjcumHUWEb5DbBrm',\n};\n\nexport const AVALANCHE_CAIP2_TO_BLOCKCHAIN_ID_BY_NETWORK: Readonly<{\n mainnet: Readonly<Record<Caip2ChainId, string>>;\n fuji: Readonly<Record<Caip2ChainId, string>>;\n}> = {\n mainnet: {\n [AvalancheMainnetBlockchainChainIds.C]: AvalancheMainnetBlockchainIds.C,\n [AvalancheMainnetBlockchainChainIds.P]: AvalancheMainnetBlockchainIds.P,\n [AvalancheMainnetBlockchainChainIds.X]: AvalancheMainnetBlockchainIds.X,\n },\n fuji: {\n [AvalancheFujiBlockchainChainIds.C]: AvalancheFujiBlockchainIds.C,\n [AvalancheFujiBlockchainChainIds.P]: AvalancheFujiBlockchainIds.P,\n [AvalancheFujiBlockchainChainIds.X]: AvalancheFujiBlockchainIds.X,\n },\n};\n\nexport const AVALANCHE_FUJI_CHAIN: Chain = {\n chainId: AvalancheChainIds.FUJI,\n chainName: 'Avalanche Fuji (C-Chain)',\n networkToken: {\n type: TokenType.NATIVE,\n name: 'AVAX',\n symbol: 'AVAX',\n decimals: 18,\n },\n rpcUrl: 'https://api.avax-test.network/ext/bc/C/rpc',\n};\n\nexport const AVALANCHE_MAINNET_CHAIN: Chain = {\n chainId: AvalancheChainIds.MAINNET,\n chainName: 'Avalanche Mainnet (C-Chain)',\n rpcUrl: 'https://api.avax.network/ext/bc/C/rpc',\n networkToken: {\n type: TokenType.NATIVE,\n name: 'AVAX',\n symbol: 'AVAX',\n decimals: 18,\n },\n};\n\nexport const AVALANCHE_MAINNET_P_CHAIN: Chain = {\n chainId: AvalancheMainnetBlockchainChainIds.P,\n chainName: 'Avalanche Mainnet (P-Chain)',\n rpcUrl: 'https://api.avax.network/ext/bc/P',\n networkToken: {\n type: TokenType.NATIVE,\n name: 'AVAX',\n symbol: 'AVAX',\n decimals: 9,\n },\n};\n\nexport const AVALANCHE_FUJI_P_CHAIN: Chain = {\n chainId: AvalancheFujiBlockchainChainIds.P,\n chainName: 'Avalanche Fuji (P-Chain)',\n rpcUrl: 'https://api.avax-test.network/ext/bc/P',\n networkToken: {\n type: TokenType.NATIVE,\n name: 'AVAX',\n symbol: 'AVAX',\n decimals: 9,\n },\n};\n\nexport const AVALANCHE_MAINNET_X_CHAIN: Chain = {\n chainId: AvalancheMainnetBlockchainChainIds.X,\n chainName: 'Avalanche Mainnet (X-Chain)',\n rpcUrl: 'https://api.avax.network/ext/bc/X',\n networkToken: {\n type: TokenType.NATIVE,\n name: 'AVAX',\n symbol: 'AVAX',\n decimals: 9,\n },\n};\n\nexport const AVALANCHE_FUJI_X_CHAIN: Chain = {\n chainId: AvalancheFujiBlockchainChainIds.X,\n chainName: 'Avalanche Fuji (X-Chain)',\n rpcUrl: 'https://api.avax-test.network/ext/bc/X',\n networkToken: {\n type: TokenType.NATIVE,\n name: 'AVAX',\n symbol: 'AVAX',\n decimals: 9,\n },\n};\n\nexport const ETHEREUM_SEPOLIA_CHAIN: Chain = {\n chainId: EthereumChainIds.SEPOLIA,\n chainName: 'Ethereum Sepolia',\n rpcUrl: 'https://proxy-api.avax.network/proxy/infura/sepolia',\n networkToken: {\n type: TokenType.NATIVE,\n name: 'ETH',\n symbol: 'ETH',\n decimals: 18,\n },\n};\n\nexport const ETHEREUM_MAINNET_CHAIN: Chain = {\n chainId: EthereumChainIds.MAINNET,\n chainName: 'Ethereum Mainnet',\n rpcUrl: 'https://proxy-api.avax.network/proxy/infura/mainnet',\n networkToken: {\n type: TokenType.NATIVE,\n name: 'ETH',\n symbol: 'ETH',\n decimals: 18,\n },\n};\n\nexport const BITCOIN_TESTNET_CHAIN: Chain = {\n chainId: BitcoinChainIds.TESTNET,\n chainName: 'Bitcoin Testnet',\n rpcUrl: '',\n networkToken: {\n type: TokenType.NATIVE,\n name: 'Bitcoin',\n symbol: 'BTC',\n decimals: 8,\n },\n};\n\nexport const BITCOIN_MAINNET_CHAIN: Chain = {\n chainId: BitcoinChainIds.MAINNET,\n chainName: 'Bitcoin Mainnet',\n rpcUrl: '',\n networkToken: {\n type: TokenType.NATIVE,\n name: 'Bitcoin',\n symbol: 'BTC',\n decimals: 8,\n },\n};\n\nexport const SOLANA_MAINNET_CHAIN: Chain = {\n chainId: SolanaChainIds.MAINNET,\n chainName: 'Solana',\n rpcUrl: 'https://proxy-api.avax.network/proxy/nownodes/sol',\n networkToken: {\n type: TokenType.NATIVE,\n name: 'SOL',\n symbol: 'SOL',\n decimals: 9,\n },\n};\n\nexport const SOLANA_DEVNET_CHAIN: Chain = {\n chainId: SolanaChainIds.DEVNET,\n chainName: 'Solana (Devnet)',\n rpcUrl: 'https://api.devnet.solana.com',\n networkToken: {\n type: TokenType.NATIVE,\n name: 'SOL',\n symbol: 'SOL',\n decimals: 9,\n },\n};\nexport const NATIVE_AVAX: NativeAsset = {\n type: TokenType.NATIVE,\n name: 'Avalanche',\n symbol: 'AVAX',\n decimals: 18,\n logoUri:\n 'https://images.ctfassets.net/gcj8jwzm6086/5VHupNKwnDYJvqMENeV7iJ/fdd6326b7a82c8388e4ee9d4be7062d4/avalanche-avax-logo.svg',\n};\nexport const NATIVE_ETH: NativeAsset = {\n type: TokenType.NATIVE,\n name: 'Ether',\n symbol: 'ETH',\n decimals: 18,\n logoUri:\n 'https://images.ctfassets.net/gcj8jwzm6086/6l56QLVZmvacuBfjHBTThP/791d743dd2c526692562780c2325fedf/eth-circle__1_.svg',\n};\n\nexport enum Blockchain {\n AVALANCHE = 'avalanche',\n BITCOIN = 'bitcoin',\n ETHEREUM = 'ethereum',\n SOLANA = 'solana',\n UNKNOWN = '_unknown',\n}\n\nexport enum EvmChainId {\n AVALANCHE_MAINNET = 43114,\n AVALANCHE_TESTNET = 43113,\n ETHEREUM_HOMESTEAD = 1,\n ETHEREUM_TEST_SEPOLIA = 11155111,\n /**\n * This is not a real chain ID, as Bitcoin does not have a chain ID.\n * It is used internally to represent Bitcoin in a way that avoids\n * conflicts with real EVM chain IDs.\n */\n BITCOIN = 4_503_599_627_370_476 - 1,\n /**\n * This is not a real chain ID, as Bitcoin does not have a chain ID.\n * It is used internally to represent Bitcoin in a way that avoids\n * conflicts with real EVM chain IDs.\n */\n BITCOIN_TESTNET = 4_503_599_627_370_476 - 2,\n}\n\n/**\n * Maps the unified {@link FeeRateTier} to the Bitcoin-specific\n * {@link BitcoinFeeRateTier} (`low | medium | high`).\n */\nexport const FEE_RATE_TIER_TO_BITCOIN: Record<FeeRateTier, BitcoinFeeRateTier> = {\n slow: 'low',\n normal: 'medium',\n fast: 'high',\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"constants.cjs","names":[],"sources":["../src/constants.ts"],"sourcesContent":["import type { Address as SolAddress } from '@solana/kit';\nimport type { Address as EvmAddress } from 'viem';\nimport type { NativeAsset } from './types/asset';\nimport type { BitcoinFeeRateTier } from './types/bitcoin';\nimport type { Caip2ChainId } from './types/caip';\nimport type { Chain } from './types/chain';\nimport type { FeeRateTier } from './types/fee';\n\nexport enum Environment {\n DEV = 'dev',\n PROD = 'production',\n TEST = 'test',\n}\n\nexport enum TokenType {\n NATIVE = 'native',\n ERC20 = 'erc20',\n SPL = 'spl',\n}\n\nexport enum ServiceType {\n /** Avalanche Cross-chain transfer service. Export/import between C/P/X Avalanche chains. */\n AVALANCHE_CCT = 'avalanche-cct',\n /** Bridge between EVM chains within Avalanche (or EVM-compatible flows). */\n AVALANCHE_EVM = 'avalanche-evm',\n /** Bitcoin → Avalanche. */\n LOMBARD_BTC_TO_BTCB = 'lombard-btc-to-btcb',\n /** Avalanche → Bitcoin. */\n LOMBARD_BTCB_TO_BTC = 'lombard-btcb-to-btc',\n MARKR = 'markr',\n /** Same-chain wrap/unwrap of native ETH ↔ WETH and AVAX ↔ WAVAX. */\n WRAP_UNWRAP = 'wrap-unwrap',\n}\n\nexport const BTC_SERVICE_TYPES: readonly [ServiceType.LOMBARD_BTCB_TO_BTC, ServiceType.LOMBARD_BTC_TO_BTCB] = [\n ServiceType.LOMBARD_BTCB_TO_BTC,\n ServiceType.LOMBARD_BTC_TO_BTCB,\n];\n\nexport const EVM_SERVICE_TYPES: readonly [ServiceType.AVALANCHE_EVM, ServiceType.WRAP_UNWRAP] = [\n ServiceType.AVALANCHE_EVM,\n ServiceType.WRAP_UNWRAP,\n];\n\n/** Reasons for user signatures during execution. */\nexport enum TransferSignatureReason {\n AddressOwnership = 'address-ownership',\n /** ERC-20 allowance approval for router/bridge. */\n AllowanceApproval = 'allowance-approval',\n /** Primary signature for cross-chain export transaction. */\n AvalancheCrossChainExport = 'avalanche-cross-chain-export',\n /** Primary signature for cross-chain import transaction. */\n AvalancheCrossChainImport = 'avalanche-cross-chain-import',\n /** The primary token movement call (swap or bridge submit). */\n TokensTransfer = 'tokens-transfer',\n /** Optional wrap/unwrap step for native token handling. */\n WrapToken = 'wrap-token',\n /** Hyperliquid 2-phase withdrawal: step 1, nonce-mapping authorization (Relay protocol). */\n HyperliquidAuthorize = 'hyperliquid-authorize',\n /** Hyperliquid 2-phase withdrawal: step 2, the `sendAsset` transfer. */\n HyperliquidSendAsset = 'hyperliquid-send-asset',\n /** Markr recurring: first-fill swap that schedules the recurring order on-chain. */\n ScheduleRecurringSwap = 'schedule-recurring-swap',\n /** Markr recurring: pause an active schedule (preserves allowance). */\n PauseRecurringSwap = 'pause-recurring-swap',\n /** Markr recurring: resume (unpause) a paused schedule. */\n ResumeRecurringSwap = 'resume-recurring-swap',\n /** Markr recurring: cancel an active or paused schedule. */\n CancelRecurringSwap = 'cancel-recurring-swap',\n}\n\nexport const ERC_ZERO_ADDRESS: EvmAddress = '0x0000000000000000000000000000000000000000';\nexport const NATIVE_SOL_ADDRESS: SolAddress = '11111111111111111111111111111111' as SolAddress;\n\nexport enum AvalancheChainIds {\n FUJI = 'eip155:43113',\n MAINNET = 'eip155:43114',\n}\n\nexport enum EthereumChainIds {\n MAINNET = 'eip155:1',\n SEPOLIA = 'eip155:11155111',\n}\n\nexport enum BitcoinChainIds {\n MAINNET = 'bip122:000000000019d6689c085ae165831e93',\n TESTNET = 'bip122:000000000933ea01ad0ee984209779ba',\n}\n\nexport enum SolanaChainIds {\n MAINNET = 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp',\n DEVNET = 'solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1',\n}\n\n/**\n * Hyperliquid is identified by CAIP-2 `eip155:1337` per Relay's convention.\n * It's an EVM-namespaced chain ID but has no real EVM execution — withdrawals\n * use a two-signature EIP-712 flow against Hyperliquid's `/exchange` API.\n */\nexport enum HyperliquidChainIds {\n MAINNET = 'eip155:1337',\n}\n\nexport enum BaseChainIds {\n MAINNET = 'eip155:8453',\n SEPOLIA = 'eip155:84532',\n}\n\nexport enum PolygonChainIds {\n MAINNET = 'eip155:137',\n AMOY = 'eip155:80002',\n}\n\nexport type AvalancheBlockchainAlias = 'C' | 'P' | 'X';\n\nexport const AvalancheMainnetBlockchainChainIds: Readonly<Record<AvalancheBlockchainAlias, Caip2ChainId>> = {\n C: AvalancheChainIds.MAINNET,\n P: 'avax:Rr9hnPVPxuUvrdCul-vjEsU1zmqKqRDo',\n X: 'avax:imji8papUf2EhV3le337w1vgFauqkJg-',\n};\n\nexport const AvalancheFujiBlockchainChainIds: Readonly<Record<AvalancheBlockchainAlias, Caip2ChainId>> = {\n C: AvalancheChainIds.FUJI,\n P: 'avax:Sj7NVE3jXTbJvwFAiu7OEUo_8g8ctXMG',\n X: 'avax:8AJTpRj3SAqv1e80Mtl9em08LhvKEbkl',\n};\n\nexport const AvalancheMainnetBlockchainIds: Readonly<Record<AvalancheBlockchainAlias, string>> = {\n C: '2q9e4r6Mu3U68nU1fYjgbR6JvwrRx36CohpAX5UQxse55x1Q5',\n P: '11111111111111111111111111111111LpoYY',\n X: '2oYMBNV4eNHyqk2fjjV5nVQLDbtmNJzq5s3qs3Lo6ftnC6FByM',\n};\n\nexport const AvalancheFujiBlockchainIds: Readonly<Record<AvalancheBlockchainAlias, string>> = {\n C: 'yH8D7ThNJkxmtkuv2jgBa4P1Rn3Qpr4pPr7QYNfcdoS6k6HWp',\n P: '11111111111111111111111111111111LpoYY',\n X: '2JVSBoinj9C2J33VntvzYtVJNZdN2NKiwwKjcumHUWEb5DbBrm',\n};\n\nexport const AVALANCHE_CAIP2_TO_BLOCKCHAIN_ID_BY_NETWORK: Readonly<{\n mainnet: Readonly<Record<Caip2ChainId, string>>;\n fuji: Readonly<Record<Caip2ChainId, string>>;\n}> = {\n mainnet: {\n [AvalancheMainnetBlockchainChainIds.C]: AvalancheMainnetBlockchainIds.C,\n [AvalancheMainnetBlockchainChainIds.P]: AvalancheMainnetBlockchainIds.P,\n [AvalancheMainnetBlockchainChainIds.X]: AvalancheMainnetBlockchainIds.X,\n },\n fuji: {\n [AvalancheFujiBlockchainChainIds.C]: AvalancheFujiBlockchainIds.C,\n [AvalancheFujiBlockchainChainIds.P]: AvalancheFujiBlockchainIds.P,\n [AvalancheFujiBlockchainChainIds.X]: AvalancheFujiBlockchainIds.X,\n },\n};\n\nexport const AVALANCHE_FUJI_CHAIN: Chain = {\n chainId: AvalancheChainIds.FUJI,\n chainName: 'Avalanche Fuji (C-Chain)',\n networkToken: {\n type: TokenType.NATIVE,\n name: 'AVAX',\n symbol: 'AVAX',\n decimals: 18,\n },\n rpcUrl: 'https://api.avax-test.network/ext/bc/C/rpc',\n};\n\nexport const AVALANCHE_MAINNET_CHAIN: Chain = {\n chainId: AvalancheChainIds.MAINNET,\n chainName: 'Avalanche Mainnet (C-Chain)',\n rpcUrl: 'https://api.avax.network/ext/bc/C/rpc',\n networkToken: {\n type: TokenType.NATIVE,\n name: 'AVAX',\n symbol: 'AVAX',\n decimals: 18,\n },\n};\n\nexport const AVALANCHE_MAINNET_P_CHAIN: Chain = {\n chainId: AvalancheMainnetBlockchainChainIds.P,\n chainName: 'Avalanche Mainnet (P-Chain)',\n rpcUrl: 'https://api.avax.network/ext/bc/P',\n networkToken: {\n type: TokenType.NATIVE,\n name: 'AVAX',\n symbol: 'AVAX',\n decimals: 9,\n },\n};\n\nexport const AVALANCHE_FUJI_P_CHAIN: Chain = {\n chainId: AvalancheFujiBlockchainChainIds.P,\n chainName: 'Avalanche Fuji (P-Chain)',\n rpcUrl: 'https://api.avax-test.network/ext/bc/P',\n networkToken: {\n type: TokenType.NATIVE,\n name: 'AVAX',\n symbol: 'AVAX',\n decimals: 9,\n },\n};\n\nexport const AVALANCHE_MAINNET_X_CHAIN: Chain = {\n chainId: AvalancheMainnetBlockchainChainIds.X,\n chainName: 'Avalanche Mainnet (X-Chain)',\n rpcUrl: 'https://api.avax.network/ext/bc/X',\n networkToken: {\n type: TokenType.NATIVE,\n name: 'AVAX',\n symbol: 'AVAX',\n decimals: 9,\n },\n};\n\nexport const AVALANCHE_FUJI_X_CHAIN: Chain = {\n chainId: AvalancheFujiBlockchainChainIds.X,\n chainName: 'Avalanche Fuji (X-Chain)',\n rpcUrl: 'https://api.avax-test.network/ext/bc/X',\n networkToken: {\n type: TokenType.NATIVE,\n name: 'AVAX',\n symbol: 'AVAX',\n decimals: 9,\n },\n};\n\nexport const ETHEREUM_SEPOLIA_CHAIN: Chain = {\n chainId: EthereumChainIds.SEPOLIA,\n chainName: 'Ethereum Sepolia',\n rpcUrl: 'https://proxy-api.avax.network/proxy/infura/sepolia',\n networkToken: {\n type: TokenType.NATIVE,\n name: 'ETH',\n symbol: 'ETH',\n decimals: 18,\n },\n};\n\nexport const ETHEREUM_MAINNET_CHAIN: Chain = {\n chainId: EthereumChainIds.MAINNET,\n chainName: 'Ethereum Mainnet',\n rpcUrl: 'https://proxy-api.avax.network/proxy/infura/mainnet',\n networkToken: {\n type: TokenType.NATIVE,\n name: 'ETH',\n symbol: 'ETH',\n decimals: 18,\n },\n};\n\nexport const BITCOIN_TESTNET_CHAIN: Chain = {\n chainId: BitcoinChainIds.TESTNET,\n chainName: 'Bitcoin Testnet',\n rpcUrl: '',\n networkToken: {\n type: TokenType.NATIVE,\n name: 'Bitcoin',\n symbol: 'BTC',\n decimals: 8,\n },\n};\n\nexport const BITCOIN_MAINNET_CHAIN: Chain = {\n chainId: BitcoinChainIds.MAINNET,\n chainName: 'Bitcoin Mainnet',\n rpcUrl: '',\n networkToken: {\n type: TokenType.NATIVE,\n name: 'Bitcoin',\n symbol: 'BTC',\n decimals: 8,\n },\n};\n\nexport const SOLANA_MAINNET_CHAIN: Chain = {\n chainId: SolanaChainIds.MAINNET,\n chainName: 'Solana',\n rpcUrl: 'https://proxy-api.avax.network/proxy/nownodes/sol',\n networkToken: {\n type: TokenType.NATIVE,\n name: 'SOL',\n symbol: 'SOL',\n decimals: 9,\n },\n};\n\nexport const SOLANA_DEVNET_CHAIN: Chain = {\n chainId: SolanaChainIds.DEVNET,\n chainName: 'Solana (Devnet)',\n rpcUrl: 'https://api.devnet.solana.com',\n networkToken: {\n type: TokenType.NATIVE,\n name: 'SOL',\n symbol: 'SOL',\n decimals: 9,\n },\n};\nexport const NATIVE_AVAX: NativeAsset = {\n type: TokenType.NATIVE,\n name: 'Avalanche',\n symbol: 'AVAX',\n decimals: 18,\n logoUri:\n 'https://images.ctfassets.net/gcj8jwzm6086/5VHupNKwnDYJvqMENeV7iJ/fdd6326b7a82c8388e4ee9d4be7062d4/avalanche-avax-logo.svg',\n};\nexport const NATIVE_ETH: NativeAsset = {\n type: TokenType.NATIVE,\n name: 'Ether',\n symbol: 'ETH',\n decimals: 18,\n logoUri:\n 'https://images.ctfassets.net/gcj8jwzm6086/6l56QLVZmvacuBfjHBTThP/791d743dd2c526692562780c2325fedf/eth-circle__1_.svg',\n};\n\nexport enum Blockchain {\n AVALANCHE = 'avalanche',\n BITCOIN = 'bitcoin',\n ETHEREUM = 'ethereum',\n SOLANA = 'solana',\n UNKNOWN = '_unknown',\n}\n\nexport enum EvmChainId {\n AVALANCHE_MAINNET = 43114,\n AVALANCHE_TESTNET = 43113,\n ETHEREUM_HOMESTEAD = 1,\n ETHEREUM_TEST_SEPOLIA = 11155111,\n /**\n * This is not a real chain ID, as Bitcoin does not have a chain ID.\n * It is used internally to represent Bitcoin in a way that avoids\n * conflicts with real EVM chain IDs.\n */\n BITCOIN = 4_503_599_627_370_476 - 1,\n /**\n * This is not a real chain ID, as Bitcoin does not have a chain ID.\n * It is used internally to represent Bitcoin in a way that avoids\n * conflicts with real EVM chain IDs.\n */\n BITCOIN_TESTNET = 4_503_599_627_370_476 - 2,\n}\n\n/**\n * Maps the unified {@link FeeRateTier} to the Bitcoin-specific\n * {@link BitcoinFeeRateTier} (`low | medium | high`).\n */\nexport const FEE_RATE_TIER_TO_BITCOIN: Record<FeeRateTier, BitcoinFeeRateTier> = {\n slow: 'low',\n normal: 'medium',\n fast: 'high',\n};\n"],"mappings":"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"}
@@ -84,6 +84,14 @@ declare enum SolanaChainIds {
84
84
  declare enum HyperliquidChainIds {
85
85
  MAINNET = "eip155:1337"
86
86
  }
87
+ declare enum BaseChainIds {
88
+ MAINNET = "eip155:8453",
89
+ SEPOLIA = "eip155:84532"
90
+ }
91
+ declare enum PolygonChainIds {
92
+ MAINNET = "eip155:137",
93
+ AMOY = "eip155:80002"
94
+ }
87
95
  type AvalancheBlockchainAlias = "C" | "P" | "X";
88
96
  declare const AvalancheMainnetBlockchainChainIds: Readonly<Record<AvalancheBlockchainAlias, Caip2ChainId>>;
89
97
  declare const AvalancheFujiBlockchainChainIds: Readonly<Record<AvalancheBlockchainAlias, Caip2ChainId>>;
@@ -138,5 +146,5 @@ declare enum EvmChainId {
138
146
  */
139
147
  declare const FEE_RATE_TIER_TO_BITCOIN: Record<FeeRateTier, BitcoinFeeRateTier>;
140
148
  //#endregion
141
- export { AVALANCHE_CAIP2_TO_BLOCKCHAIN_ID_BY_NETWORK, AVALANCHE_FUJI_CHAIN, AVALANCHE_FUJI_P_CHAIN, AVALANCHE_FUJI_X_CHAIN, AVALANCHE_MAINNET_CHAIN, AVALANCHE_MAINNET_P_CHAIN, AVALANCHE_MAINNET_X_CHAIN, AvalancheBlockchainAlias, AvalancheChainIds, AvalancheFujiBlockchainChainIds, AvalancheFujiBlockchainIds, AvalancheMainnetBlockchainChainIds, AvalancheMainnetBlockchainIds, BITCOIN_MAINNET_CHAIN, BITCOIN_TESTNET_CHAIN, BTC_SERVICE_TYPES, BitcoinChainIds, Blockchain, ERC_ZERO_ADDRESS, ETHEREUM_MAINNET_CHAIN, ETHEREUM_SEPOLIA_CHAIN, EVM_SERVICE_TYPES, Environment, EthereumChainIds, EvmChainId, FEE_RATE_TIER_TO_BITCOIN, HyperliquidChainIds, NATIVE_AVAX, NATIVE_ETH, NATIVE_SOL_ADDRESS, SOLANA_DEVNET_CHAIN, SOLANA_MAINNET_CHAIN, ServiceType, SolanaChainIds, TokenType, TransferSignatureReason };
149
+ export { AVALANCHE_CAIP2_TO_BLOCKCHAIN_ID_BY_NETWORK, AVALANCHE_FUJI_CHAIN, AVALANCHE_FUJI_P_CHAIN, AVALANCHE_FUJI_X_CHAIN, AVALANCHE_MAINNET_CHAIN, AVALANCHE_MAINNET_P_CHAIN, AVALANCHE_MAINNET_X_CHAIN, AvalancheBlockchainAlias, AvalancheChainIds, AvalancheFujiBlockchainChainIds, AvalancheFujiBlockchainIds, AvalancheMainnetBlockchainChainIds, AvalancheMainnetBlockchainIds, BITCOIN_MAINNET_CHAIN, BITCOIN_TESTNET_CHAIN, BTC_SERVICE_TYPES, BaseChainIds, BitcoinChainIds, Blockchain, ERC_ZERO_ADDRESS, ETHEREUM_MAINNET_CHAIN, ETHEREUM_SEPOLIA_CHAIN, EVM_SERVICE_TYPES, Environment, EthereumChainIds, EvmChainId, FEE_RATE_TIER_TO_BITCOIN, HyperliquidChainIds, NATIVE_AVAX, NATIVE_ETH, NATIVE_SOL_ADDRESS, PolygonChainIds, SOLANA_DEVNET_CHAIN, SOLANA_MAINNET_CHAIN, ServiceType, SolanaChainIds, TokenType, TransferSignatureReason };
142
150
  //# sourceMappingURL=constants.d.cts.map
@@ -84,6 +84,14 @@ declare enum SolanaChainIds {
84
84
  declare enum HyperliquidChainIds {
85
85
  MAINNET = "eip155:1337"
86
86
  }
87
+ declare enum BaseChainIds {
88
+ MAINNET = "eip155:8453",
89
+ SEPOLIA = "eip155:84532"
90
+ }
91
+ declare enum PolygonChainIds {
92
+ MAINNET = "eip155:137",
93
+ AMOY = "eip155:80002"
94
+ }
87
95
  type AvalancheBlockchainAlias = "C" | "P" | "X";
88
96
  declare const AvalancheMainnetBlockchainChainIds: Readonly<Record<AvalancheBlockchainAlias, Caip2ChainId>>;
89
97
  declare const AvalancheFujiBlockchainChainIds: Readonly<Record<AvalancheBlockchainAlias, Caip2ChainId>>;
@@ -138,5 +146,5 @@ declare enum EvmChainId {
138
146
  */
139
147
  declare const FEE_RATE_TIER_TO_BITCOIN: Record<FeeRateTier, BitcoinFeeRateTier>;
140
148
  //#endregion
141
- export { AVALANCHE_CAIP2_TO_BLOCKCHAIN_ID_BY_NETWORK, AVALANCHE_FUJI_CHAIN, AVALANCHE_FUJI_P_CHAIN, AVALANCHE_FUJI_X_CHAIN, AVALANCHE_MAINNET_CHAIN, AVALANCHE_MAINNET_P_CHAIN, AVALANCHE_MAINNET_X_CHAIN, AvalancheBlockchainAlias, AvalancheChainIds, AvalancheFujiBlockchainChainIds, AvalancheFujiBlockchainIds, AvalancheMainnetBlockchainChainIds, AvalancheMainnetBlockchainIds, BITCOIN_MAINNET_CHAIN, BITCOIN_TESTNET_CHAIN, BTC_SERVICE_TYPES, BitcoinChainIds, Blockchain, ERC_ZERO_ADDRESS, ETHEREUM_MAINNET_CHAIN, ETHEREUM_SEPOLIA_CHAIN, EVM_SERVICE_TYPES, Environment, EthereumChainIds, EvmChainId, FEE_RATE_TIER_TO_BITCOIN, HyperliquidChainIds, NATIVE_AVAX, NATIVE_ETH, NATIVE_SOL_ADDRESS, SOLANA_DEVNET_CHAIN, SOLANA_MAINNET_CHAIN, ServiceType, SolanaChainIds, TokenType, TransferSignatureReason };
149
+ export { AVALANCHE_CAIP2_TO_BLOCKCHAIN_ID_BY_NETWORK, AVALANCHE_FUJI_CHAIN, AVALANCHE_FUJI_P_CHAIN, AVALANCHE_FUJI_X_CHAIN, AVALANCHE_MAINNET_CHAIN, AVALANCHE_MAINNET_P_CHAIN, AVALANCHE_MAINNET_X_CHAIN, AvalancheBlockchainAlias, AvalancheChainIds, AvalancheFujiBlockchainChainIds, AvalancheFujiBlockchainIds, AvalancheMainnetBlockchainChainIds, AvalancheMainnetBlockchainIds, BITCOIN_MAINNET_CHAIN, BITCOIN_TESTNET_CHAIN, BTC_SERVICE_TYPES, BaseChainIds, BitcoinChainIds, Blockchain, ERC_ZERO_ADDRESS, ETHEREUM_MAINNET_CHAIN, ETHEREUM_SEPOLIA_CHAIN, EVM_SERVICE_TYPES, Environment, EthereumChainIds, EvmChainId, FEE_RATE_TIER_TO_BITCOIN, HyperliquidChainIds, NATIVE_AVAX, NATIVE_ETH, NATIVE_SOL_ADDRESS, PolygonChainIds, SOLANA_DEVNET_CHAIN, SOLANA_MAINNET_CHAIN, ServiceType, SolanaChainIds, TokenType, TransferSignatureReason };
142
150
  //# sourceMappingURL=constants.d.ts.map
package/dist/constants.js CHANGED
@@ -1,2 +1,2 @@
1
- let e=function(e){return e.DEV=`dev`,e.PROD=`production`,e.TEST=`test`,e}({}),t=function(e){return e.NATIVE=`native`,e.ERC20=`erc20`,e.SPL=`spl`,e}({}),n=function(e){return e.AVALANCHE_CCT=`avalanche-cct`,e.AVALANCHE_EVM=`avalanche-evm`,e.LOMBARD_BTC_TO_BTCB=`lombard-btc-to-btcb`,e.LOMBARD_BTCB_TO_BTC=`lombard-btcb-to-btc`,e.MARKR=`markr`,e.WRAP_UNWRAP=`wrap-unwrap`,e}({});const r=[n.LOMBARD_BTCB_TO_BTC,n.LOMBARD_BTC_TO_BTCB],i=[n.AVALANCHE_EVM,n.WRAP_UNWRAP];let a=function(e){return e.AddressOwnership=`address-ownership`,e.AllowanceApproval=`allowance-approval`,e.AvalancheCrossChainExport=`avalanche-cross-chain-export`,e.AvalancheCrossChainImport=`avalanche-cross-chain-import`,e.TokensTransfer=`tokens-transfer`,e.WrapToken=`wrap-token`,e.HyperliquidAuthorize=`hyperliquid-authorize`,e.HyperliquidSendAsset=`hyperliquid-send-asset`,e.ScheduleRecurringSwap=`schedule-recurring-swap`,e.PauseRecurringSwap=`pause-recurring-swap`,e.ResumeRecurringSwap=`resume-recurring-swap`,e.CancelRecurringSwap=`cancel-recurring-swap`,e}({});const o=`0x0000000000000000000000000000000000000000`,s=`11111111111111111111111111111111`;let c=function(e){return e.FUJI=`eip155:43113`,e.MAINNET=`eip155:43114`,e}({}),l=function(e){return e.MAINNET=`eip155:1`,e.SEPOLIA=`eip155:11155111`,e}({}),u=function(e){return e.MAINNET=`bip122:000000000019d6689c085ae165831e93`,e.TESTNET=`bip122:000000000933ea01ad0ee984209779ba`,e}({}),d=function(e){return e.MAINNET=`solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp`,e.DEVNET=`solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1`,e}({}),f=function(e){return e.MAINNET=`eip155:1337`,e}({});const p={C:c.MAINNET,P:`avax:Rr9hnPVPxuUvrdCul-vjEsU1zmqKqRDo`,X:`avax:imji8papUf2EhV3le337w1vgFauqkJg-`},m={C:c.FUJI,P:`avax:Sj7NVE3jXTbJvwFAiu7OEUo_8g8ctXMG`,X:`avax:8AJTpRj3SAqv1e80Mtl9em08LhvKEbkl`},h={C:`2q9e4r6Mu3U68nU1fYjgbR6JvwrRx36CohpAX5UQxse55x1Q5`,P:`11111111111111111111111111111111LpoYY`,X:`2oYMBNV4eNHyqk2fjjV5nVQLDbtmNJzq5s3qs3Lo6ftnC6FByM`},g={C:`yH8D7ThNJkxmtkuv2jgBa4P1Rn3Qpr4pPr7QYNfcdoS6k6HWp`,P:`11111111111111111111111111111111LpoYY`,X:`2JVSBoinj9C2J33VntvzYtVJNZdN2NKiwwKjcumHUWEb5DbBrm`},_={mainnet:{[p.C]:h.C,[p.P]:h.P,[p.X]:h.X},fuji:{[m.C]:g.C,[m.P]:g.P,[m.X]:g.X}},v={chainId:c.FUJI,chainName:`Avalanche Fuji (C-Chain)`,networkToken:{type:t.NATIVE,name:`AVAX`,symbol:`AVAX`,decimals:18},rpcUrl:`https://api.avax-test.network/ext/bc/C/rpc`},y={chainId:c.MAINNET,chainName:`Avalanche Mainnet (C-Chain)`,rpcUrl:`https://api.avax.network/ext/bc/C/rpc`,networkToken:{type:t.NATIVE,name:`AVAX`,symbol:`AVAX`,decimals:18}},b={chainId:p.P,chainName:`Avalanche Mainnet (P-Chain)`,rpcUrl:`https://api.avax.network/ext/bc/P`,networkToken:{type:t.NATIVE,name:`AVAX`,symbol:`AVAX`,decimals:9}},x={chainId:m.P,chainName:`Avalanche Fuji (P-Chain)`,rpcUrl:`https://api.avax-test.network/ext/bc/P`,networkToken:{type:t.NATIVE,name:`AVAX`,symbol:`AVAX`,decimals:9}},S={chainId:p.X,chainName:`Avalanche Mainnet (X-Chain)`,rpcUrl:`https://api.avax.network/ext/bc/X`,networkToken:{type:t.NATIVE,name:`AVAX`,symbol:`AVAX`,decimals:9}},C={chainId:m.X,chainName:`Avalanche Fuji (X-Chain)`,rpcUrl:`https://api.avax-test.network/ext/bc/X`,networkToken:{type:t.NATIVE,name:`AVAX`,symbol:`AVAX`,decimals:9}},w={chainId:l.SEPOLIA,chainName:`Ethereum Sepolia`,rpcUrl:`https://proxy-api.avax.network/proxy/infura/sepolia`,networkToken:{type:t.NATIVE,name:`ETH`,symbol:`ETH`,decimals:18}},T={chainId:l.MAINNET,chainName:`Ethereum Mainnet`,rpcUrl:`https://proxy-api.avax.network/proxy/infura/mainnet`,networkToken:{type:t.NATIVE,name:`ETH`,symbol:`ETH`,decimals:18}},E={chainId:u.TESTNET,chainName:`Bitcoin Testnet`,rpcUrl:``,networkToken:{type:t.NATIVE,name:`Bitcoin`,symbol:`BTC`,decimals:8}},D={chainId:u.MAINNET,chainName:`Bitcoin Mainnet`,rpcUrl:``,networkToken:{type:t.NATIVE,name:`Bitcoin`,symbol:`BTC`,decimals:8}},O={chainId:d.MAINNET,chainName:`Solana`,rpcUrl:`https://proxy-api.avax.network/proxy/nownodes/sol`,networkToken:{type:t.NATIVE,name:`SOL`,symbol:`SOL`,decimals:9}},k={chainId:d.DEVNET,chainName:`Solana (Devnet)`,rpcUrl:`https://api.devnet.solana.com`,networkToken:{type:t.NATIVE,name:`SOL`,symbol:`SOL`,decimals:9}},A={type:t.NATIVE,name:`Avalanche`,symbol:`AVAX`,decimals:18,logoUri:`https://images.ctfassets.net/gcj8jwzm6086/5VHupNKwnDYJvqMENeV7iJ/fdd6326b7a82c8388e4ee9d4be7062d4/avalanche-avax-logo.svg`},j={type:t.NATIVE,name:`Ether`,symbol:`ETH`,decimals:18,logoUri:`https://images.ctfassets.net/gcj8jwzm6086/6l56QLVZmvacuBfjHBTThP/791d743dd2c526692562780c2325fedf/eth-circle__1_.svg`};let M=function(e){return e.AVALANCHE=`avalanche`,e.BITCOIN=`bitcoin`,e.ETHEREUM=`ethereum`,e.SOLANA=`solana`,e.UNKNOWN=`_unknown`,e}({}),N=function(e){return e[e.AVALANCHE_MAINNET=43114]=`AVALANCHE_MAINNET`,e[e.AVALANCHE_TESTNET=43113]=`AVALANCHE_TESTNET`,e[e.ETHEREUM_HOMESTEAD=1]=`ETHEREUM_HOMESTEAD`,e[e.ETHEREUM_TEST_SEPOLIA=11155111]=`ETHEREUM_TEST_SEPOLIA`,e[e.BITCOIN=0xfffffffffffeb]=`BITCOIN`,e[e.BITCOIN_TESTNET=0xfffffffffffea]=`BITCOIN_TESTNET`,e}({});const P={slow:`low`,normal:`medium`,fast:`high`};export{_ as AVALANCHE_CAIP2_TO_BLOCKCHAIN_ID_BY_NETWORK,v as AVALANCHE_FUJI_CHAIN,x as AVALANCHE_FUJI_P_CHAIN,C as AVALANCHE_FUJI_X_CHAIN,y as AVALANCHE_MAINNET_CHAIN,b as AVALANCHE_MAINNET_P_CHAIN,S as AVALANCHE_MAINNET_X_CHAIN,c as AvalancheChainIds,m as AvalancheFujiBlockchainChainIds,g as AvalancheFujiBlockchainIds,p as AvalancheMainnetBlockchainChainIds,h as AvalancheMainnetBlockchainIds,D as BITCOIN_MAINNET_CHAIN,E as BITCOIN_TESTNET_CHAIN,r as BTC_SERVICE_TYPES,u as BitcoinChainIds,M as Blockchain,o as ERC_ZERO_ADDRESS,T as ETHEREUM_MAINNET_CHAIN,w as ETHEREUM_SEPOLIA_CHAIN,i as EVM_SERVICE_TYPES,e as Environment,l as EthereumChainIds,N as EvmChainId,P as FEE_RATE_TIER_TO_BITCOIN,f as HyperliquidChainIds,A as NATIVE_AVAX,j as NATIVE_ETH,s as NATIVE_SOL_ADDRESS,k as SOLANA_DEVNET_CHAIN,O as SOLANA_MAINNET_CHAIN,n as ServiceType,d as SolanaChainIds,t as TokenType,a as TransferSignatureReason};
1
+ let e=function(e){return e.DEV=`dev`,e.PROD=`production`,e.TEST=`test`,e}({}),t=function(e){return e.NATIVE=`native`,e.ERC20=`erc20`,e.SPL=`spl`,e}({}),n=function(e){return e.AVALANCHE_CCT=`avalanche-cct`,e.AVALANCHE_EVM=`avalanche-evm`,e.LOMBARD_BTC_TO_BTCB=`lombard-btc-to-btcb`,e.LOMBARD_BTCB_TO_BTC=`lombard-btcb-to-btc`,e.MARKR=`markr`,e.WRAP_UNWRAP=`wrap-unwrap`,e}({});const r=[n.LOMBARD_BTCB_TO_BTC,n.LOMBARD_BTC_TO_BTCB],i=[n.AVALANCHE_EVM,n.WRAP_UNWRAP];let a=function(e){return e.AddressOwnership=`address-ownership`,e.AllowanceApproval=`allowance-approval`,e.AvalancheCrossChainExport=`avalanche-cross-chain-export`,e.AvalancheCrossChainImport=`avalanche-cross-chain-import`,e.TokensTransfer=`tokens-transfer`,e.WrapToken=`wrap-token`,e.HyperliquidAuthorize=`hyperliquid-authorize`,e.HyperliquidSendAsset=`hyperliquid-send-asset`,e.ScheduleRecurringSwap=`schedule-recurring-swap`,e.PauseRecurringSwap=`pause-recurring-swap`,e.ResumeRecurringSwap=`resume-recurring-swap`,e.CancelRecurringSwap=`cancel-recurring-swap`,e}({});const o=`0x0000000000000000000000000000000000000000`,s=`11111111111111111111111111111111`;let c=function(e){return e.FUJI=`eip155:43113`,e.MAINNET=`eip155:43114`,e}({}),l=function(e){return e.MAINNET=`eip155:1`,e.SEPOLIA=`eip155:11155111`,e}({}),u=function(e){return e.MAINNET=`bip122:000000000019d6689c085ae165831e93`,e.TESTNET=`bip122:000000000933ea01ad0ee984209779ba`,e}({}),d=function(e){return e.MAINNET=`solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp`,e.DEVNET=`solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1`,e}({}),f=function(e){return e.MAINNET=`eip155:1337`,e}({}),p=function(e){return e.MAINNET=`eip155:8453`,e.SEPOLIA=`eip155:84532`,e}({}),m=function(e){return e.MAINNET=`eip155:137`,e.AMOY=`eip155:80002`,e}({});const h={C:c.MAINNET,P:`avax:Rr9hnPVPxuUvrdCul-vjEsU1zmqKqRDo`,X:`avax:imji8papUf2EhV3le337w1vgFauqkJg-`},g={C:c.FUJI,P:`avax:Sj7NVE3jXTbJvwFAiu7OEUo_8g8ctXMG`,X:`avax:8AJTpRj3SAqv1e80Mtl9em08LhvKEbkl`},_={C:`2q9e4r6Mu3U68nU1fYjgbR6JvwrRx36CohpAX5UQxse55x1Q5`,P:`11111111111111111111111111111111LpoYY`,X:`2oYMBNV4eNHyqk2fjjV5nVQLDbtmNJzq5s3qs3Lo6ftnC6FByM`},v={C:`yH8D7ThNJkxmtkuv2jgBa4P1Rn3Qpr4pPr7QYNfcdoS6k6HWp`,P:`11111111111111111111111111111111LpoYY`,X:`2JVSBoinj9C2J33VntvzYtVJNZdN2NKiwwKjcumHUWEb5DbBrm`},y={mainnet:{[h.C]:_.C,[h.P]:_.P,[h.X]:_.X},fuji:{[g.C]:v.C,[g.P]:v.P,[g.X]:v.X}},b={chainId:c.FUJI,chainName:`Avalanche Fuji (C-Chain)`,networkToken:{type:t.NATIVE,name:`AVAX`,symbol:`AVAX`,decimals:18},rpcUrl:`https://api.avax-test.network/ext/bc/C/rpc`},x={chainId:c.MAINNET,chainName:`Avalanche Mainnet (C-Chain)`,rpcUrl:`https://api.avax.network/ext/bc/C/rpc`,networkToken:{type:t.NATIVE,name:`AVAX`,symbol:`AVAX`,decimals:18}},S={chainId:h.P,chainName:`Avalanche Mainnet (P-Chain)`,rpcUrl:`https://api.avax.network/ext/bc/P`,networkToken:{type:t.NATIVE,name:`AVAX`,symbol:`AVAX`,decimals:9}},C={chainId:g.P,chainName:`Avalanche Fuji (P-Chain)`,rpcUrl:`https://api.avax-test.network/ext/bc/P`,networkToken:{type:t.NATIVE,name:`AVAX`,symbol:`AVAX`,decimals:9}},w={chainId:h.X,chainName:`Avalanche Mainnet (X-Chain)`,rpcUrl:`https://api.avax.network/ext/bc/X`,networkToken:{type:t.NATIVE,name:`AVAX`,symbol:`AVAX`,decimals:9}},T={chainId:g.X,chainName:`Avalanche Fuji (X-Chain)`,rpcUrl:`https://api.avax-test.network/ext/bc/X`,networkToken:{type:t.NATIVE,name:`AVAX`,symbol:`AVAX`,decimals:9}},E={chainId:l.SEPOLIA,chainName:`Ethereum Sepolia`,rpcUrl:`https://proxy-api.avax.network/proxy/infura/sepolia`,networkToken:{type:t.NATIVE,name:`ETH`,symbol:`ETH`,decimals:18}},D={chainId:l.MAINNET,chainName:`Ethereum Mainnet`,rpcUrl:`https://proxy-api.avax.network/proxy/infura/mainnet`,networkToken:{type:t.NATIVE,name:`ETH`,symbol:`ETH`,decimals:18}},O={chainId:u.TESTNET,chainName:`Bitcoin Testnet`,rpcUrl:``,networkToken:{type:t.NATIVE,name:`Bitcoin`,symbol:`BTC`,decimals:8}},k={chainId:u.MAINNET,chainName:`Bitcoin Mainnet`,rpcUrl:``,networkToken:{type:t.NATIVE,name:`Bitcoin`,symbol:`BTC`,decimals:8}},A={chainId:d.MAINNET,chainName:`Solana`,rpcUrl:`https://proxy-api.avax.network/proxy/nownodes/sol`,networkToken:{type:t.NATIVE,name:`SOL`,symbol:`SOL`,decimals:9}},j={chainId:d.DEVNET,chainName:`Solana (Devnet)`,rpcUrl:`https://api.devnet.solana.com`,networkToken:{type:t.NATIVE,name:`SOL`,symbol:`SOL`,decimals:9}},M={type:t.NATIVE,name:`Avalanche`,symbol:`AVAX`,decimals:18,logoUri:`https://images.ctfassets.net/gcj8jwzm6086/5VHupNKwnDYJvqMENeV7iJ/fdd6326b7a82c8388e4ee9d4be7062d4/avalanche-avax-logo.svg`},N={type:t.NATIVE,name:`Ether`,symbol:`ETH`,decimals:18,logoUri:`https://images.ctfassets.net/gcj8jwzm6086/6l56QLVZmvacuBfjHBTThP/791d743dd2c526692562780c2325fedf/eth-circle__1_.svg`};let P=function(e){return e.AVALANCHE=`avalanche`,e.BITCOIN=`bitcoin`,e.ETHEREUM=`ethereum`,e.SOLANA=`solana`,e.UNKNOWN=`_unknown`,e}({}),F=function(e){return e[e.AVALANCHE_MAINNET=43114]=`AVALANCHE_MAINNET`,e[e.AVALANCHE_TESTNET=43113]=`AVALANCHE_TESTNET`,e[e.ETHEREUM_HOMESTEAD=1]=`ETHEREUM_HOMESTEAD`,e[e.ETHEREUM_TEST_SEPOLIA=11155111]=`ETHEREUM_TEST_SEPOLIA`,e[e.BITCOIN=0xfffffffffffeb]=`BITCOIN`,e[e.BITCOIN_TESTNET=0xfffffffffffea]=`BITCOIN_TESTNET`,e}({});const I={slow:`low`,normal:`medium`,fast:`high`};export{y as AVALANCHE_CAIP2_TO_BLOCKCHAIN_ID_BY_NETWORK,b as AVALANCHE_FUJI_CHAIN,C as AVALANCHE_FUJI_P_CHAIN,T as AVALANCHE_FUJI_X_CHAIN,x as AVALANCHE_MAINNET_CHAIN,S as AVALANCHE_MAINNET_P_CHAIN,w as AVALANCHE_MAINNET_X_CHAIN,c as AvalancheChainIds,g as AvalancheFujiBlockchainChainIds,v as AvalancheFujiBlockchainIds,h as AvalancheMainnetBlockchainChainIds,_ as AvalancheMainnetBlockchainIds,k as BITCOIN_MAINNET_CHAIN,O as BITCOIN_TESTNET_CHAIN,r as BTC_SERVICE_TYPES,p as BaseChainIds,u as BitcoinChainIds,P as Blockchain,o as ERC_ZERO_ADDRESS,D as ETHEREUM_MAINNET_CHAIN,E as ETHEREUM_SEPOLIA_CHAIN,i as EVM_SERVICE_TYPES,e as Environment,l as EthereumChainIds,F as EvmChainId,I as FEE_RATE_TIER_TO_BITCOIN,f as HyperliquidChainIds,M as NATIVE_AVAX,N as NATIVE_ETH,s as NATIVE_SOL_ADDRESS,m as PolygonChainIds,j as SOLANA_DEVNET_CHAIN,A as SOLANA_MAINNET_CHAIN,n as ServiceType,d as SolanaChainIds,t as TokenType,a as TransferSignatureReason};
2
2
  //# sourceMappingURL=constants.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"constants.js","names":[],"sources":["../src/constants.ts"],"sourcesContent":["import type { Address as SolAddress } from '@solana/kit';\nimport type { Address as EvmAddress } from 'viem';\nimport type { NativeAsset } from './types/asset';\nimport type { BitcoinFeeRateTier } from './types/bitcoin';\nimport type { Caip2ChainId } from './types/caip';\nimport type { Chain } from './types/chain';\nimport type { FeeRateTier } from './types/fee';\n\nexport enum Environment {\n DEV = 'dev',\n PROD = 'production',\n TEST = 'test',\n}\n\nexport enum TokenType {\n NATIVE = 'native',\n ERC20 = 'erc20',\n SPL = 'spl',\n}\n\nexport enum ServiceType {\n /** Avalanche Cross-chain transfer service. Export/import between C/P/X Avalanche chains. */\n AVALANCHE_CCT = 'avalanche-cct',\n /** Bridge between EVM chains within Avalanche (or EVM-compatible flows). */\n AVALANCHE_EVM = 'avalanche-evm',\n /** Bitcoin → Avalanche. */\n LOMBARD_BTC_TO_BTCB = 'lombard-btc-to-btcb',\n /** Avalanche → Bitcoin. */\n LOMBARD_BTCB_TO_BTC = 'lombard-btcb-to-btc',\n MARKR = 'markr',\n /** Same-chain wrap/unwrap of native ETH ↔ WETH and AVAX ↔ WAVAX. */\n WRAP_UNWRAP = 'wrap-unwrap',\n}\n\nexport const BTC_SERVICE_TYPES: readonly [ServiceType.LOMBARD_BTCB_TO_BTC, ServiceType.LOMBARD_BTC_TO_BTCB] = [\n ServiceType.LOMBARD_BTCB_TO_BTC,\n ServiceType.LOMBARD_BTC_TO_BTCB,\n];\n\nexport const EVM_SERVICE_TYPES: readonly [ServiceType.AVALANCHE_EVM, ServiceType.WRAP_UNWRAP] = [\n ServiceType.AVALANCHE_EVM,\n ServiceType.WRAP_UNWRAP,\n];\n\n/** Reasons for user signatures during execution. */\nexport enum TransferSignatureReason {\n AddressOwnership = 'address-ownership',\n /** ERC-20 allowance approval for router/bridge. */\n AllowanceApproval = 'allowance-approval',\n /** Primary signature for cross-chain export transaction. */\n AvalancheCrossChainExport = 'avalanche-cross-chain-export',\n /** Primary signature for cross-chain import transaction. */\n AvalancheCrossChainImport = 'avalanche-cross-chain-import',\n /** The primary token movement call (swap or bridge submit). */\n TokensTransfer = 'tokens-transfer',\n /** Optional wrap/unwrap step for native token handling. */\n WrapToken = 'wrap-token',\n /** Hyperliquid 2-phase withdrawal: step 1, nonce-mapping authorization (Relay protocol). */\n HyperliquidAuthorize = 'hyperliquid-authorize',\n /** Hyperliquid 2-phase withdrawal: step 2, the `sendAsset` transfer. */\n HyperliquidSendAsset = 'hyperliquid-send-asset',\n /** Markr recurring: first-fill swap that schedules the recurring order on-chain. */\n ScheduleRecurringSwap = 'schedule-recurring-swap',\n /** Markr recurring: pause an active schedule (preserves allowance). */\n PauseRecurringSwap = 'pause-recurring-swap',\n /** Markr recurring: resume (unpause) a paused schedule. */\n ResumeRecurringSwap = 'resume-recurring-swap',\n /** Markr recurring: cancel an active or paused schedule. */\n CancelRecurringSwap = 'cancel-recurring-swap',\n}\n\nexport const ERC_ZERO_ADDRESS: EvmAddress = '0x0000000000000000000000000000000000000000';\nexport const NATIVE_SOL_ADDRESS: SolAddress = '11111111111111111111111111111111' as SolAddress;\n\nexport enum AvalancheChainIds {\n FUJI = 'eip155:43113',\n MAINNET = 'eip155:43114',\n}\n\nexport enum EthereumChainIds {\n MAINNET = 'eip155:1',\n SEPOLIA = 'eip155:11155111',\n}\n\nexport enum BitcoinChainIds {\n MAINNET = 'bip122:000000000019d6689c085ae165831e93',\n TESTNET = 'bip122:000000000933ea01ad0ee984209779ba',\n}\n\nexport enum SolanaChainIds {\n MAINNET = 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp',\n DEVNET = 'solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1',\n}\n\n/**\n * Hyperliquid is identified by CAIP-2 `eip155:1337` per Relay's convention.\n * It's an EVM-namespaced chain ID but has no real EVM execution — withdrawals\n * use a two-signature EIP-712 flow against Hyperliquid's `/exchange` API.\n */\nexport enum HyperliquidChainIds {\n MAINNET = 'eip155:1337',\n}\n\nexport type AvalancheBlockchainAlias = 'C' | 'P' | 'X';\n\nexport const AvalancheMainnetBlockchainChainIds: Readonly<Record<AvalancheBlockchainAlias, Caip2ChainId>> = {\n C: AvalancheChainIds.MAINNET,\n P: 'avax:Rr9hnPVPxuUvrdCul-vjEsU1zmqKqRDo',\n X: 'avax:imji8papUf2EhV3le337w1vgFauqkJg-',\n};\n\nexport const AvalancheFujiBlockchainChainIds: Readonly<Record<AvalancheBlockchainAlias, Caip2ChainId>> = {\n C: AvalancheChainIds.FUJI,\n P: 'avax:Sj7NVE3jXTbJvwFAiu7OEUo_8g8ctXMG',\n X: 'avax:8AJTpRj3SAqv1e80Mtl9em08LhvKEbkl',\n};\n\nexport const AvalancheMainnetBlockchainIds: Readonly<Record<AvalancheBlockchainAlias, string>> = {\n C: '2q9e4r6Mu3U68nU1fYjgbR6JvwrRx36CohpAX5UQxse55x1Q5',\n P: '11111111111111111111111111111111LpoYY',\n X: '2oYMBNV4eNHyqk2fjjV5nVQLDbtmNJzq5s3qs3Lo6ftnC6FByM',\n};\n\nexport const AvalancheFujiBlockchainIds: Readonly<Record<AvalancheBlockchainAlias, string>> = {\n C: 'yH8D7ThNJkxmtkuv2jgBa4P1Rn3Qpr4pPr7QYNfcdoS6k6HWp',\n P: '11111111111111111111111111111111LpoYY',\n X: '2JVSBoinj9C2J33VntvzYtVJNZdN2NKiwwKjcumHUWEb5DbBrm',\n};\n\nexport const AVALANCHE_CAIP2_TO_BLOCKCHAIN_ID_BY_NETWORK: Readonly<{\n mainnet: Readonly<Record<Caip2ChainId, string>>;\n fuji: Readonly<Record<Caip2ChainId, string>>;\n}> = {\n mainnet: {\n [AvalancheMainnetBlockchainChainIds.C]: AvalancheMainnetBlockchainIds.C,\n [AvalancheMainnetBlockchainChainIds.P]: AvalancheMainnetBlockchainIds.P,\n [AvalancheMainnetBlockchainChainIds.X]: AvalancheMainnetBlockchainIds.X,\n },\n fuji: {\n [AvalancheFujiBlockchainChainIds.C]: AvalancheFujiBlockchainIds.C,\n [AvalancheFujiBlockchainChainIds.P]: AvalancheFujiBlockchainIds.P,\n [AvalancheFujiBlockchainChainIds.X]: AvalancheFujiBlockchainIds.X,\n },\n};\n\nexport const AVALANCHE_FUJI_CHAIN: Chain = {\n chainId: AvalancheChainIds.FUJI,\n chainName: 'Avalanche Fuji (C-Chain)',\n networkToken: {\n type: TokenType.NATIVE,\n name: 'AVAX',\n symbol: 'AVAX',\n decimals: 18,\n },\n rpcUrl: 'https://api.avax-test.network/ext/bc/C/rpc',\n};\n\nexport const AVALANCHE_MAINNET_CHAIN: Chain = {\n chainId: AvalancheChainIds.MAINNET,\n chainName: 'Avalanche Mainnet (C-Chain)',\n rpcUrl: 'https://api.avax.network/ext/bc/C/rpc',\n networkToken: {\n type: TokenType.NATIVE,\n name: 'AVAX',\n symbol: 'AVAX',\n decimals: 18,\n },\n};\n\nexport const AVALANCHE_MAINNET_P_CHAIN: Chain = {\n chainId: AvalancheMainnetBlockchainChainIds.P,\n chainName: 'Avalanche Mainnet (P-Chain)',\n rpcUrl: 'https://api.avax.network/ext/bc/P',\n networkToken: {\n type: TokenType.NATIVE,\n name: 'AVAX',\n symbol: 'AVAX',\n decimals: 9,\n },\n};\n\nexport const AVALANCHE_FUJI_P_CHAIN: Chain = {\n chainId: AvalancheFujiBlockchainChainIds.P,\n chainName: 'Avalanche Fuji (P-Chain)',\n rpcUrl: 'https://api.avax-test.network/ext/bc/P',\n networkToken: {\n type: TokenType.NATIVE,\n name: 'AVAX',\n symbol: 'AVAX',\n decimals: 9,\n },\n};\n\nexport const AVALANCHE_MAINNET_X_CHAIN: Chain = {\n chainId: AvalancheMainnetBlockchainChainIds.X,\n chainName: 'Avalanche Mainnet (X-Chain)',\n rpcUrl: 'https://api.avax.network/ext/bc/X',\n networkToken: {\n type: TokenType.NATIVE,\n name: 'AVAX',\n symbol: 'AVAX',\n decimals: 9,\n },\n};\n\nexport const AVALANCHE_FUJI_X_CHAIN: Chain = {\n chainId: AvalancheFujiBlockchainChainIds.X,\n chainName: 'Avalanche Fuji (X-Chain)',\n rpcUrl: 'https://api.avax-test.network/ext/bc/X',\n networkToken: {\n type: TokenType.NATIVE,\n name: 'AVAX',\n symbol: 'AVAX',\n decimals: 9,\n },\n};\n\nexport const ETHEREUM_SEPOLIA_CHAIN: Chain = {\n chainId: EthereumChainIds.SEPOLIA,\n chainName: 'Ethereum Sepolia',\n rpcUrl: 'https://proxy-api.avax.network/proxy/infura/sepolia',\n networkToken: {\n type: TokenType.NATIVE,\n name: 'ETH',\n symbol: 'ETH',\n decimals: 18,\n },\n};\n\nexport const ETHEREUM_MAINNET_CHAIN: Chain = {\n chainId: EthereumChainIds.MAINNET,\n chainName: 'Ethereum Mainnet',\n rpcUrl: 'https://proxy-api.avax.network/proxy/infura/mainnet',\n networkToken: {\n type: TokenType.NATIVE,\n name: 'ETH',\n symbol: 'ETH',\n decimals: 18,\n },\n};\n\nexport const BITCOIN_TESTNET_CHAIN: Chain = {\n chainId: BitcoinChainIds.TESTNET,\n chainName: 'Bitcoin Testnet',\n rpcUrl: '',\n networkToken: {\n type: TokenType.NATIVE,\n name: 'Bitcoin',\n symbol: 'BTC',\n decimals: 8,\n },\n};\n\nexport const BITCOIN_MAINNET_CHAIN: Chain = {\n chainId: BitcoinChainIds.MAINNET,\n chainName: 'Bitcoin Mainnet',\n rpcUrl: '',\n networkToken: {\n type: TokenType.NATIVE,\n name: 'Bitcoin',\n symbol: 'BTC',\n decimals: 8,\n },\n};\n\nexport const SOLANA_MAINNET_CHAIN: Chain = {\n chainId: SolanaChainIds.MAINNET,\n chainName: 'Solana',\n rpcUrl: 'https://proxy-api.avax.network/proxy/nownodes/sol',\n networkToken: {\n type: TokenType.NATIVE,\n name: 'SOL',\n symbol: 'SOL',\n decimals: 9,\n },\n};\n\nexport const SOLANA_DEVNET_CHAIN: Chain = {\n chainId: SolanaChainIds.DEVNET,\n chainName: 'Solana (Devnet)',\n rpcUrl: 'https://api.devnet.solana.com',\n networkToken: {\n type: TokenType.NATIVE,\n name: 'SOL',\n symbol: 'SOL',\n decimals: 9,\n },\n};\nexport const NATIVE_AVAX: NativeAsset = {\n type: TokenType.NATIVE,\n name: 'Avalanche',\n symbol: 'AVAX',\n decimals: 18,\n logoUri:\n 'https://images.ctfassets.net/gcj8jwzm6086/5VHupNKwnDYJvqMENeV7iJ/fdd6326b7a82c8388e4ee9d4be7062d4/avalanche-avax-logo.svg',\n};\nexport const NATIVE_ETH: NativeAsset = {\n type: TokenType.NATIVE,\n name: 'Ether',\n symbol: 'ETH',\n decimals: 18,\n logoUri:\n 'https://images.ctfassets.net/gcj8jwzm6086/6l56QLVZmvacuBfjHBTThP/791d743dd2c526692562780c2325fedf/eth-circle__1_.svg',\n};\n\nexport enum Blockchain {\n AVALANCHE = 'avalanche',\n BITCOIN = 'bitcoin',\n ETHEREUM = 'ethereum',\n SOLANA = 'solana',\n UNKNOWN = '_unknown',\n}\n\nexport enum EvmChainId {\n AVALANCHE_MAINNET = 43114,\n AVALANCHE_TESTNET = 43113,\n ETHEREUM_HOMESTEAD = 1,\n ETHEREUM_TEST_SEPOLIA = 11155111,\n /**\n * This is not a real chain ID, as Bitcoin does not have a chain ID.\n * It is used internally to represent Bitcoin in a way that avoids\n * conflicts with real EVM chain IDs.\n */\n BITCOIN = 4_503_599_627_370_476 - 1,\n /**\n * This is not a real chain ID, as Bitcoin does not have a chain ID.\n * It is used internally to represent Bitcoin in a way that avoids\n * conflicts with real EVM chain IDs.\n */\n BITCOIN_TESTNET = 4_503_599_627_370_476 - 2,\n}\n\n/**\n * Maps the unified {@link FeeRateTier} to the Bitcoin-specific\n * {@link BitcoinFeeRateTier} (`low | medium | high`).\n */\nexport const FEE_RATE_TIER_TO_BITCOIN: Record<FeeRateTier, BitcoinFeeRateTier> = {\n slow: 'low',\n normal: 'medium',\n fast: 'high',\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"constants.js","names":[],"sources":["../src/constants.ts"],"sourcesContent":["import type { Address as SolAddress } from '@solana/kit';\nimport type { Address as EvmAddress } from 'viem';\nimport type { NativeAsset } from './types/asset';\nimport type { BitcoinFeeRateTier } from './types/bitcoin';\nimport type { Caip2ChainId } from './types/caip';\nimport type { Chain } from './types/chain';\nimport type { FeeRateTier } from './types/fee';\n\nexport enum Environment {\n DEV = 'dev',\n PROD = 'production',\n TEST = 'test',\n}\n\nexport enum TokenType {\n NATIVE = 'native',\n ERC20 = 'erc20',\n SPL = 'spl',\n}\n\nexport enum ServiceType {\n /** Avalanche Cross-chain transfer service. Export/import between C/P/X Avalanche chains. */\n AVALANCHE_CCT = 'avalanche-cct',\n /** Bridge between EVM chains within Avalanche (or EVM-compatible flows). */\n AVALANCHE_EVM = 'avalanche-evm',\n /** Bitcoin → Avalanche. */\n LOMBARD_BTC_TO_BTCB = 'lombard-btc-to-btcb',\n /** Avalanche → Bitcoin. */\n LOMBARD_BTCB_TO_BTC = 'lombard-btcb-to-btc',\n MARKR = 'markr',\n /** Same-chain wrap/unwrap of native ETH ↔ WETH and AVAX ↔ WAVAX. */\n WRAP_UNWRAP = 'wrap-unwrap',\n}\n\nexport const BTC_SERVICE_TYPES: readonly [ServiceType.LOMBARD_BTCB_TO_BTC, ServiceType.LOMBARD_BTC_TO_BTCB] = [\n ServiceType.LOMBARD_BTCB_TO_BTC,\n ServiceType.LOMBARD_BTC_TO_BTCB,\n];\n\nexport const EVM_SERVICE_TYPES: readonly [ServiceType.AVALANCHE_EVM, ServiceType.WRAP_UNWRAP] = [\n ServiceType.AVALANCHE_EVM,\n ServiceType.WRAP_UNWRAP,\n];\n\n/** Reasons for user signatures during execution. */\nexport enum TransferSignatureReason {\n AddressOwnership = 'address-ownership',\n /** ERC-20 allowance approval for router/bridge. */\n AllowanceApproval = 'allowance-approval',\n /** Primary signature for cross-chain export transaction. */\n AvalancheCrossChainExport = 'avalanche-cross-chain-export',\n /** Primary signature for cross-chain import transaction. */\n AvalancheCrossChainImport = 'avalanche-cross-chain-import',\n /** The primary token movement call (swap or bridge submit). */\n TokensTransfer = 'tokens-transfer',\n /** Optional wrap/unwrap step for native token handling. */\n WrapToken = 'wrap-token',\n /** Hyperliquid 2-phase withdrawal: step 1, nonce-mapping authorization (Relay protocol). */\n HyperliquidAuthorize = 'hyperliquid-authorize',\n /** Hyperliquid 2-phase withdrawal: step 2, the `sendAsset` transfer. */\n HyperliquidSendAsset = 'hyperliquid-send-asset',\n /** Markr recurring: first-fill swap that schedules the recurring order on-chain. */\n ScheduleRecurringSwap = 'schedule-recurring-swap',\n /** Markr recurring: pause an active schedule (preserves allowance). */\n PauseRecurringSwap = 'pause-recurring-swap',\n /** Markr recurring: resume (unpause) a paused schedule. */\n ResumeRecurringSwap = 'resume-recurring-swap',\n /** Markr recurring: cancel an active or paused schedule. */\n CancelRecurringSwap = 'cancel-recurring-swap',\n}\n\nexport const ERC_ZERO_ADDRESS: EvmAddress = '0x0000000000000000000000000000000000000000';\nexport const NATIVE_SOL_ADDRESS: SolAddress = '11111111111111111111111111111111' as SolAddress;\n\nexport enum AvalancheChainIds {\n FUJI = 'eip155:43113',\n MAINNET = 'eip155:43114',\n}\n\nexport enum EthereumChainIds {\n MAINNET = 'eip155:1',\n SEPOLIA = 'eip155:11155111',\n}\n\nexport enum BitcoinChainIds {\n MAINNET = 'bip122:000000000019d6689c085ae165831e93',\n TESTNET = 'bip122:000000000933ea01ad0ee984209779ba',\n}\n\nexport enum SolanaChainIds {\n MAINNET = 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp',\n DEVNET = 'solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1',\n}\n\n/**\n * Hyperliquid is identified by CAIP-2 `eip155:1337` per Relay's convention.\n * It's an EVM-namespaced chain ID but has no real EVM execution — withdrawals\n * use a two-signature EIP-712 flow against Hyperliquid's `/exchange` API.\n */\nexport enum HyperliquidChainIds {\n MAINNET = 'eip155:1337',\n}\n\nexport enum BaseChainIds {\n MAINNET = 'eip155:8453',\n SEPOLIA = 'eip155:84532',\n}\n\nexport enum PolygonChainIds {\n MAINNET = 'eip155:137',\n AMOY = 'eip155:80002',\n}\n\nexport type AvalancheBlockchainAlias = 'C' | 'P' | 'X';\n\nexport const AvalancheMainnetBlockchainChainIds: Readonly<Record<AvalancheBlockchainAlias, Caip2ChainId>> = {\n C: AvalancheChainIds.MAINNET,\n P: 'avax:Rr9hnPVPxuUvrdCul-vjEsU1zmqKqRDo',\n X: 'avax:imji8papUf2EhV3le337w1vgFauqkJg-',\n};\n\nexport const AvalancheFujiBlockchainChainIds: Readonly<Record<AvalancheBlockchainAlias, Caip2ChainId>> = {\n C: AvalancheChainIds.FUJI,\n P: 'avax:Sj7NVE3jXTbJvwFAiu7OEUo_8g8ctXMG',\n X: 'avax:8AJTpRj3SAqv1e80Mtl9em08LhvKEbkl',\n};\n\nexport const AvalancheMainnetBlockchainIds: Readonly<Record<AvalancheBlockchainAlias, string>> = {\n C: '2q9e4r6Mu3U68nU1fYjgbR6JvwrRx36CohpAX5UQxse55x1Q5',\n P: '11111111111111111111111111111111LpoYY',\n X: '2oYMBNV4eNHyqk2fjjV5nVQLDbtmNJzq5s3qs3Lo6ftnC6FByM',\n};\n\nexport const AvalancheFujiBlockchainIds: Readonly<Record<AvalancheBlockchainAlias, string>> = {\n C: 'yH8D7ThNJkxmtkuv2jgBa4P1Rn3Qpr4pPr7QYNfcdoS6k6HWp',\n P: '11111111111111111111111111111111LpoYY',\n X: '2JVSBoinj9C2J33VntvzYtVJNZdN2NKiwwKjcumHUWEb5DbBrm',\n};\n\nexport const AVALANCHE_CAIP2_TO_BLOCKCHAIN_ID_BY_NETWORK: Readonly<{\n mainnet: Readonly<Record<Caip2ChainId, string>>;\n fuji: Readonly<Record<Caip2ChainId, string>>;\n}> = {\n mainnet: {\n [AvalancheMainnetBlockchainChainIds.C]: AvalancheMainnetBlockchainIds.C,\n [AvalancheMainnetBlockchainChainIds.P]: AvalancheMainnetBlockchainIds.P,\n [AvalancheMainnetBlockchainChainIds.X]: AvalancheMainnetBlockchainIds.X,\n },\n fuji: {\n [AvalancheFujiBlockchainChainIds.C]: AvalancheFujiBlockchainIds.C,\n [AvalancheFujiBlockchainChainIds.P]: AvalancheFujiBlockchainIds.P,\n [AvalancheFujiBlockchainChainIds.X]: AvalancheFujiBlockchainIds.X,\n },\n};\n\nexport const AVALANCHE_FUJI_CHAIN: Chain = {\n chainId: AvalancheChainIds.FUJI,\n chainName: 'Avalanche Fuji (C-Chain)',\n networkToken: {\n type: TokenType.NATIVE,\n name: 'AVAX',\n symbol: 'AVAX',\n decimals: 18,\n },\n rpcUrl: 'https://api.avax-test.network/ext/bc/C/rpc',\n};\n\nexport const AVALANCHE_MAINNET_CHAIN: Chain = {\n chainId: AvalancheChainIds.MAINNET,\n chainName: 'Avalanche Mainnet (C-Chain)',\n rpcUrl: 'https://api.avax.network/ext/bc/C/rpc',\n networkToken: {\n type: TokenType.NATIVE,\n name: 'AVAX',\n symbol: 'AVAX',\n decimals: 18,\n },\n};\n\nexport const AVALANCHE_MAINNET_P_CHAIN: Chain = {\n chainId: AvalancheMainnetBlockchainChainIds.P,\n chainName: 'Avalanche Mainnet (P-Chain)',\n rpcUrl: 'https://api.avax.network/ext/bc/P',\n networkToken: {\n type: TokenType.NATIVE,\n name: 'AVAX',\n symbol: 'AVAX',\n decimals: 9,\n },\n};\n\nexport const AVALANCHE_FUJI_P_CHAIN: Chain = {\n chainId: AvalancheFujiBlockchainChainIds.P,\n chainName: 'Avalanche Fuji (P-Chain)',\n rpcUrl: 'https://api.avax-test.network/ext/bc/P',\n networkToken: {\n type: TokenType.NATIVE,\n name: 'AVAX',\n symbol: 'AVAX',\n decimals: 9,\n },\n};\n\nexport const AVALANCHE_MAINNET_X_CHAIN: Chain = {\n chainId: AvalancheMainnetBlockchainChainIds.X,\n chainName: 'Avalanche Mainnet (X-Chain)',\n rpcUrl: 'https://api.avax.network/ext/bc/X',\n networkToken: {\n type: TokenType.NATIVE,\n name: 'AVAX',\n symbol: 'AVAX',\n decimals: 9,\n },\n};\n\nexport const AVALANCHE_FUJI_X_CHAIN: Chain = {\n chainId: AvalancheFujiBlockchainChainIds.X,\n chainName: 'Avalanche Fuji (X-Chain)',\n rpcUrl: 'https://api.avax-test.network/ext/bc/X',\n networkToken: {\n type: TokenType.NATIVE,\n name: 'AVAX',\n symbol: 'AVAX',\n decimals: 9,\n },\n};\n\nexport const ETHEREUM_SEPOLIA_CHAIN: Chain = {\n chainId: EthereumChainIds.SEPOLIA,\n chainName: 'Ethereum Sepolia',\n rpcUrl: 'https://proxy-api.avax.network/proxy/infura/sepolia',\n networkToken: {\n type: TokenType.NATIVE,\n name: 'ETH',\n symbol: 'ETH',\n decimals: 18,\n },\n};\n\nexport const ETHEREUM_MAINNET_CHAIN: Chain = {\n chainId: EthereumChainIds.MAINNET,\n chainName: 'Ethereum Mainnet',\n rpcUrl: 'https://proxy-api.avax.network/proxy/infura/mainnet',\n networkToken: {\n type: TokenType.NATIVE,\n name: 'ETH',\n symbol: 'ETH',\n decimals: 18,\n },\n};\n\nexport const BITCOIN_TESTNET_CHAIN: Chain = {\n chainId: BitcoinChainIds.TESTNET,\n chainName: 'Bitcoin Testnet',\n rpcUrl: '',\n networkToken: {\n type: TokenType.NATIVE,\n name: 'Bitcoin',\n symbol: 'BTC',\n decimals: 8,\n },\n};\n\nexport const BITCOIN_MAINNET_CHAIN: Chain = {\n chainId: BitcoinChainIds.MAINNET,\n chainName: 'Bitcoin Mainnet',\n rpcUrl: '',\n networkToken: {\n type: TokenType.NATIVE,\n name: 'Bitcoin',\n symbol: 'BTC',\n decimals: 8,\n },\n};\n\nexport const SOLANA_MAINNET_CHAIN: Chain = {\n chainId: SolanaChainIds.MAINNET,\n chainName: 'Solana',\n rpcUrl: 'https://proxy-api.avax.network/proxy/nownodes/sol',\n networkToken: {\n type: TokenType.NATIVE,\n name: 'SOL',\n symbol: 'SOL',\n decimals: 9,\n },\n};\n\nexport const SOLANA_DEVNET_CHAIN: Chain = {\n chainId: SolanaChainIds.DEVNET,\n chainName: 'Solana (Devnet)',\n rpcUrl: 'https://api.devnet.solana.com',\n networkToken: {\n type: TokenType.NATIVE,\n name: 'SOL',\n symbol: 'SOL',\n decimals: 9,\n },\n};\nexport const NATIVE_AVAX: NativeAsset = {\n type: TokenType.NATIVE,\n name: 'Avalanche',\n symbol: 'AVAX',\n decimals: 18,\n logoUri:\n 'https://images.ctfassets.net/gcj8jwzm6086/5VHupNKwnDYJvqMENeV7iJ/fdd6326b7a82c8388e4ee9d4be7062d4/avalanche-avax-logo.svg',\n};\nexport const NATIVE_ETH: NativeAsset = {\n type: TokenType.NATIVE,\n name: 'Ether',\n symbol: 'ETH',\n decimals: 18,\n logoUri:\n 'https://images.ctfassets.net/gcj8jwzm6086/6l56QLVZmvacuBfjHBTThP/791d743dd2c526692562780c2325fedf/eth-circle__1_.svg',\n};\n\nexport enum Blockchain {\n AVALANCHE = 'avalanche',\n BITCOIN = 'bitcoin',\n ETHEREUM = 'ethereum',\n SOLANA = 'solana',\n UNKNOWN = '_unknown',\n}\n\nexport enum EvmChainId {\n AVALANCHE_MAINNET = 43114,\n AVALANCHE_TESTNET = 43113,\n ETHEREUM_HOMESTEAD = 1,\n ETHEREUM_TEST_SEPOLIA = 11155111,\n /**\n * This is not a real chain ID, as Bitcoin does not have a chain ID.\n * It is used internally to represent Bitcoin in a way that avoids\n * conflicts with real EVM chain IDs.\n */\n BITCOIN = 4_503_599_627_370_476 - 1,\n /**\n * This is not a real chain ID, as Bitcoin does not have a chain ID.\n * It is used internally to represent Bitcoin in a way that avoids\n * conflicts with real EVM chain IDs.\n */\n BITCOIN_TESTNET = 4_503_599_627_370_476 - 2,\n}\n\n/**\n * Maps the unified {@link FeeRateTier} to the Bitcoin-specific\n * {@link BitcoinFeeRateTier} (`low | medium | high`).\n */\nexport const FEE_RATE_TIER_TO_BITCOIN: Record<FeeRateTier, BitcoinFeeRateTier> = {\n slow: 'low',\n normal: 'medium',\n fast: 'high',\n};\n"],"mappings":"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"}
package/dist/mod.cjs CHANGED
@@ -1 +1 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require(`./constants.cjs`),t=require(`./errors.cjs`),n=require(`./type-guards.cjs`),r=require(`./transfer-manager.cjs`),i=require(`./utils/caip.cjs`),a=require(`./utils/bridgeable-assets.cjs`),o=require(`./utils/price-impact.cjs`),s=require(`./utils/transfer-utils.cjs`),c=require(`./transfer-service/markr/recurring/types.cjs`),l=require(`./transfer-service/markr/recurring/_frequency.cjs`),u=require(`./transfer-service/_evm-approval.cjs`);exports.AVALANCHE_CAIP2_TO_BLOCKCHAIN_ID_BY_NETWORK=e.AVALANCHE_CAIP2_TO_BLOCKCHAIN_ID_BY_NETWORK,exports.AVALANCHE_FUJI_CHAIN=e.AVALANCHE_FUJI_CHAIN,exports.AVALANCHE_FUJI_P_CHAIN=e.AVALANCHE_FUJI_P_CHAIN,exports.AVALANCHE_FUJI_X_CHAIN=e.AVALANCHE_FUJI_X_CHAIN,exports.AVALANCHE_MAINNET_CHAIN=e.AVALANCHE_MAINNET_CHAIN,exports.AVALANCHE_MAINNET_P_CHAIN=e.AVALANCHE_MAINNET_P_CHAIN,exports.AVALANCHE_MAINNET_X_CHAIN=e.AVALANCHE_MAINNET_X_CHAIN,exports.AbortedError=t.AbortedError,exports.ApprovalRevertedError=u.ApprovalRevertedError,exports.AvalancheChainIds=e.AvalancheChainIds,exports.AvalancheFujiBlockchainChainIds=e.AvalancheFujiBlockchainChainIds,exports.AvalancheFujiBlockchainIds=e.AvalancheFujiBlockchainIds,exports.AvalancheMainnetBlockchainChainIds=e.AvalancheMainnetBlockchainChainIds,exports.AvalancheMainnetBlockchainIds=e.AvalancheMainnetBlockchainIds,exports.BITCOIN_MAINNET_CHAIN=e.BITCOIN_MAINNET_CHAIN,exports.BITCOIN_TESTNET_CHAIN=e.BITCOIN_TESTNET_CHAIN,exports.BTC_SERVICE_TYPES=e.BTC_SERVICE_TYPES,exports.BitcoinChainIds=e.BitcoinChainIds,exports.Blockchain=e.Blockchain,exports.ERC_ZERO_ADDRESS=e.ERC_ZERO_ADDRESS,exports.ETHEREUM_MAINNET_CHAIN=e.ETHEREUM_MAINNET_CHAIN,exports.ETHEREUM_SEPOLIA_CHAIN=e.ETHEREUM_SEPOLIA_CHAIN,exports.EVM_SERVICE_TYPES=e.EVM_SERVICE_TYPES,exports.Environment=e.Environment,exports.ErrorCode=t.ErrorCode,exports.ErrorReason=t.ErrorReason,exports.EstimateNativeFeeError=t.EstimateNativeFeeError,exports.EthereumChainIds=e.EthereumChainIds,exports.EvmChainId=e.EvmChainId,exports.FEE_RATE_TIER_TO_BITCOIN=e.FEE_RATE_TIER_TO_BITCOIN,exports.HttpError=t.HttpError,exports.HyperliquidChainIds=e.HyperliquidChainIds,exports.InsufficientFundsError=t.InsufficientFundsError,exports.InvalidParamsError=t.InvalidParamsError,exports.NATIVE_AVAX=e.NATIVE_AVAX,exports.NATIVE_ETH=e.NATIVE_ETH,exports.NATIVE_SOL_ADDRESS=e.NATIVE_SOL_ADDRESS,exports.RECURRING_FREQUENCY_UNITS=c.RECURRING_FREQUENCY_UNITS,exports.RECURRING_FREQUENCY_VALUE_MAX=l.RECURRING_FREQUENCY_VALUE_MAX,exports.RECURRING_UNLIMITED_ORDERS_SENTINEL=c.RECURRING_UNLIMITED_ORDERS_SENTINEL,exports.RecurringEligibilityReason=c.RecurringEligibilityReason,exports.RecurringOrderStatus=c.RecurringOrderStatus,exports.ResponseValidationError=t.ResponseValidationError,exports.SOLANA_DEVNET_CHAIN=e.SOLANA_DEVNET_CHAIN,exports.SOLANA_MAINNET_CHAIN=e.SOLANA_MAINNET_CHAIN,exports.SdkError=t.SdkError,exports.ServiceInitializationError=t.ServiceInitializationError,exports.ServiceType=e.ServiceType,exports.ServiceUnavailableError=t.ServiceUnavailableError,exports.SolanaChainIds=e.SolanaChainIds,exports.TimeoutError=t.TimeoutError,exports.TokenType=e.TokenType,exports.TransferSignatureReason=e.TransferSignatureReason,exports.caip2ToEip155ChainId=i.caip2ToEip155ChainId,exports.caip2ToEip155HexChainId=i.caip2ToEip155HexChainId,exports.calculatePriceImpactFromQuote=o.calculatePriceImpactFromQuote,exports.createTransferManager=r.createTransferManager,exports.dedupeBridgeableAssets=a.dedupeBridgeableAssets,exports.deriveIntervalSeconds=l.deriveIntervalSeconds,exports.eip155ChainIdToCaip2=i.eip155ChainIdToCaip2,exports.isAbortedError=t.isAbortedError,exports.isCaip2ChainId=i.isCaip2ChainId,exports.isEnvironment=n.isEnvironment,exports.isErc20Asset=n.isErc20Asset,exports.isEstimateNativeFeeError=t.isEstimateNativeFeeError,exports.isEvmBridgeInitializer=n.isEvmBridgeInitializer,exports.isHttpError=t.isHttpError,exports.isInsufficientFundsError=t.isInsufficientFundsError,exports.isInvalidParamsError=t.isInvalidParamsError,exports.isLombardServiceInitializer=n.isLombardServiceInitializer,exports.isMarkrServiceInitializer=n.isMarkrServiceInitializer,exports.isNativeAsset=n.isNativeAsset,exports.isResponseValidationError=t.isResponseValidationError,exports.isSdkError=t.isSdkError,exports.isServiceInitializationError=t.isServiceInitializationError,exports.isServiceInitializer=n.isServiceInitializer,exports.isServiceUnavailableError=t.isServiceUnavailableError,exports.isSplAsset=n.isSplAsset,exports.isTimeoutError=t.isTimeoutError,exports.parseTransfer=s.parseTransfer,exports.splitCaip2ChainId=i.splitCaip2ChainId,exports.stringifyTransfer=s.stringifyTransfer,exports.validateFrequency=l.validateFrequency;
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require(`./constants.cjs`),t=require(`./errors.cjs`),n=require(`./type-guards.cjs`),r=require(`./transfer-manager.cjs`),i=require(`./utils/caip.cjs`),a=require(`./utils/bridgeable-assets.cjs`),o=require(`./utils/destination-chains.cjs`),s=require(`./utils/price-impact.cjs`),c=require(`./utils/transfer-utils.cjs`),l=require(`./transfer-service/markr/recurring/types.cjs`),u=require(`./transfer-service/markr/recurring/_frequency.cjs`),d=require(`./transfer-service/_evm-approval.cjs`);exports.AVALANCHE_CAIP2_TO_BLOCKCHAIN_ID_BY_NETWORK=e.AVALANCHE_CAIP2_TO_BLOCKCHAIN_ID_BY_NETWORK,exports.AVALANCHE_FUJI_CHAIN=e.AVALANCHE_FUJI_CHAIN,exports.AVALANCHE_FUJI_P_CHAIN=e.AVALANCHE_FUJI_P_CHAIN,exports.AVALANCHE_FUJI_X_CHAIN=e.AVALANCHE_FUJI_X_CHAIN,exports.AVALANCHE_MAINNET_CHAIN=e.AVALANCHE_MAINNET_CHAIN,exports.AVALANCHE_MAINNET_P_CHAIN=e.AVALANCHE_MAINNET_P_CHAIN,exports.AVALANCHE_MAINNET_X_CHAIN=e.AVALANCHE_MAINNET_X_CHAIN,exports.AbortedError=t.AbortedError,exports.ApprovalRevertedError=d.ApprovalRevertedError,exports.AvalancheChainIds=e.AvalancheChainIds,exports.AvalancheFujiBlockchainChainIds=e.AvalancheFujiBlockchainChainIds,exports.AvalancheFujiBlockchainIds=e.AvalancheFujiBlockchainIds,exports.AvalancheMainnetBlockchainChainIds=e.AvalancheMainnetBlockchainChainIds,exports.AvalancheMainnetBlockchainIds=e.AvalancheMainnetBlockchainIds,exports.BITCOIN_MAINNET_CHAIN=e.BITCOIN_MAINNET_CHAIN,exports.BITCOIN_TESTNET_CHAIN=e.BITCOIN_TESTNET_CHAIN,exports.BTC_SERVICE_TYPES=e.BTC_SERVICE_TYPES,exports.BaseChainIds=e.BaseChainIds,exports.BitcoinChainIds=e.BitcoinChainIds,exports.Blockchain=e.Blockchain,exports.ERC_ZERO_ADDRESS=e.ERC_ZERO_ADDRESS,exports.ETHEREUM_MAINNET_CHAIN=e.ETHEREUM_MAINNET_CHAIN,exports.ETHEREUM_SEPOLIA_CHAIN=e.ETHEREUM_SEPOLIA_CHAIN,exports.EVM_SERVICE_TYPES=e.EVM_SERVICE_TYPES,exports.Environment=e.Environment,exports.ErrorCode=t.ErrorCode,exports.ErrorReason=t.ErrorReason,exports.EstimateNativeFeeError=t.EstimateNativeFeeError,exports.EthereumChainIds=e.EthereumChainIds,exports.EvmChainId=e.EvmChainId,exports.FEE_RATE_TIER_TO_BITCOIN=e.FEE_RATE_TIER_TO_BITCOIN,exports.HttpError=t.HttpError,exports.HyperliquidChainIds=e.HyperliquidChainIds,exports.InsufficientFundsError=t.InsufficientFundsError,exports.InvalidParamsError=t.InvalidParamsError,exports.NATIVE_AVAX=e.NATIVE_AVAX,exports.NATIVE_ETH=e.NATIVE_ETH,exports.NATIVE_SOL_ADDRESS=e.NATIVE_SOL_ADDRESS,exports.PolygonChainIds=e.PolygonChainIds,exports.RECURRING_FREQUENCY_UNITS=l.RECURRING_FREQUENCY_UNITS,exports.RECURRING_FREQUENCY_VALUE_MAX=u.RECURRING_FREQUENCY_VALUE_MAX,exports.RECURRING_UNLIMITED_ORDERS_SENTINEL=l.RECURRING_UNLIMITED_ORDERS_SENTINEL,exports.RecurringEligibilityReason=l.RecurringEligibilityReason,exports.RecurringOrderStatus=l.RecurringOrderStatus,exports.ResponseValidationError=t.ResponseValidationError,exports.SOLANA_DEVNET_CHAIN=e.SOLANA_DEVNET_CHAIN,exports.SOLANA_MAINNET_CHAIN=e.SOLANA_MAINNET_CHAIN,exports.SdkError=t.SdkError,exports.ServiceInitializationError=t.ServiceInitializationError,exports.ServiceType=e.ServiceType,exports.ServiceUnavailableError=t.ServiceUnavailableError,exports.SolanaChainIds=e.SolanaChainIds,exports.TimeoutError=t.TimeoutError,exports.TokenType=e.TokenType,exports.TransferSignatureReason=e.TransferSignatureReason,exports.caip2ToEip155ChainId=i.caip2ToEip155ChainId,exports.caip2ToEip155HexChainId=i.caip2ToEip155HexChainId,exports.calculatePriceImpactFromQuote=s.calculatePriceImpactFromQuote,exports.compareDestinationChains=o.compareDestinationChains,exports.createTransferManager=r.createTransferManager,exports.dedupeBridgeableAssets=a.dedupeBridgeableAssets,exports.deriveIntervalSeconds=u.deriveIntervalSeconds,exports.eip155ChainIdToCaip2=i.eip155ChainIdToCaip2,exports.getDestinationChainPriority=o.getDestinationChainPriority,exports.isAbortedError=t.isAbortedError,exports.isCaip2ChainId=i.isCaip2ChainId,exports.isEnvironment=n.isEnvironment,exports.isErc20Asset=n.isErc20Asset,exports.isEstimateNativeFeeError=t.isEstimateNativeFeeError,exports.isEvmBridgeInitializer=n.isEvmBridgeInitializer,exports.isHttpError=t.isHttpError,exports.isInsufficientFundsError=t.isInsufficientFundsError,exports.isInvalidParamsError=t.isInvalidParamsError,exports.isLombardServiceInitializer=n.isLombardServiceInitializer,exports.isMarkrServiceInitializer=n.isMarkrServiceInitializer,exports.isNativeAsset=n.isNativeAsset,exports.isResponseValidationError=t.isResponseValidationError,exports.isSdkError=t.isSdkError,exports.isServiceInitializationError=t.isServiceInitializationError,exports.isServiceInitializer=n.isServiceInitializer,exports.isServiceUnavailableError=t.isServiceUnavailableError,exports.isSplAsset=n.isSplAsset,exports.isTimeoutError=t.isTimeoutError,exports.parseTransfer=c.parseTransfer,exports.sortDestinationChains=o.sortDestinationChains,exports.splitCaip2ChainId=i.splitCaip2ChainId,exports.stringifyTransfer=c.stringifyTransfer,exports.validateFrequency=u.validateFrequency;
package/dist/mod.d.cts CHANGED
@@ -2,7 +2,7 @@ import { Caip10AccountId, Caip2ChainId } from "./types/caip.cjs";
2
2
  import { BitcoinFeeRateTier, BitcoinFunctions, BitcoinInputUTXO, BitcoinInputUTXOWithOptionalScript, BitcoinOutputUTXO, BitcoinTx } from "./types/bitcoin.cjs";
3
3
  import { Chain } from "./types/chain.cjs";
4
4
  import { FeeRateTier } from "./types/fee.cjs";
5
- import { AVALANCHE_CAIP2_TO_BLOCKCHAIN_ID_BY_NETWORK, AVALANCHE_FUJI_CHAIN, AVALANCHE_FUJI_P_CHAIN, AVALANCHE_FUJI_X_CHAIN, AVALANCHE_MAINNET_CHAIN, AVALANCHE_MAINNET_P_CHAIN, AVALANCHE_MAINNET_X_CHAIN, AvalancheBlockchainAlias, AvalancheChainIds, AvalancheFujiBlockchainChainIds, AvalancheFujiBlockchainIds, AvalancheMainnetBlockchainChainIds, AvalancheMainnetBlockchainIds, BITCOIN_MAINNET_CHAIN, BITCOIN_TESTNET_CHAIN, BTC_SERVICE_TYPES, BitcoinChainIds, Blockchain, ERC_ZERO_ADDRESS, ETHEREUM_MAINNET_CHAIN, ETHEREUM_SEPOLIA_CHAIN, EVM_SERVICE_TYPES, Environment, EthereumChainIds, EvmChainId, FEE_RATE_TIER_TO_BITCOIN, HyperliquidChainIds, NATIVE_AVAX, NATIVE_ETH, NATIVE_SOL_ADDRESS, SOLANA_DEVNET_CHAIN, SOLANA_MAINNET_CHAIN, ServiceType, SolanaChainIds, TokenType, TransferSignatureReason } from "./constants.cjs";
5
+ import { AVALANCHE_CAIP2_TO_BLOCKCHAIN_ID_BY_NETWORK, AVALANCHE_FUJI_CHAIN, AVALANCHE_FUJI_P_CHAIN, AVALANCHE_FUJI_X_CHAIN, AVALANCHE_MAINNET_CHAIN, AVALANCHE_MAINNET_P_CHAIN, AVALANCHE_MAINNET_X_CHAIN, AvalancheBlockchainAlias, AvalancheChainIds, AvalancheFujiBlockchainChainIds, AvalancheFujiBlockchainIds, AvalancheMainnetBlockchainChainIds, AvalancheMainnetBlockchainIds, BITCOIN_MAINNET_CHAIN, BITCOIN_TESTNET_CHAIN, BTC_SERVICE_TYPES, BaseChainIds, BitcoinChainIds, Blockchain, ERC_ZERO_ADDRESS, ETHEREUM_MAINNET_CHAIN, ETHEREUM_SEPOLIA_CHAIN, EVM_SERVICE_TYPES, Environment, EthereumChainIds, EvmChainId, FEE_RATE_TIER_TO_BITCOIN, HyperliquidChainIds, NATIVE_AVAX, NATIVE_ETH, NATIVE_SOL_ADDRESS, PolygonChainIds, SOLANA_DEVNET_CHAIN, SOLANA_MAINNET_CHAIN, ServiceType, SolanaChainIds, TokenType, TransferSignatureReason } from "./constants.cjs";
6
6
  import { Asset, AssetWithExtras, BridgeableAsset, BridgeableUiAsset, ChainAssetMap, DestinationInfo, Erc20Asset, NativeAsset, SplAsset, TransferableAsset } from "./types/asset.cjs";
7
7
  import { Quote, QuoteFee, QuoteFeeFundingModel, QuoteFeeToken, QuoteFeeType, QuoteFees, QuoterDonePayload, QuoterDonePayloadNoEligibleServices, QuoterDonePayloadNoQuotes, QuoterDonePayloadUnsubscribed, QuoterDoneReason, QuoterEventArgs, QuoterEventHandler, QuoterInterface, QuoterProps, QuotesTuple, ServiceQuoteEventArgs, ServiceQuoteEventHandler } from "./types/quote.cjs";
8
8
  import { ArrayElement, Brand, DeepMutable, Fetch, Mutable } from "./types/utility-types.cjs";
@@ -18,9 +18,10 @@ import { isEnvironment, isErc20Asset, isEvmBridgeInitializer, isLombardServiceIn
18
18
  import { createTransferManager } from "./transfer-manager.cjs";
19
19
  import { caip2ToEip155ChainId, caip2ToEip155HexChainId, eip155ChainIdToCaip2, isCaip2ChainId, splitCaip2ChainId } from "./utils/caip.cjs";
20
20
  import { dedupeBridgeableAssets } from "./utils/bridgeable-assets.cjs";
21
+ import { DestinationChainSortInput, compareDestinationChains, getDestinationChainPriority, sortDestinationChains } from "./utils/destination-chains.cjs";
21
22
  import { calculatePriceImpactFromQuote } from "./utils/price-impact.cjs";
22
23
  import { parseTransfer, stringifyTransfer } from "./utils/transfer-utils.cjs";
23
24
  import { MarkrService } from "./transfer-service/markr/markr-service.cjs";
24
25
  import { FrequencyValidationResult, RECURRING_FREQUENCY_VALUE_MAX, deriveIntervalSeconds, validateFrequency } from "./transfer-service/markr/recurring/_frequency.cjs";
25
26
  import { ApprovalRevertedError } from "./transfer-service/_evm-approval.cjs";
26
- export { AVALANCHE_CAIP2_TO_BLOCKCHAIN_ID_BY_NETWORK, AVALANCHE_FUJI_CHAIN, AVALANCHE_FUJI_P_CHAIN, AVALANCHE_FUJI_X_CHAIN, AVALANCHE_MAINNET_CHAIN, AVALANCHE_MAINNET_P_CHAIN, AVALANCHE_MAINNET_X_CHAIN, AbortedError, ApprovalRevertedError, ArrayElement, Asset, AssetBridgeMap, AssetSearchQuery, AssetWithExtras, AvalancheBlockchainAlias, AvalancheCctInitializer, AvalancheChainIds, AvalancheFujiBlockchainChainIds, AvalancheFujiBlockchainIds, AvalancheMainnetBlockchainChainIds, AvalancheMainnetBlockchainIds, AvalancheSendTxFunction, AvalancheSendTxParams, BITCOIN_MAINNET_CHAIN, BITCOIN_TESTNET_CHAIN, BTC_SERVICE_TYPES, BitcoinChainIds, BitcoinFeeRateTier, BitcoinFunctions, BitcoinInputUTXO, BitcoinInputUTXOWithOptionalScript, BitcoinOutputUTXO, BitcoinTx, Blockchain, Brand, BridgeableAsset, BridgeableUiAsset, BtcDispatch, BtcSign, BtcSigner, BtcTransactionRequest, Caip10AccountId, Caip2ChainId, Chain, ChainAssetMap, type CheckRecurringEligibilityParams, CompletedTransfer, CreateTransferManagerOptions, DeepMutable, DestinationInfo, ERC_ZERO_ADDRESS, ETHEREUM_MAINNET_CHAIN, ETHEREUM_SEPOLIA_CHAIN, EVM_SERVICE_TYPES, Environment, Erc20Asset, ErrorCode, ErrorReason, EstimateNativeFeeError, type EstimateNativeFeeErrorDetails, EstimateNativeFeeOptions, EthereumChainIds, EvmChainId, EvmDispatch, EvmServiceInitializer, EvmSign, EvmSignBatch, EvmSignMessage, EvmSignTypedData, EvmSigner, EvmSignerWithMessage, EvmTransactionRequest, EvmTypedData, FEE_RATE_TIER_TO_BITCOIN, FailedTransfer, FeeRateTier, Fetch, type FrequencyValidationResult, GasSettings, type GetAtomicUtxosCallback, GetBridgeableAssetsProps, GetBridgeableAssetsResult, type GetCoreEthAddressCallback, GetMinimumTransferAmountProps, GetSupportedChainsResult, type GetUtxosCallback, type GetWalletAddressesForChainAliasCallback, type GetWalletChangeAddressForChainAliasCallback, Hex, HttpError, HyperliquidChainIds, InsufficientFundsError, InvalidParamsError, type ListRecurringOrdersParams, type ListRecurringOrdersResponse, LombardServiceInitializer, type MarkrService, MarkrServiceInitializer, Mutable, MutableGetSupportedChainsResult, NATIVE_AVAX, NATIVE_ETH, NATIVE_SOL_ADDRESS, NativeAsset, NativeFeeEstimate, Quote, QuoteFee, QuoteFeeFundingModel, QuoteFeeToken, QuoteFeeType, QuoteFees, QuoterDonePayload, QuoterDonePayloadNoEligibleServices, QuoterDonePayloadNoQuotes, QuoterDonePayloadUnsubscribed, QuoterDoneReason, QuoterEventArgs, QuoterEventHandler, QuoterInterface, QuoterProps, QuotesTuple, RECURRING_FREQUENCY_UNITS, RECURRING_FREQUENCY_VALUE_MAX, RECURRING_UNLIMITED_ORDERS_SENTINEL, type RecurringChainInfoEntry, type RecurringChainInfoMap, type RecurringEligibility, RecurringEligibilityReason, type RecurringExecuteFirstFillParams, type RecurringExecuteOrderActionParams, type RecurringExecuteResult, type RecurringFrequency, type RecurringFrequencyUnit, type RecurringNamespace, type RecurringNamespaceCheckEligibilityParams, type RecurringNamespaceQuoteParams, type RecurringOrder, type RecurringOrderFailure, RecurringOrderStatus, type RecurringQuoteFee, type RecurringQuoteFeeType, type RecurringQuoteParams, type RecurringQuoteResponse, type RecurringSwapParams, RefundedTransfer, ResponseValidationError, SOLANA_DEVNET_CHAIN, SOLANA_MAINNET_CHAIN, SdkError, ServiceInitializationError, ServiceInitializer, ServiceQuoteEventArgs, ServiceQuoteEventHandler, ServiceQuoteOptions, ServiceStatus, ServiceStatusBaseRecord, ServiceStatusErrorRecord, ServiceStatusInitializedRecord, ServiceStatusRecord, ServiceStatusUnsupportedEnvironmentRecord, ServiceType, ServiceUnavailableError, SolanaChainIds, SolanaSendOptions, SolanaSign, SolanaSigner, SolanaTransactionParams, SourceCompletedTransfer, SourcePendingTransfer, SplAsset, TargetPendingTransfer, TimeoutError, TokenType, TrackTransferProps, Transfer, TransferAssetProps, TransferBase, TransferManager, TransferManagerStatus, TransferManagerStatusServicesRecord, TransferService, TransferSignatureReason, TransferSourceProgress, TransferStatus, TransferStepDetails, TransferTargetProgress, TransferableAsset, caip2ToEip155ChainId, caip2ToEip155HexChainId, calculatePriceImpactFromQuote, createTransferManager, dedupeBridgeableAssets, deriveIntervalSeconds, eip155ChainIdToCaip2, isAbortedError, isCaip2ChainId, isEnvironment, isErc20Asset, isEstimateNativeFeeError, isEvmBridgeInitializer, isHttpError, isInsufficientFundsError, isInvalidParamsError, isLombardServiceInitializer, isMarkrServiceInitializer, isNativeAsset, isResponseValidationError, isSdkError, isServiceInitializationError, isServiceInitializer, isServiceUnavailableError, isSplAsset, isTimeoutError, parseTransfer, splitCaip2ChainId, stringifyTransfer, validateFrequency };
27
+ export { AVALANCHE_CAIP2_TO_BLOCKCHAIN_ID_BY_NETWORK, AVALANCHE_FUJI_CHAIN, AVALANCHE_FUJI_P_CHAIN, AVALANCHE_FUJI_X_CHAIN, AVALANCHE_MAINNET_CHAIN, AVALANCHE_MAINNET_P_CHAIN, AVALANCHE_MAINNET_X_CHAIN, AbortedError, ApprovalRevertedError, ArrayElement, Asset, AssetBridgeMap, AssetSearchQuery, AssetWithExtras, AvalancheBlockchainAlias, AvalancheCctInitializer, AvalancheChainIds, AvalancheFujiBlockchainChainIds, AvalancheFujiBlockchainIds, AvalancheMainnetBlockchainChainIds, AvalancheMainnetBlockchainIds, AvalancheSendTxFunction, AvalancheSendTxParams, BITCOIN_MAINNET_CHAIN, BITCOIN_TESTNET_CHAIN, BTC_SERVICE_TYPES, BaseChainIds, BitcoinChainIds, BitcoinFeeRateTier, BitcoinFunctions, BitcoinInputUTXO, BitcoinInputUTXOWithOptionalScript, BitcoinOutputUTXO, BitcoinTx, Blockchain, Brand, BridgeableAsset, BridgeableUiAsset, BtcDispatch, BtcSign, BtcSigner, BtcTransactionRequest, Caip10AccountId, Caip2ChainId, Chain, ChainAssetMap, type CheckRecurringEligibilityParams, CompletedTransfer, CreateTransferManagerOptions, DeepMutable, type DestinationChainSortInput, DestinationInfo, ERC_ZERO_ADDRESS, ETHEREUM_MAINNET_CHAIN, ETHEREUM_SEPOLIA_CHAIN, EVM_SERVICE_TYPES, Environment, Erc20Asset, ErrorCode, ErrorReason, EstimateNativeFeeError, type EstimateNativeFeeErrorDetails, EstimateNativeFeeOptions, EthereumChainIds, EvmChainId, EvmDispatch, EvmServiceInitializer, EvmSign, EvmSignBatch, EvmSignMessage, EvmSignTypedData, EvmSigner, EvmSignerWithMessage, EvmTransactionRequest, EvmTypedData, FEE_RATE_TIER_TO_BITCOIN, FailedTransfer, FeeRateTier, Fetch, type FrequencyValidationResult, GasSettings, type GetAtomicUtxosCallback, GetBridgeableAssetsProps, GetBridgeableAssetsResult, type GetCoreEthAddressCallback, GetMinimumTransferAmountProps, GetSupportedChainsResult, type GetUtxosCallback, type GetWalletAddressesForChainAliasCallback, type GetWalletChangeAddressForChainAliasCallback, Hex, HttpError, HyperliquidChainIds, InsufficientFundsError, InvalidParamsError, type ListRecurringOrdersParams, type ListRecurringOrdersResponse, LombardServiceInitializer, type MarkrService, MarkrServiceInitializer, Mutable, MutableGetSupportedChainsResult, NATIVE_AVAX, NATIVE_ETH, NATIVE_SOL_ADDRESS, NativeAsset, NativeFeeEstimate, PolygonChainIds, Quote, QuoteFee, QuoteFeeFundingModel, QuoteFeeToken, QuoteFeeType, QuoteFees, QuoterDonePayload, QuoterDonePayloadNoEligibleServices, QuoterDonePayloadNoQuotes, QuoterDonePayloadUnsubscribed, QuoterDoneReason, QuoterEventArgs, QuoterEventHandler, QuoterInterface, QuoterProps, QuotesTuple, RECURRING_FREQUENCY_UNITS, RECURRING_FREQUENCY_VALUE_MAX, RECURRING_UNLIMITED_ORDERS_SENTINEL, type RecurringChainInfoEntry, type RecurringChainInfoMap, type RecurringEligibility, RecurringEligibilityReason, type RecurringExecuteFirstFillParams, type RecurringExecuteOrderActionParams, type RecurringExecuteResult, type RecurringFrequency, type RecurringFrequencyUnit, type RecurringNamespace, type RecurringNamespaceCheckEligibilityParams, type RecurringNamespaceQuoteParams, type RecurringOrder, type RecurringOrderFailure, RecurringOrderStatus, type RecurringQuoteFee, type RecurringQuoteFeeType, type RecurringQuoteParams, type RecurringQuoteResponse, type RecurringSwapParams, RefundedTransfer, ResponseValidationError, SOLANA_DEVNET_CHAIN, SOLANA_MAINNET_CHAIN, SdkError, ServiceInitializationError, ServiceInitializer, ServiceQuoteEventArgs, ServiceQuoteEventHandler, ServiceQuoteOptions, ServiceStatus, ServiceStatusBaseRecord, ServiceStatusErrorRecord, ServiceStatusInitializedRecord, ServiceStatusRecord, ServiceStatusUnsupportedEnvironmentRecord, ServiceType, ServiceUnavailableError, SolanaChainIds, SolanaSendOptions, SolanaSign, SolanaSigner, SolanaTransactionParams, SourceCompletedTransfer, SourcePendingTransfer, SplAsset, TargetPendingTransfer, TimeoutError, TokenType, TrackTransferProps, Transfer, TransferAssetProps, TransferBase, TransferManager, TransferManagerStatus, TransferManagerStatusServicesRecord, TransferService, TransferSignatureReason, TransferSourceProgress, TransferStatus, TransferStepDetails, TransferTargetProgress, TransferableAsset, caip2ToEip155ChainId, caip2ToEip155HexChainId, calculatePriceImpactFromQuote, compareDestinationChains, createTransferManager, dedupeBridgeableAssets, deriveIntervalSeconds, eip155ChainIdToCaip2, getDestinationChainPriority, isAbortedError, isCaip2ChainId, isEnvironment, isErc20Asset, isEstimateNativeFeeError, isEvmBridgeInitializer, isHttpError, isInsufficientFundsError, isInvalidParamsError, isLombardServiceInitializer, isMarkrServiceInitializer, isNativeAsset, isResponseValidationError, isSdkError, isServiceInitializationError, isServiceInitializer, isServiceUnavailableError, isSplAsset, isTimeoutError, parseTransfer, sortDestinationChains, splitCaip2ChainId, stringifyTransfer, validateFrequency };
package/dist/mod.d.ts CHANGED
@@ -2,7 +2,7 @@ import { Caip10AccountId, Caip2ChainId } from "./types/caip.js";
2
2
  import { BitcoinFeeRateTier, BitcoinFunctions, BitcoinInputUTXO, BitcoinInputUTXOWithOptionalScript, BitcoinOutputUTXO, BitcoinTx } from "./types/bitcoin.js";
3
3
  import { Chain } from "./types/chain.js";
4
4
  import { FeeRateTier } from "./types/fee.js";
5
- import { AVALANCHE_CAIP2_TO_BLOCKCHAIN_ID_BY_NETWORK, AVALANCHE_FUJI_CHAIN, AVALANCHE_FUJI_P_CHAIN, AVALANCHE_FUJI_X_CHAIN, AVALANCHE_MAINNET_CHAIN, AVALANCHE_MAINNET_P_CHAIN, AVALANCHE_MAINNET_X_CHAIN, AvalancheBlockchainAlias, AvalancheChainIds, AvalancheFujiBlockchainChainIds, AvalancheFujiBlockchainIds, AvalancheMainnetBlockchainChainIds, AvalancheMainnetBlockchainIds, BITCOIN_MAINNET_CHAIN, BITCOIN_TESTNET_CHAIN, BTC_SERVICE_TYPES, BitcoinChainIds, Blockchain, ERC_ZERO_ADDRESS, ETHEREUM_MAINNET_CHAIN, ETHEREUM_SEPOLIA_CHAIN, EVM_SERVICE_TYPES, Environment, EthereumChainIds, EvmChainId, FEE_RATE_TIER_TO_BITCOIN, HyperliquidChainIds, NATIVE_AVAX, NATIVE_ETH, NATIVE_SOL_ADDRESS, SOLANA_DEVNET_CHAIN, SOLANA_MAINNET_CHAIN, ServiceType, SolanaChainIds, TokenType, TransferSignatureReason } from "./constants.js";
5
+ import { AVALANCHE_CAIP2_TO_BLOCKCHAIN_ID_BY_NETWORK, AVALANCHE_FUJI_CHAIN, AVALANCHE_FUJI_P_CHAIN, AVALANCHE_FUJI_X_CHAIN, AVALANCHE_MAINNET_CHAIN, AVALANCHE_MAINNET_P_CHAIN, AVALANCHE_MAINNET_X_CHAIN, AvalancheBlockchainAlias, AvalancheChainIds, AvalancheFujiBlockchainChainIds, AvalancheFujiBlockchainIds, AvalancheMainnetBlockchainChainIds, AvalancheMainnetBlockchainIds, BITCOIN_MAINNET_CHAIN, BITCOIN_TESTNET_CHAIN, BTC_SERVICE_TYPES, BaseChainIds, BitcoinChainIds, Blockchain, ERC_ZERO_ADDRESS, ETHEREUM_MAINNET_CHAIN, ETHEREUM_SEPOLIA_CHAIN, EVM_SERVICE_TYPES, Environment, EthereumChainIds, EvmChainId, FEE_RATE_TIER_TO_BITCOIN, HyperliquidChainIds, NATIVE_AVAX, NATIVE_ETH, NATIVE_SOL_ADDRESS, PolygonChainIds, SOLANA_DEVNET_CHAIN, SOLANA_MAINNET_CHAIN, ServiceType, SolanaChainIds, TokenType, TransferSignatureReason } from "./constants.js";
6
6
  import { Asset, AssetWithExtras, BridgeableAsset, BridgeableUiAsset, ChainAssetMap, DestinationInfo, Erc20Asset, NativeAsset, SplAsset, TransferableAsset } from "./types/asset.js";
7
7
  import { Quote, QuoteFee, QuoteFeeFundingModel, QuoteFeeToken, QuoteFeeType, QuoteFees, QuoterDonePayload, QuoterDonePayloadNoEligibleServices, QuoterDonePayloadNoQuotes, QuoterDonePayloadUnsubscribed, QuoterDoneReason, QuoterEventArgs, QuoterEventHandler, QuoterInterface, QuoterProps, QuotesTuple, ServiceQuoteEventArgs, ServiceQuoteEventHandler } from "./types/quote.js";
8
8
  import { ArrayElement, Brand, DeepMutable, Fetch, Mutable } from "./types/utility-types.js";
@@ -18,9 +18,10 @@ import { isEnvironment, isErc20Asset, isEvmBridgeInitializer, isLombardServiceIn
18
18
  import { createTransferManager } from "./transfer-manager.js";
19
19
  import { caip2ToEip155ChainId, caip2ToEip155HexChainId, eip155ChainIdToCaip2, isCaip2ChainId, splitCaip2ChainId } from "./utils/caip.js";
20
20
  import { dedupeBridgeableAssets } from "./utils/bridgeable-assets.js";
21
+ import { DestinationChainSortInput, compareDestinationChains, getDestinationChainPriority, sortDestinationChains } from "./utils/destination-chains.js";
21
22
  import { calculatePriceImpactFromQuote } from "./utils/price-impact.js";
22
23
  import { parseTransfer, stringifyTransfer } from "./utils/transfer-utils.js";
23
24
  import { MarkrService } from "./transfer-service/markr/markr-service.js";
24
25
  import { FrequencyValidationResult, RECURRING_FREQUENCY_VALUE_MAX, deriveIntervalSeconds, validateFrequency } from "./transfer-service/markr/recurring/_frequency.js";
25
26
  import { ApprovalRevertedError } from "./transfer-service/_evm-approval.js";
26
- export { AVALANCHE_CAIP2_TO_BLOCKCHAIN_ID_BY_NETWORK, AVALANCHE_FUJI_CHAIN, AVALANCHE_FUJI_P_CHAIN, AVALANCHE_FUJI_X_CHAIN, AVALANCHE_MAINNET_CHAIN, AVALANCHE_MAINNET_P_CHAIN, AVALANCHE_MAINNET_X_CHAIN, AbortedError, ApprovalRevertedError, ArrayElement, Asset, AssetBridgeMap, AssetSearchQuery, AssetWithExtras, AvalancheBlockchainAlias, AvalancheCctInitializer, AvalancheChainIds, AvalancheFujiBlockchainChainIds, AvalancheFujiBlockchainIds, AvalancheMainnetBlockchainChainIds, AvalancheMainnetBlockchainIds, AvalancheSendTxFunction, AvalancheSendTxParams, BITCOIN_MAINNET_CHAIN, BITCOIN_TESTNET_CHAIN, BTC_SERVICE_TYPES, BitcoinChainIds, BitcoinFeeRateTier, BitcoinFunctions, BitcoinInputUTXO, BitcoinInputUTXOWithOptionalScript, BitcoinOutputUTXO, BitcoinTx, Blockchain, Brand, BridgeableAsset, BridgeableUiAsset, BtcDispatch, BtcSign, BtcSigner, BtcTransactionRequest, Caip10AccountId, Caip2ChainId, Chain, ChainAssetMap, type CheckRecurringEligibilityParams, CompletedTransfer, CreateTransferManagerOptions, DeepMutable, DestinationInfo, ERC_ZERO_ADDRESS, ETHEREUM_MAINNET_CHAIN, ETHEREUM_SEPOLIA_CHAIN, EVM_SERVICE_TYPES, Environment, Erc20Asset, ErrorCode, ErrorReason, EstimateNativeFeeError, type EstimateNativeFeeErrorDetails, EstimateNativeFeeOptions, EthereumChainIds, EvmChainId, EvmDispatch, EvmServiceInitializer, EvmSign, EvmSignBatch, EvmSignMessage, EvmSignTypedData, EvmSigner, EvmSignerWithMessage, EvmTransactionRequest, EvmTypedData, FEE_RATE_TIER_TO_BITCOIN, FailedTransfer, FeeRateTier, Fetch, type FrequencyValidationResult, GasSettings, type GetAtomicUtxosCallback, GetBridgeableAssetsProps, GetBridgeableAssetsResult, type GetCoreEthAddressCallback, GetMinimumTransferAmountProps, GetSupportedChainsResult, type GetUtxosCallback, type GetWalletAddressesForChainAliasCallback, type GetWalletChangeAddressForChainAliasCallback, Hex, HttpError, HyperliquidChainIds, InsufficientFundsError, InvalidParamsError, type ListRecurringOrdersParams, type ListRecurringOrdersResponse, LombardServiceInitializer, type MarkrService, MarkrServiceInitializer, Mutable, MutableGetSupportedChainsResult, NATIVE_AVAX, NATIVE_ETH, NATIVE_SOL_ADDRESS, NativeAsset, NativeFeeEstimate, Quote, QuoteFee, QuoteFeeFundingModel, QuoteFeeToken, QuoteFeeType, QuoteFees, QuoterDonePayload, QuoterDonePayloadNoEligibleServices, QuoterDonePayloadNoQuotes, QuoterDonePayloadUnsubscribed, QuoterDoneReason, QuoterEventArgs, QuoterEventHandler, QuoterInterface, QuoterProps, QuotesTuple, RECURRING_FREQUENCY_UNITS, RECURRING_FREQUENCY_VALUE_MAX, RECURRING_UNLIMITED_ORDERS_SENTINEL, type RecurringChainInfoEntry, type RecurringChainInfoMap, type RecurringEligibility, RecurringEligibilityReason, type RecurringExecuteFirstFillParams, type RecurringExecuteOrderActionParams, type RecurringExecuteResult, type RecurringFrequency, type RecurringFrequencyUnit, type RecurringNamespace, type RecurringNamespaceCheckEligibilityParams, type RecurringNamespaceQuoteParams, type RecurringOrder, type RecurringOrderFailure, RecurringOrderStatus, type RecurringQuoteFee, type RecurringQuoteFeeType, type RecurringQuoteParams, type RecurringQuoteResponse, type RecurringSwapParams, RefundedTransfer, ResponseValidationError, SOLANA_DEVNET_CHAIN, SOLANA_MAINNET_CHAIN, SdkError, ServiceInitializationError, ServiceInitializer, ServiceQuoteEventArgs, ServiceQuoteEventHandler, ServiceQuoteOptions, ServiceStatus, ServiceStatusBaseRecord, ServiceStatusErrorRecord, ServiceStatusInitializedRecord, ServiceStatusRecord, ServiceStatusUnsupportedEnvironmentRecord, ServiceType, ServiceUnavailableError, SolanaChainIds, SolanaSendOptions, SolanaSign, SolanaSigner, SolanaTransactionParams, SourceCompletedTransfer, SourcePendingTransfer, SplAsset, TargetPendingTransfer, TimeoutError, TokenType, TrackTransferProps, Transfer, TransferAssetProps, TransferBase, TransferManager, TransferManagerStatus, TransferManagerStatusServicesRecord, TransferService, TransferSignatureReason, TransferSourceProgress, TransferStatus, TransferStepDetails, TransferTargetProgress, TransferableAsset, caip2ToEip155ChainId, caip2ToEip155HexChainId, calculatePriceImpactFromQuote, createTransferManager, dedupeBridgeableAssets, deriveIntervalSeconds, eip155ChainIdToCaip2, isAbortedError, isCaip2ChainId, isEnvironment, isErc20Asset, isEstimateNativeFeeError, isEvmBridgeInitializer, isHttpError, isInsufficientFundsError, isInvalidParamsError, isLombardServiceInitializer, isMarkrServiceInitializer, isNativeAsset, isResponseValidationError, isSdkError, isServiceInitializationError, isServiceInitializer, isServiceUnavailableError, isSplAsset, isTimeoutError, parseTransfer, splitCaip2ChainId, stringifyTransfer, validateFrequency };
27
+ export { AVALANCHE_CAIP2_TO_BLOCKCHAIN_ID_BY_NETWORK, AVALANCHE_FUJI_CHAIN, AVALANCHE_FUJI_P_CHAIN, AVALANCHE_FUJI_X_CHAIN, AVALANCHE_MAINNET_CHAIN, AVALANCHE_MAINNET_P_CHAIN, AVALANCHE_MAINNET_X_CHAIN, AbortedError, ApprovalRevertedError, ArrayElement, Asset, AssetBridgeMap, AssetSearchQuery, AssetWithExtras, AvalancheBlockchainAlias, AvalancheCctInitializer, AvalancheChainIds, AvalancheFujiBlockchainChainIds, AvalancheFujiBlockchainIds, AvalancheMainnetBlockchainChainIds, AvalancheMainnetBlockchainIds, AvalancheSendTxFunction, AvalancheSendTxParams, BITCOIN_MAINNET_CHAIN, BITCOIN_TESTNET_CHAIN, BTC_SERVICE_TYPES, BaseChainIds, BitcoinChainIds, BitcoinFeeRateTier, BitcoinFunctions, BitcoinInputUTXO, BitcoinInputUTXOWithOptionalScript, BitcoinOutputUTXO, BitcoinTx, Blockchain, Brand, BridgeableAsset, BridgeableUiAsset, BtcDispatch, BtcSign, BtcSigner, BtcTransactionRequest, Caip10AccountId, Caip2ChainId, Chain, ChainAssetMap, type CheckRecurringEligibilityParams, CompletedTransfer, CreateTransferManagerOptions, DeepMutable, type DestinationChainSortInput, DestinationInfo, ERC_ZERO_ADDRESS, ETHEREUM_MAINNET_CHAIN, ETHEREUM_SEPOLIA_CHAIN, EVM_SERVICE_TYPES, Environment, Erc20Asset, ErrorCode, ErrorReason, EstimateNativeFeeError, type EstimateNativeFeeErrorDetails, EstimateNativeFeeOptions, EthereumChainIds, EvmChainId, EvmDispatch, EvmServiceInitializer, EvmSign, EvmSignBatch, EvmSignMessage, EvmSignTypedData, EvmSigner, EvmSignerWithMessage, EvmTransactionRequest, EvmTypedData, FEE_RATE_TIER_TO_BITCOIN, FailedTransfer, FeeRateTier, Fetch, type FrequencyValidationResult, GasSettings, type GetAtomicUtxosCallback, GetBridgeableAssetsProps, GetBridgeableAssetsResult, type GetCoreEthAddressCallback, GetMinimumTransferAmountProps, GetSupportedChainsResult, type GetUtxosCallback, type GetWalletAddressesForChainAliasCallback, type GetWalletChangeAddressForChainAliasCallback, Hex, HttpError, HyperliquidChainIds, InsufficientFundsError, InvalidParamsError, type ListRecurringOrdersParams, type ListRecurringOrdersResponse, LombardServiceInitializer, type MarkrService, MarkrServiceInitializer, Mutable, MutableGetSupportedChainsResult, NATIVE_AVAX, NATIVE_ETH, NATIVE_SOL_ADDRESS, NativeAsset, NativeFeeEstimate, PolygonChainIds, Quote, QuoteFee, QuoteFeeFundingModel, QuoteFeeToken, QuoteFeeType, QuoteFees, QuoterDonePayload, QuoterDonePayloadNoEligibleServices, QuoterDonePayloadNoQuotes, QuoterDonePayloadUnsubscribed, QuoterDoneReason, QuoterEventArgs, QuoterEventHandler, QuoterInterface, QuoterProps, QuotesTuple, RECURRING_FREQUENCY_UNITS, RECURRING_FREQUENCY_VALUE_MAX, RECURRING_UNLIMITED_ORDERS_SENTINEL, type RecurringChainInfoEntry, type RecurringChainInfoMap, type RecurringEligibility, RecurringEligibilityReason, type RecurringExecuteFirstFillParams, type RecurringExecuteOrderActionParams, type RecurringExecuteResult, type RecurringFrequency, type RecurringFrequencyUnit, type RecurringNamespace, type RecurringNamespaceCheckEligibilityParams, type RecurringNamespaceQuoteParams, type RecurringOrder, type RecurringOrderFailure, RecurringOrderStatus, type RecurringQuoteFee, type RecurringQuoteFeeType, type RecurringQuoteParams, type RecurringQuoteResponse, type RecurringSwapParams, RefundedTransfer, ResponseValidationError, SOLANA_DEVNET_CHAIN, SOLANA_MAINNET_CHAIN, SdkError, ServiceInitializationError, ServiceInitializer, ServiceQuoteEventArgs, ServiceQuoteEventHandler, ServiceQuoteOptions, ServiceStatus, ServiceStatusBaseRecord, ServiceStatusErrorRecord, ServiceStatusInitializedRecord, ServiceStatusRecord, ServiceStatusUnsupportedEnvironmentRecord, ServiceType, ServiceUnavailableError, SolanaChainIds, SolanaSendOptions, SolanaSign, SolanaSigner, SolanaTransactionParams, SourceCompletedTransfer, SourcePendingTransfer, SplAsset, TargetPendingTransfer, TimeoutError, TokenType, TrackTransferProps, Transfer, TransferAssetProps, TransferBase, TransferManager, TransferManagerStatus, TransferManagerStatusServicesRecord, TransferService, TransferSignatureReason, TransferSourceProgress, TransferStatus, TransferStepDetails, TransferTargetProgress, TransferableAsset, caip2ToEip155ChainId, caip2ToEip155HexChainId, calculatePriceImpactFromQuote, compareDestinationChains, createTransferManager, dedupeBridgeableAssets, deriveIntervalSeconds, eip155ChainIdToCaip2, getDestinationChainPriority, isAbortedError, isCaip2ChainId, isEnvironment, isErc20Asset, isEstimateNativeFeeError, isEvmBridgeInitializer, isHttpError, isInsufficientFundsError, isInvalidParamsError, isLombardServiceInitializer, isMarkrServiceInitializer, isNativeAsset, isResponseValidationError, isSdkError, isServiceInitializationError, isServiceInitializer, isServiceUnavailableError, isSplAsset, isTimeoutError, parseTransfer, sortDestinationChains, splitCaip2ChainId, stringifyTransfer, validateFrequency };
package/dist/mod.js CHANGED
@@ -1 +1 @@
1
- import{AVALANCHE_CAIP2_TO_BLOCKCHAIN_ID_BY_NETWORK as e,AVALANCHE_FUJI_CHAIN as t,AVALANCHE_FUJI_P_CHAIN as n,AVALANCHE_FUJI_X_CHAIN as r,AVALANCHE_MAINNET_CHAIN as i,AVALANCHE_MAINNET_P_CHAIN as a,AVALANCHE_MAINNET_X_CHAIN as o,AvalancheChainIds as s,AvalancheFujiBlockchainChainIds as c,AvalancheFujiBlockchainIds as l,AvalancheMainnetBlockchainChainIds as u,AvalancheMainnetBlockchainIds as d,BITCOIN_MAINNET_CHAIN as f,BITCOIN_TESTNET_CHAIN as p,BTC_SERVICE_TYPES as m,BitcoinChainIds as h,Blockchain as g,ERC_ZERO_ADDRESS as _,ETHEREUM_MAINNET_CHAIN as v,ETHEREUM_SEPOLIA_CHAIN as y,EVM_SERVICE_TYPES as b,Environment as x,EthereumChainIds as S,EvmChainId as C,FEE_RATE_TIER_TO_BITCOIN as w,HyperliquidChainIds as T,NATIVE_AVAX as E,NATIVE_ETH as D,NATIVE_SOL_ADDRESS as O,SOLANA_DEVNET_CHAIN as k,SOLANA_MAINNET_CHAIN as A,ServiceType as j,SolanaChainIds as M,TokenType as N,TransferSignatureReason as P}from"./constants.js";import{AbortedError as F,ErrorCode as I,ErrorReason as L,EstimateNativeFeeError as R,HttpError as z,InsufficientFundsError as B,InvalidParamsError as V,ResponseValidationError as H,SdkError as U,ServiceInitializationError as W,ServiceUnavailableError as G,TimeoutError as K,isAbortedError as q,isEstimateNativeFeeError as J,isHttpError as Y,isInsufficientFundsError as X,isInvalidParamsError as Z,isResponseValidationError as Q,isSdkError as $,isServiceInitializationError as ee,isServiceUnavailableError as te,isTimeoutError as ne}from"./errors.js";import{isEnvironment as re,isErc20Asset as ie,isEvmBridgeInitializer as ae,isLombardServiceInitializer as oe,isMarkrServiceInitializer as se,isNativeAsset as ce,isServiceInitializer as le,isSplAsset as ue}from"./type-guards.js";import{createTransferManager as de}from"./transfer-manager.js";import{caip2ToEip155ChainId as fe,caip2ToEip155HexChainId as pe,eip155ChainIdToCaip2 as me,isCaip2ChainId as he,splitCaip2ChainId as ge}from"./utils/caip.js";import{dedupeBridgeableAssets as _e}from"./utils/bridgeable-assets.js";import{calculatePriceImpactFromQuote as ve}from"./utils/price-impact.js";import{parseTransfer as ye,stringifyTransfer as be}from"./utils/transfer-utils.js";import{RECURRING_FREQUENCY_UNITS as xe,RECURRING_UNLIMITED_ORDERS_SENTINEL as Se,RecurringEligibilityReason as Ce,RecurringOrderStatus as we}from"./transfer-service/markr/recurring/types.js";import{RECURRING_FREQUENCY_VALUE_MAX as Te,deriveIntervalSeconds as Ee,validateFrequency as De}from"./transfer-service/markr/recurring/_frequency.js";import{ApprovalRevertedError as Oe}from"./transfer-service/_evm-approval.js";export{e as AVALANCHE_CAIP2_TO_BLOCKCHAIN_ID_BY_NETWORK,t as AVALANCHE_FUJI_CHAIN,n as AVALANCHE_FUJI_P_CHAIN,r as AVALANCHE_FUJI_X_CHAIN,i as AVALANCHE_MAINNET_CHAIN,a as AVALANCHE_MAINNET_P_CHAIN,o as AVALANCHE_MAINNET_X_CHAIN,F as AbortedError,Oe as ApprovalRevertedError,s as AvalancheChainIds,c as AvalancheFujiBlockchainChainIds,l as AvalancheFujiBlockchainIds,u as AvalancheMainnetBlockchainChainIds,d as AvalancheMainnetBlockchainIds,f as BITCOIN_MAINNET_CHAIN,p as BITCOIN_TESTNET_CHAIN,m as BTC_SERVICE_TYPES,h as BitcoinChainIds,g as Blockchain,_ as ERC_ZERO_ADDRESS,v as ETHEREUM_MAINNET_CHAIN,y as ETHEREUM_SEPOLIA_CHAIN,b as EVM_SERVICE_TYPES,x as Environment,I as ErrorCode,L as ErrorReason,R as EstimateNativeFeeError,S as EthereumChainIds,C as EvmChainId,w as FEE_RATE_TIER_TO_BITCOIN,z as HttpError,T as HyperliquidChainIds,B as InsufficientFundsError,V as InvalidParamsError,E as NATIVE_AVAX,D as NATIVE_ETH,O as NATIVE_SOL_ADDRESS,xe as RECURRING_FREQUENCY_UNITS,Te as RECURRING_FREQUENCY_VALUE_MAX,Se as RECURRING_UNLIMITED_ORDERS_SENTINEL,Ce as RecurringEligibilityReason,we as RecurringOrderStatus,H as ResponseValidationError,k as SOLANA_DEVNET_CHAIN,A as SOLANA_MAINNET_CHAIN,U as SdkError,W as ServiceInitializationError,j as ServiceType,G as ServiceUnavailableError,M as SolanaChainIds,K as TimeoutError,N as TokenType,P as TransferSignatureReason,fe as caip2ToEip155ChainId,pe as caip2ToEip155HexChainId,ve as calculatePriceImpactFromQuote,de as createTransferManager,_e as dedupeBridgeableAssets,Ee as deriveIntervalSeconds,me as eip155ChainIdToCaip2,q as isAbortedError,he as isCaip2ChainId,re as isEnvironment,ie as isErc20Asset,J as isEstimateNativeFeeError,ae as isEvmBridgeInitializer,Y as isHttpError,X as isInsufficientFundsError,Z as isInvalidParamsError,oe as isLombardServiceInitializer,se as isMarkrServiceInitializer,ce as isNativeAsset,Q as isResponseValidationError,$ as isSdkError,ee as isServiceInitializationError,le as isServiceInitializer,te as isServiceUnavailableError,ue as isSplAsset,ne as isTimeoutError,ye as parseTransfer,ge as splitCaip2ChainId,be as stringifyTransfer,De as validateFrequency};
1
+ import{AVALANCHE_CAIP2_TO_BLOCKCHAIN_ID_BY_NETWORK as e,AVALANCHE_FUJI_CHAIN as t,AVALANCHE_FUJI_P_CHAIN as n,AVALANCHE_FUJI_X_CHAIN as r,AVALANCHE_MAINNET_CHAIN as i,AVALANCHE_MAINNET_P_CHAIN as a,AVALANCHE_MAINNET_X_CHAIN as o,AvalancheChainIds as s,AvalancheFujiBlockchainChainIds as c,AvalancheFujiBlockchainIds as l,AvalancheMainnetBlockchainChainIds as u,AvalancheMainnetBlockchainIds as d,BITCOIN_MAINNET_CHAIN as f,BITCOIN_TESTNET_CHAIN as p,BTC_SERVICE_TYPES as m,BaseChainIds as h,BitcoinChainIds as g,Blockchain as _,ERC_ZERO_ADDRESS as v,ETHEREUM_MAINNET_CHAIN as y,ETHEREUM_SEPOLIA_CHAIN as b,EVM_SERVICE_TYPES as x,Environment as S,EthereumChainIds as C,EvmChainId as w,FEE_RATE_TIER_TO_BITCOIN as T,HyperliquidChainIds as E,NATIVE_AVAX as D,NATIVE_ETH as O,NATIVE_SOL_ADDRESS as k,PolygonChainIds as A,SOLANA_DEVNET_CHAIN as j,SOLANA_MAINNET_CHAIN as M,ServiceType as N,SolanaChainIds as P,TokenType as F,TransferSignatureReason as I}from"./constants.js";import{AbortedError as L,ErrorCode as R,ErrorReason as z,EstimateNativeFeeError as B,HttpError as V,InsufficientFundsError as H,InvalidParamsError as U,ResponseValidationError as W,SdkError as G,ServiceInitializationError as K,ServiceUnavailableError as q,TimeoutError as J,isAbortedError as Y,isEstimateNativeFeeError as X,isHttpError as Z,isInsufficientFundsError as Q,isInvalidParamsError as $,isResponseValidationError as ee,isSdkError as te,isServiceInitializationError as ne,isServiceUnavailableError as re,isTimeoutError as ie}from"./errors.js";import{isEnvironment as ae,isErc20Asset as oe,isEvmBridgeInitializer as se,isLombardServiceInitializer as ce,isMarkrServiceInitializer as le,isNativeAsset as ue,isServiceInitializer as de,isSplAsset as fe}from"./type-guards.js";import{createTransferManager as pe}from"./transfer-manager.js";import{caip2ToEip155ChainId as me,caip2ToEip155HexChainId as he,eip155ChainIdToCaip2 as ge,isCaip2ChainId as _e,splitCaip2ChainId as ve}from"./utils/caip.js";import{dedupeBridgeableAssets as ye}from"./utils/bridgeable-assets.js";import{compareDestinationChains as be,getDestinationChainPriority as xe,sortDestinationChains as Se}from"./utils/destination-chains.js";import{calculatePriceImpactFromQuote as Ce}from"./utils/price-impact.js";import{parseTransfer as we,stringifyTransfer as Te}from"./utils/transfer-utils.js";import{RECURRING_FREQUENCY_UNITS as Ee,RECURRING_UNLIMITED_ORDERS_SENTINEL as De,RecurringEligibilityReason as Oe,RecurringOrderStatus as ke}from"./transfer-service/markr/recurring/types.js";import{RECURRING_FREQUENCY_VALUE_MAX as Ae,deriveIntervalSeconds as je,validateFrequency as Me}from"./transfer-service/markr/recurring/_frequency.js";import{ApprovalRevertedError as Ne}from"./transfer-service/_evm-approval.js";export{e as AVALANCHE_CAIP2_TO_BLOCKCHAIN_ID_BY_NETWORK,t as AVALANCHE_FUJI_CHAIN,n as AVALANCHE_FUJI_P_CHAIN,r as AVALANCHE_FUJI_X_CHAIN,i as AVALANCHE_MAINNET_CHAIN,a as AVALANCHE_MAINNET_P_CHAIN,o as AVALANCHE_MAINNET_X_CHAIN,L as AbortedError,Ne as ApprovalRevertedError,s as AvalancheChainIds,c as AvalancheFujiBlockchainChainIds,l as AvalancheFujiBlockchainIds,u as AvalancheMainnetBlockchainChainIds,d as AvalancheMainnetBlockchainIds,f as BITCOIN_MAINNET_CHAIN,p as BITCOIN_TESTNET_CHAIN,m as BTC_SERVICE_TYPES,h as BaseChainIds,g as BitcoinChainIds,_ as Blockchain,v as ERC_ZERO_ADDRESS,y as ETHEREUM_MAINNET_CHAIN,b as ETHEREUM_SEPOLIA_CHAIN,x as EVM_SERVICE_TYPES,S as Environment,R as ErrorCode,z as ErrorReason,B as EstimateNativeFeeError,C as EthereumChainIds,w as EvmChainId,T as FEE_RATE_TIER_TO_BITCOIN,V as HttpError,E as HyperliquidChainIds,H as InsufficientFundsError,U as InvalidParamsError,D as NATIVE_AVAX,O as NATIVE_ETH,k as NATIVE_SOL_ADDRESS,A as PolygonChainIds,Ee as RECURRING_FREQUENCY_UNITS,Ae as RECURRING_FREQUENCY_VALUE_MAX,De as RECURRING_UNLIMITED_ORDERS_SENTINEL,Oe as RecurringEligibilityReason,ke as RecurringOrderStatus,W as ResponseValidationError,j as SOLANA_DEVNET_CHAIN,M as SOLANA_MAINNET_CHAIN,G as SdkError,K as ServiceInitializationError,N as ServiceType,q as ServiceUnavailableError,P as SolanaChainIds,J as TimeoutError,F as TokenType,I as TransferSignatureReason,me as caip2ToEip155ChainId,he as caip2ToEip155HexChainId,Ce as calculatePriceImpactFromQuote,be as compareDestinationChains,pe as createTransferManager,ye as dedupeBridgeableAssets,je as deriveIntervalSeconds,ge as eip155ChainIdToCaip2,xe as getDestinationChainPriority,Y as isAbortedError,_e as isCaip2ChainId,ae as isEnvironment,oe as isErc20Asset,X as isEstimateNativeFeeError,se as isEvmBridgeInitializer,Z as isHttpError,Q as isInsufficientFundsError,$ as isInvalidParamsError,ce as isLombardServiceInitializer,le as isMarkrServiceInitializer,ue as isNativeAsset,ee as isResponseValidationError,te as isSdkError,ne as isServiceInitializationError,de as isServiceInitializer,re as isServiceUnavailableError,fe as isSplAsset,ie as isTimeoutError,we as parseTransfer,Se as sortDestinationChains,ve as splitCaip2ChainId,Te as stringifyTransfer,Me as validateFrequency};
@@ -1 +1 @@
1
- {"version":3,"file":"quoter.cjs","names":["sortQuotes","pruneExpiredQuotes","isQuoteExpired","upsertQuote","QUOTER_EMPTY_RETRY_MAX_DELAY_MS","QUOTER_EMPTY_RETRY_BASE_DELAY_MS","earliestExpirationForService","z","isNativeAsset","TokenType"],"sources":["../../src/quoter/quoter.ts"],"sourcesContent":["import { z } from 'zod';\nimport type {\n Quote,\n QuoterDonePayload,\n QuoterDoneReason,\n QuoterEventHandler,\n QuoterInterface,\n QuoterProps,\n ServiceQuoteEventArgs,\n QuotesTuple,\n ServiceQuoteEventHandler,\n} from '../types/quote';\nimport type { ServiceQuoteOptions, TransferService } from '../types/service';\nimport { earliestExpirationForService, isQuoteExpired, pruneExpiredQuotes, sortQuotes, upsertQuote } from './_utils';\nimport {\n QUOTER_DEFAULT_PRUNE_INTERVAL_MS,\n QUOTER_DEFAULT_REFRESH_BUFFER_SECONDS,\n QUOTER_EMPTY_RETRY_BASE_DELAY_MS,\n QUOTER_EMPTY_RETRY_MAX_DELAY_MS,\n} from './constants';\nimport { ServiceType, TokenType } from '../constants';\nimport { isNativeAsset } from '../type-guards';\nimport { isAddressEqual } from 'viem';\n\n/**\n * Function that returns the current UNIX time in seconds.\n * Injected for deterministic testing.\n */\nexport type Clock = () => number;\n\n/**\n * Options for constructing a Quoter instance.\n *\n * These options tune how often quote state is maintained and when services are\n * proactively restarted before quote expiry.\n */\nexport interface QuoterOptions {\n /**\n * Dangerously allows cross-chain quotes where fromAddress and toAddress differ\n * even when a service would otherwise require them to match.\n *\n * This is intended for explicit proxy-recipient funding flows. By default,\n * services preserve their existing address safety checks.\n */\n readonly dangerouslyAllowAddressMismatch?: boolean;\n /** Clock function returning current time in seconds (defaults to Date.now()/1000). */\n readonly clock?: Clock;\n /** Interval for pruning expired quotes (milliseconds).\n *\n * @default 1_000\n */\n readonly pruneIntervalMs?: number;\n /**\n * Amount of seconds to pre-buffer a stream restart before the earliest service quote\n * expiration. Helps ensure continuity before actual expiry is reached.\n *\n * @default 5\n */\n readonly refreshBufferSeconds?: number;\n}\n\n/**\n * Quoter orchestrates quote streaming across multiple transfer services and emits a unified event stream.\n *\n * High-level lifecycle:\n * - Idle until first subscriber.\n * - On first subscribe, starts all eligible services.\n * - Collects and ranks active quotes, pruning expired ones over time.\n * - Completes when explicitly unsubscribed (last subscriber), when no service is eligible,\n * or when all eligible services finish without producing any quote (`no-quotes`).\n *\n * Event model:\n * - Service `quote` -> Quoter upserts quote, recomputes best quote, emits `quote`.\n * - Service `error` -> Quoter emits `error` (non-terminal by itself).\n * - Service `done` -> Quoter marks that service attempt as completed and evaluates retry/complete rules.\n *\n * Retry/refresh behavior:\n * - Refresh: services that have active quotes are restarted shortly before the earliest quote expires.\n * - Retry: services that complete with no quote and no error are only retried after the quoter has\n * already observed at least one quote from any service in this session.\n *\n * This design keeps first-pass \"no quotes anywhere\" terminal and fast, while still allowing services\n * like Markr to be retried in sessions where other providers are returning quotes.\n */\nexport class Quoter implements QuoterInterface {\n private readonly clock: Clock;\n private readonly props: QuoterProps;\n private readonly pruneIntervalMs: number;\n private readonly serviceQuoteOptions: ServiceQuoteOptions;\n private readonly transferServices: readonly TransferService[];\n private readonly refreshBufferSeconds: number;\n\n private quotes: Quote[] = [];\n private subscribers: Set<QuoterEventHandler> = new Set();\n private started = false;\n private done = false;\n private isStartingFromSubscribe = false;\n private pruneTimerId: ReturnType<typeof setInterval> | null = null;\n private lastBestId: string | null = null;\n private hasReceivedAnyQuote = false;\n\n public readonly id: string = crypto.randomUUID();\n\n /**\n * Per-service runtime state for the active quote session.\n *\n * This tracks whether a service has completed, errored, produced quotes,\n * and any pending timers used for retry/refresh orchestration.\n */\n private serviceState: Map<\n TransferService['type'],\n {\n cancel: () => void;\n done: boolean;\n hasErrored: boolean;\n hasReturnedQuote: boolean;\n retryAttempt: number;\n retryTimer: ReturnType<typeof setTimeout> | null;\n refreshTimer: ReturnType<typeof setTimeout> | null;\n refreshAtSeconds: number | null;\n }\n > = new Map();\n\n /**\n * Create a new Quoter instance.\n *\n * @param props Quoting request parameters shared across all services.\n * @param transferServices Candidate services; eligibility is resolved at `start()` time.\n * @param options Optional runtime tuning for pruning and refresh behavior.\n */\n constructor(props: QuoterProps, transferServices: readonly TransferService[], options: QuoterOptions = {}) {\n this.clock = options.clock ?? (() => Math.floor(Date.now() / 1_000));\n this.props = props;\n this.pruneIntervalMs = options.pruneIntervalMs ?? QUOTER_DEFAULT_PRUNE_INTERVAL_MS;\n this.serviceQuoteOptions = {\n dangerouslyAllowAddressMismatch: options.dangerouslyAllowAddressMismatch,\n };\n this.transferServices = transferServices;\n this.refreshBufferSeconds = options.refreshBufferSeconds ?? QUOTER_DEFAULT_REFRESH_BUFFER_SECONDS;\n }\n\n /**\n * Get the current best quote and all active quotes (sorted by desirability).\n */\n public getQuotes(): QuotesTuple {\n const now = this.clock();\n const active = pruneExpiredQuotes({ quotes: this.quotes, nowSeconds: now });\n const sorted = sortQuotes(active);\n const best = sorted[0] ?? null;\n\n return [best, sorted];\n }\n\n /**\n * Subscribe for quoter events.\n *\n * First subscriber lazily starts orchestration.\n * Last subscriber triggers terminal completion with reason `unsubscribed`.\n *\n * @returns Unsubscribe function (idempotent).\n */\n public subscribe(handler: QuoterEventHandler): () => void {\n this.subscribers.add(handler);\n let unsubscribed = false;\n\n if (!this.started) {\n this.isStartingFromSubscribe = true;\n try {\n this.start();\n } finally {\n this.isStartingFromSubscribe = false;\n }\n }\n\n return () => {\n if (unsubscribed) {\n return;\n }\n unsubscribed = true;\n\n if (this.done) {\n this.subscribers.delete(handler);\n return;\n }\n\n const wasLastSubscriber = this.subscribers.size === 1 && this.subscribers.has(handler);\n if (wasLastSubscriber) {\n this.complete('unsubscribed');\n return;\n }\n\n this.subscribers.delete(handler);\n };\n }\n\n // ----- Internal orchestration -----\n\n /**\n * Start a fresh quote session.\n *\n * Resets session-local state, validates basic request viability,\n * starts streams for eligible services, and begins prune ticks.\n */\n private start(): void {\n this.started = true;\n this.done = false;\n this.quotes = [];\n this.lastBestId = null;\n this.hasReceivedAnyQuote = false;\n\n // Same-chain quotes for the *same* asset are not a valid transfer scenario.\n if (isInvalidSameChainQuoteRequest(this.props)) {\n this.complete('no-eligible-services');\n return;\n }\n\n let hasEligibleService = false;\n\n // Start streams for eligible services\n for (const svc of this.transferServices) {\n const eligible = svc.analyzeSupport({\n sourceAsset: this.props.sourceAsset,\n sourceChainId: this.props.sourceChain.chainId,\n targetAsset: this.props.targetAsset,\n targetChainId: this.props.targetChain.chainId,\n });\n\n if (!eligible) continue;\n hasEligibleService = true;\n\n this.startStreamForService(svc);\n }\n\n if (!hasEligibleService) {\n this.complete('no-eligible-services');\n return;\n }\n\n // Start periodic prune\n this.pruneTimerId = setInterval(() => this.onPruneTick(), this.pruneIntervalMs);\n }\n\n /**\n * Stop all streams and timers.\n * Quotes are retained for snapshot access via getQuotes(), though they\n * can still be pruned due to expiration.\n */\n private stop(): void {\n this.started = false;\n\n if (this.pruneTimerId) {\n clearInterval(this.pruneTimerId);\n this.pruneTimerId = null;\n }\n\n for (const [type, state] of this.serviceState) {\n try {\n state.cancel();\n } catch {\n /* ignore */\n }\n\n if (state.refreshTimer) {\n clearTimeout(state.refreshTimer);\n }\n\n if (state.retryTimer) {\n clearTimeout(state.retryTimer);\n }\n\n this.serviceState.set(type, {\n cancel: () => {},\n done: false,\n hasErrored: false,\n hasReturnedQuote: false,\n retryAttempt: 0,\n retryTimer: null,\n refreshTimer: null,\n refreshAtSeconds: null,\n });\n }\n }\n\n /**\n * Begin or restart streaming for a specific service.\n *\n * Any previous stream/timers for that service are canceled before starting a new attempt.\n */\n private startStreamForService(svc: TransferService): void {\n // Clean up any existing stream and refresh timer\n const existing = this.serviceState.get(svc.type);\n\n if (existing) {\n try {\n existing.cancel();\n } catch {\n /* ignore */\n }\n\n if (existing.refreshTimer) clearTimeout(existing.refreshTimer);\n if (existing.retryTimer) clearTimeout(existing.retryTimer);\n }\n\n const handler = this.makeServiceHandler(svc.type);\n const bufferedEvents: ServiceQuoteEventArgs[] = [];\n let isStartingStream = true;\n\n // Some services emit quote/done synchronously inside streamQuotes().\n // If those events run before subscribe() returns, consumers can hit TDZ\n // when they reference the returned unsubscribe function in their callback.\n // Buffer startup emissions and flush them after stream initialization.\n const guardedHandler: ServiceQuoteEventHandler = (...eventArgs) => {\n if (isStartingStream) {\n bufferedEvents.push(eventArgs);\n return;\n }\n\n handler(...eventArgs);\n };\n\n const { cancel } = svc.streamQuotes(this.props, guardedHandler, this.serviceQuoteOptions);\n isStartingStream = false;\n\n if (bufferedEvents.length > 0) {\n // Use a microtask so subscribe() can return before the first callback fires.\n // This preserves event order while avoiding re-entrancy during subscription.\n queueMicrotask(() => {\n for (const bufferedEvent of bufferedEvents) {\n handler(...bufferedEvent);\n }\n });\n }\n\n this.serviceState.set(svc.type, {\n cancel,\n done: false,\n hasErrored: false,\n hasReturnedQuote: false,\n retryAttempt: existing?.retryAttempt ?? 0,\n retryTimer: null,\n refreshTimer: null,\n refreshAtSeconds: null,\n });\n }\n\n /**\n * Create the service-scoped event handler consumed by `TransferService.streamQuotes`.\n *\n * The handler enforces service/quote consistency and translates service events into\n * quoter state transitions.\n */\n private makeServiceHandler(serviceType: TransferService['type']): ServiceQuoteEventHandler {\n return (event, ...args) => {\n // Ignore any service events once stopped to prevent post-stop mutations.\n if (!this.started) {\n return;\n }\n if (event === 'quote') {\n const maybeQuote = args[0];\n if (isQuoteValue(maybeQuote)) {\n // Enforce the quote belongs to the emitting service\n if (maybeQuote.serviceType !== serviceType) {\n // Ignore quotes mismatched to service; defensive\n return;\n }\n const state = this.serviceState.get(serviceType);\n if (state) {\n state.hasReturnedQuote = true;\n }\n this.onIncomingQuote(maybeQuote);\n this.scheduleServiceRefresh(serviceType);\n }\n\n return;\n }\n if (event === 'done') {\n this.onServiceDone(serviceType);\n\n return;\n }\n if (event === 'error') {\n const state = this.serviceState.get(serviceType);\n if (state) {\n state.hasErrored = true;\n }\n const maybeErr = args[0];\n if (maybeErr instanceof Error) {\n this.emitError(maybeErr);\n }\n }\n };\n }\n\n /**\n * Handle an incoming quote event.\n *\n * Expired quotes are ignored. Valid quotes are upserted into active state,\n * then sorted/pruned and emitted to subscribers.\n */\n private onIncomingQuote(quote: Quote): void {\n const now = this.clock();\n\n if (isQuoteExpired({ quote, nowSeconds: now })) {\n return;\n }\n\n this.hasReceivedAnyQuote = true;\n\n this.resetRetryForService(quote.serviceType);\n\n this.quotes = sortQuotes(pruneExpiredQuotes({ quotes: upsertQuote(this.quotes, quote), nowSeconds: now }));\n\n // Always emit on every incoming quote\n const best = this.quotes[0];\n if (best) {\n this.lastBestId = best.id;\n this.emitQuote({ bestQuote: best, quote, quotes: this.quotes });\n }\n }\n\n private resetRetryForService(serviceType: TransferService['type']): void {\n const state = this.serviceState.get(serviceType);\n\n if (!state) {\n return;\n }\n\n state.retryAttempt = 0;\n if (state.retryTimer) {\n clearTimeout(state.retryTimer);\n state.retryTimer = null;\n }\n }\n\n /**\n * Schedule a retry attempt for a service using exponential backoff.\n *\n * This is used only for quote-less successful completions once the overall session\n * has already produced at least one quote from some service.\n */\n private scheduleServiceRetry(serviceType: TransferService['type']): void {\n const state = this.serviceState.get(serviceType);\n\n if (!state) {\n return;\n }\n\n if (state.retryTimer) {\n clearTimeout(state.retryTimer);\n state.retryTimer = null;\n }\n\n const delayMs = Math.min(\n QUOTER_EMPTY_RETRY_MAX_DELAY_MS,\n QUOTER_EMPTY_RETRY_BASE_DELAY_MS * 2 ** state.retryAttempt,\n );\n state.retryAttempt += 1;\n\n state.retryTimer = setTimeout(\n () => {\n const current = this.serviceState.get(serviceType);\n if (current) {\n current.retryTimer = null;\n }\n\n if (!this.started) {\n return;\n }\n\n const svc = this.transferServices.find((s) => s.type === serviceType);\n if (svc) {\n this.startStreamForService(svc);\n }\n },\n Math.max(0, delayMs),\n );\n }\n\n /**\n * Handle service completion (`done`).\n *\n * A completion may schedule:\n * - refresh (if the service has active quotes), and/or\n * - retry (quote-less/non-error completion, but only after any quote has existed in session).\n *\n * Then evaluates whether the full quoter can complete with `no-quotes`.\n */\n private onServiceDone(serviceType: TransferService['type']): void {\n const state = this.serviceState.get(serviceType);\n\n if (!state) {\n return;\n }\n\n state.done = true;\n this.scheduleServiceRefresh(serviceType);\n\n if (this.hasReceivedAnyQuote && !state.hasErrored && !state.hasReturnedQuote) {\n this.scheduleServiceRetry(serviceType);\n }\n\n this.maybeCompleteNoQuotes();\n }\n\n /**\n * Complete with `no-quotes` when every eligible service has finished and\n * no quote was ever observed during this session.\n */\n private maybeCompleteNoQuotes(): void {\n if (!this.started || this.done || this.hasReceivedAnyQuote || this.serviceState.size === 0) {\n return;\n }\n\n const allServicesDone = [...this.serviceState.values()].every((state) => state.done);\n\n if (allServicesDone) {\n this.complete('no-quotes');\n }\n }\n\n /**\n * Finalize the quoter session and broadcast terminal reason exactly once.\n */\n private complete(reason: QuoterDoneReason): void {\n if (this.done) {\n return;\n }\n\n const payload = this.makeDonePayload(reason);\n\n this.done = true;\n this.stop();\n\n // When complete() happens during subscribe()->start(), emit done on a microtask\n // so callers can safely reference the returned unsubscribe in their handler.\n if (this.isStartingFromSubscribe) {\n queueMicrotask(() => {\n const handlers = [...this.subscribers];\n this.subscribers.clear();\n\n for (const handler of handlers) {\n handler('done', payload);\n }\n });\n return;\n }\n\n const handlers = [...this.subscribers];\n this.subscribers.clear();\n\n for (const handler of handlers) {\n handler('done', payload);\n }\n }\n\n private getInitializedServices(): ServiceType[] {\n return [...new Set(this.transferServices.map((service) => service.type))];\n }\n\n private getEligibleServices(): ServiceType[] {\n return [...this.serviceState.keys()];\n }\n\n private makeDonePayload(reason: QuoterDoneReason): QuoterDonePayload {\n if (reason === 'unsubscribed') {\n return { reason, data: undefined };\n }\n\n const initializedServices = this.getInitializedServices();\n\n if (reason === 'no-eligible-services') {\n return {\n reason,\n data: {\n initializedServices,\n quoterProps: this.props,\n },\n };\n }\n\n return {\n reason,\n data: {\n eligibleServices: this.getEligibleServices(),\n initializedServices,\n quoterProps: this.props,\n },\n };\n }\n\n /** Periodic prune tick to evict expired quotes and emit best changes. */\n private onPruneTick(): void {\n const now = this.clock();\n const pruned = pruneExpiredQuotes({ quotes: this.quotes, nowSeconds: now });\n\n if (pruned.length !== this.quotes.length) {\n this.quotes = sortQuotes(pruned);\n const best = this.quotes[0] ?? null;\n const bestId = best ? best.id : null;\n\n if (best && bestId !== this.lastBestId) {\n this.lastBestId = bestId;\n this.emitQuote({ bestQuote: best, quote: best, quotes: this.quotes });\n } else if (!best) {\n this.lastBestId = null;\n }\n }\n\n // Re-evaluate refresh scheduling for all services on prune tick\n for (const svc of this.transferServices) {\n if (this.serviceState.has(svc.type)) {\n this.scheduleServiceRefresh(svc.type);\n }\n }\n }\n\n /** Schedule a refresh (restart) of streaming for the service at its earliest quote expiration. */\n private scheduleServiceRefresh(serviceType: TransferService['type']): void {\n const state = this.serviceState.get(serviceType);\n\n if (!state) return;\n\n const now = this.clock();\n const earliest = earliestExpirationForService({ quotes: this.quotes, serviceType, nowSeconds: now });\n\n if (earliest === null) {\n // No quotes -> clear any pending refresh\n if (state.refreshTimer) {\n clearTimeout(state.refreshTimer);\n state.refreshTimer = null;\n }\n state.refreshAtSeconds = null;\n return;\n }\n\n // Only reschedule if earlier than currently scheduled or no timer\n const targetAt = Math.max(0, earliest - this.refreshBufferSeconds);\n\n // If target time has already passed, do not schedule another refresh here.\n if (targetAt <= now) {\n return;\n }\n\n // Reschedule only when the desired refresh time changes (earlier OR later).\n // We key refresh off the soonest-expiring active quote for this service.\n if (state.refreshAtSeconds === targetAt && state.refreshTimer) {\n return;\n }\n\n if (state.refreshTimer) {\n clearTimeout(state.refreshTimer);\n }\n\n const delayMs = Math.max(0, (targetAt - now) * 1_000);\n state.refreshAtSeconds = targetAt;\n state.refreshTimer = setTimeout(() => {\n // Clear timer/marker before restarting to avoid stale state if restart fails.\n const current = this.serviceState.get(serviceType);\n if (current) {\n current.refreshTimer = null;\n current.refreshAtSeconds = null;\n }\n\n // Restart stream and clear timer/marker\n const svc = this.transferServices.find((s) => s.type === serviceType);\n\n if (svc) {\n this.startStreamForService(svc);\n }\n }, delayMs);\n }\n\n // ----- Emission helpers -----\n /** Emit a quote event to all subscribers. */\n private emitQuote(payload: { bestQuote: Quote; quote: Quote; quotes: readonly Quote[] }): void {\n for (const handler of this.subscribers) {\n handler('quote', payload);\n }\n }\n\n /** Emit an error event to all subscribers. */\n private emitError(error: Error): void {\n for (const handler of this.subscribers) {\n handler('error', error);\n }\n }\n}\n\n/**\n * Zod schema to validate the minimal Quote fields used for runtime gating.\n *\n * This is a simple schema, and is not a fully safe runtime validate for Quote.\n * That isn't necessary here since we only need to verify basic structure before\n * using the quote in internal logic.\n *\n * @internal\n */\nconst QuoteSchema = z.object({\n id: z.string(),\n expiresAt: z.number().int().nonnegative(),\n amountOut: z.bigint().nonnegative(),\n amountIn: z.bigint().nonnegative(),\n serviceType: z.string(),\n});\n\nfunction isInvalidSameChainQuoteRequest(props: QuoterProps): boolean {\n const { sourceAsset, sourceChain, targetAsset, targetChain } = props;\n\n if (sourceChain.chainId !== targetChain.chainId) {\n return false;\n }\n\n // Native -> native on the same chain is a no-op.\n if (isNativeAsset(sourceAsset) && isNativeAsset(targetAsset)) {\n return true;\n }\n\n // If token types differ, it's potentially a swap on the same chain.\n if (sourceAsset.type !== targetAsset.type) {\n return false;\n }\n\n // Same token type and address on the same chain is a no-op.\n if (sourceAsset.type === TokenType.ERC20 && targetAsset.type === TokenType.ERC20) {\n return isAddressEqual(sourceAsset.address, targetAsset.address);\n }\n\n if (sourceAsset.type === TokenType.SPL && targetAsset.type === TokenType.SPL) {\n return sourceAsset.address === targetAsset.address;\n }\n\n return false;\n}\n\nfunction isQuoteValue(value: unknown): value is Quote {\n const result = QuoteSchema.safeParse(value);\n\n return result.success;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"quoter.cjs","names":["sortQuotes","pruneExpiredQuotes","isQuoteExpired","upsertQuote","QUOTER_EMPTY_RETRY_MAX_DELAY_MS","QUOTER_EMPTY_RETRY_BASE_DELAY_MS","earliestExpirationForService","z","isNativeAsset","TokenType"],"sources":["../../src/quoter/quoter.ts"],"sourcesContent":["import { z } from 'zod';\nimport type {\n Quote,\n QuoterDonePayload,\n QuoterDoneReason,\n QuoterEventHandler,\n QuoterInterface,\n QuoterProps,\n ServiceQuoteEventArgs,\n QuotesTuple,\n ServiceQuoteEventHandler,\n} from '../types/quote';\nimport type { ServiceQuoteOptions, TransferService } from '../types/service';\nimport { earliestExpirationForService, isQuoteExpired, pruneExpiredQuotes, sortQuotes, upsertQuote } from './_utils';\nimport {\n QUOTER_DEFAULT_PRUNE_INTERVAL_MS,\n QUOTER_DEFAULT_REFRESH_BUFFER_SECONDS,\n QUOTER_EMPTY_RETRY_BASE_DELAY_MS,\n QUOTER_EMPTY_RETRY_MAX_DELAY_MS,\n} from './constants';\nimport { ServiceType, TokenType } from '../constants';\nimport { isNativeAsset } from '../type-guards';\nimport { isAddressEqual } from 'viem';\n\n/**\n * Function that returns the current UNIX time in seconds.\n * Injected for deterministic testing.\n */\nexport type Clock = () => number;\n\n/**\n * Options for constructing a Quoter instance.\n *\n * These options tune how often quote state is maintained and when services are\n * proactively restarted before quote expiry.\n */\nexport interface QuoterOptions {\n /**\n * Dangerously allows quotes where fromAddress and toAddress differ\n * even when a service would otherwise require them to match.\n *\n * This applies to both same-chain and cross-chain quotes.\n *\n * This is intended for explicit proxy-recipient funding flows. By default,\n * services preserve their existing address safety checks.\n */\n readonly dangerouslyAllowAddressMismatch?: boolean;\n /** Clock function returning current time in seconds (defaults to Date.now()/1000). */\n readonly clock?: Clock;\n /** Interval for pruning expired quotes (milliseconds).\n *\n * @default 1_000\n */\n readonly pruneIntervalMs?: number;\n /**\n * Amount of seconds to pre-buffer a stream restart before the earliest service quote\n * expiration. Helps ensure continuity before actual expiry is reached.\n *\n * @default 5\n */\n readonly refreshBufferSeconds?: number;\n}\n\n/**\n * Quoter orchestrates quote streaming across multiple transfer services and emits a unified event stream.\n *\n * High-level lifecycle:\n * - Idle until first subscriber.\n * - On first subscribe, starts all eligible services.\n * - Collects and ranks active quotes, pruning expired ones over time.\n * - Completes when explicitly unsubscribed (last subscriber), when no service is eligible,\n * or when all eligible services finish without producing any quote (`no-quotes`).\n *\n * Event model:\n * - Service `quote` -> Quoter upserts quote, recomputes best quote, emits `quote`.\n * - Service `error` -> Quoter emits `error` (non-terminal by itself).\n * - Service `done` -> Quoter marks that service attempt as completed and evaluates retry/complete rules.\n *\n * Retry/refresh behavior:\n * - Refresh: services that have active quotes are restarted shortly before the earliest quote expires.\n * - Retry: services that complete with no quote and no error are only retried after the quoter has\n * already observed at least one quote from any service in this session.\n *\n * This design keeps first-pass \"no quotes anywhere\" terminal and fast, while still allowing services\n * like Markr to be retried in sessions where other providers are returning quotes.\n */\nexport class Quoter implements QuoterInterface {\n private readonly clock: Clock;\n private readonly props: QuoterProps;\n private readonly pruneIntervalMs: number;\n private readonly serviceQuoteOptions: ServiceQuoteOptions;\n private readonly transferServices: readonly TransferService[];\n private readonly refreshBufferSeconds: number;\n\n private quotes: Quote[] = [];\n private subscribers: Set<QuoterEventHandler> = new Set();\n private started = false;\n private done = false;\n private isStartingFromSubscribe = false;\n private pruneTimerId: ReturnType<typeof setInterval> | null = null;\n private lastBestId: string | null = null;\n private hasReceivedAnyQuote = false;\n\n public readonly id: string = crypto.randomUUID();\n\n /**\n * Per-service runtime state for the active quote session.\n *\n * This tracks whether a service has completed, errored, produced quotes,\n * and any pending timers used for retry/refresh orchestration.\n */\n private serviceState: Map<\n TransferService['type'],\n {\n cancel: () => void;\n done: boolean;\n hasErrored: boolean;\n hasReturnedQuote: boolean;\n retryAttempt: number;\n retryTimer: ReturnType<typeof setTimeout> | null;\n refreshTimer: ReturnType<typeof setTimeout> | null;\n refreshAtSeconds: number | null;\n }\n > = new Map();\n\n /**\n * Create a new Quoter instance.\n *\n * @param props Quoting request parameters shared across all services.\n * @param transferServices Candidate services; eligibility is resolved at `start()` time.\n * @param options Optional runtime tuning for pruning and refresh behavior.\n */\n constructor(props: QuoterProps, transferServices: readonly TransferService[], options: QuoterOptions = {}) {\n this.clock = options.clock ?? (() => Math.floor(Date.now() / 1_000));\n this.props = props;\n this.pruneIntervalMs = options.pruneIntervalMs ?? QUOTER_DEFAULT_PRUNE_INTERVAL_MS;\n this.serviceQuoteOptions = {\n dangerouslyAllowAddressMismatch: options.dangerouslyAllowAddressMismatch,\n };\n this.transferServices = transferServices;\n this.refreshBufferSeconds = options.refreshBufferSeconds ?? QUOTER_DEFAULT_REFRESH_BUFFER_SECONDS;\n }\n\n /**\n * Get the current best quote and all active quotes (sorted by desirability).\n */\n public getQuotes(): QuotesTuple {\n const now = this.clock();\n const active = pruneExpiredQuotes({ quotes: this.quotes, nowSeconds: now });\n const sorted = sortQuotes(active);\n const best = sorted[0] ?? null;\n\n return [best, sorted];\n }\n\n /**\n * Subscribe for quoter events.\n *\n * First subscriber lazily starts orchestration.\n * Last subscriber triggers terminal completion with reason `unsubscribed`.\n *\n * @returns Unsubscribe function (idempotent).\n */\n public subscribe(handler: QuoterEventHandler): () => void {\n this.subscribers.add(handler);\n let unsubscribed = false;\n\n if (!this.started) {\n this.isStartingFromSubscribe = true;\n try {\n this.start();\n } finally {\n this.isStartingFromSubscribe = false;\n }\n }\n\n return () => {\n if (unsubscribed) {\n return;\n }\n unsubscribed = true;\n\n if (this.done) {\n this.subscribers.delete(handler);\n return;\n }\n\n const wasLastSubscriber = this.subscribers.size === 1 && this.subscribers.has(handler);\n if (wasLastSubscriber) {\n this.complete('unsubscribed');\n return;\n }\n\n this.subscribers.delete(handler);\n };\n }\n\n // ----- Internal orchestration -----\n\n /**\n * Start a fresh quote session.\n *\n * Resets session-local state, validates basic request viability,\n * starts streams for eligible services, and begins prune ticks.\n */\n private start(): void {\n this.started = true;\n this.done = false;\n this.quotes = [];\n this.lastBestId = null;\n this.hasReceivedAnyQuote = false;\n\n // Same-chain quotes for the *same* asset are not a valid transfer scenario.\n if (isInvalidSameChainQuoteRequest(this.props)) {\n this.complete('no-eligible-services');\n return;\n }\n\n let hasEligibleService = false;\n\n // Start streams for eligible services\n for (const svc of this.transferServices) {\n const eligible = svc.analyzeSupport({\n sourceAsset: this.props.sourceAsset,\n sourceChainId: this.props.sourceChain.chainId,\n targetAsset: this.props.targetAsset,\n targetChainId: this.props.targetChain.chainId,\n });\n\n if (!eligible) continue;\n hasEligibleService = true;\n\n this.startStreamForService(svc);\n }\n\n if (!hasEligibleService) {\n this.complete('no-eligible-services');\n return;\n }\n\n // Start periodic prune\n this.pruneTimerId = setInterval(() => this.onPruneTick(), this.pruneIntervalMs);\n }\n\n /**\n * Stop all streams and timers.\n * Quotes are retained for snapshot access via getQuotes(), though they\n * can still be pruned due to expiration.\n */\n private stop(): void {\n this.started = false;\n\n if (this.pruneTimerId) {\n clearInterval(this.pruneTimerId);\n this.pruneTimerId = null;\n }\n\n for (const [type, state] of this.serviceState) {\n try {\n state.cancel();\n } catch {\n /* ignore */\n }\n\n if (state.refreshTimer) {\n clearTimeout(state.refreshTimer);\n }\n\n if (state.retryTimer) {\n clearTimeout(state.retryTimer);\n }\n\n this.serviceState.set(type, {\n cancel: () => {},\n done: false,\n hasErrored: false,\n hasReturnedQuote: false,\n retryAttempt: 0,\n retryTimer: null,\n refreshTimer: null,\n refreshAtSeconds: null,\n });\n }\n }\n\n /**\n * Begin or restart streaming for a specific service.\n *\n * Any previous stream/timers for that service are canceled before starting a new attempt.\n */\n private startStreamForService(svc: TransferService): void {\n // Clean up any existing stream and refresh timer\n const existing = this.serviceState.get(svc.type);\n\n if (existing) {\n try {\n existing.cancel();\n } catch {\n /* ignore */\n }\n\n if (existing.refreshTimer) clearTimeout(existing.refreshTimer);\n if (existing.retryTimer) clearTimeout(existing.retryTimer);\n }\n\n const handler = this.makeServiceHandler(svc.type);\n const bufferedEvents: ServiceQuoteEventArgs[] = [];\n let isStartingStream = true;\n\n // Some services emit quote/done synchronously inside streamQuotes().\n // If those events run before subscribe() returns, consumers can hit TDZ\n // when they reference the returned unsubscribe function in their callback.\n // Buffer startup emissions and flush them after stream initialization.\n const guardedHandler: ServiceQuoteEventHandler = (...eventArgs) => {\n if (isStartingStream) {\n bufferedEvents.push(eventArgs);\n return;\n }\n\n handler(...eventArgs);\n };\n\n const { cancel } = svc.streamQuotes(this.props, guardedHandler, this.serviceQuoteOptions);\n isStartingStream = false;\n\n if (bufferedEvents.length > 0) {\n // Use a microtask so subscribe() can return before the first callback fires.\n // This preserves event order while avoiding re-entrancy during subscription.\n queueMicrotask(() => {\n for (const bufferedEvent of bufferedEvents) {\n handler(...bufferedEvent);\n }\n });\n }\n\n this.serviceState.set(svc.type, {\n cancel,\n done: false,\n hasErrored: false,\n hasReturnedQuote: false,\n retryAttempt: existing?.retryAttempt ?? 0,\n retryTimer: null,\n refreshTimer: null,\n refreshAtSeconds: null,\n });\n }\n\n /**\n * Create the service-scoped event handler consumed by `TransferService.streamQuotes`.\n *\n * The handler enforces service/quote consistency and translates service events into\n * quoter state transitions.\n */\n private makeServiceHandler(serviceType: TransferService['type']): ServiceQuoteEventHandler {\n return (event, ...args) => {\n // Ignore any service events once stopped to prevent post-stop mutations.\n if (!this.started) {\n return;\n }\n if (event === 'quote') {\n const maybeQuote = args[0];\n if (isQuoteValue(maybeQuote)) {\n // Enforce the quote belongs to the emitting service\n if (maybeQuote.serviceType !== serviceType) {\n // Ignore quotes mismatched to service; defensive\n return;\n }\n const state = this.serviceState.get(serviceType);\n if (state) {\n state.hasReturnedQuote = true;\n }\n this.onIncomingQuote(maybeQuote);\n this.scheduleServiceRefresh(serviceType);\n }\n\n return;\n }\n if (event === 'done') {\n this.onServiceDone(serviceType);\n\n return;\n }\n if (event === 'error') {\n const state = this.serviceState.get(serviceType);\n if (state) {\n state.hasErrored = true;\n }\n const maybeErr = args[0];\n if (maybeErr instanceof Error) {\n this.emitError(maybeErr);\n }\n }\n };\n }\n\n /**\n * Handle an incoming quote event.\n *\n * Expired quotes are ignored. Valid quotes are upserted into active state,\n * then sorted/pruned and emitted to subscribers.\n */\n private onIncomingQuote(quote: Quote): void {\n const now = this.clock();\n\n if (isQuoteExpired({ quote, nowSeconds: now })) {\n return;\n }\n\n this.hasReceivedAnyQuote = true;\n\n this.resetRetryForService(quote.serviceType);\n\n this.quotes = sortQuotes(pruneExpiredQuotes({ quotes: upsertQuote(this.quotes, quote), nowSeconds: now }));\n\n // Always emit on every incoming quote\n const best = this.quotes[0];\n if (best) {\n this.lastBestId = best.id;\n this.emitQuote({ bestQuote: best, quote, quotes: this.quotes });\n }\n }\n\n private resetRetryForService(serviceType: TransferService['type']): void {\n const state = this.serviceState.get(serviceType);\n\n if (!state) {\n return;\n }\n\n state.retryAttempt = 0;\n if (state.retryTimer) {\n clearTimeout(state.retryTimer);\n state.retryTimer = null;\n }\n }\n\n /**\n * Schedule a retry attempt for a service using exponential backoff.\n *\n * This is used only for quote-less successful completions once the overall session\n * has already produced at least one quote from some service.\n */\n private scheduleServiceRetry(serviceType: TransferService['type']): void {\n const state = this.serviceState.get(serviceType);\n\n if (!state) {\n return;\n }\n\n if (state.retryTimer) {\n clearTimeout(state.retryTimer);\n state.retryTimer = null;\n }\n\n const delayMs = Math.min(\n QUOTER_EMPTY_RETRY_MAX_DELAY_MS,\n QUOTER_EMPTY_RETRY_BASE_DELAY_MS * 2 ** state.retryAttempt,\n );\n state.retryAttempt += 1;\n\n state.retryTimer = setTimeout(\n () => {\n const current = this.serviceState.get(serviceType);\n if (current) {\n current.retryTimer = null;\n }\n\n if (!this.started) {\n return;\n }\n\n const svc = this.transferServices.find((s) => s.type === serviceType);\n if (svc) {\n this.startStreamForService(svc);\n }\n },\n Math.max(0, delayMs),\n );\n }\n\n /**\n * Handle service completion (`done`).\n *\n * A completion may schedule:\n * - refresh (if the service has active quotes), and/or\n * - retry (quote-less/non-error completion, but only after any quote has existed in session).\n *\n * Then evaluates whether the full quoter can complete with `no-quotes`.\n */\n private onServiceDone(serviceType: TransferService['type']): void {\n const state = this.serviceState.get(serviceType);\n\n if (!state) {\n return;\n }\n\n state.done = true;\n this.scheduleServiceRefresh(serviceType);\n\n if (this.hasReceivedAnyQuote && !state.hasErrored && !state.hasReturnedQuote) {\n this.scheduleServiceRetry(serviceType);\n }\n\n this.maybeCompleteNoQuotes();\n }\n\n /**\n * Complete with `no-quotes` when every eligible service has finished and\n * no quote was ever observed during this session.\n */\n private maybeCompleteNoQuotes(): void {\n if (!this.started || this.done || this.hasReceivedAnyQuote || this.serviceState.size === 0) {\n return;\n }\n\n const allServicesDone = [...this.serviceState.values()].every((state) => state.done);\n\n if (allServicesDone) {\n this.complete('no-quotes');\n }\n }\n\n /**\n * Finalize the quoter session and broadcast terminal reason exactly once.\n */\n private complete(reason: QuoterDoneReason): void {\n if (this.done) {\n return;\n }\n\n const payload = this.makeDonePayload(reason);\n\n this.done = true;\n this.stop();\n\n // When complete() happens during subscribe()->start(), emit done on a microtask\n // so callers can safely reference the returned unsubscribe in their handler.\n if (this.isStartingFromSubscribe) {\n queueMicrotask(() => {\n const handlers = [...this.subscribers];\n this.subscribers.clear();\n\n for (const handler of handlers) {\n handler('done', payload);\n }\n });\n return;\n }\n\n const handlers = [...this.subscribers];\n this.subscribers.clear();\n\n for (const handler of handlers) {\n handler('done', payload);\n }\n }\n\n private getInitializedServices(): ServiceType[] {\n return [...new Set(this.transferServices.map((service) => service.type))];\n }\n\n private getEligibleServices(): ServiceType[] {\n return [...this.serviceState.keys()];\n }\n\n private makeDonePayload(reason: QuoterDoneReason): QuoterDonePayload {\n if (reason === 'unsubscribed') {\n return { reason, data: undefined };\n }\n\n const initializedServices = this.getInitializedServices();\n\n if (reason === 'no-eligible-services') {\n return {\n reason,\n data: {\n initializedServices,\n quoterProps: this.props,\n },\n };\n }\n\n return {\n reason,\n data: {\n eligibleServices: this.getEligibleServices(),\n initializedServices,\n quoterProps: this.props,\n },\n };\n }\n\n /** Periodic prune tick to evict expired quotes and emit best changes. */\n private onPruneTick(): void {\n const now = this.clock();\n const pruned = pruneExpiredQuotes({ quotes: this.quotes, nowSeconds: now });\n\n if (pruned.length !== this.quotes.length) {\n this.quotes = sortQuotes(pruned);\n const best = this.quotes[0] ?? null;\n const bestId = best ? best.id : null;\n\n if (best && bestId !== this.lastBestId) {\n this.lastBestId = bestId;\n this.emitQuote({ bestQuote: best, quote: best, quotes: this.quotes });\n } else if (!best) {\n this.lastBestId = null;\n }\n }\n\n // Re-evaluate refresh scheduling for all services on prune tick\n for (const svc of this.transferServices) {\n if (this.serviceState.has(svc.type)) {\n this.scheduleServiceRefresh(svc.type);\n }\n }\n }\n\n /** Schedule a refresh (restart) of streaming for the service at its earliest quote expiration. */\n private scheduleServiceRefresh(serviceType: TransferService['type']): void {\n const state = this.serviceState.get(serviceType);\n\n if (!state) return;\n\n const now = this.clock();\n const earliest = earliestExpirationForService({ quotes: this.quotes, serviceType, nowSeconds: now });\n\n if (earliest === null) {\n // No quotes -> clear any pending refresh\n if (state.refreshTimer) {\n clearTimeout(state.refreshTimer);\n state.refreshTimer = null;\n }\n state.refreshAtSeconds = null;\n return;\n }\n\n // Only reschedule if earlier than currently scheduled or no timer\n const targetAt = Math.max(0, earliest - this.refreshBufferSeconds);\n\n // If target time has already passed, do not schedule another refresh here.\n if (targetAt <= now) {\n return;\n }\n\n // Reschedule only when the desired refresh time changes (earlier OR later).\n // We key refresh off the soonest-expiring active quote for this service.\n if (state.refreshAtSeconds === targetAt && state.refreshTimer) {\n return;\n }\n\n if (state.refreshTimer) {\n clearTimeout(state.refreshTimer);\n }\n\n const delayMs = Math.max(0, (targetAt - now) * 1_000);\n state.refreshAtSeconds = targetAt;\n state.refreshTimer = setTimeout(() => {\n // Clear timer/marker before restarting to avoid stale state if restart fails.\n const current = this.serviceState.get(serviceType);\n if (current) {\n current.refreshTimer = null;\n current.refreshAtSeconds = null;\n }\n\n // Restart stream and clear timer/marker\n const svc = this.transferServices.find((s) => s.type === serviceType);\n\n if (svc) {\n this.startStreamForService(svc);\n }\n }, delayMs);\n }\n\n // ----- Emission helpers -----\n /** Emit a quote event to all subscribers. */\n private emitQuote(payload: { bestQuote: Quote; quote: Quote; quotes: readonly Quote[] }): void {\n for (const handler of this.subscribers) {\n handler('quote', payload);\n }\n }\n\n /** Emit an error event to all subscribers. */\n private emitError(error: Error): void {\n for (const handler of this.subscribers) {\n handler('error', error);\n }\n }\n}\n\n/**\n * Zod schema to validate the minimal Quote fields used for runtime gating.\n *\n * This is a simple schema, and is not a fully safe runtime validate for Quote.\n * That isn't necessary here since we only need to verify basic structure before\n * using the quote in internal logic.\n *\n * @internal\n */\nconst QuoteSchema = z.object({\n id: z.string(),\n expiresAt: z.number().int().nonnegative(),\n amountOut: z.bigint().nonnegative(),\n amountIn: z.bigint().nonnegative(),\n serviceType: z.string(),\n});\n\nfunction isInvalidSameChainQuoteRequest(props: QuoterProps): boolean {\n const { sourceAsset, sourceChain, targetAsset, targetChain } = props;\n\n if (sourceChain.chainId !== targetChain.chainId) {\n return false;\n }\n\n // Native -> native on the same chain is a no-op.\n if (isNativeAsset(sourceAsset) && isNativeAsset(targetAsset)) {\n return true;\n }\n\n // If token types differ, it's potentially a swap on the same chain.\n if (sourceAsset.type !== targetAsset.type) {\n return false;\n }\n\n // Same token type and address on the same chain is a no-op.\n if (sourceAsset.type === TokenType.ERC20 && targetAsset.type === TokenType.ERC20) {\n return isAddressEqual(sourceAsset.address, targetAsset.address);\n }\n\n if (sourceAsset.type === TokenType.SPL && targetAsset.type === TokenType.SPL) {\n return sourceAsset.address === targetAsset.address;\n }\n\n return false;\n}\n\nfunction isQuoteValue(value: unknown): value is Quote {\n const result = QuoteSchema.safeParse(value);\n\n return result.success;\n}\n"],"mappings":"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"}
@@ -12,9 +12,11 @@ type Clock = () => number;
12
12
  */
13
13
  interface QuoterOptions {
14
14
  /**
15
- * Dangerously allows cross-chain quotes where fromAddress and toAddress differ
15
+ * Dangerously allows quotes where fromAddress and toAddress differ
16
16
  * even when a service would otherwise require them to match.
17
17
  *
18
+ * This applies to both same-chain and cross-chain quotes.
19
+ *
18
20
  * This is intended for explicit proxy-recipient funding flows. By default,
19
21
  * services preserve their existing address safety checks.
20
22
  */
@@ -12,9 +12,11 @@ type Clock = () => number;
12
12
  */
13
13
  interface QuoterOptions {
14
14
  /**
15
- * Dangerously allows cross-chain quotes where fromAddress and toAddress differ
15
+ * Dangerously allows quotes where fromAddress and toAddress differ
16
16
  * even when a service would otherwise require them to match.
17
17
  *
18
+ * This applies to both same-chain and cross-chain quotes.
19
+ *
18
20
  * This is intended for explicit proxy-recipient funding flows. By default,
19
21
  * services preserve their existing address safety checks.
20
22
  */
@@ -1 +1 @@
1
- {"version":3,"file":"quoter.js","names":[],"sources":["../../src/quoter/quoter.ts"],"sourcesContent":["import { z } from 'zod';\nimport type {\n Quote,\n QuoterDonePayload,\n QuoterDoneReason,\n QuoterEventHandler,\n QuoterInterface,\n QuoterProps,\n ServiceQuoteEventArgs,\n QuotesTuple,\n ServiceQuoteEventHandler,\n} from '../types/quote';\nimport type { ServiceQuoteOptions, TransferService } from '../types/service';\nimport { earliestExpirationForService, isQuoteExpired, pruneExpiredQuotes, sortQuotes, upsertQuote } from './_utils';\nimport {\n QUOTER_DEFAULT_PRUNE_INTERVAL_MS,\n QUOTER_DEFAULT_REFRESH_BUFFER_SECONDS,\n QUOTER_EMPTY_RETRY_BASE_DELAY_MS,\n QUOTER_EMPTY_RETRY_MAX_DELAY_MS,\n} from './constants';\nimport { ServiceType, TokenType } from '../constants';\nimport { isNativeAsset } from '../type-guards';\nimport { isAddressEqual } from 'viem';\n\n/**\n * Function that returns the current UNIX time in seconds.\n * Injected for deterministic testing.\n */\nexport type Clock = () => number;\n\n/**\n * Options for constructing a Quoter instance.\n *\n * These options tune how often quote state is maintained and when services are\n * proactively restarted before quote expiry.\n */\nexport interface QuoterOptions {\n /**\n * Dangerously allows cross-chain quotes where fromAddress and toAddress differ\n * even when a service would otherwise require them to match.\n *\n * This is intended for explicit proxy-recipient funding flows. By default,\n * services preserve their existing address safety checks.\n */\n readonly dangerouslyAllowAddressMismatch?: boolean;\n /** Clock function returning current time in seconds (defaults to Date.now()/1000). */\n readonly clock?: Clock;\n /** Interval for pruning expired quotes (milliseconds).\n *\n * @default 1_000\n */\n readonly pruneIntervalMs?: number;\n /**\n * Amount of seconds to pre-buffer a stream restart before the earliest service quote\n * expiration. Helps ensure continuity before actual expiry is reached.\n *\n * @default 5\n */\n readonly refreshBufferSeconds?: number;\n}\n\n/**\n * Quoter orchestrates quote streaming across multiple transfer services and emits a unified event stream.\n *\n * High-level lifecycle:\n * - Idle until first subscriber.\n * - On first subscribe, starts all eligible services.\n * - Collects and ranks active quotes, pruning expired ones over time.\n * - Completes when explicitly unsubscribed (last subscriber), when no service is eligible,\n * or when all eligible services finish without producing any quote (`no-quotes`).\n *\n * Event model:\n * - Service `quote` -> Quoter upserts quote, recomputes best quote, emits `quote`.\n * - Service `error` -> Quoter emits `error` (non-terminal by itself).\n * - Service `done` -> Quoter marks that service attempt as completed and evaluates retry/complete rules.\n *\n * Retry/refresh behavior:\n * - Refresh: services that have active quotes are restarted shortly before the earliest quote expires.\n * - Retry: services that complete with no quote and no error are only retried after the quoter has\n * already observed at least one quote from any service in this session.\n *\n * This design keeps first-pass \"no quotes anywhere\" terminal and fast, while still allowing services\n * like Markr to be retried in sessions where other providers are returning quotes.\n */\nexport class Quoter implements QuoterInterface {\n private readonly clock: Clock;\n private readonly props: QuoterProps;\n private readonly pruneIntervalMs: number;\n private readonly serviceQuoteOptions: ServiceQuoteOptions;\n private readonly transferServices: readonly TransferService[];\n private readonly refreshBufferSeconds: number;\n\n private quotes: Quote[] = [];\n private subscribers: Set<QuoterEventHandler> = new Set();\n private started = false;\n private done = false;\n private isStartingFromSubscribe = false;\n private pruneTimerId: ReturnType<typeof setInterval> | null = null;\n private lastBestId: string | null = null;\n private hasReceivedAnyQuote = false;\n\n public readonly id: string = crypto.randomUUID();\n\n /**\n * Per-service runtime state for the active quote session.\n *\n * This tracks whether a service has completed, errored, produced quotes,\n * and any pending timers used for retry/refresh orchestration.\n */\n private serviceState: Map<\n TransferService['type'],\n {\n cancel: () => void;\n done: boolean;\n hasErrored: boolean;\n hasReturnedQuote: boolean;\n retryAttempt: number;\n retryTimer: ReturnType<typeof setTimeout> | null;\n refreshTimer: ReturnType<typeof setTimeout> | null;\n refreshAtSeconds: number | null;\n }\n > = new Map();\n\n /**\n * Create a new Quoter instance.\n *\n * @param props Quoting request parameters shared across all services.\n * @param transferServices Candidate services; eligibility is resolved at `start()` time.\n * @param options Optional runtime tuning for pruning and refresh behavior.\n */\n constructor(props: QuoterProps, transferServices: readonly TransferService[], options: QuoterOptions = {}) {\n this.clock = options.clock ?? (() => Math.floor(Date.now() / 1_000));\n this.props = props;\n this.pruneIntervalMs = options.pruneIntervalMs ?? QUOTER_DEFAULT_PRUNE_INTERVAL_MS;\n this.serviceQuoteOptions = {\n dangerouslyAllowAddressMismatch: options.dangerouslyAllowAddressMismatch,\n };\n this.transferServices = transferServices;\n this.refreshBufferSeconds = options.refreshBufferSeconds ?? QUOTER_DEFAULT_REFRESH_BUFFER_SECONDS;\n }\n\n /**\n * Get the current best quote and all active quotes (sorted by desirability).\n */\n public getQuotes(): QuotesTuple {\n const now = this.clock();\n const active = pruneExpiredQuotes({ quotes: this.quotes, nowSeconds: now });\n const sorted = sortQuotes(active);\n const best = sorted[0] ?? null;\n\n return [best, sorted];\n }\n\n /**\n * Subscribe for quoter events.\n *\n * First subscriber lazily starts orchestration.\n * Last subscriber triggers terminal completion with reason `unsubscribed`.\n *\n * @returns Unsubscribe function (idempotent).\n */\n public subscribe(handler: QuoterEventHandler): () => void {\n this.subscribers.add(handler);\n let unsubscribed = false;\n\n if (!this.started) {\n this.isStartingFromSubscribe = true;\n try {\n this.start();\n } finally {\n this.isStartingFromSubscribe = false;\n }\n }\n\n return () => {\n if (unsubscribed) {\n return;\n }\n unsubscribed = true;\n\n if (this.done) {\n this.subscribers.delete(handler);\n return;\n }\n\n const wasLastSubscriber = this.subscribers.size === 1 && this.subscribers.has(handler);\n if (wasLastSubscriber) {\n this.complete('unsubscribed');\n return;\n }\n\n this.subscribers.delete(handler);\n };\n }\n\n // ----- Internal orchestration -----\n\n /**\n * Start a fresh quote session.\n *\n * Resets session-local state, validates basic request viability,\n * starts streams for eligible services, and begins prune ticks.\n */\n private start(): void {\n this.started = true;\n this.done = false;\n this.quotes = [];\n this.lastBestId = null;\n this.hasReceivedAnyQuote = false;\n\n // Same-chain quotes for the *same* asset are not a valid transfer scenario.\n if (isInvalidSameChainQuoteRequest(this.props)) {\n this.complete('no-eligible-services');\n return;\n }\n\n let hasEligibleService = false;\n\n // Start streams for eligible services\n for (const svc of this.transferServices) {\n const eligible = svc.analyzeSupport({\n sourceAsset: this.props.sourceAsset,\n sourceChainId: this.props.sourceChain.chainId,\n targetAsset: this.props.targetAsset,\n targetChainId: this.props.targetChain.chainId,\n });\n\n if (!eligible) continue;\n hasEligibleService = true;\n\n this.startStreamForService(svc);\n }\n\n if (!hasEligibleService) {\n this.complete('no-eligible-services');\n return;\n }\n\n // Start periodic prune\n this.pruneTimerId = setInterval(() => this.onPruneTick(), this.pruneIntervalMs);\n }\n\n /**\n * Stop all streams and timers.\n * Quotes are retained for snapshot access via getQuotes(), though they\n * can still be pruned due to expiration.\n */\n private stop(): void {\n this.started = false;\n\n if (this.pruneTimerId) {\n clearInterval(this.pruneTimerId);\n this.pruneTimerId = null;\n }\n\n for (const [type, state] of this.serviceState) {\n try {\n state.cancel();\n } catch {\n /* ignore */\n }\n\n if (state.refreshTimer) {\n clearTimeout(state.refreshTimer);\n }\n\n if (state.retryTimer) {\n clearTimeout(state.retryTimer);\n }\n\n this.serviceState.set(type, {\n cancel: () => {},\n done: false,\n hasErrored: false,\n hasReturnedQuote: false,\n retryAttempt: 0,\n retryTimer: null,\n refreshTimer: null,\n refreshAtSeconds: null,\n });\n }\n }\n\n /**\n * Begin or restart streaming for a specific service.\n *\n * Any previous stream/timers for that service are canceled before starting a new attempt.\n */\n private startStreamForService(svc: TransferService): void {\n // Clean up any existing stream and refresh timer\n const existing = this.serviceState.get(svc.type);\n\n if (existing) {\n try {\n existing.cancel();\n } catch {\n /* ignore */\n }\n\n if (existing.refreshTimer) clearTimeout(existing.refreshTimer);\n if (existing.retryTimer) clearTimeout(existing.retryTimer);\n }\n\n const handler = this.makeServiceHandler(svc.type);\n const bufferedEvents: ServiceQuoteEventArgs[] = [];\n let isStartingStream = true;\n\n // Some services emit quote/done synchronously inside streamQuotes().\n // If those events run before subscribe() returns, consumers can hit TDZ\n // when they reference the returned unsubscribe function in their callback.\n // Buffer startup emissions and flush them after stream initialization.\n const guardedHandler: ServiceQuoteEventHandler = (...eventArgs) => {\n if (isStartingStream) {\n bufferedEvents.push(eventArgs);\n return;\n }\n\n handler(...eventArgs);\n };\n\n const { cancel } = svc.streamQuotes(this.props, guardedHandler, this.serviceQuoteOptions);\n isStartingStream = false;\n\n if (bufferedEvents.length > 0) {\n // Use a microtask so subscribe() can return before the first callback fires.\n // This preserves event order while avoiding re-entrancy during subscription.\n queueMicrotask(() => {\n for (const bufferedEvent of bufferedEvents) {\n handler(...bufferedEvent);\n }\n });\n }\n\n this.serviceState.set(svc.type, {\n cancel,\n done: false,\n hasErrored: false,\n hasReturnedQuote: false,\n retryAttempt: existing?.retryAttempt ?? 0,\n retryTimer: null,\n refreshTimer: null,\n refreshAtSeconds: null,\n });\n }\n\n /**\n * Create the service-scoped event handler consumed by `TransferService.streamQuotes`.\n *\n * The handler enforces service/quote consistency and translates service events into\n * quoter state transitions.\n */\n private makeServiceHandler(serviceType: TransferService['type']): ServiceQuoteEventHandler {\n return (event, ...args) => {\n // Ignore any service events once stopped to prevent post-stop mutations.\n if (!this.started) {\n return;\n }\n if (event === 'quote') {\n const maybeQuote = args[0];\n if (isQuoteValue(maybeQuote)) {\n // Enforce the quote belongs to the emitting service\n if (maybeQuote.serviceType !== serviceType) {\n // Ignore quotes mismatched to service; defensive\n return;\n }\n const state = this.serviceState.get(serviceType);\n if (state) {\n state.hasReturnedQuote = true;\n }\n this.onIncomingQuote(maybeQuote);\n this.scheduleServiceRefresh(serviceType);\n }\n\n return;\n }\n if (event === 'done') {\n this.onServiceDone(serviceType);\n\n return;\n }\n if (event === 'error') {\n const state = this.serviceState.get(serviceType);\n if (state) {\n state.hasErrored = true;\n }\n const maybeErr = args[0];\n if (maybeErr instanceof Error) {\n this.emitError(maybeErr);\n }\n }\n };\n }\n\n /**\n * Handle an incoming quote event.\n *\n * Expired quotes are ignored. Valid quotes are upserted into active state,\n * then sorted/pruned and emitted to subscribers.\n */\n private onIncomingQuote(quote: Quote): void {\n const now = this.clock();\n\n if (isQuoteExpired({ quote, nowSeconds: now })) {\n return;\n }\n\n this.hasReceivedAnyQuote = true;\n\n this.resetRetryForService(quote.serviceType);\n\n this.quotes = sortQuotes(pruneExpiredQuotes({ quotes: upsertQuote(this.quotes, quote), nowSeconds: now }));\n\n // Always emit on every incoming quote\n const best = this.quotes[0];\n if (best) {\n this.lastBestId = best.id;\n this.emitQuote({ bestQuote: best, quote, quotes: this.quotes });\n }\n }\n\n private resetRetryForService(serviceType: TransferService['type']): void {\n const state = this.serviceState.get(serviceType);\n\n if (!state) {\n return;\n }\n\n state.retryAttempt = 0;\n if (state.retryTimer) {\n clearTimeout(state.retryTimer);\n state.retryTimer = null;\n }\n }\n\n /**\n * Schedule a retry attempt for a service using exponential backoff.\n *\n * This is used only for quote-less successful completions once the overall session\n * has already produced at least one quote from some service.\n */\n private scheduleServiceRetry(serviceType: TransferService['type']): void {\n const state = this.serviceState.get(serviceType);\n\n if (!state) {\n return;\n }\n\n if (state.retryTimer) {\n clearTimeout(state.retryTimer);\n state.retryTimer = null;\n }\n\n const delayMs = Math.min(\n QUOTER_EMPTY_RETRY_MAX_DELAY_MS,\n QUOTER_EMPTY_RETRY_BASE_DELAY_MS * 2 ** state.retryAttempt,\n );\n state.retryAttempt += 1;\n\n state.retryTimer = setTimeout(\n () => {\n const current = this.serviceState.get(serviceType);\n if (current) {\n current.retryTimer = null;\n }\n\n if (!this.started) {\n return;\n }\n\n const svc = this.transferServices.find((s) => s.type === serviceType);\n if (svc) {\n this.startStreamForService(svc);\n }\n },\n Math.max(0, delayMs),\n );\n }\n\n /**\n * Handle service completion (`done`).\n *\n * A completion may schedule:\n * - refresh (if the service has active quotes), and/or\n * - retry (quote-less/non-error completion, but only after any quote has existed in session).\n *\n * Then evaluates whether the full quoter can complete with `no-quotes`.\n */\n private onServiceDone(serviceType: TransferService['type']): void {\n const state = this.serviceState.get(serviceType);\n\n if (!state) {\n return;\n }\n\n state.done = true;\n this.scheduleServiceRefresh(serviceType);\n\n if (this.hasReceivedAnyQuote && !state.hasErrored && !state.hasReturnedQuote) {\n this.scheduleServiceRetry(serviceType);\n }\n\n this.maybeCompleteNoQuotes();\n }\n\n /**\n * Complete with `no-quotes` when every eligible service has finished and\n * no quote was ever observed during this session.\n */\n private maybeCompleteNoQuotes(): void {\n if (!this.started || this.done || this.hasReceivedAnyQuote || this.serviceState.size === 0) {\n return;\n }\n\n const allServicesDone = [...this.serviceState.values()].every((state) => state.done);\n\n if (allServicesDone) {\n this.complete('no-quotes');\n }\n }\n\n /**\n * Finalize the quoter session and broadcast terminal reason exactly once.\n */\n private complete(reason: QuoterDoneReason): void {\n if (this.done) {\n return;\n }\n\n const payload = this.makeDonePayload(reason);\n\n this.done = true;\n this.stop();\n\n // When complete() happens during subscribe()->start(), emit done on a microtask\n // so callers can safely reference the returned unsubscribe in their handler.\n if (this.isStartingFromSubscribe) {\n queueMicrotask(() => {\n const handlers = [...this.subscribers];\n this.subscribers.clear();\n\n for (const handler of handlers) {\n handler('done', payload);\n }\n });\n return;\n }\n\n const handlers = [...this.subscribers];\n this.subscribers.clear();\n\n for (const handler of handlers) {\n handler('done', payload);\n }\n }\n\n private getInitializedServices(): ServiceType[] {\n return [...new Set(this.transferServices.map((service) => service.type))];\n }\n\n private getEligibleServices(): ServiceType[] {\n return [...this.serviceState.keys()];\n }\n\n private makeDonePayload(reason: QuoterDoneReason): QuoterDonePayload {\n if (reason === 'unsubscribed') {\n return { reason, data: undefined };\n }\n\n const initializedServices = this.getInitializedServices();\n\n if (reason === 'no-eligible-services') {\n return {\n reason,\n data: {\n initializedServices,\n quoterProps: this.props,\n },\n };\n }\n\n return {\n reason,\n data: {\n eligibleServices: this.getEligibleServices(),\n initializedServices,\n quoterProps: this.props,\n },\n };\n }\n\n /** Periodic prune tick to evict expired quotes and emit best changes. */\n private onPruneTick(): void {\n const now = this.clock();\n const pruned = pruneExpiredQuotes({ quotes: this.quotes, nowSeconds: now });\n\n if (pruned.length !== this.quotes.length) {\n this.quotes = sortQuotes(pruned);\n const best = this.quotes[0] ?? null;\n const bestId = best ? best.id : null;\n\n if (best && bestId !== this.lastBestId) {\n this.lastBestId = bestId;\n this.emitQuote({ bestQuote: best, quote: best, quotes: this.quotes });\n } else if (!best) {\n this.lastBestId = null;\n }\n }\n\n // Re-evaluate refresh scheduling for all services on prune tick\n for (const svc of this.transferServices) {\n if (this.serviceState.has(svc.type)) {\n this.scheduleServiceRefresh(svc.type);\n }\n }\n }\n\n /** Schedule a refresh (restart) of streaming for the service at its earliest quote expiration. */\n private scheduleServiceRefresh(serviceType: TransferService['type']): void {\n const state = this.serviceState.get(serviceType);\n\n if (!state) return;\n\n const now = this.clock();\n const earliest = earliestExpirationForService({ quotes: this.quotes, serviceType, nowSeconds: now });\n\n if (earliest === null) {\n // No quotes -> clear any pending refresh\n if (state.refreshTimer) {\n clearTimeout(state.refreshTimer);\n state.refreshTimer = null;\n }\n state.refreshAtSeconds = null;\n return;\n }\n\n // Only reschedule if earlier than currently scheduled or no timer\n const targetAt = Math.max(0, earliest - this.refreshBufferSeconds);\n\n // If target time has already passed, do not schedule another refresh here.\n if (targetAt <= now) {\n return;\n }\n\n // Reschedule only when the desired refresh time changes (earlier OR later).\n // We key refresh off the soonest-expiring active quote for this service.\n if (state.refreshAtSeconds === targetAt && state.refreshTimer) {\n return;\n }\n\n if (state.refreshTimer) {\n clearTimeout(state.refreshTimer);\n }\n\n const delayMs = Math.max(0, (targetAt - now) * 1_000);\n state.refreshAtSeconds = targetAt;\n state.refreshTimer = setTimeout(() => {\n // Clear timer/marker before restarting to avoid stale state if restart fails.\n const current = this.serviceState.get(serviceType);\n if (current) {\n current.refreshTimer = null;\n current.refreshAtSeconds = null;\n }\n\n // Restart stream and clear timer/marker\n const svc = this.transferServices.find((s) => s.type === serviceType);\n\n if (svc) {\n this.startStreamForService(svc);\n }\n }, delayMs);\n }\n\n // ----- Emission helpers -----\n /** Emit a quote event to all subscribers. */\n private emitQuote(payload: { bestQuote: Quote; quote: Quote; quotes: readonly Quote[] }): void {\n for (const handler of this.subscribers) {\n handler('quote', payload);\n }\n }\n\n /** Emit an error event to all subscribers. */\n private emitError(error: Error): void {\n for (const handler of this.subscribers) {\n handler('error', error);\n }\n }\n}\n\n/**\n * Zod schema to validate the minimal Quote fields used for runtime gating.\n *\n * This is a simple schema, and is not a fully safe runtime validate for Quote.\n * That isn't necessary here since we only need to verify basic structure before\n * using the quote in internal logic.\n *\n * @internal\n */\nconst QuoteSchema = z.object({\n id: z.string(),\n expiresAt: z.number().int().nonnegative(),\n amountOut: z.bigint().nonnegative(),\n amountIn: z.bigint().nonnegative(),\n serviceType: z.string(),\n});\n\nfunction isInvalidSameChainQuoteRequest(props: QuoterProps): boolean {\n const { sourceAsset, sourceChain, targetAsset, targetChain } = props;\n\n if (sourceChain.chainId !== targetChain.chainId) {\n return false;\n }\n\n // Native -> native on the same chain is a no-op.\n if (isNativeAsset(sourceAsset) && isNativeAsset(targetAsset)) {\n return true;\n }\n\n // If token types differ, it's potentially a swap on the same chain.\n if (sourceAsset.type !== targetAsset.type) {\n return false;\n }\n\n // Same token type and address on the same chain is a no-op.\n if (sourceAsset.type === TokenType.ERC20 && targetAsset.type === TokenType.ERC20) {\n return isAddressEqual(sourceAsset.address, targetAsset.address);\n }\n\n if (sourceAsset.type === TokenType.SPL && targetAsset.type === TokenType.SPL) {\n return sourceAsset.address === targetAsset.address;\n }\n\n return false;\n}\n\nfunction isQuoteValue(value: unknown): value is Quote {\n const result = QuoteSchema.safeParse(value);\n\n return result.success;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"quoter.js","names":[],"sources":["../../src/quoter/quoter.ts"],"sourcesContent":["import { z } from 'zod';\nimport type {\n Quote,\n QuoterDonePayload,\n QuoterDoneReason,\n QuoterEventHandler,\n QuoterInterface,\n QuoterProps,\n ServiceQuoteEventArgs,\n QuotesTuple,\n ServiceQuoteEventHandler,\n} from '../types/quote';\nimport type { ServiceQuoteOptions, TransferService } from '../types/service';\nimport { earliestExpirationForService, isQuoteExpired, pruneExpiredQuotes, sortQuotes, upsertQuote } from './_utils';\nimport {\n QUOTER_DEFAULT_PRUNE_INTERVAL_MS,\n QUOTER_DEFAULT_REFRESH_BUFFER_SECONDS,\n QUOTER_EMPTY_RETRY_BASE_DELAY_MS,\n QUOTER_EMPTY_RETRY_MAX_DELAY_MS,\n} from './constants';\nimport { ServiceType, TokenType } from '../constants';\nimport { isNativeAsset } from '../type-guards';\nimport { isAddressEqual } from 'viem';\n\n/**\n * Function that returns the current UNIX time in seconds.\n * Injected for deterministic testing.\n */\nexport type Clock = () => number;\n\n/**\n * Options for constructing a Quoter instance.\n *\n * These options tune how often quote state is maintained and when services are\n * proactively restarted before quote expiry.\n */\nexport interface QuoterOptions {\n /**\n * Dangerously allows quotes where fromAddress and toAddress differ\n * even when a service would otherwise require them to match.\n *\n * This applies to both same-chain and cross-chain quotes.\n *\n * This is intended for explicit proxy-recipient funding flows. By default,\n * services preserve their existing address safety checks.\n */\n readonly dangerouslyAllowAddressMismatch?: boolean;\n /** Clock function returning current time in seconds (defaults to Date.now()/1000). */\n readonly clock?: Clock;\n /** Interval for pruning expired quotes (milliseconds).\n *\n * @default 1_000\n */\n readonly pruneIntervalMs?: number;\n /**\n * Amount of seconds to pre-buffer a stream restart before the earliest service quote\n * expiration. Helps ensure continuity before actual expiry is reached.\n *\n * @default 5\n */\n readonly refreshBufferSeconds?: number;\n}\n\n/**\n * Quoter orchestrates quote streaming across multiple transfer services and emits a unified event stream.\n *\n * High-level lifecycle:\n * - Idle until first subscriber.\n * - On first subscribe, starts all eligible services.\n * - Collects and ranks active quotes, pruning expired ones over time.\n * - Completes when explicitly unsubscribed (last subscriber), when no service is eligible,\n * or when all eligible services finish without producing any quote (`no-quotes`).\n *\n * Event model:\n * - Service `quote` -> Quoter upserts quote, recomputes best quote, emits `quote`.\n * - Service `error` -> Quoter emits `error` (non-terminal by itself).\n * - Service `done` -> Quoter marks that service attempt as completed and evaluates retry/complete rules.\n *\n * Retry/refresh behavior:\n * - Refresh: services that have active quotes are restarted shortly before the earliest quote expires.\n * - Retry: services that complete with no quote and no error are only retried after the quoter has\n * already observed at least one quote from any service in this session.\n *\n * This design keeps first-pass \"no quotes anywhere\" terminal and fast, while still allowing services\n * like Markr to be retried in sessions where other providers are returning quotes.\n */\nexport class Quoter implements QuoterInterface {\n private readonly clock: Clock;\n private readonly props: QuoterProps;\n private readonly pruneIntervalMs: number;\n private readonly serviceQuoteOptions: ServiceQuoteOptions;\n private readonly transferServices: readonly TransferService[];\n private readonly refreshBufferSeconds: number;\n\n private quotes: Quote[] = [];\n private subscribers: Set<QuoterEventHandler> = new Set();\n private started = false;\n private done = false;\n private isStartingFromSubscribe = false;\n private pruneTimerId: ReturnType<typeof setInterval> | null = null;\n private lastBestId: string | null = null;\n private hasReceivedAnyQuote = false;\n\n public readonly id: string = crypto.randomUUID();\n\n /**\n * Per-service runtime state for the active quote session.\n *\n * This tracks whether a service has completed, errored, produced quotes,\n * and any pending timers used for retry/refresh orchestration.\n */\n private serviceState: Map<\n TransferService['type'],\n {\n cancel: () => void;\n done: boolean;\n hasErrored: boolean;\n hasReturnedQuote: boolean;\n retryAttempt: number;\n retryTimer: ReturnType<typeof setTimeout> | null;\n refreshTimer: ReturnType<typeof setTimeout> | null;\n refreshAtSeconds: number | null;\n }\n > = new Map();\n\n /**\n * Create a new Quoter instance.\n *\n * @param props Quoting request parameters shared across all services.\n * @param transferServices Candidate services; eligibility is resolved at `start()` time.\n * @param options Optional runtime tuning for pruning and refresh behavior.\n */\n constructor(props: QuoterProps, transferServices: readonly TransferService[], options: QuoterOptions = {}) {\n this.clock = options.clock ?? (() => Math.floor(Date.now() / 1_000));\n this.props = props;\n this.pruneIntervalMs = options.pruneIntervalMs ?? QUOTER_DEFAULT_PRUNE_INTERVAL_MS;\n this.serviceQuoteOptions = {\n dangerouslyAllowAddressMismatch: options.dangerouslyAllowAddressMismatch,\n };\n this.transferServices = transferServices;\n this.refreshBufferSeconds = options.refreshBufferSeconds ?? QUOTER_DEFAULT_REFRESH_BUFFER_SECONDS;\n }\n\n /**\n * Get the current best quote and all active quotes (sorted by desirability).\n */\n public getQuotes(): QuotesTuple {\n const now = this.clock();\n const active = pruneExpiredQuotes({ quotes: this.quotes, nowSeconds: now });\n const sorted = sortQuotes(active);\n const best = sorted[0] ?? null;\n\n return [best, sorted];\n }\n\n /**\n * Subscribe for quoter events.\n *\n * First subscriber lazily starts orchestration.\n * Last subscriber triggers terminal completion with reason `unsubscribed`.\n *\n * @returns Unsubscribe function (idempotent).\n */\n public subscribe(handler: QuoterEventHandler): () => void {\n this.subscribers.add(handler);\n let unsubscribed = false;\n\n if (!this.started) {\n this.isStartingFromSubscribe = true;\n try {\n this.start();\n } finally {\n this.isStartingFromSubscribe = false;\n }\n }\n\n return () => {\n if (unsubscribed) {\n return;\n }\n unsubscribed = true;\n\n if (this.done) {\n this.subscribers.delete(handler);\n return;\n }\n\n const wasLastSubscriber = this.subscribers.size === 1 && this.subscribers.has(handler);\n if (wasLastSubscriber) {\n this.complete('unsubscribed');\n return;\n }\n\n this.subscribers.delete(handler);\n };\n }\n\n // ----- Internal orchestration -----\n\n /**\n * Start a fresh quote session.\n *\n * Resets session-local state, validates basic request viability,\n * starts streams for eligible services, and begins prune ticks.\n */\n private start(): void {\n this.started = true;\n this.done = false;\n this.quotes = [];\n this.lastBestId = null;\n this.hasReceivedAnyQuote = false;\n\n // Same-chain quotes for the *same* asset are not a valid transfer scenario.\n if (isInvalidSameChainQuoteRequest(this.props)) {\n this.complete('no-eligible-services');\n return;\n }\n\n let hasEligibleService = false;\n\n // Start streams for eligible services\n for (const svc of this.transferServices) {\n const eligible = svc.analyzeSupport({\n sourceAsset: this.props.sourceAsset,\n sourceChainId: this.props.sourceChain.chainId,\n targetAsset: this.props.targetAsset,\n targetChainId: this.props.targetChain.chainId,\n });\n\n if (!eligible) continue;\n hasEligibleService = true;\n\n this.startStreamForService(svc);\n }\n\n if (!hasEligibleService) {\n this.complete('no-eligible-services');\n return;\n }\n\n // Start periodic prune\n this.pruneTimerId = setInterval(() => this.onPruneTick(), this.pruneIntervalMs);\n }\n\n /**\n * Stop all streams and timers.\n * Quotes are retained for snapshot access via getQuotes(), though they\n * can still be pruned due to expiration.\n */\n private stop(): void {\n this.started = false;\n\n if (this.pruneTimerId) {\n clearInterval(this.pruneTimerId);\n this.pruneTimerId = null;\n }\n\n for (const [type, state] of this.serviceState) {\n try {\n state.cancel();\n } catch {\n /* ignore */\n }\n\n if (state.refreshTimer) {\n clearTimeout(state.refreshTimer);\n }\n\n if (state.retryTimer) {\n clearTimeout(state.retryTimer);\n }\n\n this.serviceState.set(type, {\n cancel: () => {},\n done: false,\n hasErrored: false,\n hasReturnedQuote: false,\n retryAttempt: 0,\n retryTimer: null,\n refreshTimer: null,\n refreshAtSeconds: null,\n });\n }\n }\n\n /**\n * Begin or restart streaming for a specific service.\n *\n * Any previous stream/timers for that service are canceled before starting a new attempt.\n */\n private startStreamForService(svc: TransferService): void {\n // Clean up any existing stream and refresh timer\n const existing = this.serviceState.get(svc.type);\n\n if (existing) {\n try {\n existing.cancel();\n } catch {\n /* ignore */\n }\n\n if (existing.refreshTimer) clearTimeout(existing.refreshTimer);\n if (existing.retryTimer) clearTimeout(existing.retryTimer);\n }\n\n const handler = this.makeServiceHandler(svc.type);\n const bufferedEvents: ServiceQuoteEventArgs[] = [];\n let isStartingStream = true;\n\n // Some services emit quote/done synchronously inside streamQuotes().\n // If those events run before subscribe() returns, consumers can hit TDZ\n // when they reference the returned unsubscribe function in their callback.\n // Buffer startup emissions and flush them after stream initialization.\n const guardedHandler: ServiceQuoteEventHandler = (...eventArgs) => {\n if (isStartingStream) {\n bufferedEvents.push(eventArgs);\n return;\n }\n\n handler(...eventArgs);\n };\n\n const { cancel } = svc.streamQuotes(this.props, guardedHandler, this.serviceQuoteOptions);\n isStartingStream = false;\n\n if (bufferedEvents.length > 0) {\n // Use a microtask so subscribe() can return before the first callback fires.\n // This preserves event order while avoiding re-entrancy during subscription.\n queueMicrotask(() => {\n for (const bufferedEvent of bufferedEvents) {\n handler(...bufferedEvent);\n }\n });\n }\n\n this.serviceState.set(svc.type, {\n cancel,\n done: false,\n hasErrored: false,\n hasReturnedQuote: false,\n retryAttempt: existing?.retryAttempt ?? 0,\n retryTimer: null,\n refreshTimer: null,\n refreshAtSeconds: null,\n });\n }\n\n /**\n * Create the service-scoped event handler consumed by `TransferService.streamQuotes`.\n *\n * The handler enforces service/quote consistency and translates service events into\n * quoter state transitions.\n */\n private makeServiceHandler(serviceType: TransferService['type']): ServiceQuoteEventHandler {\n return (event, ...args) => {\n // Ignore any service events once stopped to prevent post-stop mutations.\n if (!this.started) {\n return;\n }\n if (event === 'quote') {\n const maybeQuote = args[0];\n if (isQuoteValue(maybeQuote)) {\n // Enforce the quote belongs to the emitting service\n if (maybeQuote.serviceType !== serviceType) {\n // Ignore quotes mismatched to service; defensive\n return;\n }\n const state = this.serviceState.get(serviceType);\n if (state) {\n state.hasReturnedQuote = true;\n }\n this.onIncomingQuote(maybeQuote);\n this.scheduleServiceRefresh(serviceType);\n }\n\n return;\n }\n if (event === 'done') {\n this.onServiceDone(serviceType);\n\n return;\n }\n if (event === 'error') {\n const state = this.serviceState.get(serviceType);\n if (state) {\n state.hasErrored = true;\n }\n const maybeErr = args[0];\n if (maybeErr instanceof Error) {\n this.emitError(maybeErr);\n }\n }\n };\n }\n\n /**\n * Handle an incoming quote event.\n *\n * Expired quotes are ignored. Valid quotes are upserted into active state,\n * then sorted/pruned and emitted to subscribers.\n */\n private onIncomingQuote(quote: Quote): void {\n const now = this.clock();\n\n if (isQuoteExpired({ quote, nowSeconds: now })) {\n return;\n }\n\n this.hasReceivedAnyQuote = true;\n\n this.resetRetryForService(quote.serviceType);\n\n this.quotes = sortQuotes(pruneExpiredQuotes({ quotes: upsertQuote(this.quotes, quote), nowSeconds: now }));\n\n // Always emit on every incoming quote\n const best = this.quotes[0];\n if (best) {\n this.lastBestId = best.id;\n this.emitQuote({ bestQuote: best, quote, quotes: this.quotes });\n }\n }\n\n private resetRetryForService(serviceType: TransferService['type']): void {\n const state = this.serviceState.get(serviceType);\n\n if (!state) {\n return;\n }\n\n state.retryAttempt = 0;\n if (state.retryTimer) {\n clearTimeout(state.retryTimer);\n state.retryTimer = null;\n }\n }\n\n /**\n * Schedule a retry attempt for a service using exponential backoff.\n *\n * This is used only for quote-less successful completions once the overall session\n * has already produced at least one quote from some service.\n */\n private scheduleServiceRetry(serviceType: TransferService['type']): void {\n const state = this.serviceState.get(serviceType);\n\n if (!state) {\n return;\n }\n\n if (state.retryTimer) {\n clearTimeout(state.retryTimer);\n state.retryTimer = null;\n }\n\n const delayMs = Math.min(\n QUOTER_EMPTY_RETRY_MAX_DELAY_MS,\n QUOTER_EMPTY_RETRY_BASE_DELAY_MS * 2 ** state.retryAttempt,\n );\n state.retryAttempt += 1;\n\n state.retryTimer = setTimeout(\n () => {\n const current = this.serviceState.get(serviceType);\n if (current) {\n current.retryTimer = null;\n }\n\n if (!this.started) {\n return;\n }\n\n const svc = this.transferServices.find((s) => s.type === serviceType);\n if (svc) {\n this.startStreamForService(svc);\n }\n },\n Math.max(0, delayMs),\n );\n }\n\n /**\n * Handle service completion (`done`).\n *\n * A completion may schedule:\n * - refresh (if the service has active quotes), and/or\n * - retry (quote-less/non-error completion, but only after any quote has existed in session).\n *\n * Then evaluates whether the full quoter can complete with `no-quotes`.\n */\n private onServiceDone(serviceType: TransferService['type']): void {\n const state = this.serviceState.get(serviceType);\n\n if (!state) {\n return;\n }\n\n state.done = true;\n this.scheduleServiceRefresh(serviceType);\n\n if (this.hasReceivedAnyQuote && !state.hasErrored && !state.hasReturnedQuote) {\n this.scheduleServiceRetry(serviceType);\n }\n\n this.maybeCompleteNoQuotes();\n }\n\n /**\n * Complete with `no-quotes` when every eligible service has finished and\n * no quote was ever observed during this session.\n */\n private maybeCompleteNoQuotes(): void {\n if (!this.started || this.done || this.hasReceivedAnyQuote || this.serviceState.size === 0) {\n return;\n }\n\n const allServicesDone = [...this.serviceState.values()].every((state) => state.done);\n\n if (allServicesDone) {\n this.complete('no-quotes');\n }\n }\n\n /**\n * Finalize the quoter session and broadcast terminal reason exactly once.\n */\n private complete(reason: QuoterDoneReason): void {\n if (this.done) {\n return;\n }\n\n const payload = this.makeDonePayload(reason);\n\n this.done = true;\n this.stop();\n\n // When complete() happens during subscribe()->start(), emit done on a microtask\n // so callers can safely reference the returned unsubscribe in their handler.\n if (this.isStartingFromSubscribe) {\n queueMicrotask(() => {\n const handlers = [...this.subscribers];\n this.subscribers.clear();\n\n for (const handler of handlers) {\n handler('done', payload);\n }\n });\n return;\n }\n\n const handlers = [...this.subscribers];\n this.subscribers.clear();\n\n for (const handler of handlers) {\n handler('done', payload);\n }\n }\n\n private getInitializedServices(): ServiceType[] {\n return [...new Set(this.transferServices.map((service) => service.type))];\n }\n\n private getEligibleServices(): ServiceType[] {\n return [...this.serviceState.keys()];\n }\n\n private makeDonePayload(reason: QuoterDoneReason): QuoterDonePayload {\n if (reason === 'unsubscribed') {\n return { reason, data: undefined };\n }\n\n const initializedServices = this.getInitializedServices();\n\n if (reason === 'no-eligible-services') {\n return {\n reason,\n data: {\n initializedServices,\n quoterProps: this.props,\n },\n };\n }\n\n return {\n reason,\n data: {\n eligibleServices: this.getEligibleServices(),\n initializedServices,\n quoterProps: this.props,\n },\n };\n }\n\n /** Periodic prune tick to evict expired quotes and emit best changes. */\n private onPruneTick(): void {\n const now = this.clock();\n const pruned = pruneExpiredQuotes({ quotes: this.quotes, nowSeconds: now });\n\n if (pruned.length !== this.quotes.length) {\n this.quotes = sortQuotes(pruned);\n const best = this.quotes[0] ?? null;\n const bestId = best ? best.id : null;\n\n if (best && bestId !== this.lastBestId) {\n this.lastBestId = bestId;\n this.emitQuote({ bestQuote: best, quote: best, quotes: this.quotes });\n } else if (!best) {\n this.lastBestId = null;\n }\n }\n\n // Re-evaluate refresh scheduling for all services on prune tick\n for (const svc of this.transferServices) {\n if (this.serviceState.has(svc.type)) {\n this.scheduleServiceRefresh(svc.type);\n }\n }\n }\n\n /** Schedule a refresh (restart) of streaming for the service at its earliest quote expiration. */\n private scheduleServiceRefresh(serviceType: TransferService['type']): void {\n const state = this.serviceState.get(serviceType);\n\n if (!state) return;\n\n const now = this.clock();\n const earliest = earliestExpirationForService({ quotes: this.quotes, serviceType, nowSeconds: now });\n\n if (earliest === null) {\n // No quotes -> clear any pending refresh\n if (state.refreshTimer) {\n clearTimeout(state.refreshTimer);\n state.refreshTimer = null;\n }\n state.refreshAtSeconds = null;\n return;\n }\n\n // Only reschedule if earlier than currently scheduled or no timer\n const targetAt = Math.max(0, earliest - this.refreshBufferSeconds);\n\n // If target time has already passed, do not schedule another refresh here.\n if (targetAt <= now) {\n return;\n }\n\n // Reschedule only when the desired refresh time changes (earlier OR later).\n // We key refresh off the soonest-expiring active quote for this service.\n if (state.refreshAtSeconds === targetAt && state.refreshTimer) {\n return;\n }\n\n if (state.refreshTimer) {\n clearTimeout(state.refreshTimer);\n }\n\n const delayMs = Math.max(0, (targetAt - now) * 1_000);\n state.refreshAtSeconds = targetAt;\n state.refreshTimer = setTimeout(() => {\n // Clear timer/marker before restarting to avoid stale state if restart fails.\n const current = this.serviceState.get(serviceType);\n if (current) {\n current.refreshTimer = null;\n current.refreshAtSeconds = null;\n }\n\n // Restart stream and clear timer/marker\n const svc = this.transferServices.find((s) => s.type === serviceType);\n\n if (svc) {\n this.startStreamForService(svc);\n }\n }, delayMs);\n }\n\n // ----- Emission helpers -----\n /** Emit a quote event to all subscribers. */\n private emitQuote(payload: { bestQuote: Quote; quote: Quote; quotes: readonly Quote[] }): void {\n for (const handler of this.subscribers) {\n handler('quote', payload);\n }\n }\n\n /** Emit an error event to all subscribers. */\n private emitError(error: Error): void {\n for (const handler of this.subscribers) {\n handler('error', error);\n }\n }\n}\n\n/**\n * Zod schema to validate the minimal Quote fields used for runtime gating.\n *\n * This is a simple schema, and is not a fully safe runtime validate for Quote.\n * That isn't necessary here since we only need to verify basic structure before\n * using the quote in internal logic.\n *\n * @internal\n */\nconst QuoteSchema = z.object({\n id: z.string(),\n expiresAt: z.number().int().nonnegative(),\n amountOut: z.bigint().nonnegative(),\n amountIn: z.bigint().nonnegative(),\n serviceType: z.string(),\n});\n\nfunction isInvalidSameChainQuoteRequest(props: QuoterProps): boolean {\n const { sourceAsset, sourceChain, targetAsset, targetChain } = props;\n\n if (sourceChain.chainId !== targetChain.chainId) {\n return false;\n }\n\n // Native -> native on the same chain is a no-op.\n if (isNativeAsset(sourceAsset) && isNativeAsset(targetAsset)) {\n return true;\n }\n\n // If token types differ, it's potentially a swap on the same chain.\n if (sourceAsset.type !== targetAsset.type) {\n return false;\n }\n\n // Same token type and address on the same chain is a no-op.\n if (sourceAsset.type === TokenType.ERC20 && targetAsset.type === TokenType.ERC20) {\n return isAddressEqual(sourceAsset.address, targetAsset.address);\n }\n\n if (sourceAsset.type === TokenType.SPL && targetAsset.type === TokenType.SPL) {\n return sourceAsset.address === targetAsset.address;\n }\n\n return false;\n}\n\nfunction isQuoteValue(value: unknown): value is Quote {\n const result = QuoteSchema.safeParse(value);\n\n return result.success;\n}\n"],"mappings":"2YAsFA,IAAa,EAAb,KAA+C,CAC7C,MACA,MACA,gBACA,oBACA,iBACA,qBAEA,OAA0B,EAAE,CAC5B,YAA+C,IAAI,IACnD,QAAkB,GAClB,KAAe,GACf,wBAAkC,GAClC,aAA8D,KAC9D,WAAoC,KACpC,oBAA8B,GAE9B,GAA6B,OAAO,YAAY,CAQhD,aAYI,IAAI,IASR,YAAY,EAAoB,EAA8C,EAAyB,EAAE,CAAE,CACzG,KAAK,MAAQ,EAAQ,YAAgB,KAAK,MAAM,KAAK,KAAK,CAAG,IAAM,EACnE,KAAK,MAAQ,EACb,KAAK,gBAAkB,EAAQ,iBAAA,IAC/B,KAAK,oBAAsB,CACzB,gCAAiC,EAAQ,gCAC1C,CACD,KAAK,iBAAmB,EACxB,KAAK,qBAAuB,EAAQ,sBAAA,EAMtC,WAAgC,CAC9B,IAAM,EAAM,KAAK,OAAO,CAElB,EAAS,EADA,EAAmB,CAAE,OAAQ,KAAK,OAAQ,WAAY,EAAK,CAAC,CAC1C,CAGjC,MAAO,CAFM,EAAO,IAAM,KAEZ,EAAO,CAWvB,UAAiB,EAAyC,CACxD,KAAK,YAAY,IAAI,EAAQ,CAC7B,IAAI,EAAe,GAEnB,GAAI,CAAC,KAAK,QAAS,CACjB,KAAK,wBAA0B,GAC/B,GAAI,CACF,KAAK,OAAO,QACJ,CACR,KAAK,wBAA0B,IAInC,UAAa,CACP,MAKJ,IAFA,EAAe,GAEX,KAAK,KAAM,CACb,KAAK,YAAY,OAAO,EAAQ,CAChC,OAIF,GAD0B,KAAK,YAAY,OAAS,GAAK,KAAK,YAAY,IAAI,EAAQ,CAC/D,CACrB,KAAK,SAAS,eAAe,CAC7B,OAGF,KAAK,YAAY,OAAO,EAAQ,GAYpC,OAAsB,CAQpB,GAPA,KAAK,QAAU,GACf,KAAK,KAAO,GACZ,KAAK,OAAS,EAAE,CAChB,KAAK,WAAa,KAClB,KAAK,oBAAsB,GAGvB,EAA+B,KAAK,MAAM,CAAE,CAC9C,KAAK,SAAS,uBAAuB,CACrC,OAGF,IAAI,EAAqB,GAGzB,IAAK,IAAM,KAAO,KAAK,iBACJ,EAAI,eAAe,CAClC,YAAa,KAAK,MAAM,YACxB,cAAe,KAAK,MAAM,YAAY,QACtC,YAAa,KAAK,MAAM,YACxB,cAAe,KAAK,MAAM,YAAY,QACvC,CAAC,GAGF,EAAqB,GAErB,KAAK,sBAAsB,EAAI,EAGjC,GAAI,CAAC,EAAoB,CACvB,KAAK,SAAS,uBAAuB,CACrC,OAIF,KAAK,aAAe,gBAAkB,KAAK,aAAa,CAAE,KAAK,gBAAgB,CAQjF,MAAqB,CACnB,KAAK,QAAU,GAEf,AAEE,KAAK,gBADL,cAAc,KAAK,aAAa,CACZ,MAGtB,IAAK,GAAM,CAAC,EAAM,KAAU,KAAK,aAAc,CAC7C,GAAI,CACF,EAAM,QAAQ,MACR,EAIJ,EAAM,cACR,aAAa,EAAM,aAAa,CAG9B,EAAM,YACR,aAAa,EAAM,WAAW,CAGhC,KAAK,aAAa,IAAI,EAAM,CAC1B,WAAc,GACd,KAAM,GACN,WAAY,GACZ,iBAAkB,GAClB,aAAc,EACd,WAAY,KACZ,aAAc,KACd,iBAAkB,KACnB,CAAC,EASN,sBAA8B,EAA4B,CAExD,IAAM,EAAW,KAAK,aAAa,IAAI,EAAI,KAAK,CAEhD,GAAI,EAAU,CACZ,GAAI,CACF,EAAS,QAAQ,MACX,EAIJ,EAAS,cAAc,aAAa,EAAS,aAAa,CAC1D,EAAS,YAAY,aAAa,EAAS,WAAW,CAG5D,IAAM,EAAU,KAAK,mBAAmB,EAAI,KAAK,CAC3C,EAA0C,EAAE,CAC9C,EAAmB,GAejB,CAAE,UAAW,EAAI,aAAa,KAAK,OATS,GAAG,IAAc,CACjE,GAAI,EAAkB,CACpB,EAAe,KAAK,EAAU,CAC9B,OAGF,EAAQ,GAAG,EAAU,EAGyC,KAAK,oBAAoB,CACzF,EAAmB,GAEf,EAAe,OAAS,GAG1B,mBAAqB,CACnB,IAAK,IAAM,KAAiB,EAC1B,EAAQ,GAAG,EAAc,EAE3B,CAGJ,KAAK,aAAa,IAAI,EAAI,KAAM,CAC9B,SACA,KAAM,GACN,WAAY,GACZ,iBAAkB,GAClB,aAAc,GAAU,cAAgB,EACxC,WAAY,KACZ,aAAc,KACd,iBAAkB,KACnB,CAAC,CASJ,mBAA2B,EAAgE,CACzF,OAAQ,EAAO,GAAG,IAAS,CAEpB,QAAK,QAGV,IAAI,IAAU,QAAS,CACrB,IAAM,EAAa,EAAK,GACxB,GAAI,EAAa,EAAW,CAAE,CAE5B,GAAI,EAAW,cAAgB,EAE7B,OAEF,IAAM,EAAQ,KAAK,aAAa,IAAI,EAAY,CAC5C,IACF,EAAM,iBAAmB,IAE3B,KAAK,gBAAgB,EAAW,CAChC,KAAK,uBAAuB,EAAY,CAG1C,OAEF,GAAI,IAAU,OAAQ,CACpB,KAAK,cAAc,EAAY,CAE/B,OAEF,GAAI,IAAU,QAAS,CACrB,IAAM,EAAQ,KAAK,aAAa,IAAI,EAAY,CAC5C,IACF,EAAM,WAAa,IAErB,IAAM,EAAW,EAAK,GAClB,aAAoB,OACtB,KAAK,UAAU,EAAS,IAYhC,gBAAwB,EAAoB,CAC1C,IAAM,EAAM,KAAK,OAAO,CAExB,GAAI,EAAe,CAAE,QAAO,WAAY,EAAK,CAAC,CAC5C,OAGF,KAAK,oBAAsB,GAE3B,KAAK,qBAAqB,EAAM,YAAY,CAE5C,KAAK,OAAS,EAAW,EAAmB,CAAE,OAAQ,EAAY,KAAK,OAAQ,EAAM,CAAE,WAAY,EAAK,CAAC,CAAC,CAG1G,IAAM,EAAO,KAAK,OAAO,GACrB,IACF,KAAK,WAAa,EAAK,GACvB,KAAK,UAAU,CAAE,UAAW,EAAM,QAAO,OAAQ,KAAK,OAAQ,CAAC,EAInE,qBAA6B,EAA4C,CACvE,IAAM,EAAQ,KAAK,aAAa,IAAI,EAAY,CAE3C,IAIL,EAAM,aAAe,EACrB,AAEE,EAAM,cADN,aAAa,EAAM,WAAW,CACX,OAUvB,qBAA6B,EAA4C,CACvE,IAAM,EAAQ,KAAK,aAAa,IAAI,EAAY,CAEhD,GAAI,CAAC,EACH,OAGF,AAEE,EAAM,cADN,aAAa,EAAM,WAAW,CACX,MAGrB,IAAM,EAAU,KAAK,IACnB,EACA,EAAmC,GAAK,EAAM,aAC/C,CACD,EAAM,cAAgB,EAEtB,EAAM,WAAa,eACX,CACJ,IAAM,EAAU,KAAK,aAAa,IAAI,EAAY,CAKlD,GAJI,IACF,EAAQ,WAAa,MAGnB,CAAC,KAAK,QACR,OAGF,IAAM,EAAM,KAAK,iBAAiB,KAAM,GAAM,EAAE,OAAS,EAAY,CACjE,GACF,KAAK,sBAAsB,EAAI,EAGnC,KAAK,IAAI,EAAG,EAAQ,CACrB,CAYH,cAAsB,EAA4C,CAChE,IAAM,EAAQ,KAAK,aAAa,IAAI,EAAY,CAE3C,IAIL,EAAM,KAAO,GACb,KAAK,uBAAuB,EAAY,CAEpC,KAAK,qBAAuB,CAAC,EAAM,YAAc,CAAC,EAAM,kBAC1D,KAAK,qBAAqB,EAAY,CAGxC,KAAK,uBAAuB,EAO9B,uBAAsC,CAChC,CAAC,KAAK,SAAW,KAAK,MAAQ,KAAK,qBAAuB,KAAK,aAAa,OAAS,GAIjE,CAAC,GAAG,KAAK,aAAa,QAAQ,CAAC,CAAC,MAAO,GAAU,EAAM,KAAK,EAGlF,KAAK,SAAS,YAAY,CAO9B,SAAiB,EAAgC,CAC/C,GAAI,KAAK,KACP,OAGF,IAAM,EAAU,KAAK,gBAAgB,EAAO,CAO5C,GALA,KAAK,KAAO,GACZ,KAAK,MAAM,CAIP,KAAK,wBAAyB,CAChC,mBAAqB,CACnB,IAAM,EAAW,CAAC,GAAG,KAAK,YAAY,CACtC,KAAK,YAAY,OAAO,CAExB,IAAK,IAAM,KAAW,EACpB,EAAQ,OAAQ,EAAQ,EAE1B,CACF,OAGF,IAAM,EAAW,CAAC,GAAG,KAAK,YAAY,CACtC,KAAK,YAAY,OAAO,CAExB,IAAK,IAAM,KAAW,EACpB,EAAQ,OAAQ,EAAQ,CAI5B,wBAAgD,CAC9C,MAAO,CAAC,GAAG,IAAI,IAAI,KAAK,iBAAiB,IAAK,GAAY,EAAQ,KAAK,CAAC,CAAC,CAG3E,qBAA6C,CAC3C,MAAO,CAAC,GAAG,KAAK,aAAa,MAAM,CAAC,CAGtC,gBAAwB,EAA6C,CACnE,GAAI,IAAW,eACb,MAAO,CAAE,SAAQ,KAAM,IAAA,GAAW,CAGpC,IAAM,EAAsB,KAAK,wBAAwB,CAYzD,OAVI,IAAW,uBACN,CACL,SACA,KAAM,CACJ,sBACA,YAAa,KAAK,MACnB,CACF,CAGI,CACL,SACA,KAAM,CACJ,iBAAkB,KAAK,qBAAqB,CAC5C,sBACA,YAAa,KAAK,MACnB,CACF,CAIH,aAA4B,CAC1B,IAAM,EAAM,KAAK,OAAO,CAClB,EAAS,EAAmB,CAAE,OAAQ,KAAK,OAAQ,WAAY,EAAK,CAAC,CAE3E,GAAI,EAAO,SAAW,KAAK,OAAO,OAAQ,CACxC,KAAK,OAAS,EAAW,EAAO,CAChC,IAAM,EAAO,KAAK,OAAO,IAAM,KACzB,EAAS,EAAO,EAAK,GAAK,KAE5B,GAAQ,IAAW,KAAK,YAC1B,KAAK,WAAa,EAClB,KAAK,UAAU,CAAE,UAAW,EAAM,MAAO,EAAM,OAAQ,KAAK,OAAQ,CAAC,EAC3D,IACV,KAAK,WAAa,MAKtB,IAAK,IAAM,KAAO,KAAK,iBACjB,KAAK,aAAa,IAAI,EAAI,KAAK,EACjC,KAAK,uBAAuB,EAAI,KAAK,CAM3C,uBAA+B,EAA4C,CACzE,IAAM,EAAQ,KAAK,aAAa,IAAI,EAAY,CAEhD,GAAI,CAAC,EAAO,OAEZ,IAAM,EAAM,KAAK,OAAO,CAClB,EAAW,EAA6B,CAAE,OAAQ,KAAK,OAAQ,cAAa,WAAY,EAAK,CAAC,CAEpG,GAAI,IAAa,KAAM,CAErB,AAEE,EAAM,gBADN,aAAa,EAAM,aAAa,CACX,MAEvB,EAAM,iBAAmB,KACzB,OAIF,IAAM,EAAW,KAAK,IAAI,EAAG,EAAW,KAAK,qBAAqB,CASlE,GANI,GAAY,GAMZ,EAAM,mBAAqB,GAAY,EAAM,aAC/C,OAGE,EAAM,cACR,aAAa,EAAM,aAAa,CAGlC,IAAM,EAAU,KAAK,IAAI,GAAI,EAAW,GAAO,IAAM,CACrD,EAAM,iBAAmB,EACzB,EAAM,aAAe,eAAiB,CAEpC,IAAM,EAAU,KAAK,aAAa,IAAI,EAAY,CAC9C,IACF,EAAQ,aAAe,KACvB,EAAQ,iBAAmB,MAI7B,IAAM,EAAM,KAAK,iBAAiB,KAAM,GAAM,EAAE,OAAS,EAAY,CAEjE,GACF,KAAK,sBAAsB,EAAI,EAEhC,EAAQ,CAKb,UAAkB,EAA6E,CAC7F,IAAK,IAAM,KAAW,KAAK,YACzB,EAAQ,QAAS,EAAQ,CAK7B,UAAkB,EAAoB,CACpC,IAAK,IAAM,KAAW,KAAK,YACzB,EAAQ,QAAS,EAAM,GAc7B,MAAM,EAAc,EAAE,OAAO,CAC3B,GAAI,EAAE,QAAQ,CACd,UAAW,EAAE,QAAQ,CAAC,KAAK,CAAC,aAAa,CACzC,UAAW,EAAE,QAAQ,CAAC,aAAa,CACnC,SAAU,EAAE,QAAQ,CAAC,aAAa,CAClC,YAAa,EAAE,QAAQ,CACxB,CAAC,CAEF,SAAS,EAA+B,EAA6B,CACnE,GAAM,CAAE,cAAa,cAAa,cAAa,eAAgB,EAyB/D,OAvBI,EAAY,UAAY,EAAY,QAKpC,EAAc,EAAY,EAAI,EAAc,EAAY,CACnD,GAIL,EAAY,OAAS,EAAY,KAKjC,EAAY,OAAS,EAAU,OAAS,EAAY,OAAS,EAAU,MAClE,EAAe,EAAY,QAAS,EAAY,QAAQ,CAG7D,EAAY,OAAS,EAAU,KAAO,EAAY,OAAS,EAAU,IAChE,EAAY,UAAY,EAAY,QAGtC,GAZE,GAVA,GAyBX,SAAS,EAAa,EAAgC,CAGpD,OAFe,EAAY,UAAU,EAAM,CAE7B"}
@@ -1,2 +1,2 @@
1
- const e=require(`../../../errors.cjs`),t=require(`../../../utils/caip.cjs`),n=require(`../../../_utils/chain.cjs`),r=require(`../../../utils/evm-address.cjs`),i=require(`../_api.cjs`),a=require(`../../../utils/sol-address.cjs`),o=require(`../_utils.cjs`);function s({apiOptions:e,appId:r,partnerFeeBps:a}){return(s,l,u)=>{let d=new AbortController,{userEvmAddress:f,userSolanaAddress:p,validationError:m}=c(s,u);return m?(l(`error`,m),l(`done`),{cancel:()=>{}}):(i.markrStreamQuote(e,{amount:s.amount.toString(),aggregator:s.aggregator,appId:r,chainId:n.isEvmNamespace(s.sourceChain.chainId)?t.caip2ToEip155ChainId(s.sourceChain.chainId):s.sourceChain.chainId,destinationChainId:s.sourceChain.chainId===s.targetChain.chainId?void 0:n.isEvmNamespace(s.targetChain.chainId)?t.caip2ToEip155ChainId(s.targetChain.chainId):s.targetChain.chainId,slippage:s.slippageBps,tokenIn:o.assetToAddressString(s.sourceAsset,s.sourceChain.chainId),tokenInDecimals:s.sourceAsset.decimals,tokenOut:o.assetToAddressString(s.targetAsset,s.targetChain.chainId),tokenOutDecimals:s.targetAsset.decimals,userEvmAddress:f,userSolanaAddress:p},{onDone:()=>{d.signal.aborted||l(`done`)},onError:e=>{d.signal.aborted||(l(`error`,e),l(`done`))},onQuote:e=>{d.signal.aborted||l(`quote`,o.quoteFromMarkrQuoteResponseData(e,s,a))},signal:d.signal}),{cancel:()=>{d.abort()}})}}function c(t,i){let o=t.sourceChain.chainId!==t.targetChain.chainId,s=n.isEvmNamespace(t.sourceChain.chainId),c=n.isEvmNamespace(t.targetChain.chainId),l=n.isSolanaNamespace(t.sourceChain.chainId),u=n.isSolanaNamespace(t.targetChain.chainId);return s&&!r.isEvmAddress(t.fromAddress)?{userEvmAddress:void 0,userSolanaAddress:void 0,validationError:new e.InvalidParamsError(e.ErrorReason.INVALID_PARAMS,`Invalid fromAddress for EVM source chain.`)}:c&&!r.isEvmAddress(t.toAddress)?{userEvmAddress:void 0,userSolanaAddress:void 0,validationError:new e.InvalidParamsError(e.ErrorReason.INVALID_PARAMS,`Invalid toAddress for EVM target chain.`)}:l&&!a.isSolAddress(t.fromAddress)?{userEvmAddress:void 0,userSolanaAddress:void 0,validationError:new e.InvalidParamsError(e.ErrorReason.INVALID_PARAMS,`Invalid fromAddress for Solana source chain.`)}:u&&!a.isSolAddress(t.toAddress)?{userEvmAddress:void 0,userSolanaAddress:void 0,validationError:new e.InvalidParamsError(e.ErrorReason.INVALID_PARAMS,`Invalid toAddress for Solana target chain.`)}:o&&(s&&c||l&&u)&&!i?.dangerouslyAllowAddressMismatch&&t.fromAddress!==t.toAddress?{userEvmAddress:void 0,userSolanaAddress:void 0,validationError:new e.InvalidParamsError(e.ErrorReason.INVALID_PARAMS,`fromAddress and toAddress must match for same-namespace cross-chain swaps.`)}:o?{userEvmAddress:c&&r.isEvmAddress(t.toAddress)?t.toAddress:s&&r.isEvmAddress(t.fromAddress)?t.fromAddress:void 0,userSolanaAddress:u&&a.isSolAddress(t.toAddress)?t.toAddress:l&&a.isSolAddress(t.fromAddress)?t.fromAddress:void 0}:t.fromAddress===t.toAddress?{userEvmAddress:void 0,userSolanaAddress:void 0}:{userEvmAddress:void 0,userSolanaAddress:void 0,validationError:new e.InvalidParamsError(e.ErrorReason.INVALID_PARAMS,`fromAddress and toAddress must match for same-chain swaps.`)}}exports.streamQuotesFactory=s;
1
+ const e=require(`../../../errors.cjs`),t=require(`../../../utils/caip.cjs`),n=require(`../../../_utils/chain.cjs`),r=require(`../../../utils/evm-address.cjs`),i=require(`../_api.cjs`),a=require(`../../../utils/sol-address.cjs`),o=require(`../_utils.cjs`);function s({apiOptions:e,appId:r,partnerFeeBps:a}){return(s,l,u)=>{let d=new AbortController,{userEvmAddress:f,userSolanaAddress:p,validationError:m}=c(s,u);return m?(l(`error`,m),l(`done`),{cancel:()=>{}}):(i.markrStreamQuote(e,{amount:s.amount.toString(),aggregator:s.aggregator,appId:r,chainId:n.isEvmNamespace(s.sourceChain.chainId)?t.caip2ToEip155ChainId(s.sourceChain.chainId):s.sourceChain.chainId,destinationChainId:s.sourceChain.chainId===s.targetChain.chainId?void 0:n.isEvmNamespace(s.targetChain.chainId)?t.caip2ToEip155ChainId(s.targetChain.chainId):s.targetChain.chainId,slippage:s.slippageBps,tokenIn:o.assetToAddressString(s.sourceAsset,s.sourceChain.chainId),tokenInDecimals:s.sourceAsset.decimals,tokenOut:o.assetToAddressString(s.targetAsset,s.targetChain.chainId),tokenOutDecimals:s.targetAsset.decimals,userEvmAddress:f,userSolanaAddress:p},{onDone:()=>{d.signal.aborted||l(`done`)},onError:e=>{d.signal.aborted||(l(`error`,e),l(`done`))},onQuote:e=>{d.signal.aborted||l(`quote`,o.quoteFromMarkrQuoteResponseData(e,s,a))},signal:d.signal}),{cancel:()=>{d.abort()}})}}function c(t,i){let o=t.sourceChain.chainId!==t.targetChain.chainId,s=!o,c=n.isEvmNamespace(t.sourceChain.chainId),l=n.isEvmNamespace(t.targetChain.chainId),u=n.isSolanaNamespace(t.sourceChain.chainId),d=n.isSolanaNamespace(t.targetChain.chainId),f=i?.dangerouslyAllowAddressMismatch===!0,p=t.fromAddress!==t.toAddress,m=t=>({userEvmAddress:void 0,userSolanaAddress:void 0,validationError:new e.InvalidParamsError(e.ErrorReason.INVALID_PARAMS,t)});if(c&&!r.isEvmAddress(t.fromAddress))return m(`Invalid fromAddress for EVM source chain.`);if(l&&!r.isEvmAddress(t.toAddress))return m(`Invalid toAddress for EVM target chain.`);if(u&&!a.isSolAddress(t.fromAddress))return m(`Invalid fromAddress for Solana source chain.`);if(d&&!a.isSolAddress(t.toAddress))return m(`Invalid toAddress for Solana target chain.`);if(o&&(c&&l||u&&d)&&p&&!f)return m(`fromAddress and toAddress must match for same-namespace cross-chain swaps.`);if(s){if(p&&!f)return m(`fromAddress and toAddress must match for same-chain swaps.`);if(!f)return{userEvmAddress:void 0,userSolanaAddress:void 0}}return{userEvmAddress:l&&r.isEvmAddress(t.toAddress)?t.toAddress:c&&r.isEvmAddress(t.fromAddress)?t.fromAddress:void 0,userSolanaAddress:d&&a.isSolAddress(t.toAddress)?t.toAddress:u&&a.isSolAddress(t.fromAddress)?t.fromAddress:void 0}}exports.streamQuotesFactory=s;
2
2
  //# sourceMappingURL=stream-quotes.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"stream-quotes.cjs","names":["markrStreamQuote","isEvmNamespace","caip2ToEip155ChainId","assetToAddressString","quoteFromMarkrQuoteResponseData","isSolanaNamespace","isEvmAddress","InvalidParamsError","ErrorReason","isSolAddress"],"sources":["../../../../src/transfer-service/markr/_handlers/stream-quotes.ts"],"sourcesContent":["import { caip2ToEip155ChainId } from '../../../utils/caip';\nimport type { ServiceQuoteOptions, TransferService } from '../../../types/service';\nimport { markrStreamQuote, type ApiOptions, type MarkrStreamQuoteParams } from '../_api';\nimport { assetToAddressString, quoteFromMarkrQuoteResponseData } from '../_utils';\nimport { isEvmNamespace, isSolanaNamespace } from '../../../_utils/chain';\nimport { isEvmAddress } from '../../../utils/evm-address';\nimport { isSolAddress } from '../../../utils/sol-address';\nimport { ErrorReason, InvalidParamsError } from '../../../errors';\n\nexport interface StreamQuotesFactoryConfig {\n apiOptions: ApiOptions;\n appId: string;\n partnerFeeBps: number;\n}\n\nexport function streamQuotesFactory({\n apiOptions,\n appId,\n partnerFeeBps,\n}: StreamQuotesFactoryConfig): TransferService['streamQuotes'] {\n return (props, handler, options) => {\n const ac = new AbortController();\n const { userEvmAddress, userSolanaAddress, validationError } = _validateAndGetUserAddresses(props, options);\n\n if (validationError) {\n handler('error', validationError);\n handler('done');\n\n return {\n cancel: () => {},\n };\n }\n\n void markrStreamQuote(\n apiOptions,\n {\n amount: props.amount.toString(),\n // Forwarded only when the caller pins one; otherwise Markr races every aggregator.\n aggregator: props.aggregator,\n appId,\n chainId: isEvmNamespace(props.sourceChain.chainId)\n ? caip2ToEip155ChainId(props.sourceChain.chainId)\n : props.sourceChain.chainId,\n // For cross-chain requests, destinationChainId is required.\n // Use EVM numeric chain IDs for EVM targets and CAIP-2 IDs for non-EVM targets.\n destinationChainId:\n props.sourceChain.chainId !== props.targetChain.chainId\n ? isEvmNamespace(props.targetChain.chainId)\n ? caip2ToEip155ChainId(props.targetChain.chainId)\n : props.targetChain.chainId\n : undefined,\n slippage: props.slippageBps,\n tokenIn: assetToAddressString(props.sourceAsset, props.sourceChain.chainId),\n tokenInDecimals: props.sourceAsset.decimals,\n tokenOut: assetToAddressString(props.targetAsset, props.targetChain.chainId),\n tokenOutDecimals: props.targetAsset.decimals,\n userEvmAddress,\n userSolanaAddress,\n },\n {\n onDone: () => {\n if (!ac.signal.aborted) {\n handler('done');\n }\n },\n onError: (error) => {\n if (!ac.signal.aborted) {\n handler('error', error);\n handler('done');\n }\n },\n onQuote: (data) => {\n if (!ac.signal.aborted) {\n handler('quote', quoteFromMarkrQuoteResponseData(data, props, partnerFeeBps));\n }\n },\n signal: ac.signal,\n },\n );\n\n return {\n cancel: () => {\n ac.abort();\n },\n };\n };\n}\n\nexport function _validateAndGetUserAddresses(\n props: Parameters<TransferService['streamQuotes']>[0],\n options?: ServiceQuoteOptions,\n): Pick<MarkrStreamQuoteParams, 'userEvmAddress' | 'userSolanaAddress'> & { validationError?: InvalidParamsError } {\n const isCrossChainSwap = props.sourceChain.chainId !== props.targetChain.chainId;\n const sourceIsEvm = isEvmNamespace(props.sourceChain.chainId);\n const targetIsEvm = isEvmNamespace(props.targetChain.chainId);\n const sourceIsSolana = isSolanaNamespace(props.sourceChain.chainId);\n const targetIsSolana = isSolanaNamespace(props.targetChain.chainId);\n\n if (sourceIsEvm && !isEvmAddress(props.fromAddress)) {\n return {\n userEvmAddress: undefined,\n userSolanaAddress: undefined,\n validationError: new InvalidParamsError(ErrorReason.INVALID_PARAMS, 'Invalid fromAddress for EVM source chain.'),\n };\n }\n\n if (targetIsEvm && !isEvmAddress(props.toAddress)) {\n return {\n userEvmAddress: undefined,\n userSolanaAddress: undefined,\n validationError: new InvalidParamsError(ErrorReason.INVALID_PARAMS, 'Invalid toAddress for EVM target chain.'),\n };\n }\n\n if (sourceIsSolana && !isSolAddress(props.fromAddress)) {\n return {\n userEvmAddress: undefined,\n userSolanaAddress: undefined,\n validationError: new InvalidParamsError(\n ErrorReason.INVALID_PARAMS,\n 'Invalid fromAddress for Solana source chain.',\n ),\n };\n }\n\n if (targetIsSolana && !isSolAddress(props.toAddress)) {\n return {\n userEvmAddress: undefined,\n userSolanaAddress: undefined,\n validationError: new InvalidParamsError(ErrorReason.INVALID_PARAMS, 'Invalid toAddress for Solana target chain.'),\n };\n }\n\n if (\n isCrossChainSwap &&\n ((sourceIsEvm && targetIsEvm) || (sourceIsSolana && targetIsSolana)) &&\n !options?.dangerouslyAllowAddressMismatch\n ) {\n if (props.fromAddress !== props.toAddress) {\n return {\n userEvmAddress: undefined,\n userSolanaAddress: undefined,\n validationError: new InvalidParamsError(\n ErrorReason.INVALID_PARAMS,\n 'fromAddress and toAddress must match for same-namespace cross-chain swaps.',\n ),\n };\n }\n }\n\n if (!isCrossChainSwap) {\n if (props.fromAddress !== props.toAddress) {\n return {\n userEvmAddress: undefined,\n userSolanaAddress: undefined,\n validationError: new InvalidParamsError(\n ErrorReason.INVALID_PARAMS,\n 'fromAddress and toAddress must match for same-chain swaps.',\n ),\n };\n }\n\n return {\n userEvmAddress: undefined,\n userSolanaAddress: undefined,\n };\n }\n\n const userEvmAddress =\n targetIsEvm && isEvmAddress(props.toAddress)\n ? props.toAddress\n : sourceIsEvm && isEvmAddress(props.fromAddress)\n ? props.fromAddress\n : undefined;\n\n const userSolanaAddress =\n targetIsSolana && isSolAddress(props.toAddress)\n ? props.toAddress\n : sourceIsSolana && isSolAddress(props.fromAddress)\n ? props.fromAddress\n : undefined;\n\n return {\n userEvmAddress,\n userSolanaAddress,\n };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"stream-quotes.cjs","names":["markrStreamQuote","isEvmNamespace","caip2ToEip155ChainId","assetToAddressString","quoteFromMarkrQuoteResponseData","isSolanaNamespace","InvalidParamsError","ErrorReason","isEvmAddress","isSolAddress"],"sources":["../../../../src/transfer-service/markr/_handlers/stream-quotes.ts"],"sourcesContent":["import { caip2ToEip155ChainId } from '../../../utils/caip';\nimport type { ServiceQuoteOptions, TransferService } from '../../../types/service';\nimport { markrStreamQuote, type ApiOptions, type MarkrStreamQuoteParams } from '../_api';\nimport { assetToAddressString, quoteFromMarkrQuoteResponseData } from '../_utils';\nimport { isEvmNamespace, isSolanaNamespace } from '../../../_utils/chain';\nimport { isEvmAddress } from '../../../utils/evm-address';\nimport { isSolAddress } from '../../../utils/sol-address';\nimport { ErrorReason, InvalidParamsError } from '../../../errors';\n\nexport interface StreamQuotesFactoryConfig {\n apiOptions: ApiOptions;\n appId: string;\n partnerFeeBps: number;\n}\n\nexport function streamQuotesFactory({\n apiOptions,\n appId,\n partnerFeeBps,\n}: StreamQuotesFactoryConfig): TransferService['streamQuotes'] {\n return (props, handler, options) => {\n const ac = new AbortController();\n const { userEvmAddress, userSolanaAddress, validationError } = _validateAndGetUserAddresses(props, options);\n\n if (validationError) {\n handler('error', validationError);\n handler('done');\n\n return {\n cancel: () => {},\n };\n }\n\n void markrStreamQuote(\n apiOptions,\n {\n amount: props.amount.toString(),\n // Forwarded only when the caller pins one; otherwise Markr races every aggregator.\n aggregator: props.aggregator,\n appId,\n chainId: isEvmNamespace(props.sourceChain.chainId)\n ? caip2ToEip155ChainId(props.sourceChain.chainId)\n : props.sourceChain.chainId,\n // For cross-chain requests, destinationChainId is required.\n // Use EVM numeric chain IDs for EVM targets and CAIP-2 IDs for non-EVM targets.\n destinationChainId:\n props.sourceChain.chainId !== props.targetChain.chainId\n ? isEvmNamespace(props.targetChain.chainId)\n ? caip2ToEip155ChainId(props.targetChain.chainId)\n : props.targetChain.chainId\n : undefined,\n slippage: props.slippageBps,\n tokenIn: assetToAddressString(props.sourceAsset, props.sourceChain.chainId),\n tokenInDecimals: props.sourceAsset.decimals,\n tokenOut: assetToAddressString(props.targetAsset, props.targetChain.chainId),\n tokenOutDecimals: props.targetAsset.decimals,\n userEvmAddress,\n userSolanaAddress,\n },\n {\n onDone: () => {\n if (!ac.signal.aborted) {\n handler('done');\n }\n },\n onError: (error) => {\n if (!ac.signal.aborted) {\n handler('error', error);\n handler('done');\n }\n },\n onQuote: (data) => {\n if (!ac.signal.aborted) {\n handler('quote', quoteFromMarkrQuoteResponseData(data, props, partnerFeeBps));\n }\n },\n signal: ac.signal,\n },\n );\n\n return {\n cancel: () => {\n ac.abort();\n },\n };\n };\n}\n\nexport function _validateAndGetUserAddresses(\n props: Parameters<TransferService['streamQuotes']>[0],\n options?: ServiceQuoteOptions,\n): Pick<MarkrStreamQuoteParams, 'userEvmAddress' | 'userSolanaAddress'> & { validationError?: InvalidParamsError } {\n const isCrossChainSwap = props.sourceChain.chainId !== props.targetChain.chainId;\n const isSameChainSwap = !isCrossChainSwap;\n const sourceIsEvm = isEvmNamespace(props.sourceChain.chainId);\n const targetIsEvm = isEvmNamespace(props.targetChain.chainId);\n const sourceIsSolana = isSolanaNamespace(props.sourceChain.chainId);\n const targetIsSolana = isSolanaNamespace(props.targetChain.chainId);\n const dangerouslyAllowAddressMismatch = options?.dangerouslyAllowAddressMismatch === true;\n const addressesMismatch = props.fromAddress !== props.toAddress;\n\n const invalidParams = (details: string) => ({\n userEvmAddress: undefined,\n userSolanaAddress: undefined,\n validationError: new InvalidParamsError(ErrorReason.INVALID_PARAMS, details),\n });\n\n if (sourceIsEvm && !isEvmAddress(props.fromAddress)) {\n return invalidParams('Invalid fromAddress for EVM source chain.');\n }\n\n if (targetIsEvm && !isEvmAddress(props.toAddress)) {\n return invalidParams('Invalid toAddress for EVM target chain.');\n }\n\n if (sourceIsSolana && !isSolAddress(props.fromAddress)) {\n return invalidParams('Invalid fromAddress for Solana source chain.');\n }\n\n if (targetIsSolana && !isSolAddress(props.toAddress)) {\n return invalidParams('Invalid toAddress for Solana target chain.');\n }\n\n const isSameNamespaceCrossChainSwap =\n isCrossChainSwap && ((sourceIsEvm && targetIsEvm) || (sourceIsSolana && targetIsSolana));\n\n if (isSameNamespaceCrossChainSwap && addressesMismatch && !dangerouslyAllowAddressMismatch) {\n return invalidParams('fromAddress and toAddress must match for same-namespace cross-chain swaps.');\n }\n\n if (isSameChainSwap) {\n if (addressesMismatch && !dangerouslyAllowAddressMismatch) {\n return invalidParams('fromAddress and toAddress must match for same-chain swaps.');\n }\n\n if (!dangerouslyAllowAddressMismatch) {\n return {\n userEvmAddress: undefined,\n userSolanaAddress: undefined,\n };\n }\n }\n\n const userEvmAddress =\n targetIsEvm && isEvmAddress(props.toAddress)\n ? props.toAddress\n : sourceIsEvm && isEvmAddress(props.fromAddress)\n ? props.fromAddress\n : undefined;\n\n const userSolanaAddress =\n targetIsSolana && isSolAddress(props.toAddress)\n ? props.toAddress\n : sourceIsSolana && isSolAddress(props.fromAddress)\n ? props.fromAddress\n : undefined;\n\n return {\n userEvmAddress,\n userSolanaAddress,\n };\n}\n"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- import{ErrorReason as e,InvalidParamsError as t}from"../../../errors.js";import{caip2ToEip155ChainId as n}from"../../../utils/caip.js";import{isEvmNamespace as r,isSolanaNamespace as i}from"../../../_utils/chain.js";import{isEvmAddress as a}from"../../../utils/evm-address.js";import{markrStreamQuote as o}from"../_api.js";import{isSolAddress as s}from"../../../utils/sol-address.js";import{assetToAddressString as c,quoteFromMarkrQuoteResponseData as l}from"../_utils.js";function u({apiOptions:e,appId:t,partnerFeeBps:i}){return(a,s,u)=>{let f=new AbortController,{userEvmAddress:p,userSolanaAddress:m,validationError:h}=d(a,u);return h?(s(`error`,h),s(`done`),{cancel:()=>{}}):(o(e,{amount:a.amount.toString(),aggregator:a.aggregator,appId:t,chainId:r(a.sourceChain.chainId)?n(a.sourceChain.chainId):a.sourceChain.chainId,destinationChainId:a.sourceChain.chainId===a.targetChain.chainId?void 0:r(a.targetChain.chainId)?n(a.targetChain.chainId):a.targetChain.chainId,slippage:a.slippageBps,tokenIn:c(a.sourceAsset,a.sourceChain.chainId),tokenInDecimals:a.sourceAsset.decimals,tokenOut:c(a.targetAsset,a.targetChain.chainId),tokenOutDecimals:a.targetAsset.decimals,userEvmAddress:p,userSolanaAddress:m},{onDone:()=>{f.signal.aborted||s(`done`)},onError:e=>{f.signal.aborted||(s(`error`,e),s(`done`))},onQuote:e=>{f.signal.aborted||s(`quote`,l(e,a,i))},signal:f.signal}),{cancel:()=>{f.abort()}})}}function d(n,o){let c=n.sourceChain.chainId!==n.targetChain.chainId,l=r(n.sourceChain.chainId),u=r(n.targetChain.chainId),d=i(n.sourceChain.chainId),f=i(n.targetChain.chainId);return l&&!a(n.fromAddress)?{userEvmAddress:void 0,userSolanaAddress:void 0,validationError:new t(e.INVALID_PARAMS,`Invalid fromAddress for EVM source chain.`)}:u&&!a(n.toAddress)?{userEvmAddress:void 0,userSolanaAddress:void 0,validationError:new t(e.INVALID_PARAMS,`Invalid toAddress for EVM target chain.`)}:d&&!s(n.fromAddress)?{userEvmAddress:void 0,userSolanaAddress:void 0,validationError:new t(e.INVALID_PARAMS,`Invalid fromAddress for Solana source chain.`)}:f&&!s(n.toAddress)?{userEvmAddress:void 0,userSolanaAddress:void 0,validationError:new t(e.INVALID_PARAMS,`Invalid toAddress for Solana target chain.`)}:c&&(l&&u||d&&f)&&!o?.dangerouslyAllowAddressMismatch&&n.fromAddress!==n.toAddress?{userEvmAddress:void 0,userSolanaAddress:void 0,validationError:new t(e.INVALID_PARAMS,`fromAddress and toAddress must match for same-namespace cross-chain swaps.`)}:c?{userEvmAddress:u&&a(n.toAddress)?n.toAddress:l&&a(n.fromAddress)?n.fromAddress:void 0,userSolanaAddress:f&&s(n.toAddress)?n.toAddress:d&&s(n.fromAddress)?n.fromAddress:void 0}:n.fromAddress===n.toAddress?{userEvmAddress:void 0,userSolanaAddress:void 0}:{userEvmAddress:void 0,userSolanaAddress:void 0,validationError:new t(e.INVALID_PARAMS,`fromAddress and toAddress must match for same-chain swaps.`)}}export{u as streamQuotesFactory};
1
+ import{ErrorReason as e,InvalidParamsError as t}from"../../../errors.js";import{caip2ToEip155ChainId as n}from"../../../utils/caip.js";import{isEvmNamespace as r,isSolanaNamespace as i}from"../../../_utils/chain.js";import{isEvmAddress as a}from"../../../utils/evm-address.js";import{markrStreamQuote as o}from"../_api.js";import{isSolAddress as s}from"../../../utils/sol-address.js";import{assetToAddressString as c,quoteFromMarkrQuoteResponseData as l}from"../_utils.js";function u({apiOptions:e,appId:t,partnerFeeBps:i}){return(a,s,u)=>{let f=new AbortController,{userEvmAddress:p,userSolanaAddress:m,validationError:h}=d(a,u);return h?(s(`error`,h),s(`done`),{cancel:()=>{}}):(o(e,{amount:a.amount.toString(),aggregator:a.aggregator,appId:t,chainId:r(a.sourceChain.chainId)?n(a.sourceChain.chainId):a.sourceChain.chainId,destinationChainId:a.sourceChain.chainId===a.targetChain.chainId?void 0:r(a.targetChain.chainId)?n(a.targetChain.chainId):a.targetChain.chainId,slippage:a.slippageBps,tokenIn:c(a.sourceAsset,a.sourceChain.chainId),tokenInDecimals:a.sourceAsset.decimals,tokenOut:c(a.targetAsset,a.targetChain.chainId),tokenOutDecimals:a.targetAsset.decimals,userEvmAddress:p,userSolanaAddress:m},{onDone:()=>{f.signal.aborted||s(`done`)},onError:e=>{f.signal.aborted||(s(`error`,e),s(`done`))},onQuote:e=>{f.signal.aborted||s(`quote`,l(e,a,i))},signal:f.signal}),{cancel:()=>{f.abort()}})}}function d(n,o){let c=n.sourceChain.chainId!==n.targetChain.chainId,l=!c,u=r(n.sourceChain.chainId),d=r(n.targetChain.chainId),f=i(n.sourceChain.chainId),p=i(n.targetChain.chainId),m=o?.dangerouslyAllowAddressMismatch===!0,h=n.fromAddress!==n.toAddress,g=n=>({userEvmAddress:void 0,userSolanaAddress:void 0,validationError:new t(e.INVALID_PARAMS,n)});if(u&&!a(n.fromAddress))return g(`Invalid fromAddress for EVM source chain.`);if(d&&!a(n.toAddress))return g(`Invalid toAddress for EVM target chain.`);if(f&&!s(n.fromAddress))return g(`Invalid fromAddress for Solana source chain.`);if(p&&!s(n.toAddress))return g(`Invalid toAddress for Solana target chain.`);if(c&&(u&&d||f&&p)&&h&&!m)return g(`fromAddress and toAddress must match for same-namespace cross-chain swaps.`);if(l){if(h&&!m)return g(`fromAddress and toAddress must match for same-chain swaps.`);if(!m)return{userEvmAddress:void 0,userSolanaAddress:void 0}}return{userEvmAddress:d&&a(n.toAddress)?n.toAddress:u&&a(n.fromAddress)?n.fromAddress:void 0,userSolanaAddress:p&&s(n.toAddress)?n.toAddress:f&&s(n.fromAddress)?n.fromAddress:void 0}}export{u as streamQuotesFactory};
2
2
  //# sourceMappingURL=stream-quotes.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"stream-quotes.js","names":[],"sources":["../../../../src/transfer-service/markr/_handlers/stream-quotes.ts"],"sourcesContent":["import { caip2ToEip155ChainId } from '../../../utils/caip';\nimport type { ServiceQuoteOptions, TransferService } from '../../../types/service';\nimport { markrStreamQuote, type ApiOptions, type MarkrStreamQuoteParams } from '../_api';\nimport { assetToAddressString, quoteFromMarkrQuoteResponseData } from '../_utils';\nimport { isEvmNamespace, isSolanaNamespace } from '../../../_utils/chain';\nimport { isEvmAddress } from '../../../utils/evm-address';\nimport { isSolAddress } from '../../../utils/sol-address';\nimport { ErrorReason, InvalidParamsError } from '../../../errors';\n\nexport interface StreamQuotesFactoryConfig {\n apiOptions: ApiOptions;\n appId: string;\n partnerFeeBps: number;\n}\n\nexport function streamQuotesFactory({\n apiOptions,\n appId,\n partnerFeeBps,\n}: StreamQuotesFactoryConfig): TransferService['streamQuotes'] {\n return (props, handler, options) => {\n const ac = new AbortController();\n const { userEvmAddress, userSolanaAddress, validationError } = _validateAndGetUserAddresses(props, options);\n\n if (validationError) {\n handler('error', validationError);\n handler('done');\n\n return {\n cancel: () => {},\n };\n }\n\n void markrStreamQuote(\n apiOptions,\n {\n amount: props.amount.toString(),\n // Forwarded only when the caller pins one; otherwise Markr races every aggregator.\n aggregator: props.aggregator,\n appId,\n chainId: isEvmNamespace(props.sourceChain.chainId)\n ? caip2ToEip155ChainId(props.sourceChain.chainId)\n : props.sourceChain.chainId,\n // For cross-chain requests, destinationChainId is required.\n // Use EVM numeric chain IDs for EVM targets and CAIP-2 IDs for non-EVM targets.\n destinationChainId:\n props.sourceChain.chainId !== props.targetChain.chainId\n ? isEvmNamespace(props.targetChain.chainId)\n ? caip2ToEip155ChainId(props.targetChain.chainId)\n : props.targetChain.chainId\n : undefined,\n slippage: props.slippageBps,\n tokenIn: assetToAddressString(props.sourceAsset, props.sourceChain.chainId),\n tokenInDecimals: props.sourceAsset.decimals,\n tokenOut: assetToAddressString(props.targetAsset, props.targetChain.chainId),\n tokenOutDecimals: props.targetAsset.decimals,\n userEvmAddress,\n userSolanaAddress,\n },\n {\n onDone: () => {\n if (!ac.signal.aborted) {\n handler('done');\n }\n },\n onError: (error) => {\n if (!ac.signal.aborted) {\n handler('error', error);\n handler('done');\n }\n },\n onQuote: (data) => {\n if (!ac.signal.aborted) {\n handler('quote', quoteFromMarkrQuoteResponseData(data, props, partnerFeeBps));\n }\n },\n signal: ac.signal,\n },\n );\n\n return {\n cancel: () => {\n ac.abort();\n },\n };\n };\n}\n\nexport function _validateAndGetUserAddresses(\n props: Parameters<TransferService['streamQuotes']>[0],\n options?: ServiceQuoteOptions,\n): Pick<MarkrStreamQuoteParams, 'userEvmAddress' | 'userSolanaAddress'> & { validationError?: InvalidParamsError } {\n const isCrossChainSwap = props.sourceChain.chainId !== props.targetChain.chainId;\n const sourceIsEvm = isEvmNamespace(props.sourceChain.chainId);\n const targetIsEvm = isEvmNamespace(props.targetChain.chainId);\n const sourceIsSolana = isSolanaNamespace(props.sourceChain.chainId);\n const targetIsSolana = isSolanaNamespace(props.targetChain.chainId);\n\n if (sourceIsEvm && !isEvmAddress(props.fromAddress)) {\n return {\n userEvmAddress: undefined,\n userSolanaAddress: undefined,\n validationError: new InvalidParamsError(ErrorReason.INVALID_PARAMS, 'Invalid fromAddress for EVM source chain.'),\n };\n }\n\n if (targetIsEvm && !isEvmAddress(props.toAddress)) {\n return {\n userEvmAddress: undefined,\n userSolanaAddress: undefined,\n validationError: new InvalidParamsError(ErrorReason.INVALID_PARAMS, 'Invalid toAddress for EVM target chain.'),\n };\n }\n\n if (sourceIsSolana && !isSolAddress(props.fromAddress)) {\n return {\n userEvmAddress: undefined,\n userSolanaAddress: undefined,\n validationError: new InvalidParamsError(\n ErrorReason.INVALID_PARAMS,\n 'Invalid fromAddress for Solana source chain.',\n ),\n };\n }\n\n if (targetIsSolana && !isSolAddress(props.toAddress)) {\n return {\n userEvmAddress: undefined,\n userSolanaAddress: undefined,\n validationError: new InvalidParamsError(ErrorReason.INVALID_PARAMS, 'Invalid toAddress for Solana target chain.'),\n };\n }\n\n if (\n isCrossChainSwap &&\n ((sourceIsEvm && targetIsEvm) || (sourceIsSolana && targetIsSolana)) &&\n !options?.dangerouslyAllowAddressMismatch\n ) {\n if (props.fromAddress !== props.toAddress) {\n return {\n userEvmAddress: undefined,\n userSolanaAddress: undefined,\n validationError: new InvalidParamsError(\n ErrorReason.INVALID_PARAMS,\n 'fromAddress and toAddress must match for same-namespace cross-chain swaps.',\n ),\n };\n }\n }\n\n if (!isCrossChainSwap) {\n if (props.fromAddress !== props.toAddress) {\n return {\n userEvmAddress: undefined,\n userSolanaAddress: undefined,\n validationError: new InvalidParamsError(\n ErrorReason.INVALID_PARAMS,\n 'fromAddress and toAddress must match for same-chain swaps.',\n ),\n };\n }\n\n return {\n userEvmAddress: undefined,\n userSolanaAddress: undefined,\n };\n }\n\n const userEvmAddress =\n targetIsEvm && isEvmAddress(props.toAddress)\n ? props.toAddress\n : sourceIsEvm && isEvmAddress(props.fromAddress)\n ? props.fromAddress\n : undefined;\n\n const userSolanaAddress =\n targetIsSolana && isSolAddress(props.toAddress)\n ? props.toAddress\n : sourceIsSolana && isSolAddress(props.fromAddress)\n ? props.fromAddress\n : undefined;\n\n return {\n userEvmAddress,\n userSolanaAddress,\n };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"stream-quotes.js","names":[],"sources":["../../../../src/transfer-service/markr/_handlers/stream-quotes.ts"],"sourcesContent":["import { caip2ToEip155ChainId } from '../../../utils/caip';\nimport type { ServiceQuoteOptions, TransferService } from '../../../types/service';\nimport { markrStreamQuote, type ApiOptions, type MarkrStreamQuoteParams } from '../_api';\nimport { assetToAddressString, quoteFromMarkrQuoteResponseData } from '../_utils';\nimport { isEvmNamespace, isSolanaNamespace } from '../../../_utils/chain';\nimport { isEvmAddress } from '../../../utils/evm-address';\nimport { isSolAddress } from '../../../utils/sol-address';\nimport { ErrorReason, InvalidParamsError } from '../../../errors';\n\nexport interface StreamQuotesFactoryConfig {\n apiOptions: ApiOptions;\n appId: string;\n partnerFeeBps: number;\n}\n\nexport function streamQuotesFactory({\n apiOptions,\n appId,\n partnerFeeBps,\n}: StreamQuotesFactoryConfig): TransferService['streamQuotes'] {\n return (props, handler, options) => {\n const ac = new AbortController();\n const { userEvmAddress, userSolanaAddress, validationError } = _validateAndGetUserAddresses(props, options);\n\n if (validationError) {\n handler('error', validationError);\n handler('done');\n\n return {\n cancel: () => {},\n };\n }\n\n void markrStreamQuote(\n apiOptions,\n {\n amount: props.amount.toString(),\n // Forwarded only when the caller pins one; otherwise Markr races every aggregator.\n aggregator: props.aggregator,\n appId,\n chainId: isEvmNamespace(props.sourceChain.chainId)\n ? caip2ToEip155ChainId(props.sourceChain.chainId)\n : props.sourceChain.chainId,\n // For cross-chain requests, destinationChainId is required.\n // Use EVM numeric chain IDs for EVM targets and CAIP-2 IDs for non-EVM targets.\n destinationChainId:\n props.sourceChain.chainId !== props.targetChain.chainId\n ? isEvmNamespace(props.targetChain.chainId)\n ? caip2ToEip155ChainId(props.targetChain.chainId)\n : props.targetChain.chainId\n : undefined,\n slippage: props.slippageBps,\n tokenIn: assetToAddressString(props.sourceAsset, props.sourceChain.chainId),\n tokenInDecimals: props.sourceAsset.decimals,\n tokenOut: assetToAddressString(props.targetAsset, props.targetChain.chainId),\n tokenOutDecimals: props.targetAsset.decimals,\n userEvmAddress,\n userSolanaAddress,\n },\n {\n onDone: () => {\n if (!ac.signal.aborted) {\n handler('done');\n }\n },\n onError: (error) => {\n if (!ac.signal.aborted) {\n handler('error', error);\n handler('done');\n }\n },\n onQuote: (data) => {\n if (!ac.signal.aborted) {\n handler('quote', quoteFromMarkrQuoteResponseData(data, props, partnerFeeBps));\n }\n },\n signal: ac.signal,\n },\n );\n\n return {\n cancel: () => {\n ac.abort();\n },\n };\n };\n}\n\nexport function _validateAndGetUserAddresses(\n props: Parameters<TransferService['streamQuotes']>[0],\n options?: ServiceQuoteOptions,\n): Pick<MarkrStreamQuoteParams, 'userEvmAddress' | 'userSolanaAddress'> & { validationError?: InvalidParamsError } {\n const isCrossChainSwap = props.sourceChain.chainId !== props.targetChain.chainId;\n const isSameChainSwap = !isCrossChainSwap;\n const sourceIsEvm = isEvmNamespace(props.sourceChain.chainId);\n const targetIsEvm = isEvmNamespace(props.targetChain.chainId);\n const sourceIsSolana = isSolanaNamespace(props.sourceChain.chainId);\n const targetIsSolana = isSolanaNamespace(props.targetChain.chainId);\n const dangerouslyAllowAddressMismatch = options?.dangerouslyAllowAddressMismatch === true;\n const addressesMismatch = props.fromAddress !== props.toAddress;\n\n const invalidParams = (details: string) => ({\n userEvmAddress: undefined,\n userSolanaAddress: undefined,\n validationError: new InvalidParamsError(ErrorReason.INVALID_PARAMS, details),\n });\n\n if (sourceIsEvm && !isEvmAddress(props.fromAddress)) {\n return invalidParams('Invalid fromAddress for EVM source chain.');\n }\n\n if (targetIsEvm && !isEvmAddress(props.toAddress)) {\n return invalidParams('Invalid toAddress for EVM target chain.');\n }\n\n if (sourceIsSolana && !isSolAddress(props.fromAddress)) {\n return invalidParams('Invalid fromAddress for Solana source chain.');\n }\n\n if (targetIsSolana && !isSolAddress(props.toAddress)) {\n return invalidParams('Invalid toAddress for Solana target chain.');\n }\n\n const isSameNamespaceCrossChainSwap =\n isCrossChainSwap && ((sourceIsEvm && targetIsEvm) || (sourceIsSolana && targetIsSolana));\n\n if (isSameNamespaceCrossChainSwap && addressesMismatch && !dangerouslyAllowAddressMismatch) {\n return invalidParams('fromAddress and toAddress must match for same-namespace cross-chain swaps.');\n }\n\n if (isSameChainSwap) {\n if (addressesMismatch && !dangerouslyAllowAddressMismatch) {\n return invalidParams('fromAddress and toAddress must match for same-chain swaps.');\n }\n\n if (!dangerouslyAllowAddressMismatch) {\n return {\n userEvmAddress: undefined,\n userSolanaAddress: undefined,\n };\n }\n }\n\n const userEvmAddress =\n targetIsEvm && isEvmAddress(props.toAddress)\n ? props.toAddress\n : sourceIsEvm && isEvmAddress(props.fromAddress)\n ? props.fromAddress\n : undefined;\n\n const userSolanaAddress =\n targetIsSolana && isSolAddress(props.toAddress)\n ? props.toAddress\n : sourceIsSolana && isSolAddress(props.fromAddress)\n ? props.fromAddress\n : undefined;\n\n return {\n userEvmAddress,\n userSolanaAddress,\n };\n}\n"],"mappings":"ydAeA,SAAgB,EAAoB,CAClC,aACA,QACA,iBAC6D,CAC7D,OAAQ,EAAO,EAAS,IAAY,CAClC,IAAM,EAAK,IAAI,gBACT,CAAE,iBAAgB,oBAAmB,mBAAoB,EAA6B,EAAO,EAAQ,CA0D3G,OAxDI,GACF,EAAQ,QAAS,EAAgB,CACjC,EAAQ,OAAO,CAER,CACL,WAAc,GACf,GAGE,EACH,EACA,CACE,OAAQ,EAAM,OAAO,UAAU,CAE/B,WAAY,EAAM,WAClB,QACA,QAAS,EAAe,EAAM,YAAY,QAAQ,CAC9C,EAAqB,EAAM,YAAY,QAAQ,CAC/C,EAAM,YAAY,QAGtB,mBACE,EAAM,YAAY,UAAY,EAAM,YAAY,QAI5C,IAAA,GAHA,EAAe,EAAM,YAAY,QAAQ,CACvC,EAAqB,EAAM,YAAY,QAAQ,CAC/C,EAAM,YAAY,QAE1B,SAAU,EAAM,YAChB,QAAS,EAAqB,EAAM,YAAa,EAAM,YAAY,QAAQ,CAC3E,gBAAiB,EAAM,YAAY,SACnC,SAAU,EAAqB,EAAM,YAAa,EAAM,YAAY,QAAQ,CAC5E,iBAAkB,EAAM,YAAY,SACpC,iBACA,oBACD,CACD,CACE,WAAc,CACP,EAAG,OAAO,SACb,EAAQ,OAAO,EAGnB,QAAU,GAAU,CACb,EAAG,OAAO,UACb,EAAQ,QAAS,EAAM,CACvB,EAAQ,OAAO,GAGnB,QAAU,GAAS,CACZ,EAAG,OAAO,SACb,EAAQ,QAAS,EAAgC,EAAM,EAAO,EAAc,CAAC,EAGjF,OAAQ,EAAG,OACZ,CACF,CAEM,CACL,WAAc,CACZ,EAAG,OAAO,EAEb,GAIL,SAAgB,EACd,EACA,EACiH,CACjH,IAAM,EAAmB,EAAM,YAAY,UAAY,EAAM,YAAY,QACnE,EAAkB,CAAC,EACnB,EAAc,EAAe,EAAM,YAAY,QAAQ,CACvD,EAAc,EAAe,EAAM,YAAY,QAAQ,CACvD,EAAiB,EAAkB,EAAM,YAAY,QAAQ,CAC7D,EAAiB,EAAkB,EAAM,YAAY,QAAQ,CAC7D,EAAkC,GAAS,kCAAoC,GAC/E,EAAoB,EAAM,cAAgB,EAAM,UAEhD,EAAiB,IAAqB,CAC1C,eAAgB,IAAA,GAChB,kBAAmB,IAAA,GACnB,gBAAiB,IAAI,EAAmB,EAAY,eAAgB,EAAQ,CAC7E,EAED,GAAI,GAAe,CAAC,EAAa,EAAM,YAAY,CACjD,OAAO,EAAc,4CAA4C,CAGnE,GAAI,GAAe,CAAC,EAAa,EAAM,UAAU,CAC/C,OAAO,EAAc,0CAA0C,CAGjE,GAAI,GAAkB,CAAC,EAAa,EAAM,YAAY,CACpD,OAAO,EAAc,+CAA+C,CAGtE,GAAI,GAAkB,CAAC,EAAa,EAAM,UAAU,CAClD,OAAO,EAAc,6CAA6C,CAMpE,GAFE,IAAsB,GAAe,GAAiB,GAAkB,IAErC,GAAqB,CAAC,EACzD,OAAO,EAAc,6EAA6E,CAGpG,GAAI,EAAiB,CACnB,GAAI,GAAqB,CAAC,EACxB,OAAO,EAAc,6DAA6D,CAGpF,GAAI,CAAC,EACH,MAAO,CACL,eAAgB,IAAA,GAChB,kBAAmB,IAAA,GACpB,CAkBL,MAAO,CACL,eAdA,GAAe,EAAa,EAAM,UAAU,CACxC,EAAM,UACN,GAAe,EAAa,EAAM,YAAY,CAC9C,EAAM,YACN,IAAA,GAWJ,kBARA,GAAkB,EAAa,EAAM,UAAU,CAC3C,EAAM,UACN,GAAkB,EAAa,EAAM,YAAY,CACjD,EAAM,YACN,IAAA,GAKL"}
@@ -125,9 +125,11 @@ interface EstimateNativeFeeOptions {
125
125
  }
126
126
  interface ServiceQuoteOptions {
127
127
  /**
128
- * Dangerously allows cross-chain quotes where fromAddress and toAddress differ
128
+ * Dangerously allows quotes where fromAddress and toAddress differ,
129
129
  * even when a service would otherwise require them to match.
130
130
  *
131
+ * This applies to both same-chain and cross-chain quotes.
132
+ *
131
133
  * This is intended for explicit proxy-recipient funding flows. Services should
132
134
  * preserve their default address safety checks unless this is set.
133
135
  */
@@ -125,9 +125,11 @@ interface EstimateNativeFeeOptions {
125
125
  }
126
126
  interface ServiceQuoteOptions {
127
127
  /**
128
- * Dangerously allows cross-chain quotes where fromAddress and toAddress differ
128
+ * Dangerously allows quotes where fromAddress and toAddress differ,
129
129
  * even when a service would otherwise require them to match.
130
130
  *
131
+ * This applies to both same-chain and cross-chain quotes.
132
+ *
131
133
  * This is intended for explicit proxy-recipient funding flows. Services should
132
134
  * preserve their default address safety checks unless this is set.
133
135
  */
@@ -0,0 +1,2 @@
1
+ const e=require(`../constants.cjs`),t=e=>typeof e==`number`?`eip155:${e}`:e,n=e=>{let n=e.universalChainId??e.chainId;return n===void 0?``:t(n)},r=(e,t=n(e))=>e.name??e.chainName??t,i=t=>t===e.AvalancheChainIds.MAINNET||t===e.AvalancheChainIds.FUJI,a=t=>t===e.AvalancheMainnetBlockchainChainIds.P||t===e.AvalancheFujiBlockchainChainIds.P,o=t=>t===e.AvalancheMainnetBlockchainChainIds.X||t===e.AvalancheFujiBlockchainChainIds.X,s=t=>t===e.EthereumChainIds.MAINNET||t===e.EthereumChainIds.SEPOLIA,c=t=>t===e.BitcoinChainIds.MAINNET||t===e.BitcoinChainIds.TESTNET,l=t=>t===e.SolanaChainIds.MAINNET||t===e.SolanaChainIds.DEVNET,u=t=>t===e.BaseChainIds.MAINNET||t===e.BaseChainIds.SEPOLIA,d=t=>t===e.PolygonChainIds.MAINNET||t===e.PolygonChainIds.AMOY,f=e=>{let r=typeof e==`object`?n(e):t(e);return i(r)?0:a(r)?1:o(r)?2:s(r)?3:c(r)?4:l(r)?5:u(r)?6:d(r)?7:8},p=(e,t)=>e===t?0:e<t?-1:1,m=(e,t)=>{let i=n(e),a=n(t),o=f(i)-f(a);if(o!==0)return o;let s=r(e,i).localeCompare(r(t,a),`en-US`);return s===0?p(i,a):s},h=e=>[...e].sort(m);exports.compareDestinationChains=m,exports.getDestinationChainPriority=f,exports.sortDestinationChains=h;
2
+ //# sourceMappingURL=destination-chains.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"destination-chains.cjs","names":["AvalancheChainIds","AvalancheMainnetBlockchainChainIds","AvalancheFujiBlockchainChainIds","EthereumChainIds","BitcoinChainIds","SolanaChainIds","BaseChainIds","PolygonChainIds"],"sources":["../../src/utils/destination-chains.ts"],"sourcesContent":["import {\n AvalancheChainIds,\n AvalancheFujiBlockchainChainIds,\n AvalancheMainnetBlockchainChainIds,\n BaseChainIds,\n BitcoinChainIds,\n EthereumChainIds,\n PolygonChainIds,\n SolanaChainIds,\n} from '../constants';\n\ntype ChainIdentifier = number | string;\n\n/**\n * Chain shape accepted by the destination chain sorting utilities.\n *\n * Supports Fusion `Chain` objects (`chainId`, `chainName`) and app-level chain\n * info objects (`universalChainId`, `name`).\n */\nexport type DestinationChainSortInput = Readonly<{\n chainId?: ChainIdentifier;\n chainName?: string;\n name?: string;\n universalChainId?: ChainIdentifier;\n}> &\n ({ readonly chainId: ChainIdentifier } | { readonly universalChainId: ChainIdentifier });\n\nconst DESTINATION_CHAIN_SORT_LOCALE = 'en-US';\n\nconst asCaip2ChainId = (chainId: ChainIdentifier): string => {\n return typeof chainId === 'number' ? `eip155:${chainId}` : chainId;\n};\n\nconst getDestinationChainId = (chain: DestinationChainSortInput): string => {\n const chainId = chain.universalChainId ?? chain.chainId;\n\n return chainId === undefined ? '' : asCaip2ChainId(chainId);\n};\n\nconst getDestinationChainName = (chain: DestinationChainSortInput, chainId = getDestinationChainId(chain)): string => {\n return chain.name ?? chain.chainName ?? chainId;\n};\n\nconst isCChainId = (chainId: string): boolean => {\n return chainId === AvalancheChainIds.MAINNET || chainId === AvalancheChainIds.FUJI;\n};\n\nconst isPChainId = (chainId: string): boolean => {\n return chainId === AvalancheMainnetBlockchainChainIds.P || chainId === AvalancheFujiBlockchainChainIds.P;\n};\n\nconst isXChainId = (chainId: string): boolean => {\n return chainId === AvalancheMainnetBlockchainChainIds.X || chainId === AvalancheFujiBlockchainChainIds.X;\n};\n\nconst isEthereumChainId = (chainId: string): boolean => {\n return chainId === EthereumChainIds.MAINNET || chainId === EthereumChainIds.SEPOLIA;\n};\n\nconst isBitcoinChainId = (chainId: string): boolean => {\n return chainId === BitcoinChainIds.MAINNET || chainId === BitcoinChainIds.TESTNET;\n};\n\nconst isSolanaChainId = (chainId: string): boolean => {\n return chainId === SolanaChainIds.MAINNET || chainId === SolanaChainIds.DEVNET;\n};\n\nconst isBaseChainId = (chainId: string): boolean => {\n return chainId === BaseChainIds.MAINNET || chainId === BaseChainIds.SEPOLIA;\n};\n\nconst isPolygonChainId = (chainId: string): boolean => {\n return chainId === PolygonChainIds.MAINNET || chainId === PolygonChainIds.AMOY;\n};\n\n/**\n * Returns the deterministic display priority for a destination chain.\n *\n * Lower values sort first. Numeric chain IDs are treated as EIP-155 IDs.\n *\n * Priority order:\n * C-Chain, P-Chain, X-Chain, Ethereum, Bitcoin/BVM, Solana, Base, Polygon, then unknown chains.\n *\n * @param chain - Chain object, CAIP-2 chain ID, or numeric EIP-155 chain ID to prioritize.\n * @returns Numeric priority used by {@link compareDestinationChains}.\n */\nexport const getDestinationChainPriority = (chain: DestinationChainSortInput | ChainIdentifier): number => {\n const chainId = typeof chain === 'object' ? getDestinationChainId(chain) : asCaip2ChainId(chain);\n\n if (isCChainId(chainId)) {\n return 0;\n }\n if (isPChainId(chainId)) {\n return 1;\n }\n if (isXChainId(chainId)) {\n return 2;\n }\n if (isEthereumChainId(chainId)) {\n return 3;\n }\n if (isBitcoinChainId(chainId)) {\n return 4;\n }\n if (isSolanaChainId(chainId)) {\n return 5;\n }\n if (isBaseChainId(chainId)) {\n return 6;\n }\n if (isPolygonChainId(chainId)) {\n return 7;\n }\n\n return 8;\n};\n\nconst compareLexically = (a: string, b: string): number => (a === b ? 0 : a < b ? -1 : 1);\n\n/**\n * Compares two destination chains using shared Fusion SDK destination ordering.\n *\n * Sorts by priority first, then by display name, then by chain ID for a stable tie-breaker.\n *\n * @param a - First chain to compare.\n * @param b - Second chain to compare.\n * @returns Negative when `a` sorts first, positive when `b` sorts first, or zero when equivalent.\n */\nexport const compareDestinationChains = <TChain extends DestinationChainSortInput>(a: TChain, b: TChain): number => {\n const aChainId = getDestinationChainId(a);\n const bChainId = getDestinationChainId(b);\n const priorityDifference = getDestinationChainPriority(aChainId) - getDestinationChainPriority(bChainId);\n\n if (priorityDifference !== 0) {\n return priorityDifference;\n }\n\n // Names are user-facing labels, so locale-aware ordering is still appropriate here.\n const nameDifference = getDestinationChainName(a, aChainId).localeCompare(\n getDestinationChainName(b, bChainId),\n DESTINATION_CHAIN_SORT_LOCALE,\n );\n\n if (nameDifference !== 0) {\n return nameDifference;\n }\n\n // Chain IDs are technical identifiers, so use raw lexical ordering for a deterministic final tie-breaker.\n return compareLexically(aChainId, bChainId);\n};\n\n/**\n * Returns a new array of destination chains sorted with {@link compareDestinationChains}.\n *\n * The input array is not mutated.\n *\n * @param chains - Destination chains to sort.\n * @returns Sorted copy of the provided chains.\n */\nexport const sortDestinationChains = <TChain extends DestinationChainSortInput>(\n chains: readonly TChain[],\n): readonly TChain[] => {\n return [...chains].sort(compareDestinationChains);\n};\n"],"mappings":"oCA6BM,EAAkB,GACf,OAAO,GAAY,SAAW,UAAU,IAAY,EAGvD,EAAyB,GAA6C,CAC1E,IAAM,EAAU,EAAM,kBAAoB,EAAM,QAEhD,OAAO,IAAY,IAAA,GAAY,GAAK,EAAe,EAAQ,EAGvD,GAA2B,EAAkC,EAAU,EAAsB,EAAM,GAChG,EAAM,MAAQ,EAAM,WAAa,EAGpC,EAAc,GACX,IAAYA,EAAAA,kBAAkB,SAAW,IAAYA,EAAAA,kBAAkB,KAG1E,EAAc,GACX,IAAYC,EAAAA,mCAAmC,GAAK,IAAYC,EAAAA,gCAAgC,EAGnG,EAAc,GACX,IAAYD,EAAAA,mCAAmC,GAAK,IAAYC,EAAAA,gCAAgC,EAGnG,EAAqB,GAClB,IAAYC,EAAAA,iBAAiB,SAAW,IAAYA,EAAAA,iBAAiB,QAGxE,EAAoB,GACjB,IAAYC,EAAAA,gBAAgB,SAAW,IAAYA,EAAAA,gBAAgB,QAGtE,EAAmB,GAChB,IAAYC,EAAAA,eAAe,SAAW,IAAYA,EAAAA,eAAe,OAGpE,EAAiB,GACd,IAAYC,EAAAA,aAAa,SAAW,IAAYA,EAAAA,aAAa,QAGhE,EAAoB,GACjB,IAAYC,EAAAA,gBAAgB,SAAW,IAAYA,EAAAA,gBAAgB,KAc/D,EAA+B,GAA+D,CACzG,IAAM,EAAU,OAAO,GAAU,SAAW,EAAsB,EAAM,CAAG,EAAe,EAAM,CA2BhG,OAzBI,EAAW,EAAQ,CACd,EAEL,EAAW,EAAQ,CACd,EAEL,EAAW,EAAQ,CACd,EAEL,EAAkB,EAAQ,CACrB,EAEL,EAAiB,EAAQ,CACpB,EAEL,EAAgB,EAAQ,CACnB,EAEL,EAAc,EAAQ,CACjB,EAEL,EAAiB,EAAQ,CACpB,EAGF,GAGH,GAAoB,EAAW,IAAuB,IAAM,EAAI,EAAI,EAAI,EAAI,GAAK,EAW1E,GAAsE,EAAW,IAAsB,CAClH,IAAM,EAAW,EAAsB,EAAE,CACnC,EAAW,EAAsB,EAAE,CACnC,EAAqB,EAA4B,EAAS,CAAG,EAA4B,EAAS,CAExG,GAAI,IAAuB,EACzB,OAAO,EAIT,IAAM,EAAiB,EAAwB,EAAG,EAAS,CAAC,cAC1D,EAAwB,EAAG,EAAS,CACpC,QACD,CAOD,OALI,IAAmB,EAKhB,EAAiB,EAAU,EAAS,CAJlC,GAeE,EACX,GAEO,CAAC,GAAG,EAAO,CAAC,KAAK,EAAyB"}
@@ -0,0 +1,52 @@
1
+ //#region src/utils/destination-chains.d.ts
2
+ type ChainIdentifier = number | string;
3
+ /**
4
+ * Chain shape accepted by the destination chain sorting utilities.
5
+ *
6
+ * Supports Fusion `Chain` objects (`chainId`, `chainName`) and app-level chain
7
+ * info objects (`universalChainId`, `name`).
8
+ */
9
+ type DestinationChainSortInput = Readonly<{
10
+ chainId?: ChainIdentifier;
11
+ chainName?: string;
12
+ name?: string;
13
+ universalChainId?: ChainIdentifier;
14
+ }> & ({
15
+ readonly chainId: ChainIdentifier;
16
+ } | {
17
+ readonly universalChainId: ChainIdentifier;
18
+ });
19
+ /**
20
+ * Returns the deterministic display priority for a destination chain.
21
+ *
22
+ * Lower values sort first. Numeric chain IDs are treated as EIP-155 IDs.
23
+ *
24
+ * Priority order:
25
+ * C-Chain, P-Chain, X-Chain, Ethereum, Bitcoin/BVM, Solana, Base, Polygon, then unknown chains.
26
+ *
27
+ * @param chain - Chain object, CAIP-2 chain ID, or numeric EIP-155 chain ID to prioritize.
28
+ * @returns Numeric priority used by {@link compareDestinationChains}.
29
+ */
30
+ declare const getDestinationChainPriority: (chain: DestinationChainSortInput | ChainIdentifier) => number;
31
+ /**
32
+ * Compares two destination chains using shared Fusion SDK destination ordering.
33
+ *
34
+ * Sorts by priority first, then by display name, then by chain ID for a stable tie-breaker.
35
+ *
36
+ * @param a - First chain to compare.
37
+ * @param b - Second chain to compare.
38
+ * @returns Negative when `a` sorts first, positive when `b` sorts first, or zero when equivalent.
39
+ */
40
+ declare const compareDestinationChains: <TChain extends DestinationChainSortInput>(a: TChain, b: TChain) => number;
41
+ /**
42
+ * Returns a new array of destination chains sorted with {@link compareDestinationChains}.
43
+ *
44
+ * The input array is not mutated.
45
+ *
46
+ * @param chains - Destination chains to sort.
47
+ * @returns Sorted copy of the provided chains.
48
+ */
49
+ declare const sortDestinationChains: <TChain extends DestinationChainSortInput>(chains: readonly TChain[]) => readonly TChain[];
50
+ //#endregion
51
+ export { DestinationChainSortInput, compareDestinationChains, getDestinationChainPriority, sortDestinationChains };
52
+ //# sourceMappingURL=destination-chains.d.cts.map
@@ -0,0 +1,52 @@
1
+ //#region src/utils/destination-chains.d.ts
2
+ type ChainIdentifier = number | string;
3
+ /**
4
+ * Chain shape accepted by the destination chain sorting utilities.
5
+ *
6
+ * Supports Fusion `Chain` objects (`chainId`, `chainName`) and app-level chain
7
+ * info objects (`universalChainId`, `name`).
8
+ */
9
+ type DestinationChainSortInput = Readonly<{
10
+ chainId?: ChainIdentifier;
11
+ chainName?: string;
12
+ name?: string;
13
+ universalChainId?: ChainIdentifier;
14
+ }> & ({
15
+ readonly chainId: ChainIdentifier;
16
+ } | {
17
+ readonly universalChainId: ChainIdentifier;
18
+ });
19
+ /**
20
+ * Returns the deterministic display priority for a destination chain.
21
+ *
22
+ * Lower values sort first. Numeric chain IDs are treated as EIP-155 IDs.
23
+ *
24
+ * Priority order:
25
+ * C-Chain, P-Chain, X-Chain, Ethereum, Bitcoin/BVM, Solana, Base, Polygon, then unknown chains.
26
+ *
27
+ * @param chain - Chain object, CAIP-2 chain ID, or numeric EIP-155 chain ID to prioritize.
28
+ * @returns Numeric priority used by {@link compareDestinationChains}.
29
+ */
30
+ declare const getDestinationChainPriority: (chain: DestinationChainSortInput | ChainIdentifier) => number;
31
+ /**
32
+ * Compares two destination chains using shared Fusion SDK destination ordering.
33
+ *
34
+ * Sorts by priority first, then by display name, then by chain ID for a stable tie-breaker.
35
+ *
36
+ * @param a - First chain to compare.
37
+ * @param b - Second chain to compare.
38
+ * @returns Negative when `a` sorts first, positive when `b` sorts first, or zero when equivalent.
39
+ */
40
+ declare const compareDestinationChains: <TChain extends DestinationChainSortInput>(a: TChain, b: TChain) => number;
41
+ /**
42
+ * Returns a new array of destination chains sorted with {@link compareDestinationChains}.
43
+ *
44
+ * The input array is not mutated.
45
+ *
46
+ * @param chains - Destination chains to sort.
47
+ * @returns Sorted copy of the provided chains.
48
+ */
49
+ declare const sortDestinationChains: <TChain extends DestinationChainSortInput>(chains: readonly TChain[]) => readonly TChain[];
50
+ //#endregion
51
+ export { DestinationChainSortInput, compareDestinationChains, getDestinationChainPriority, sortDestinationChains };
52
+ //# sourceMappingURL=destination-chains.d.ts.map
@@ -0,0 +1,2 @@
1
+ import{AvalancheChainIds as e,AvalancheFujiBlockchainChainIds as t,AvalancheMainnetBlockchainChainIds as n,BaseChainIds as r,BitcoinChainIds as i,EthereumChainIds as a,PolygonChainIds as o,SolanaChainIds as s}from"../constants.js";const c=e=>typeof e==`number`?`eip155:${e}`:e,l=e=>{let t=e.universalChainId??e.chainId;return t===void 0?``:c(t)},u=(e,t=l(e))=>e.name??e.chainName??t,d=t=>t===e.MAINNET||t===e.FUJI,f=e=>e===n.P||e===t.P,p=e=>e===n.X||e===t.X,m=e=>e===a.MAINNET||e===a.SEPOLIA,h=e=>e===i.MAINNET||e===i.TESTNET,g=e=>e===s.MAINNET||e===s.DEVNET,_=e=>e===r.MAINNET||e===r.SEPOLIA,v=e=>e===o.MAINNET||e===o.AMOY,y=e=>{let t=typeof e==`object`?l(e):c(e);return d(t)?0:f(t)?1:p(t)?2:m(t)?3:h(t)?4:g(t)?5:_(t)?6:v(t)?7:8},b=(e,t)=>e===t?0:e<t?-1:1,x=(e,t)=>{let n=l(e),r=l(t),i=y(n)-y(r);if(i!==0)return i;let a=u(e,n).localeCompare(u(t,r),`en-US`);return a===0?b(n,r):a},S=e=>[...e].sort(x);export{x as compareDestinationChains,y as getDestinationChainPriority,S as sortDestinationChains};
2
+ //# sourceMappingURL=destination-chains.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"destination-chains.js","names":[],"sources":["../../src/utils/destination-chains.ts"],"sourcesContent":["import {\n AvalancheChainIds,\n AvalancheFujiBlockchainChainIds,\n AvalancheMainnetBlockchainChainIds,\n BaseChainIds,\n BitcoinChainIds,\n EthereumChainIds,\n PolygonChainIds,\n SolanaChainIds,\n} from '../constants';\n\ntype ChainIdentifier = number | string;\n\n/**\n * Chain shape accepted by the destination chain sorting utilities.\n *\n * Supports Fusion `Chain` objects (`chainId`, `chainName`) and app-level chain\n * info objects (`universalChainId`, `name`).\n */\nexport type DestinationChainSortInput = Readonly<{\n chainId?: ChainIdentifier;\n chainName?: string;\n name?: string;\n universalChainId?: ChainIdentifier;\n}> &\n ({ readonly chainId: ChainIdentifier } | { readonly universalChainId: ChainIdentifier });\n\nconst DESTINATION_CHAIN_SORT_LOCALE = 'en-US';\n\nconst asCaip2ChainId = (chainId: ChainIdentifier): string => {\n return typeof chainId === 'number' ? `eip155:${chainId}` : chainId;\n};\n\nconst getDestinationChainId = (chain: DestinationChainSortInput): string => {\n const chainId = chain.universalChainId ?? chain.chainId;\n\n return chainId === undefined ? '' : asCaip2ChainId(chainId);\n};\n\nconst getDestinationChainName = (chain: DestinationChainSortInput, chainId = getDestinationChainId(chain)): string => {\n return chain.name ?? chain.chainName ?? chainId;\n};\n\nconst isCChainId = (chainId: string): boolean => {\n return chainId === AvalancheChainIds.MAINNET || chainId === AvalancheChainIds.FUJI;\n};\n\nconst isPChainId = (chainId: string): boolean => {\n return chainId === AvalancheMainnetBlockchainChainIds.P || chainId === AvalancheFujiBlockchainChainIds.P;\n};\n\nconst isXChainId = (chainId: string): boolean => {\n return chainId === AvalancheMainnetBlockchainChainIds.X || chainId === AvalancheFujiBlockchainChainIds.X;\n};\n\nconst isEthereumChainId = (chainId: string): boolean => {\n return chainId === EthereumChainIds.MAINNET || chainId === EthereumChainIds.SEPOLIA;\n};\n\nconst isBitcoinChainId = (chainId: string): boolean => {\n return chainId === BitcoinChainIds.MAINNET || chainId === BitcoinChainIds.TESTNET;\n};\n\nconst isSolanaChainId = (chainId: string): boolean => {\n return chainId === SolanaChainIds.MAINNET || chainId === SolanaChainIds.DEVNET;\n};\n\nconst isBaseChainId = (chainId: string): boolean => {\n return chainId === BaseChainIds.MAINNET || chainId === BaseChainIds.SEPOLIA;\n};\n\nconst isPolygonChainId = (chainId: string): boolean => {\n return chainId === PolygonChainIds.MAINNET || chainId === PolygonChainIds.AMOY;\n};\n\n/**\n * Returns the deterministic display priority for a destination chain.\n *\n * Lower values sort first. Numeric chain IDs are treated as EIP-155 IDs.\n *\n * Priority order:\n * C-Chain, P-Chain, X-Chain, Ethereum, Bitcoin/BVM, Solana, Base, Polygon, then unknown chains.\n *\n * @param chain - Chain object, CAIP-2 chain ID, or numeric EIP-155 chain ID to prioritize.\n * @returns Numeric priority used by {@link compareDestinationChains}.\n */\nexport const getDestinationChainPriority = (chain: DestinationChainSortInput | ChainIdentifier): number => {\n const chainId = typeof chain === 'object' ? getDestinationChainId(chain) : asCaip2ChainId(chain);\n\n if (isCChainId(chainId)) {\n return 0;\n }\n if (isPChainId(chainId)) {\n return 1;\n }\n if (isXChainId(chainId)) {\n return 2;\n }\n if (isEthereumChainId(chainId)) {\n return 3;\n }\n if (isBitcoinChainId(chainId)) {\n return 4;\n }\n if (isSolanaChainId(chainId)) {\n return 5;\n }\n if (isBaseChainId(chainId)) {\n return 6;\n }\n if (isPolygonChainId(chainId)) {\n return 7;\n }\n\n return 8;\n};\n\nconst compareLexically = (a: string, b: string): number => (a === b ? 0 : a < b ? -1 : 1);\n\n/**\n * Compares two destination chains using shared Fusion SDK destination ordering.\n *\n * Sorts by priority first, then by display name, then by chain ID for a stable tie-breaker.\n *\n * @param a - First chain to compare.\n * @param b - Second chain to compare.\n * @returns Negative when `a` sorts first, positive when `b` sorts first, or zero when equivalent.\n */\nexport const compareDestinationChains = <TChain extends DestinationChainSortInput>(a: TChain, b: TChain): number => {\n const aChainId = getDestinationChainId(a);\n const bChainId = getDestinationChainId(b);\n const priorityDifference = getDestinationChainPriority(aChainId) - getDestinationChainPriority(bChainId);\n\n if (priorityDifference !== 0) {\n return priorityDifference;\n }\n\n // Names are user-facing labels, so locale-aware ordering is still appropriate here.\n const nameDifference = getDestinationChainName(a, aChainId).localeCompare(\n getDestinationChainName(b, bChainId),\n DESTINATION_CHAIN_SORT_LOCALE,\n );\n\n if (nameDifference !== 0) {\n return nameDifference;\n }\n\n // Chain IDs are technical identifiers, so use raw lexical ordering for a deterministic final tie-breaker.\n return compareLexically(aChainId, bChainId);\n};\n\n/**\n * Returns a new array of destination chains sorted with {@link compareDestinationChains}.\n *\n * The input array is not mutated.\n *\n * @param chains - Destination chains to sort.\n * @returns Sorted copy of the provided chains.\n */\nexport const sortDestinationChains = <TChain extends DestinationChainSortInput>(\n chains: readonly TChain[],\n): readonly TChain[] => {\n return [...chains].sort(compareDestinationChains);\n};\n"],"mappings":"uOA2BA,MAEM,EAAkB,GACf,OAAO,GAAY,SAAW,UAAU,IAAY,EAGvD,EAAyB,GAA6C,CAC1E,IAAM,EAAU,EAAM,kBAAoB,EAAM,QAEhD,OAAO,IAAY,IAAA,GAAY,GAAK,EAAe,EAAQ,EAGvD,GAA2B,EAAkC,EAAU,EAAsB,EAAM,GAChG,EAAM,MAAQ,EAAM,WAAa,EAGpC,EAAc,GACX,IAAY,EAAkB,SAAW,IAAY,EAAkB,KAG1E,EAAc,GACX,IAAY,EAAmC,GAAK,IAAY,EAAgC,EAGnG,EAAc,GACX,IAAY,EAAmC,GAAK,IAAY,EAAgC,EAGnG,EAAqB,GAClB,IAAY,EAAiB,SAAW,IAAY,EAAiB,QAGxE,EAAoB,GACjB,IAAY,EAAgB,SAAW,IAAY,EAAgB,QAGtE,EAAmB,GAChB,IAAY,EAAe,SAAW,IAAY,EAAe,OAGpE,EAAiB,GACd,IAAY,EAAa,SAAW,IAAY,EAAa,QAGhE,EAAoB,GACjB,IAAY,EAAgB,SAAW,IAAY,EAAgB,KAc/D,EAA+B,GAA+D,CACzG,IAAM,EAAU,OAAO,GAAU,SAAW,EAAsB,EAAM,CAAG,EAAe,EAAM,CA2BhG,OAzBI,EAAW,EAAQ,CACd,EAEL,EAAW,EAAQ,CACd,EAEL,EAAW,EAAQ,CACd,EAEL,EAAkB,EAAQ,CACrB,EAEL,EAAiB,EAAQ,CACpB,EAEL,EAAgB,EAAQ,CACnB,EAEL,EAAc,EAAQ,CACjB,EAEL,EAAiB,EAAQ,CACpB,EAGF,GAGH,GAAoB,EAAW,IAAuB,IAAM,EAAI,EAAI,EAAI,EAAI,GAAK,EAW1E,GAAsE,EAAW,IAAsB,CAClH,IAAM,EAAW,EAAsB,EAAE,CACnC,EAAW,EAAsB,EAAE,CACnC,EAAqB,EAA4B,EAAS,CAAG,EAA4B,EAAS,CAExG,GAAI,IAAuB,EACzB,OAAO,EAIT,IAAM,EAAiB,EAAwB,EAAG,EAAS,CAAC,cAC1D,EAAwB,EAAG,EAAS,CACpC,QACD,CAOD,OALI,IAAmB,EAKhB,EAAiB,EAAU,EAAS,CAJlC,GAeE,EACX,GAEO,CAAC,GAAG,EAAO,CAAC,KAAK,EAAyB"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@avalabs/fusion-sdk",
3
3
  "license": "Limited Ecosystem License",
4
- "version": "0.23.0",
4
+ "version": "0.24.0",
5
5
  "type": "module",
6
6
  "main": "./dist/mod.cjs",
7
7
  "module": "./dist/mod.js",
@@ -49,8 +49,8 @@
49
49
  "vitest": "4.0.6",
50
50
  "tsdown": "0.21.4",
51
51
  "zod": "4.1.12",
52
- "eslint-config-custom": "0.1.0",
53
- "@internal/tsdown-config": "0.0.1"
52
+ "@internal/tsdown-config": "0.0.1",
53
+ "eslint-config-custom": "0.1.0"
54
54
  },
55
55
  "sideEffects": false,
56
56
  "scripts": {