@avalabs/fusion-sdk 0.15.1 → 0.17.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.
- package/dist/constants.cjs +1 -1
- package/dist/constants.cjs.map +1 -1
- package/dist/constants.d.cts +21 -1
- package/dist/constants.d.ts +21 -1
- package/dist/constants.js +1 -1
- package/dist/constants.js.map +1 -1
- package/dist/errors.cjs +1 -1
- package/dist/errors.cjs.map +1 -1
- package/dist/errors.js +1 -1
- package/dist/errors.js.map +1 -1
- package/dist/mod.cjs +1 -1
- package/dist/mod.d.cts +7 -5
- package/dist/mod.d.ts +7 -5
- package/dist/mod.js +1 -1
- package/dist/quoter/quoter.cjs +1 -1
- package/dist/quoter/quoter.cjs.map +1 -1
- package/dist/quoter/quoter.js +1 -1
- package/dist/quoter/quoter.js.map +1 -1
- package/dist/transfer-manager.cjs +1 -1
- package/dist/transfer-manager.cjs.map +1 -1
- package/dist/transfer-manager.js +1 -1
- package/dist/transfer-manager.js.map +1 -1
- package/dist/transfer-service/_evm-gas.cjs +1 -1
- package/dist/transfer-service/_evm-gas.js +1 -1
- package/dist/transfer-service/_utils.cjs +1 -1
- package/dist/transfer-service/_utils.cjs.map +1 -1
- package/dist/transfer-service/_utils.js +1 -1
- package/dist/transfer-service/_utils.js.map +1 -1
- package/dist/transfer-service/avalanche-cct/_handlers/analyze-support.cjs +2 -0
- package/dist/transfer-service/avalanche-cct/_handlers/analyze-support.cjs.map +1 -0
- package/dist/transfer-service/avalanche-cct/_handlers/analyze-support.js +2 -0
- package/dist/transfer-service/avalanche-cct/_handlers/analyze-support.js.map +1 -0
- package/dist/transfer-service/avalanche-cct/_handlers/estimate-native-fee.cjs +2 -0
- package/dist/transfer-service/avalanche-cct/_handlers/estimate-native-fee.cjs.map +1 -0
- package/dist/transfer-service/avalanche-cct/_handlers/estimate-native-fee.js +2 -0
- package/dist/transfer-service/avalanche-cct/_handlers/estimate-native-fee.js.map +1 -0
- package/dist/transfer-service/avalanche-cct/_handlers/get-bridgeable-assets.cjs +2 -0
- package/dist/transfer-service/avalanche-cct/_handlers/get-bridgeable-assets.cjs.map +1 -0
- package/dist/transfer-service/avalanche-cct/_handlers/get-bridgeable-assets.js +2 -0
- package/dist/transfer-service/avalanche-cct/_handlers/get-bridgeable-assets.js.map +1 -0
- package/dist/transfer-service/avalanche-cct/_handlers/get-minimum-transfer-amount.cjs +2 -0
- package/dist/transfer-service/avalanche-cct/_handlers/get-minimum-transfer-amount.cjs.map +1 -0
- package/dist/transfer-service/avalanche-cct/_handlers/get-minimum-transfer-amount.js +2 -0
- package/dist/transfer-service/avalanche-cct/_handlers/get-minimum-transfer-amount.js.map +1 -0
- package/dist/transfer-service/avalanche-cct/_handlers/get-supported-chains.cjs +2 -0
- package/dist/transfer-service/avalanche-cct/_handlers/get-supported-chains.cjs.map +1 -0
- package/dist/transfer-service/avalanche-cct/_handlers/get-supported-chains.js +2 -0
- package/dist/transfer-service/avalanche-cct/_handlers/get-supported-chains.js.map +1 -0
- package/dist/transfer-service/avalanche-cct/_handlers/stream-quotes.cjs +2 -0
- package/dist/transfer-service/avalanche-cct/_handlers/stream-quotes.cjs.map +1 -0
- package/dist/transfer-service/avalanche-cct/_handlers/stream-quotes.js +2 -0
- package/dist/transfer-service/avalanche-cct/_handlers/stream-quotes.js.map +1 -0
- package/dist/transfer-service/avalanche-cct/_handlers/track-transfer.cjs +2 -0
- package/dist/transfer-service/avalanche-cct/_handlers/track-transfer.cjs.map +1 -0
- package/dist/transfer-service/avalanche-cct/_handlers/track-transfer.js +2 -0
- package/dist/transfer-service/avalanche-cct/_handlers/track-transfer.js.map +1 -0
- package/dist/transfer-service/avalanche-cct/_handlers/transfer-asset.cjs +2 -0
- package/dist/transfer-service/avalanche-cct/_handlers/transfer-asset.cjs.map +1 -0
- package/dist/transfer-service/avalanche-cct/_handlers/transfer-asset.js +2 -0
- package/dist/transfer-service/avalanche-cct/_handlers/transfer-asset.js.map +1 -0
- package/dist/transfer-service/avalanche-cct/_type-guards.cjs +2 -0
- package/dist/transfer-service/avalanche-cct/_type-guards.cjs.map +1 -0
- package/dist/transfer-service/avalanche-cct/_type-guards.js +2 -0
- package/dist/transfer-service/avalanche-cct/_type-guards.js.map +1 -0
- package/dist/transfer-service/avalanche-cct/_utils/addresses.cjs +2 -0
- package/dist/transfer-service/avalanche-cct/_utils/addresses.cjs.map +1 -0
- package/dist/transfer-service/avalanche-cct/_utils/addresses.js +2 -0
- package/dist/transfer-service/avalanche-cct/_utils/addresses.js.map +1 -0
- package/dist/transfer-service/avalanche-cct/_utils/fees.cjs +2 -0
- package/dist/transfer-service/avalanche-cct/_utils/fees.cjs.map +1 -0
- package/dist/transfer-service/avalanche-cct/_utils/fees.js +2 -0
- package/dist/transfer-service/avalanche-cct/_utils/fees.js.map +1 -0
- package/dist/transfer-service/avalanche-cct/_utils/p-chain.cjs +2 -0
- package/dist/transfer-service/avalanche-cct/_utils/p-chain.cjs.map +1 -0
- package/dist/transfer-service/avalanche-cct/_utils/p-chain.js +2 -0
- package/dist/transfer-service/avalanche-cct/_utils/p-chain.js.map +1 -0
- package/dist/transfer-service/avalanche-cct/_utils/polling.cjs +2 -0
- package/dist/transfer-service/avalanche-cct/_utils/polling.cjs.map +1 -0
- package/dist/transfer-service/avalanche-cct/_utils/polling.js +2 -0
- package/dist/transfer-service/avalanche-cct/_utils/polling.js.map +1 -0
- package/dist/transfer-service/avalanche-cct/_utils/transactions.cjs +2 -0
- package/dist/transfer-service/avalanche-cct/_utils/transactions.cjs.map +1 -0
- package/dist/transfer-service/avalanche-cct/_utils/transactions.js +2 -0
- package/dist/transfer-service/avalanche-cct/_utils/transactions.js.map +1 -0
- package/dist/transfer-service/avalanche-cct/_utils.cjs +2 -0
- package/dist/transfer-service/avalanche-cct/_utils.cjs.map +1 -0
- package/dist/transfer-service/avalanche-cct/_utils.js +2 -0
- package/dist/transfer-service/avalanche-cct/_utils.js.map +1 -0
- package/dist/transfer-service/avalanche-cct/avalanche-cct-service.cjs +2 -0
- package/dist/transfer-service/avalanche-cct/avalanche-cct-service.cjs.map +1 -0
- package/dist/transfer-service/avalanche-cct/avalanche-cct-service.js +2 -0
- package/dist/transfer-service/avalanche-cct/avalanche-cct-service.js.map +1 -0
- package/dist/transfer-service/avalanche-cct/constants.cjs +2 -0
- package/dist/transfer-service/avalanche-cct/constants.cjs.map +1 -0
- package/dist/transfer-service/avalanche-cct/constants.js +2 -0
- package/dist/transfer-service/avalanche-cct/constants.js.map +1 -0
- package/dist/transfer-service/avalanche-cct/types.d.cts +33 -0
- package/dist/transfer-service/avalanche-cct/types.d.ts +33 -0
- package/dist/transfer-service/avalanche-evm/_handlers/get-bridgeable-assets.cjs +1 -1
- package/dist/transfer-service/avalanche-evm/_handlers/get-bridgeable-assets.cjs.map +1 -1
- package/dist/transfer-service/avalanche-evm/_handlers/get-bridgeable-assets.js +1 -1
- package/dist/transfer-service/avalanche-evm/_handlers/get-bridgeable-assets.js.map +1 -1
- package/dist/transfer-service/avalanche-evm/_handlers/transfer-asset.cjs +1 -1
- package/dist/transfer-service/avalanche-evm/_handlers/transfer-asset.js +1 -1
- package/dist/transfer-service/avalanche-evm/_utils/wrap.cjs +1 -1
- package/dist/transfer-service/avalanche-evm/_utils/wrap.js +1 -1
- package/dist/transfer-service/fetch-utilities.cjs +1 -1
- package/dist/transfer-service/fetch-utilities.cjs.map +1 -1
- package/dist/transfer-service/fetch-utilities.js +1 -1
- package/dist/transfer-service/fetch-utilities.js.map +1 -1
- package/dist/transfer-service/lombard/btc-to-btcb/_handlers/get-bridgeable-assets.cjs +1 -1
- package/dist/transfer-service/lombard/btc-to-btcb/_handlers/get-bridgeable-assets.cjs.map +1 -1
- package/dist/transfer-service/lombard/btc-to-btcb/_handlers/get-bridgeable-assets.js +1 -1
- package/dist/transfer-service/lombard/btc-to-btcb/_handlers/get-bridgeable-assets.js.map +1 -1
- package/dist/transfer-service/lombard/btcb-to-btc/_handlers/get-bridgeable-assets.cjs +1 -1
- package/dist/transfer-service/lombard/btcb-to-btc/_handlers/get-bridgeable-assets.cjs.map +1 -1
- package/dist/transfer-service/lombard/btcb-to-btc/_handlers/get-bridgeable-assets.js +1 -1
- package/dist/transfer-service/lombard/btcb-to-btc/_handlers/get-bridgeable-assets.js.map +1 -1
- package/dist/transfer-service/markr/_handlers/estimate-native-fee.cjs +1 -1
- package/dist/transfer-service/markr/_handlers/estimate-native-fee.js +1 -1
- package/dist/transfer-service/markr/_handlers/get-bridgeable-assets.cjs +1 -1
- package/dist/transfer-service/markr/_handlers/get-bridgeable-assets.cjs.map +1 -1
- package/dist/transfer-service/markr/_handlers/get-bridgeable-assets.js +1 -1
- package/dist/transfer-service/markr/_handlers/get-bridgeable-assets.js.map +1 -1
- package/dist/transfer-service/markr/_handlers/track-transfer.cjs +1 -1
- package/dist/transfer-service/markr/_handlers/track-transfer.js +1 -1
- package/dist/transfer-service/markr/_handlers/transfer-asset.cjs +1 -1
- package/dist/transfer-service/markr/_handlers/transfer-asset.js +1 -1
- package/dist/transfer-service/markr/_schema.cjs +1 -1
- package/dist/transfer-service/markr/_schema.cjs.map +1 -1
- package/dist/transfer-service/markr/_schema.js +1 -1
- package/dist/transfer-service/markr/_schema.js.map +1 -1
- package/dist/transfer-service/markr/markr-service.cjs.map +1 -1
- package/dist/transfer-service/markr/markr-service.js.map +1 -1
- package/dist/transfer-service/service-schemas.cjs +1 -1
- package/dist/transfer-service/service-schemas.cjs.map +1 -1
- package/dist/transfer-service/service-schemas.js +1 -1
- package/dist/transfer-service/service-schemas.js.map +1 -1
- package/dist/transfer-service/wrap-unwrap/_handlers/get-bridgeable-assets.cjs +1 -1
- package/dist/transfer-service/wrap-unwrap/_handlers/get-bridgeable-assets.cjs.map +1 -1
- package/dist/transfer-service/wrap-unwrap/_handlers/get-bridgeable-assets.js +1 -1
- package/dist/transfer-service/wrap-unwrap/_handlers/get-bridgeable-assets.js.map +1 -1
- package/dist/transfer-service/wrap-unwrap/_handlers/transfer-asset.cjs +1 -1
- package/dist/transfer-service/wrap-unwrap/_handlers/transfer-asset.js +1 -1
- package/dist/types/asset.d.cts +18 -2
- package/dist/types/asset.d.ts +18 -2
- package/dist/types/quote.d.cts +1 -1
- package/dist/types/quote.d.ts +1 -1
- package/dist/types/service.d.cts +95 -7
- package/dist/types/service.d.ts +95 -7
- package/dist/types/transfer-manager.d.cts +19 -10
- package/dist/types/transfer-manager.d.ts +19 -10
- package/dist/types/utility-types.d.cts +8 -1
- package/dist/types/utility-types.d.ts +8 -1
- package/dist/utils/asset-id.cjs +1 -1
- package/dist/utils/asset-id.cjs.map +1 -1
- package/dist/utils/asset-id.js +1 -1
- package/dist/utils/asset-id.js.map +1 -1
- package/dist/utils/bridgeable-assets.cjs +2 -0
- package/dist/utils/bridgeable-assets.cjs.map +1 -0
- package/dist/utils/bridgeable-assets.d.cts +16 -0
- package/dist/utils/bridgeable-assets.d.ts +16 -0
- package/dist/utils/bridgeable-assets.js +2 -0
- package/dist/utils/bridgeable-assets.js.map +1 -0
- package/dist/utils/transfer-utils.cjs +1 -1
- package/dist/utils/transfer-utils.cjs.map +1 -1
- package/dist/utils/transfer-utils.js +1 -1
- package/dist/utils/transfer-utils.js.map +1 -1
- package/package.json +5 -3
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transfer-manager.js","names":[],"sources":["../src/transfer-manager.ts"],"sourcesContent":["import { Environment, ServiceType } from './constants';\nimport { ErrorReason, InvalidParamsError, ServiceInitializationError, ServiceUnavailableError } from './errors';\nimport type { BridgeableUiAsset } from './types/asset';\nimport { isEnvironment, isServiceInitializer } from './type-guards';\nimport type { MutableGetSupportedChainsResult, ServiceInitializer, TransferService } from './types/service';\nimport type {\n CreateTransferManagerOptions,\n TransferManager,\n TransferManagerStatus,\n TransferManagerStatusServicesRecord,\n} from './types/transfer-manager';\nimport { Quoter } from './quoter/quoter';\nimport { getAssetId } from './utils/asset-id';\nimport type { Caip2ChainId } from './types/caip';\nimport type { Fetch } from './types/utility-types';\n\n/**\n * Validates the provided \"environment\" option.\n *\n * @throws {ServiceInitializationError} If the environment is invalid.\n */\nconst validateEnvironment = (environment: Environment): void => {\n if (!isEnvironment(environment)) {\n throw new ServiceInitializationError(ErrorReason.ENVIRONMENT_NOT_SUPPORTED);\n }\n};\n\n/**\n * Validates the provided \"serviceInitializers\" option.\n *\n * Checks for the following:\n * - At least one service initializer is provided.\n * - All service initializers are valid.\n * - No duplicate service types are initialized.\n *\n * @throws {ServiceInitializationError} If the service initializers are invalid.\n */\nconst validateServiceInitializers = (serviceInitializers: readonly ServiceInitializer[]): void => {\n if (serviceInitializers.length === 0) {\n throw new ServiceInitializationError('No service initializers provided.');\n }\n\n if (serviceInitializers.some((serviceInitializer) => !isServiceInitializer(serviceInitializer))) {\n throw new ServiceInitializationError('One or more service initializers are invalid.');\n }\n\n const serviceInitializerTypes = new Set<ServiceType>();\n for (const initializer of serviceInitializers) {\n if (serviceInitializerTypes.has(initializer.type)) {\n throw new ServiceInitializationError(\n ErrorReason.DUPLICATE_SERVICE_INITIALIZATION,\n `Service type \"${initializer.type}\" has been initialized more than once.`,\n );\n }\n serviceInitializerTypes.add(initializer.type);\n }\n};\n\nconst initializeServices = async ({\n environment,\n serviceInitializers,\n fetch: customFetch,\n}: {\n environment: Environment;\n serviceInitializers: readonly ServiceInitializer[];\n fetch?: Fetch;\n}): Promise<{\n services: Map<ServiceType, TransferService>;\n status: TransferManagerStatus;\n}> => {\n const initializedServicesMap: Map<ServiceType, TransferService> = new Map();\n const serviceStatuses: TransferManagerStatusServicesRecord = {};\n\n const wrapInitializationError = (serviceType: ServiceType, error: unknown): ServiceInitializationError => {\n if (error instanceof ServiceInitializationError) {\n return error;\n }\n\n const details = error instanceof Error ? error.message : String(error);\n\n return new ServiceInitializationError(\n ErrorReason.UNKNOWN,\n `Failed to initialize service type \"${serviceType}\". ${details}`,\n error,\n );\n };\n\n const initializeService = async (\n serviceType: ServiceType,\n initializer: () => Promise<TransferService>,\n ): Promise<void> => {\n try {\n const service = await initializer();\n initializedServicesMap.set(serviceType, service);\n serviceStatuses[serviceType] = { status: 'initialized' };\n } catch (error) {\n const wrappedError = wrapInitializationError(serviceType, error);\n\n serviceStatuses[serviceType] = {\n status: 'error',\n error: wrappedError,\n };\n }\n };\n\n for (const initializer of serviceInitializers) {\n // Error on duplicate initialization attempts.\n if (initializedServicesMap.has(initializer.type)) {\n throw new ServiceInitializationError(\n ErrorReason.DUPLICATE_SERVICE_INITIALIZATION,\n `Service type \"${initializer.type}\" has been initialized more than once.`,\n );\n }\n\n switch (initializer.type) {\n case ServiceType.AVALANCHE_EVM: {\n await initializeService(ServiceType.AVALANCHE_EVM, async () => {\n const { createAvalancheEvmService } = await import('./transfer-service/avalanche-evm/avalanche-evm-service');\n\n return await createAvalancheEvmService({\n environment,\n evmSigner: initializer.evmSigner,\n fetch: customFetch,\n });\n });\n\n break;\n }\n\n case ServiceType.LOMBARD_BTCB_TO_BTC: {\n await initializeService(ServiceType.LOMBARD_BTCB_TO_BTC, async () => {\n const { createBtcbToBtcService } = await import('./transfer-service/lombard/btcb-to-btc-service');\n\n return await createBtcbToBtcService({\n bitcoinFunctions: initializer.btcFunctions,\n environment,\n evmSigner: initializer.evmSigner,\n fetch: customFetch,\n });\n });\n\n break;\n }\n\n case ServiceType.LOMBARD_BTC_TO_BTCB: {\n await initializeService(ServiceType.LOMBARD_BTC_TO_BTCB, async () => {\n const { createBtcToBtcbService } = await import('./transfer-service/lombard/btc-to-btcb-service');\n\n return await createBtcToBtcbService({\n bitcoinFunctions: initializer.btcFunctions,\n btcSigner: initializer.btcSigner,\n environment,\n evmSigner: initializer.evmSigner,\n fetch: customFetch,\n });\n });\n\n break;\n }\n\n case ServiceType.MARKR: {\n if (environment !== Environment.PROD) {\n serviceStatuses[ServiceType.MARKR] = {\n status: 'unsupported-environment',\n message: `Service type \"${ServiceType.MARKR}\" is only supported in production environment.`,\n };\n break;\n }\n\n await initializeService(ServiceType.MARKR, async () => {\n const { createMarkrService } = await import('./transfer-service/markr/markr-service');\n\n return await createMarkrService({\n apiBaseUrl: initializer.markrApiUrl,\n apiToken: initializer.markrApiToken,\n appId: initializer.markrAppId,\n disableCrossChainSwaps: initializer.disableCrossChainSwaps,\n fetch: customFetch,\n environment,\n evmSigner: initializer.evmSigner,\n getTargetChainAssets: initializer.getTargetChainAssets,\n solanaSigner: initializer.solanaSigner,\n });\n });\n\n break;\n }\n\n case ServiceType.WRAP_UNWRAP: {\n await initializeService(ServiceType.WRAP_UNWRAP, async () => {\n const { createWrapUnwrapService } = await import('./transfer-service/wrap-unwrap/wrap-unwrap-service');\n\n return await createWrapUnwrapService({\n environment,\n evmSigner: initializer.evmSigner,\n fetch: customFetch,\n });\n });\n\n break;\n }\n\n default: {\n break;\n }\n }\n }\n\n return {\n services: initializedServicesMap,\n status: {\n environment,\n services: serviceStatuses,\n },\n };\n};\n\n/**\n * Creates a TransferManager instance.\n *\n * @returns {Promise<TransferManager>} The TransferManager instance.\n * @throws {ServiceInitializationError} If the provided options are invalid.\n */\nexport const createTransferManager = async ({\n environment,\n fetch: customFetch,\n serviceInitializers,\n}: CreateTransferManagerOptions): Promise<TransferManager> => {\n // Validate environment.\n validateEnvironment(environment);\n validateServiceInitializers(serviceInitializers);\n\n const { services, status } = await initializeServices({ environment, serviceInitializers, fetch: customFetch });\n\n return {\n id: crypto.randomUUID(),\n estimateNativeFee: async (quote, options) => {\n const now = Math.floor(Date.now() / 1_000);\n\n if (quote.expiresAt <= now) {\n const expiredSecondsAgo = now - quote.expiresAt;\n\n throw new InvalidParamsError(ErrorReason.QUOTE_EXPIRED, `Quote expired ${expiredSecondsAgo} seconds ago.`);\n }\n\n const service = services.get(quote.serviceType);\n\n if (!service) {\n throw new ServiceUnavailableError(ErrorReason.SERVICE_TYPE_NOT_CONFIGURED);\n }\n\n return await service.estimateNativeFee(quote, options);\n },\n getBridgeableAssets: async ({ sourceAsset, sourceChainId, targetChainId }) => {\n const settledResults = await Promise.allSettled(\n Array.from(services.values()).map((service) =>\n service.getBridgeableAssets({ sourceAsset, sourceChainId, targetChainId }),\n ),\n );\n\n const merged = new Map<string, BridgeableUiAsset>();\n\n for (const settled of settledResults) {\n if (settled.status !== 'fulfilled') continue;\n for (const result of settled.value) {\n const { bridgeProviders, ...asset } = result;\n const key = getAssetId(targetChainId, asset);\n\n const existing = merged.get(key);\n if (existing) {\n const combined = [...new Set([...existing.bridgeProviders, ...bridgeProviders])];\n merged.set(key, { ...existing, bridgeProviders: combined });\n } else {\n merged.set(key, { ...asset, bridgeProviders: [...bridgeProviders] });\n }\n }\n }\n\n return Array.from(merged.values());\n },\n getMinimumTransferAmount: async (props) => {\n const serviceMinimums: { [key in ServiceType]?: bigint } = {};\n\n for (const service of services.values()) {\n if (service.analyzeSupport(props)) {\n const serviceMinAmount = await service.getMinimumTransferAmount(props);\n serviceMinimums[service.type] = serviceMinAmount;\n }\n }\n\n return Object.keys(serviceMinimums).length > 0 ? serviceMinimums : null;\n },\n getSupportedChains: async () => {\n const supportedChainsMap: MutableGetSupportedChainsResult = new Map();\n\n // Fetch supported chains from all configured services in parallel.\n const serviceResults = await Promise.all(\n Array.from(services.values()).map((service) => service.getSupportedChains()),\n );\n\n // Merge results: union destination sets for identical source chain IDs.\n for (const result of serviceResults) {\n for (const [sourceChainId, targetChainIds] of result.entries()) {\n let mergedTargets = supportedChainsMap.get(sourceChainId);\n if (!mergedTargets) {\n mergedTargets = new Set<Caip2ChainId>();\n supportedChainsMap.set(sourceChainId, mergedTargets);\n }\n\n for (const targetChainId of targetChainIds) {\n mergedTargets.add(targetChainId);\n }\n }\n }\n\n return supportedChainsMap;\n },\n getQuoter: (props, options) => {\n return new Quoter(props, Array.from(services.values()), options);\n },\n status: () => status,\n trackTransfer: (props) => {\n const { transfer } = props;\n const service = services.get(transfer.type);\n\n if (!service) {\n throw new ServiceUnavailableError(ErrorReason.SERVICE_TYPE_NOT_CONFIGURED);\n }\n\n return service.trackTransfer(props);\n },\n transferAsset: async (props) => {\n const { quote } = props;\n const service = services.get(quote.serviceType);\n\n if (!service) {\n throw new ServiceUnavailableError(ErrorReason.SERVICE_TYPE_NOT_CONFIGURED);\n }\n\n return await service.transferAsset(props);\n },\n } satisfies TransferManager;\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"transfer-manager.js","names":[],"sources":["../src/transfer-manager.ts"],"sourcesContent":["import { Environment, ServiceType } from './constants';\nimport { ErrorReason, InvalidParamsError, ServiceInitializationError, ServiceUnavailableError } from './errors';\nimport type { BridgeableUiAsset } from './types/asset';\nimport { isEnvironment, isServiceInitializer } from './type-guards';\nimport type { MutableGetSupportedChainsResult, ServiceInitializer, TransferService } from './types/service';\nimport type {\n CreateTransferManagerOptions,\n TransferManager,\n TransferManagerStatus,\n TransferManagerStatusServicesRecord,\n} from './types/transfer-manager';\nimport { Quoter } from './quoter/quoter';\nimport type { Caip2ChainId } from './types/caip';\nimport type { Fetch } from './types/utility-types';\n\n/**\n * Validates the provided \"environment\" option.\n *\n * @throws {ServiceInitializationError} If the environment is invalid.\n */\nconst validateEnvironment = (environment: Environment): void => {\n if (!isEnvironment(environment)) {\n throw new ServiceInitializationError(ErrorReason.ENVIRONMENT_NOT_SUPPORTED);\n }\n};\n\n/**\n * Validates the provided \"serviceInitializers\" option.\n *\n * Checks for the following:\n * - At least one service initializer is provided.\n * - All service initializers are valid.\n * - No duplicate service types are initialized.\n *\n * @throws {ServiceInitializationError} If the service initializers are invalid.\n */\nconst validateServiceInitializers = (serviceInitializers: readonly ServiceInitializer[]): void => {\n if (serviceInitializers.length === 0) {\n throw new ServiceInitializationError('No service initializers provided.');\n }\n\n if (serviceInitializers.some((serviceInitializer) => !isServiceInitializer(serviceInitializer))) {\n throw new ServiceInitializationError('One or more service initializers are invalid.');\n }\n\n const serviceInitializerTypes = new Set<ServiceType>();\n for (const initializer of serviceInitializers) {\n if (serviceInitializerTypes.has(initializer.type)) {\n throw new ServiceInitializationError(\n ErrorReason.DUPLICATE_SERVICE_INITIALIZATION,\n `Service type \"${initializer.type}\" has been initialized more than once.`,\n );\n }\n serviceInitializerTypes.add(initializer.type);\n }\n};\n\nconst initializeServices = async ({\n environment,\n serviceInitializers,\n fetch: customFetch,\n}: {\n environment: Environment;\n serviceInitializers: readonly ServiceInitializer[];\n fetch?: Fetch;\n}): Promise<{\n services: Map<ServiceType, TransferService>;\n status: TransferManagerStatus;\n}> => {\n const initializedServicesMap: Map<ServiceType, TransferService> = new Map();\n const serviceStatuses: TransferManagerStatusServicesRecord = {};\n\n const wrapInitializationError = (serviceType: ServiceType, error: unknown): ServiceInitializationError => {\n if (error instanceof ServiceInitializationError) {\n return error;\n }\n\n const details = error instanceof Error ? error.message : String(error);\n\n return new ServiceInitializationError(\n ErrorReason.UNKNOWN,\n `Failed to initialize service type \"${serviceType}\". ${details}`,\n error,\n );\n };\n\n const initializeService = async (\n serviceType: ServiceType,\n initializer: () => Promise<TransferService>,\n ): Promise<void> => {\n try {\n const service = await initializer();\n initializedServicesMap.set(serviceType, service);\n serviceStatuses[serviceType] = { status: 'initialized' };\n } catch (error) {\n const wrappedError = wrapInitializationError(serviceType, error);\n\n serviceStatuses[serviceType] = {\n status: 'error',\n error: wrappedError,\n };\n }\n };\n\n for (const initializer of serviceInitializers) {\n // Error on duplicate initialization attempts.\n if (initializedServicesMap.has(initializer.type)) {\n throw new ServiceInitializationError(\n ErrorReason.DUPLICATE_SERVICE_INITIALIZATION,\n `Service type \"${initializer.type}\" has been initialized more than once.`,\n );\n }\n\n switch (initializer.type) {\n case ServiceType.AVALANCHE_CCT: {\n if (!(environment === Environment.PROD || environment === Environment.TEST)) {\n serviceStatuses[ServiceType.AVALANCHE_CCT] = {\n status: 'unsupported-environment',\n message: `Service type \"${ServiceType.AVALANCHE_CCT}\" is only supported in production or test environment.`,\n };\n break;\n }\n\n await initializeService(ServiceType.AVALANCHE_CCT, async () => {\n const { createAvalancheCctService } = await import('./transfer-service/avalanche-cct/avalanche-cct-service');\n\n return await createAvalancheCctService({\n avalancheSendTx: initializer.avalancheSendTx,\n environment,\n fetch: customFetch,\n getCoreEthAddress: initializer.getCoreEthAddress,\n getAtomicUtxos: initializer.getAtomicUtxos,\n getUtxos: initializer.getUtxos,\n getWalletAddressesForChainAlias: initializer.getWalletAddressesForChainAlias,\n getWalletChangeAddressForChainAlias: initializer.getWalletChangeAddressForChainAlias,\n });\n });\n\n break;\n }\n\n case ServiceType.AVALANCHE_EVM: {\n await initializeService(ServiceType.AVALANCHE_EVM, async () => {\n const { createAvalancheEvmService } = await import('./transfer-service/avalanche-evm/avalanche-evm-service');\n\n return await createAvalancheEvmService({\n environment,\n evmSigner: initializer.evmSigner,\n fetch: customFetch,\n });\n });\n\n break;\n }\n\n case ServiceType.LOMBARD_BTCB_TO_BTC: {\n await initializeService(ServiceType.LOMBARD_BTCB_TO_BTC, async () => {\n const { createBtcbToBtcService } = await import('./transfer-service/lombard/btcb-to-btc-service');\n\n return await createBtcbToBtcService({\n bitcoinFunctions: initializer.btcFunctions,\n environment,\n evmSigner: initializer.evmSigner,\n fetch: customFetch,\n });\n });\n\n break;\n }\n\n case ServiceType.LOMBARD_BTC_TO_BTCB: {\n await initializeService(ServiceType.LOMBARD_BTC_TO_BTCB, async () => {\n const { createBtcToBtcbService } = await import('./transfer-service/lombard/btc-to-btcb-service');\n\n return await createBtcToBtcbService({\n bitcoinFunctions: initializer.btcFunctions,\n btcSigner: initializer.btcSigner,\n environment,\n evmSigner: initializer.evmSigner,\n fetch: customFetch,\n });\n });\n\n break;\n }\n\n case ServiceType.MARKR: {\n if (environment !== Environment.PROD) {\n serviceStatuses[ServiceType.MARKR] = {\n status: 'unsupported-environment',\n message: `Service type \"${ServiceType.MARKR}\" is only supported in production environment.`,\n };\n break;\n }\n\n await initializeService(ServiceType.MARKR, async () => {\n const { createMarkrService } = await import('./transfer-service/markr/markr-service');\n\n return await createMarkrService({\n apiBaseUrl: initializer.markrApiUrl,\n apiToken: initializer.markrApiToken,\n appId: initializer.markrAppId,\n disableCrossChainSwaps: initializer.disableCrossChainSwaps,\n fetch: customFetch,\n environment,\n evmSigner: initializer.evmSigner,\n getTargetChainAssets: initializer.getTargetChainAssets,\n solanaSigner: initializer.solanaSigner,\n });\n });\n\n break;\n }\n\n case ServiceType.WRAP_UNWRAP: {\n await initializeService(ServiceType.WRAP_UNWRAP, async () => {\n const { createWrapUnwrapService } = await import('./transfer-service/wrap-unwrap/wrap-unwrap-service');\n\n return await createWrapUnwrapService({\n environment,\n evmSigner: initializer.evmSigner,\n fetch: customFetch,\n });\n });\n\n break;\n }\n\n default: {\n break;\n }\n }\n }\n\n return {\n services: initializedServicesMap,\n status: {\n environment,\n services: serviceStatuses,\n },\n };\n};\n\n/**\n * Creates a TransferManager instance.\n *\n * @returns {Promise<TransferManager>} The TransferManager instance.\n * @throws {ServiceInitializationError} If the provided options are invalid.\n */\nexport const createTransferManager = async ({\n environment,\n fetch: customFetch,\n serviceInitializers,\n}: CreateTransferManagerOptions): Promise<TransferManager> => {\n // Validate environment.\n validateEnvironment(environment);\n validateServiceInitializers(serviceInitializers);\n\n const { services, status } = await initializeServices({ environment, serviceInitializers, fetch: customFetch });\n\n return {\n id: crypto.randomUUID(),\n estimateNativeFee: async (quote, options) => {\n const now = Math.floor(Date.now() / 1_000);\n\n if (quote.expiresAt <= now) {\n const expiredSecondsAgo = now - quote.expiresAt;\n\n throw new InvalidParamsError(ErrorReason.QUOTE_EXPIRED, `Quote expired ${expiredSecondsAgo} seconds ago.`);\n }\n\n const service = services.get(quote.serviceType);\n\n if (!service) {\n throw new ServiceUnavailableError(ErrorReason.SERVICE_TYPE_NOT_CONFIGURED);\n }\n\n return await service.estimateNativeFee(quote, options);\n },\n getBridgeableAssets: async ({ sourceAsset, sourceChainId, targetChainId, limit, search, page }) => {\n if (limit !== undefined && (!Number.isInteger(limit) || limit <= 0)) {\n throw new InvalidParamsError(\n ErrorReason.INVALID_PARAMS,\n `Invalid \"limit\" provided: ${String(limit)}. Expected a positive integer.`,\n );\n }\n if (page !== undefined && (!Number.isInteger(page) || page <= 0)) {\n throw new InvalidParamsError(\n ErrorReason.INVALID_PARAMS,\n `Invalid \"page\" provided: ${String(page)}. Expected a positive integer.`,\n );\n }\n\n const pageLimit = limit ?? 100;\n const currentPage = page ?? 1;\n const configuredServices = Array.from(services.values());\n const nonMarkrServices = configuredServices\n .filter((service) => service.type !== ServiceType.MARKR)\n .sort((a, b) => a.type.localeCompare(b.type));\n const orderedServices = [\n ...configuredServices.filter((service) => service.type === ServiceType.MARKR),\n ...nonMarkrServices,\n ];\n\n const serviceResults = await Promise.all(\n orderedServices.map(async (service) => {\n try {\n const result = await service.getBridgeableAssets({\n sourceAsset,\n sourceChainId,\n targetChainId,\n limit: pageLimit,\n search,\n page: currentPage,\n });\n\n return { status: 'fulfilled' as const, result };\n } catch {\n return { status: 'rejected' as const };\n }\n }),\n );\n\n const combinedAssets: BridgeableUiAsset[] = [];\n let hasMore = false;\n\n for (const serviceResult of serviceResults) {\n if (serviceResult.status !== 'fulfilled') {\n continue;\n }\n\n combinedAssets.push(...serviceResult.result.assets);\n hasMore = hasMore || serviceResult.result.meta.hasMore;\n }\n\n return {\n assets: combinedAssets,\n meta: {\n currentPage,\n hasMore,\n ...(hasMore ? { nextPage: currentPage + 1 } : {}),\n },\n };\n },\n getMinimumTransferAmount: async (props) => {\n const serviceMinimums: { [key in ServiceType]?: bigint } = {};\n\n for (const service of services.values()) {\n if (service.analyzeSupport(props)) {\n const serviceMinAmount = await service.getMinimumTransferAmount(props);\n serviceMinimums[service.type] = serviceMinAmount;\n }\n }\n\n return Object.keys(serviceMinimums).length > 0 ? serviceMinimums : null;\n },\n getSupportedChains: async () => {\n const supportedChainsMap: MutableGetSupportedChainsResult = new Map();\n\n // Fetch supported chains from all configured services in parallel.\n // Merge fulfilled results. If every call fails, throw so callers can distinguish\n // \"no supported chains\" from \"service outage/misconfiguration\".\n const settledResults = await Promise.allSettled(\n Array.from(services.values()).map((service) => service.getSupportedChains()),\n );\n\n const fulfilledResults = settledResults.filter((settled) => settled.status === 'fulfilled');\n const rejectedResults = settledResults.filter((settled) => settled.status === 'rejected');\n\n if (settledResults.length > 0 && fulfilledResults.length === 0) {\n const details = rejectedResults\n .map((result) => (result.reason instanceof Error ? result.reason.message : String(result.reason)))\n .join('; ');\n\n throw new ServiceUnavailableError(\n ErrorReason.UNKNOWN,\n `Failed to fetch supported chains from all configured services. ${details}`,\n );\n }\n\n // Merge results: union destination sets for identical source chain IDs.\n for (const settled of fulfilledResults) {\n const result = settled.value;\n for (const [sourceChainId, targetChainIds] of result.entries()) {\n let mergedTargets = supportedChainsMap.get(sourceChainId);\n if (!mergedTargets) {\n mergedTargets = new Set<Caip2ChainId>();\n supportedChainsMap.set(sourceChainId, mergedTargets);\n }\n\n for (const targetChainId of targetChainIds) {\n mergedTargets.add(targetChainId);\n }\n }\n }\n\n return supportedChainsMap;\n },\n getQuoter: (props, options) => {\n return new Quoter(props, Array.from(services.values()), options);\n },\n status: () => status,\n trackTransfer: (props) => {\n const { transfer } = props;\n const service = services.get(transfer.type);\n\n if (!service) {\n throw new ServiceUnavailableError(ErrorReason.SERVICE_TYPE_NOT_CONFIGURED);\n }\n\n return service.trackTransfer(props);\n },\n transferAsset: async (props) => {\n const { quote } = props;\n const service = services.get(quote.serviceType);\n\n if (!service) {\n throw new ServiceUnavailableError(ErrorReason.SERVICE_TYPE_NOT_CONFIGURED);\n }\n\n return await service.transferAsset(props);\n },\n } satisfies TransferManager;\n};\n"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
require(`../_virtual/_rolldown/runtime.cjs`);const e=require(`../_utils/chain.cjs`);let t=require(`zod`),n=require(`viem`);const r=t.z.string().refine(n.isHex,{message:`Expected a hex string`}).transform(e=>(0,n.hexToBigInt)(e)),i=t.z.object({maxFeePerGas:r,maxPriorityFeePerGas:r}),a=t.z.object({slow:i,normal:i,fast:i});async function o(e){let t=await e.request({method:`eth_suggestPriceOptions`,params:[]});return a.parse(t)}async function s(t,n,r=`fast`){if(e.isCaip2AvalancheChainId(n.chainId))return(await o(t))[r];let i=await t.estimateFeesPerGas();return{maxFeePerGas:i.maxFeePerGas,maxPriorityFeePerGas:i.maxPriorityFeePerGas??0n}}exports.estimateEvmFeesPerGas=s;
|
|
1
|
+
require(`../_virtual/_rolldown/runtime.cjs`);const e=require(`../_utils/chain.cjs`);let t=require(`zod`),n=require(`viem`);const r=t.z.string().refine(n.isHex,{message:`Expected a hex string`}).transform(e=>(0,n.hexToBigInt)(e)),i=t.z.object({maxFeePerGas:r,maxPriorityFeePerGas:r}),a=t.z.object({slow:i,normal:i,fast:i});async function o(e){let t=await e.request({method:`eth_suggestPriceOptions`,params:[]});return a.parse(t)}async function s(t,n,r=`fast`){if(e.isCaip2AvalancheChainId(n.chainId))return(await o(t))[r];let i=await t.estimateFeesPerGas();return{maxFeePerGas:i.maxFeePerGas,maxPriorityFeePerGas:i.maxPriorityFeePerGas??0n}}exports.estimateEvmFeesPerGas=s,exports.fetchSuggestedGasPrices=o;
|
|
2
2
|
//# sourceMappingURL=_evm-gas.cjs.map
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{isCaip2AvalancheChainId as e}from"../_utils/chain.js";import{z as t}from"zod";import{hexToBigInt as n,isHex as r}from"viem";const i=t.string().refine(r,{message:`Expected a hex string`}).transform(e=>n(e)),a=t.object({maxFeePerGas:i,maxPriorityFeePerGas:i}),o=t.object({slow:a,normal:a,fast:a});async function s(e){let t=await e.request({method:`eth_suggestPriceOptions`,params:[]});return o.parse(t)}async function c(t,n,r=`fast`){if(e(n.chainId))return(await s(t))[r];let i=await t.estimateFeesPerGas();return{maxFeePerGas:i.maxFeePerGas,maxPriorityFeePerGas:i.maxPriorityFeePerGas??0n}}export{c as estimateEvmFeesPerGas};
|
|
1
|
+
import{isCaip2AvalancheChainId as e}from"../_utils/chain.js";import{z as t}from"zod";import{hexToBigInt as n,isHex as r}from"viem";const i=t.string().refine(r,{message:`Expected a hex string`}).transform(e=>n(e)),a=t.object({maxFeePerGas:i,maxPriorityFeePerGas:i}),o=t.object({slow:a,normal:a,fast:a});async function s(e){let t=await e.request({method:`eth_suggestPriceOptions`,params:[]});return o.parse(t)}async function c(t,n,r=`fast`){if(e(n.chainId))return(await s(t))[r];let i=await t.estimateFeesPerGas();return{maxFeePerGas:i.maxFeePerGas,maxPriorityFeePerGas:i.maxPriorityFeePerGas??0n}}export{c as estimateEvmFeesPerGas,s as fetchSuggestedGasPrices};
|
|
2
2
|
//# sourceMappingURL=_evm-gas.js.map
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
require(`../_virtual/_rolldown/runtime.cjs`);const e=require(`../errors.cjs`),t=require(`../utils/caip.cjs`);let n=require(`viem`),r=require(`@solana/kit`);function i(n){let{namespace:r,reference:i}=t.splitCaip2ChainId(n.chainId);if(r!==`eip155`)throw new e.InvalidParamsError(`Can not get Viem chain for unsupported chain`,`Unsupported chain namespace: ${r}. Only eip155 chains are supported.`);return{id:Number(i),name:n.chainName,nativeCurrency:{decimals:n.networkToken.decimals,symbol:n.networkToken.symbol,name:n.networkToken.name},rpcUrls:{default:{http:[n.rpcUrl]},public:{http:[n.rpcUrl]}},...n.utilityAddresses?.multicall&&{contracts:{multicall3:{address:n.utilityAddresses.multicall}}}}}function a({chain:e}){return(0,n.createWalletClient)({chain:i(e),transport:(0,n.http)(e.rpcUrl,{batch:!0,retryCount:6,retryDelay:200,timeout:15e3})}).extend(n.publicActions)}function o({chain:e}){return(0,r.createSolanaRpc)(e.rpcUrl)}function s(t,n){if(n===void 0)return t;if(!Number.isInteger(n)||n<0)throw new e.InvalidParamsError(`Invalid feeUnitsMarginBps`,`feeUnitsMarginBps must be a non-negative integer, but got ${n}`);return t*BigInt(1e4+n)/10000n}function c({timeoutMs:e,signal:t}){return new Promise(n=>{let r=!1,i=()=>{r||(r=!0,clearTimeout(o),t.removeEventListener(`abort`,a),n())},a=()=>{i()},o=setTimeout(()=>{i()},e);t.addEventListener(`abort`,a,{once:!0}),t.aborted&&i()})}const l=Symbol(`aborted`);async function u(e,t){let n=await Promise.race([e,new Promise(e=>{t.addEventListener(`abort`,()=>e(l),{once:!0})})]);return n===l||t.aborted?{status:`aborted`}:{status:`ok`,value:n}}function d(e,t){return{amountIn:e.amountIn,amountOut:e.amountOut,environment:t.environment,errorCode:t.errorCode,errorReason:t.errorReason,failedAtMs:Date.now(),fees:e.fees,fromAddress:e.fromAddress,id:e.id,partnerFeeBps:e.partnerFeeBps,sourceAsset:e.assetIn,sourceChain:e.sourceChain,status:`failed`,targetAsset:e.assetOut,targetChain:e.targetChain,toAddress:e.toAddress,type:e.serviceType}}exports.applyFeeUnitsBpsMargin=s,exports.awaitOrAbort=u,exports.getEvmClientForChain=a,exports.getSolanaRpcForChain=o,exports.makeFailedTransferFromQuote=d,exports.waitForTimeoutOrAbort=c;
|
|
1
|
+
require(`../_virtual/_rolldown/runtime.cjs`);const e=require(`../errors.cjs`),t=require(`../utils/caip.cjs`);let n=require(`viem`),r=require(`@solana/kit`);function i(n){let{namespace:r,reference:i}=t.splitCaip2ChainId(n.chainId);if(r!==`eip155`)throw new e.InvalidParamsError(`Can not get Viem chain for unsupported chain`,`Unsupported chain namespace: ${r}. Only eip155 chains are supported.`);return{id:Number(i),name:n.chainName,nativeCurrency:{decimals:n.networkToken.decimals,symbol:n.networkToken.symbol,name:n.networkToken.name},rpcUrls:{default:{http:[n.rpcUrl]},public:{http:[n.rpcUrl]}},...n.utilityAddresses?.multicall&&{contracts:{multicall3:{address:n.utilityAddresses.multicall}}}}}function a({chain:e}){return(0,n.createWalletClient)({chain:i(e),transport:(0,n.http)(e.rpcUrl,{batch:!0,retryCount:6,retryDelay:200,timeout:15e3})}).extend(n.publicActions)}function o({chain:e}){return(0,r.createSolanaRpc)(e.rpcUrl)}function s(t,n){if(n===void 0)return t;if(!Number.isInteger(n)||n<0)throw new e.InvalidParamsError(`Invalid feeUnitsMarginBps`,`feeUnitsMarginBps must be a non-negative integer, but got ${n}`);return t*BigInt(1e4+n)/10000n}function c({timeoutMs:e,signal:t}){return new Promise(n=>{let r=!1,i=()=>{r||(r=!0,clearTimeout(o),t.removeEventListener(`abort`,a),n())},a=()=>{i()},o=setTimeout(()=>{i()},e);t.addEventListener(`abort`,a,{once:!0}),t.aborted&&i()})}const l=Symbol(`aborted`);async function u(e,t){let n=await Promise.race([e,new Promise(e=>{t.addEventListener(`abort`,()=>e(l),{once:!0})})]);return n===l||t.aborted?{status:`aborted`}:{status:`ok`,value:n}}function d(e,t){return{amountIn:e.amountIn,amountOut:e.amountOut,environment:t.environment,errorCode:t.errorCode,errorReason:t.errorReason,failedAtMs:Date.now(),fees:e.fees,fromAddress:e.fromAddress,id:e.id,partnerFeeBps:e.partnerFeeBps,sourceAsset:e.assetIn,sourceChain:e.sourceChain,status:`failed`,targetAsset:e.assetOut,targetChain:e.targetChain,toAddress:e.toAddress,type:e.serviceType}}async function f(t,n){return new Promise((r,i)=>{if(t<=0)return r();let a=setTimeout(()=>{s(),r()},t),o=()=>{s(),i(new e.AbortedError)},s=()=>{clearTimeout(a),n&&n.removeEventListener(`abort`,o)};if(n){if(n.aborted)return s(),i(new e.AbortedError);n.addEventListener(`abort`,o)}})}exports.applyFeeUnitsBpsMargin=s,exports.awaitOrAbort=u,exports.getEvmClientForChain=a,exports.getSolanaRpcForChain=o,exports.makeFailedTransferFromQuote=d,exports.wait=f,exports.waitForTimeoutOrAbort=c;
|
|
2
2
|
//# sourceMappingURL=_utils.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"_utils.cjs","names":["splitCaip2ChainId","InvalidParamsError","publicActions"],"sources":["../../src/transfer-service/_utils.ts"],"sourcesContent":["/**\n * @module\n * @internal\n *\n * Internal utility functions for transfer services.\n */\nimport {\n createSolanaRpc,\n isSolanaError,\n SOLANA_ERROR__BLOCK_HEIGHT_EXCEEDED,\n SOLANA_ERROR__JSON_RPC__SERVER_ERROR_NODE_UNHEALTHY,\n SOLANA_ERROR__RPC__TRANSPORT_HTTP_ERROR,\n type Rpc,\n type SolanaRpcApi,\n} from '@solana/kit';\nimport {\n createWalletClient,\n http,\n publicActions,\n WaitForTransactionReceiptTimeoutError,\n type Client,\n type HttpTransport,\n type PublicActions,\n type Chain as ViemChain,\n type WalletRpcSchema,\n} from 'viem';\nimport { splitCaip2ChainId } from '../utils/caip';\nimport type { Environment } from '../constants';\nimport { ErrorCode, InvalidParamsError } from '../errors';\nimport type { Chain } from '../types/chain';\nimport type { Quote } from '../types/quote';\nimport type { FailedTransfer } from '../types/transfer';\n\nfunction getViemChain(chain: Chain): ViemChain {\n const { namespace, reference: chainId } = splitCaip2ChainId(chain.chainId);\n\n if (namespace !== 'eip155') {\n throw new InvalidParamsError(\n 'Can not get Viem chain for unsupported chain',\n `Unsupported chain namespace: ${namespace}. Only eip155 chains are supported.`,\n );\n }\n\n return {\n id: Number(chainId),\n name: chain.chainName,\n nativeCurrency: {\n decimals: chain.networkToken.decimals,\n symbol: chain.networkToken.symbol,\n name: chain.networkToken.name,\n },\n rpcUrls: {\n default: {\n http: [chain.rpcUrl],\n },\n public: {\n http: [chain.rpcUrl],\n },\n },\n ...(chain.utilityAddresses?.multicall && {\n contracts: {\n multicall3: {\n address: chain.utilityAddresses.multicall,\n },\n },\n }),\n };\n}\n\nexport function getEvmClientForChain({\n chain,\n}: {\n chain: Chain;\n}): Client<HttpTransport, ViemChain, undefined, WalletRpcSchema, PublicActions> {\n const chainInfo = getViemChain(chain);\n\n const transport = http(chain.rpcUrl, {\n batch: true,\n retryCount: 6,\n retryDelay: 200,\n timeout: 15_000,\n });\n\n const client = createWalletClient({\n chain: chainInfo,\n transport,\n }).extend(publicActions);\n\n return client;\n}\n\nexport function getSolanaRpcForChain({ chain }: { chain: Chain }): Rpc<SolanaRpcApi> {\n return createSolanaRpc(chain.rpcUrl);\n}\n\nexport function applyFeeUnitsBpsMargin(feeUnits: bigint, feeUnitsMarginBps: number | undefined): bigint {\n if (feeUnitsMarginBps === undefined) {\n return feeUnits;\n }\n\n if (!Number.isInteger(feeUnitsMarginBps) || feeUnitsMarginBps < 0) {\n throw new InvalidParamsError(\n 'Invalid feeUnitsMarginBps',\n `feeUnitsMarginBps must be a non-negative integer, but got ${feeUnitsMarginBps}`,\n );\n }\n\n return (feeUnits * BigInt(10_000 + feeUnitsMarginBps)) / 10_000n;\n}\n\nexport function scaleAmount(amount: bigint, multiplier: number, precisionFactor = 1_000_000): bigint {\n // Verify precisionFactor is a positive integer\n if (!Number.isInteger(precisionFactor) || precisionFactor <= 0) {\n throw new Error('precisionFactor must be a positive integer');\n }\n\n return (amount * BigInt(multiplier * precisionFactor)) / BigInt(precisionFactor);\n}\n\n/**\n * Subtracts the partner fee from the given amount.\n *\n * @param amount - The original amount.\n * @param partnerFeeBps - Fee in basis points (1 bps = 0.01%)\n * @returns The amount after subtracting the partner fee.\n *\n * @throws {Error} If partnerFeeBps is not an integer or is out of range.\n */\nexport function subtractPartnerFee(amount: bigint, partnerFeeBps: number): bigint {\n if (!Number.isInteger(partnerFeeBps)) {\n throw new Error('partnerFeeBps must be an integer');\n }\n\n if (partnerFeeBps < 0 || partnerFeeBps > 10_000) {\n throw new Error('partnerFeeBps must be between 0 and 10,000');\n }\n\n return (amount * BigInt(10_000 - partnerFeeBps)) / 10_000n;\n}\n\n/**\n * Calculates the fee percentage given an input amount and a fee amount.\n *\n * @param inputAmount - The original input amount.\n * @param feeAmount - The fee amount to be calculated as a percentage of the input amount.\n * @returns An object containing the fee percentage and the number of decimal places.\n *\n * @throws {Error} If inputAmount is less than or equal to zero, or if feeAmount is negative.\n */\nexport function calculateFeePercentage(\n inputAmount: bigint,\n feeAmount: bigint,\n): { feePercentage: number; feePercentageDecimals: number } {\n if (inputAmount <= 0n) {\n throw new Error('Input amount must be greater than zero');\n }\n\n if (feeAmount < 0n) {\n throw new Error('Fee amount must be >= zero');\n }\n\n if (feeAmount === 0n) {\n return { feePercentage: 0, feePercentageDecimals: 0 };\n }\n\n const MAX_DECIMALS = 18;\n\n for (let decimals = 0; decimals <= MAX_DECIMALS; decimals++) {\n const scale = 10n ** BigInt(decimals);\n const numerator = feeAmount * 100n * scale;\n\n if (numerator % inputAmount === 0n) {\n const value = numerator / inputAmount;\n\n if (value > BigInt(Number.MAX_SAFE_INTEGER)) {\n throw new Error('feePercentage exceeds Number.MAX_SAFE_INTEGER');\n }\n\n return {\n feePercentage: Number(value),\n feePercentageDecimals: decimals,\n };\n }\n }\n\n // Fallback: highest precision, truncated\n const scale = 10n ** BigInt(MAX_DECIMALS);\n const value = (feeAmount * 100n * scale) / inputAmount;\n\n if (value > BigInt(Number.MAX_SAFE_INTEGER)) {\n throw new Error('feePercentage exceeds Number.MAX_SAFE_INTEGER');\n }\n\n return {\n feePercentage: Number(value),\n feePercentageDecimals: MAX_DECIMALS,\n };\n}\n\n/**\n * Maps Viem errors to corresponding ErrorCode values.\n *\n * @param error - The error thrown by Viem.\n * @returns The corresponding ErrorCode.\n */\nexport function getErrorCodeForViemError(error: unknown): ErrorCode {\n if (error instanceof WaitForTransactionReceiptTimeoutError) {\n return ErrorCode.TIMEOUT;\n }\n\n return ErrorCode.TRANSACTION_REVERTED;\n}\n\n/**\n * Maps `@solana/kit` errors to SDK ErrorCode values.\n *\n * `@solana/kit` throws typed `SolanaError` instances with numeric codes.\n * We use the `isSolanaError` type guard to match specific codes:\n *\n * - Transport / node-health errors → SERVICE_NOT_AVAILABLE\n * (HTTP transport failures, node-unhealthy JSON-RPC responses)\n *\n * - Block-height exceeded → TIMEOUT\n * (the transaction's blockhash has expired — the 150-slot validity\n * window has passed and the tx can no longer land)\n *\n * - Everything else → UNKNOWN\n * (unexpected JSON-RPC errors, malformed responses, internal errors, etc.)\n */\nexport function getErrorCodeForSolanaRpcError(error: unknown): ErrorCode {\n if (\n isSolanaError(error, SOLANA_ERROR__JSON_RPC__SERVER_ERROR_NODE_UNHEALTHY) ||\n isSolanaError(error, SOLANA_ERROR__RPC__TRANSPORT_HTTP_ERROR)\n ) {\n return ErrorCode.SERVICE_NOT_AVAILABLE;\n }\n\n if (isSolanaError(error, SOLANA_ERROR__BLOCK_HEIGHT_EXCEEDED)) {\n return ErrorCode.TIMEOUT;\n }\n\n return ErrorCode.UNKNOWN;\n}\n\n/**\n * Waits for either a timeout to elapse or an abort signal to be triggered.\n *\n * @param timeoutMs - The timeout duration in milliseconds.\n * @param signal - The AbortSignal to listen for abort events.\n *\n * @returns A promise that resolves when either the timeout elapses or the abort signal is triggered.\n */\nexport function waitForTimeoutOrAbort({\n timeoutMs,\n signal,\n}: Readonly<{\n timeoutMs: number;\n signal: AbortSignal;\n}>): Promise<void> {\n return new Promise((resolve) => {\n let settled = false;\n\n const finish = (): void => {\n if (settled) {\n return;\n }\n\n settled = true;\n clearTimeout(timeoutId);\n signal.removeEventListener('abort', onAbort);\n resolve();\n };\n\n const onAbort = (): void => {\n finish();\n };\n\n const timeoutId = setTimeout(() => {\n finish();\n }, timeoutMs);\n\n signal.addEventListener('abort', onAbort, { once: true });\n\n if (signal.aborted) {\n finish();\n }\n });\n}\n\nconst ABORT_TAG: unique symbol = Symbol('aborted');\n\n/**\n * @internal\n *\n * Waits for a promise to resolve or an abort signal to be triggered, whichever comes first.\n *\n * If the promise resolves first, returns an object with status 'ok' and the resolved value.\n * If the abort signal is triggered first, returns an object with status 'aborted'.\n *\n * @param awaitable - The promise to wait for.\n * @param signal - The AbortSignal to listen for abort events.\n * @returns A promise that resolves to an object indicating whether the operation was aborted or completed successfully.\n *\n * @throws Any error thrown by the awaitable promise will be propagated to the caller.\n *\n * @example\n * ```ts\n * const ac = new AbortController();\n * const result = await awaitOrAbort(someAsyncOperation(), ac.signal);\n *\n * if (result.status === 'aborted') {\n * console.log('Operation was aborted');\n * } else {\n * console.log('Operation completed with value:', result.value);\n * }\n * ```\n */\nexport async function awaitOrAbort<T>(\n awaitable: Promise<T>,\n signal: AbortSignal,\n): Promise<{ status: 'aborted' } | { status: 'ok'; value: T }> {\n const maybeAwaitable = await Promise.race([\n awaitable,\n new Promise<typeof ABORT_TAG>((resolve) => {\n signal.addEventListener('abort', () => resolve(ABORT_TAG), { once: true });\n }),\n ]);\n\n if (maybeAwaitable === ABORT_TAG || signal.aborted) {\n return { status: 'aborted' };\n }\n\n return { status: 'ok', value: maybeAwaitable };\n}\n\n/**\n * Build a `FailedTransfer` from a quote.\n *\n * Centralises the boilerplate that every transfer-service handler repeats\n * when it needs to return a failed transfer before a source tx is recorded.\n */\nexport function makeFailedTransferFromQuote(\n quote: Quote,\n options: {\n environment: Environment;\n errorCode: ErrorCode;\n errorReason: string;\n },\n): FailedTransfer {\n return {\n amountIn: quote.amountIn,\n amountOut: quote.amountOut,\n environment: options.environment,\n errorCode: options.errorCode,\n errorReason: options.errorReason,\n failedAtMs: Date.now(),\n fees: quote.fees,\n fromAddress: quote.fromAddress,\n id: quote.id,\n partnerFeeBps: quote.partnerFeeBps,\n sourceAsset: quote.assetIn,\n sourceChain: quote.sourceChain,\n status: 'failed',\n targetAsset: quote.assetOut,\n targetChain: quote.targetChain,\n toAddress: quote.toAddress,\n type: quote.serviceType,\n };\n}\n"],"mappings":"4JAiCA,SAAS,EAAa,EAAyB,CAC7C,GAAM,CAAE,YAAW,UAAW,GAAYA,EAAAA,kBAAkB,EAAM,QAAQ,CAE1E,GAAI,IAAc,SAChB,MAAM,IAAIC,EAAAA,mBACR,+CACA,gCAAgC,EAAU,qCAC3C,CAGH,MAAO,CACL,GAAI,OAAO,EAAQ,CACnB,KAAM,EAAM,UACZ,eAAgB,CACd,SAAU,EAAM,aAAa,SAC7B,OAAQ,EAAM,aAAa,OAC3B,KAAM,EAAM,aAAa,KAC1B,CACD,QAAS,CACP,QAAS,CACP,KAAM,CAAC,EAAM,OAAO,CACrB,CACD,OAAQ,CACN,KAAM,CAAC,EAAM,OAAO,CACrB,CACF,CACD,GAAI,EAAM,kBAAkB,WAAa,CACvC,UAAW,CACT,WAAY,CACV,QAAS,EAAM,iBAAiB,UACjC,CACF,CACF,CACF,CAGH,SAAgB,EAAqB,CACnC,SAG8E,CAe9E,OAAA,EAAA,EAAA,oBALkC,CAChC,MAVgB,EAAa,EAAM,CAWnC,WAAA,EAAA,EAAA,MATqB,EAAM,OAAQ,CACnC,MAAO,GACP,WAAY,EACZ,WAAY,IACZ,QAAS,KACV,CAAC,CAKD,CAAC,CAAC,OAAOC,EAAAA,cAAc,CAK1B,SAAgB,EAAqB,CAAE,SAA8C,CACnF,OAAA,EAAA,EAAA,iBAAuB,EAAM,OAAO,CAGtC,SAAgB,EAAuB,EAAkB,EAA+C,CACtG,GAAI,IAAsB,IAAA,GACxB,OAAO,EAGT,GAAI,CAAC,OAAO,UAAU,EAAkB,EAAI,EAAoB,EAC9D,MAAM,IAAID,EAAAA,mBACR,4BACA,6DAA6D,IAC9D,CAGH,OAAQ,EAAW,OAAO,IAAS,EAAkB,CAAI,OAiJ3D,SAAgB,EAAsB,CACpC,YACA,UAIiB,CACjB,OAAO,IAAI,QAAS,GAAY,CAC9B,IAAI,EAAU,GAER,MAAqB,CACrB,IAIJ,EAAU,GACV,aAAa,EAAU,CACvB,EAAO,oBAAoB,QAAS,EAAQ,CAC5C,GAAS,GAGL,MAAsB,CAC1B,GAAQ,EAGJ,EAAY,eAAiB,CACjC,GAAQ,EACP,EAAU,CAEb,EAAO,iBAAiB,QAAS,EAAS,CAAE,KAAM,GAAM,CAAC,CAErD,EAAO,SACT,GAAQ,EAEV,CAGJ,MAAM,EAA2B,OAAO,UAAU,CA4BlD,eAAsB,EACpB,EACA,EAC6D,CAC7D,IAAM,EAAiB,MAAM,QAAQ,KAAK,CACxC,EACA,IAAI,QAA2B,GAAY,CACzC,EAAO,iBAAiB,YAAe,EAAQ,EAAU,CAAE,CAAE,KAAM,GAAM,CAAC,EAC1E,CACH,CAAC,CAMF,OAJI,IAAmB,GAAa,EAAO,QAClC,CAAE,OAAQ,UAAW,CAGvB,CAAE,OAAQ,KAAM,MAAO,EAAgB,CAShD,SAAgB,EACd,EACA,EAKgB,CAChB,MAAO,CACL,SAAU,EAAM,SAChB,UAAW,EAAM,UACjB,YAAa,EAAQ,YACrB,UAAW,EAAQ,UACnB,YAAa,EAAQ,YACrB,WAAY,KAAK,KAAK,CACtB,KAAM,EAAM,KACZ,YAAa,EAAM,YACnB,GAAI,EAAM,GACV,cAAe,EAAM,cACrB,YAAa,EAAM,QACnB,YAAa,EAAM,YACnB,OAAQ,SACR,YAAa,EAAM,SACnB,YAAa,EAAM,YACnB,UAAW,EAAM,UACjB,KAAM,EAAM,YACb"}
|
|
1
|
+
{"version":3,"file":"_utils.cjs","names":["splitCaip2ChainId","InvalidParamsError","publicActions","AbortedError"],"sources":["../../src/transfer-service/_utils.ts"],"sourcesContent":["/**\n * @module\n * @internal\n *\n * Internal utility functions for transfer services.\n */\nimport {\n createSolanaRpc,\n isSolanaError,\n SOLANA_ERROR__BLOCK_HEIGHT_EXCEEDED,\n SOLANA_ERROR__JSON_RPC__SERVER_ERROR_NODE_UNHEALTHY,\n SOLANA_ERROR__RPC__TRANSPORT_HTTP_ERROR,\n type Rpc,\n type SolanaRpcApi,\n} from '@solana/kit';\nimport {\n createWalletClient,\n http,\n publicActions,\n WaitForTransactionReceiptTimeoutError,\n type Client,\n type HttpTransport,\n type PublicActions,\n type Chain as ViemChain,\n type WalletRpcSchema,\n} from 'viem';\nimport { splitCaip2ChainId } from '../utils/caip';\nimport type { Environment } from '../constants';\nimport { AbortedError, ErrorCode, InvalidParamsError } from '../errors';\nimport type { Chain } from '../types/chain';\nimport type { Quote } from '../types/quote';\nimport type { FailedTransfer } from '../types/transfer';\n\nfunction getViemChain(chain: Chain): ViemChain {\n const { namespace, reference: chainId } = splitCaip2ChainId(chain.chainId);\n\n if (namespace !== 'eip155') {\n throw new InvalidParamsError(\n 'Can not get Viem chain for unsupported chain',\n `Unsupported chain namespace: ${namespace}. Only eip155 chains are supported.`,\n );\n }\n\n return {\n id: Number(chainId),\n name: chain.chainName,\n nativeCurrency: {\n decimals: chain.networkToken.decimals,\n symbol: chain.networkToken.symbol,\n name: chain.networkToken.name,\n },\n rpcUrls: {\n default: {\n http: [chain.rpcUrl],\n },\n public: {\n http: [chain.rpcUrl],\n },\n },\n ...(chain.utilityAddresses?.multicall && {\n contracts: {\n multicall3: {\n address: chain.utilityAddresses.multicall,\n },\n },\n }),\n };\n}\n\nexport function getEvmClientForChain({\n chain,\n}: {\n chain: Chain;\n}): Client<HttpTransport, ViemChain, undefined, WalletRpcSchema, PublicActions> {\n const chainInfo = getViemChain(chain);\n\n const transport = http(chain.rpcUrl, {\n batch: true,\n retryCount: 6,\n retryDelay: 200,\n timeout: 15_000,\n });\n\n const client = createWalletClient({\n chain: chainInfo,\n transport,\n }).extend(publicActions);\n\n return client;\n}\n\nexport function getSolanaRpcForChain({ chain }: { chain: Chain }): Rpc<SolanaRpcApi> {\n return createSolanaRpc(chain.rpcUrl);\n}\n\nexport function applyFeeUnitsBpsMargin(feeUnits: bigint, feeUnitsMarginBps: number | undefined): bigint {\n if (feeUnitsMarginBps === undefined) {\n return feeUnits;\n }\n\n if (!Number.isInteger(feeUnitsMarginBps) || feeUnitsMarginBps < 0) {\n throw new InvalidParamsError(\n 'Invalid feeUnitsMarginBps',\n `feeUnitsMarginBps must be a non-negative integer, but got ${feeUnitsMarginBps}`,\n );\n }\n\n return (feeUnits * BigInt(10_000 + feeUnitsMarginBps)) / 10_000n;\n}\n\nexport function scaleAmount(amount: bigint, multiplier: number, precisionFactor = 1_000_000): bigint {\n // Verify precisionFactor is a positive integer\n if (!Number.isInteger(precisionFactor) || precisionFactor <= 0) {\n throw new Error('precisionFactor must be a positive integer');\n }\n\n return (amount * BigInt(multiplier * precisionFactor)) / BigInt(precisionFactor);\n}\n\n/**\n * Subtracts the partner fee from the given amount.\n *\n * @param amount - The original amount.\n * @param partnerFeeBps - Fee in basis points (1 bps = 0.01%)\n * @returns The amount after subtracting the partner fee.\n *\n * @throws {Error} If partnerFeeBps is not an integer or is out of range.\n */\nexport function subtractPartnerFee(amount: bigint, partnerFeeBps: number): bigint {\n if (!Number.isInteger(partnerFeeBps)) {\n throw new Error('partnerFeeBps must be an integer');\n }\n\n if (partnerFeeBps < 0 || partnerFeeBps > 10_000) {\n throw new Error('partnerFeeBps must be between 0 and 10,000');\n }\n\n return (amount * BigInt(10_000 - partnerFeeBps)) / 10_000n;\n}\n\n/**\n * Calculates the fee percentage given an input amount and a fee amount.\n *\n * @param inputAmount - The original input amount.\n * @param feeAmount - The fee amount to be calculated as a percentage of the input amount.\n * @returns An object containing the fee percentage and the number of decimal places.\n *\n * @throws {Error} If inputAmount is less than or equal to zero, or if feeAmount is negative.\n */\nexport function calculateFeePercentage(\n inputAmount: bigint,\n feeAmount: bigint,\n): { feePercentage: number; feePercentageDecimals: number } {\n if (inputAmount <= 0n) {\n throw new Error('Input amount must be greater than zero');\n }\n\n if (feeAmount < 0n) {\n throw new Error('Fee amount must be >= zero');\n }\n\n if (feeAmount === 0n) {\n return { feePercentage: 0, feePercentageDecimals: 0 };\n }\n\n const MAX_DECIMALS = 18;\n\n for (let decimals = 0; decimals <= MAX_DECIMALS; decimals++) {\n const scale = 10n ** BigInt(decimals);\n const numerator = feeAmount * 100n * scale;\n\n if (numerator % inputAmount === 0n) {\n const value = numerator / inputAmount;\n\n if (value > BigInt(Number.MAX_SAFE_INTEGER)) {\n throw new Error('feePercentage exceeds Number.MAX_SAFE_INTEGER');\n }\n\n return {\n feePercentage: Number(value),\n feePercentageDecimals: decimals,\n };\n }\n }\n\n // Fallback: highest precision, truncated\n const scale = 10n ** BigInt(MAX_DECIMALS);\n const value = (feeAmount * 100n * scale) / inputAmount;\n\n if (value > BigInt(Number.MAX_SAFE_INTEGER)) {\n throw new Error('feePercentage exceeds Number.MAX_SAFE_INTEGER');\n }\n\n return {\n feePercentage: Number(value),\n feePercentageDecimals: MAX_DECIMALS,\n };\n}\n\n/**\n * Maps Viem errors to corresponding ErrorCode values.\n *\n * @param error - The error thrown by Viem.\n * @returns The corresponding ErrorCode.\n */\nexport function getErrorCodeForViemError(error: unknown): ErrorCode {\n if (error instanceof WaitForTransactionReceiptTimeoutError) {\n return ErrorCode.TIMEOUT;\n }\n\n return ErrorCode.TRANSACTION_REVERTED;\n}\n\n/**\n * Maps `@solana/kit` errors to SDK ErrorCode values.\n *\n * `@solana/kit` throws typed `SolanaError` instances with numeric codes.\n * We use the `isSolanaError` type guard to match specific codes:\n *\n * - Transport / node-health errors → SERVICE_NOT_AVAILABLE\n * (HTTP transport failures, node-unhealthy JSON-RPC responses)\n *\n * - Block-height exceeded → TIMEOUT\n * (the transaction's blockhash has expired — the 150-slot validity\n * window has passed and the tx can no longer land)\n *\n * - Everything else → UNKNOWN\n * (unexpected JSON-RPC errors, malformed responses, internal errors, etc.)\n */\nexport function getErrorCodeForSolanaRpcError(error: unknown): ErrorCode {\n if (\n isSolanaError(error, SOLANA_ERROR__JSON_RPC__SERVER_ERROR_NODE_UNHEALTHY) ||\n isSolanaError(error, SOLANA_ERROR__RPC__TRANSPORT_HTTP_ERROR)\n ) {\n return ErrorCode.SERVICE_NOT_AVAILABLE;\n }\n\n if (isSolanaError(error, SOLANA_ERROR__BLOCK_HEIGHT_EXCEEDED)) {\n return ErrorCode.TIMEOUT;\n }\n\n return ErrorCode.UNKNOWN;\n}\n\n/**\n * Waits for either a timeout to elapse or an abort signal to be triggered.\n *\n * @param timeoutMs - The timeout duration in milliseconds.\n * @param signal - The AbortSignal to listen for abort events.\n *\n * @returns A promise that resolves when either the timeout elapses or the abort signal is triggered.\n */\nexport function waitForTimeoutOrAbort({\n timeoutMs,\n signal,\n}: Readonly<{\n timeoutMs: number;\n signal: AbortSignal;\n}>): Promise<void> {\n return new Promise((resolve) => {\n let settled = false;\n\n const finish = (): void => {\n if (settled) {\n return;\n }\n\n settled = true;\n clearTimeout(timeoutId);\n signal.removeEventListener('abort', onAbort);\n resolve();\n };\n\n const onAbort = (): void => {\n finish();\n };\n\n const timeoutId = setTimeout(() => {\n finish();\n }, timeoutMs);\n\n signal.addEventListener('abort', onAbort, { once: true });\n\n if (signal.aborted) {\n finish();\n }\n });\n}\n\nconst ABORT_TAG: unique symbol = Symbol('aborted');\n\n/**\n * @internal\n *\n * Waits for a promise to resolve or an abort signal to be triggered, whichever comes first.\n *\n * If the promise resolves first, returns an object with status 'ok' and the resolved value.\n * If the abort signal is triggered first, returns an object with status 'aborted'.\n *\n * @param awaitable - The promise to wait for.\n * @param signal - The AbortSignal to listen for abort events.\n * @returns A promise that resolves to an object indicating whether the operation was aborted or completed successfully.\n *\n * @throws Any error thrown by the awaitable promise will be propagated to the caller.\n *\n * @example\n * ```ts\n * const ac = new AbortController();\n * const result = await awaitOrAbort(someAsyncOperation(), ac.signal);\n *\n * if (result.status === 'aborted') {\n * console.log('Operation was aborted');\n * } else {\n * console.log('Operation completed with value:', result.value);\n * }\n * ```\n */\nexport async function awaitOrAbort<T>(\n awaitable: Promise<T>,\n signal: AbortSignal,\n): Promise<{ status: 'aborted' } | { status: 'ok'; value: T }> {\n const maybeAwaitable = await Promise.race([\n awaitable,\n new Promise<typeof ABORT_TAG>((resolve) => {\n signal.addEventListener('abort', () => resolve(ABORT_TAG), { once: true });\n }),\n ]);\n\n if (maybeAwaitable === ABORT_TAG || signal.aborted) {\n return { status: 'aborted' };\n }\n\n return { status: 'ok', value: maybeAwaitable };\n}\n\n/**\n * Build a `FailedTransfer` from a quote.\n *\n * Centralises the boilerplate that every transfer-service handler repeats\n * when it needs to return a failed transfer before a source tx is recorded.\n */\nexport function makeFailedTransferFromQuote(\n quote: Quote,\n options: {\n environment: Environment;\n errorCode: ErrorCode;\n errorReason: string;\n },\n): FailedTransfer {\n return {\n amountIn: quote.amountIn,\n amountOut: quote.amountOut,\n environment: options.environment,\n errorCode: options.errorCode,\n errorReason: options.errorReason,\n failedAtMs: Date.now(),\n fees: quote.fees,\n fromAddress: quote.fromAddress,\n id: quote.id,\n partnerFeeBps: quote.partnerFeeBps,\n sourceAsset: quote.assetIn,\n sourceChain: quote.sourceChain,\n status: 'failed',\n targetAsset: quote.assetOut,\n targetChain: quote.targetChain,\n toAddress: quote.toAddress,\n type: quote.serviceType,\n };\n}\n\nexport async function wait(delayMs: number, signal?: AbortSignal): Promise<void> {\n return new Promise((resolve, reject) => {\n if (delayMs <= 0) {\n return resolve();\n }\n\n const timeoutId = setTimeout(() => {\n cleanup();\n resolve();\n }, delayMs);\n\n const onAbort = () => {\n cleanup();\n reject(new AbortedError());\n };\n\n const cleanup = () => {\n clearTimeout(timeoutId);\n\n if (signal) {\n signal.removeEventListener('abort', onAbort);\n }\n };\n\n if (signal) {\n if (signal.aborted) {\n cleanup();\n\n return reject(new AbortedError());\n }\n\n signal.addEventListener('abort', onAbort);\n }\n });\n}\n"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{InvalidParamsError as
|
|
1
|
+
import{AbortedError as e,InvalidParamsError as t}from"../errors.js";import{splitCaip2ChainId as n}from"../utils/caip.js";import{createWalletClient as r,http as i,publicActions as a}from"viem";import{createSolanaRpc as o}from"@solana/kit";function s(e){let{namespace:r,reference:i}=n(e.chainId);if(r!==`eip155`)throw new t(`Can not get Viem chain for unsupported chain`,`Unsupported chain namespace: ${r}. Only eip155 chains are supported.`);return{id:Number(i),name:e.chainName,nativeCurrency:{decimals:e.networkToken.decimals,symbol:e.networkToken.symbol,name:e.networkToken.name},rpcUrls:{default:{http:[e.rpcUrl]},public:{http:[e.rpcUrl]}},...e.utilityAddresses?.multicall&&{contracts:{multicall3:{address:e.utilityAddresses.multicall}}}}}function c({chain:e}){return r({chain:s(e),transport:i(e.rpcUrl,{batch:!0,retryCount:6,retryDelay:200,timeout:15e3})}).extend(a)}function l({chain:e}){return o(e.rpcUrl)}function u(e,n){if(n===void 0)return e;if(!Number.isInteger(n)||n<0)throw new t(`Invalid feeUnitsMarginBps`,`feeUnitsMarginBps must be a non-negative integer, but got ${n}`);return e*BigInt(1e4+n)/10000n}function d({timeoutMs:e,signal:t}){return new Promise(n=>{let r=!1,i=()=>{r||(r=!0,clearTimeout(o),t.removeEventListener(`abort`,a),n())},a=()=>{i()},o=setTimeout(()=>{i()},e);t.addEventListener(`abort`,a,{once:!0}),t.aborted&&i()})}const f=Symbol(`aborted`);async function p(e,t){let n=await Promise.race([e,new Promise(e=>{t.addEventListener(`abort`,()=>e(f),{once:!0})})]);return n===f||t.aborted?{status:`aborted`}:{status:`ok`,value:n}}function m(e,t){return{amountIn:e.amountIn,amountOut:e.amountOut,environment:t.environment,errorCode:t.errorCode,errorReason:t.errorReason,failedAtMs:Date.now(),fees:e.fees,fromAddress:e.fromAddress,id:e.id,partnerFeeBps:e.partnerFeeBps,sourceAsset:e.assetIn,sourceChain:e.sourceChain,status:`failed`,targetAsset:e.assetOut,targetChain:e.targetChain,toAddress:e.toAddress,type:e.serviceType}}async function h(t,n){return new Promise((r,i)=>{if(t<=0)return r();let a=setTimeout(()=>{s(),r()},t),o=()=>{s(),i(new e)},s=()=>{clearTimeout(a),n&&n.removeEventListener(`abort`,o)};if(n){if(n.aborted)return s(),i(new e);n.addEventListener(`abort`,o)}})}export{u as applyFeeUnitsBpsMargin,p as awaitOrAbort,c as getEvmClientForChain,l as getSolanaRpcForChain,m as makeFailedTransferFromQuote,h as wait,d as waitForTimeoutOrAbort};
|
|
2
2
|
//# sourceMappingURL=_utils.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"_utils.js","names":[],"sources":["../../src/transfer-service/_utils.ts"],"sourcesContent":["/**\n * @module\n * @internal\n *\n * Internal utility functions for transfer services.\n */\nimport {\n createSolanaRpc,\n isSolanaError,\n SOLANA_ERROR__BLOCK_HEIGHT_EXCEEDED,\n SOLANA_ERROR__JSON_RPC__SERVER_ERROR_NODE_UNHEALTHY,\n SOLANA_ERROR__RPC__TRANSPORT_HTTP_ERROR,\n type Rpc,\n type SolanaRpcApi,\n} from '@solana/kit';\nimport {\n createWalletClient,\n http,\n publicActions,\n WaitForTransactionReceiptTimeoutError,\n type Client,\n type HttpTransport,\n type PublicActions,\n type Chain as ViemChain,\n type WalletRpcSchema,\n} from 'viem';\nimport { splitCaip2ChainId } from '../utils/caip';\nimport type { Environment } from '../constants';\nimport { ErrorCode, InvalidParamsError } from '../errors';\nimport type { Chain } from '../types/chain';\nimport type { Quote } from '../types/quote';\nimport type { FailedTransfer } from '../types/transfer';\n\nfunction getViemChain(chain: Chain): ViemChain {\n const { namespace, reference: chainId } = splitCaip2ChainId(chain.chainId);\n\n if (namespace !== 'eip155') {\n throw new InvalidParamsError(\n 'Can not get Viem chain for unsupported chain',\n `Unsupported chain namespace: ${namespace}. Only eip155 chains are supported.`,\n );\n }\n\n return {\n id: Number(chainId),\n name: chain.chainName,\n nativeCurrency: {\n decimals: chain.networkToken.decimals,\n symbol: chain.networkToken.symbol,\n name: chain.networkToken.name,\n },\n rpcUrls: {\n default: {\n http: [chain.rpcUrl],\n },\n public: {\n http: [chain.rpcUrl],\n },\n },\n ...(chain.utilityAddresses?.multicall && {\n contracts: {\n multicall3: {\n address: chain.utilityAddresses.multicall,\n },\n },\n }),\n };\n}\n\nexport function getEvmClientForChain({\n chain,\n}: {\n chain: Chain;\n}): Client<HttpTransport, ViemChain, undefined, WalletRpcSchema, PublicActions> {\n const chainInfo = getViemChain(chain);\n\n const transport = http(chain.rpcUrl, {\n batch: true,\n retryCount: 6,\n retryDelay: 200,\n timeout: 15_000,\n });\n\n const client = createWalletClient({\n chain: chainInfo,\n transport,\n }).extend(publicActions);\n\n return client;\n}\n\nexport function getSolanaRpcForChain({ chain }: { chain: Chain }): Rpc<SolanaRpcApi> {\n return createSolanaRpc(chain.rpcUrl);\n}\n\nexport function applyFeeUnitsBpsMargin(feeUnits: bigint, feeUnitsMarginBps: number | undefined): bigint {\n if (feeUnitsMarginBps === undefined) {\n return feeUnits;\n }\n\n if (!Number.isInteger(feeUnitsMarginBps) || feeUnitsMarginBps < 0) {\n throw new InvalidParamsError(\n 'Invalid feeUnitsMarginBps',\n `feeUnitsMarginBps must be a non-negative integer, but got ${feeUnitsMarginBps}`,\n );\n }\n\n return (feeUnits * BigInt(10_000 + feeUnitsMarginBps)) / 10_000n;\n}\n\nexport function scaleAmount(amount: bigint, multiplier: number, precisionFactor = 1_000_000): bigint {\n // Verify precisionFactor is a positive integer\n if (!Number.isInteger(precisionFactor) || precisionFactor <= 0) {\n throw new Error('precisionFactor must be a positive integer');\n }\n\n return (amount * BigInt(multiplier * precisionFactor)) / BigInt(precisionFactor);\n}\n\n/**\n * Subtracts the partner fee from the given amount.\n *\n * @param amount - The original amount.\n * @param partnerFeeBps - Fee in basis points (1 bps = 0.01%)\n * @returns The amount after subtracting the partner fee.\n *\n * @throws {Error} If partnerFeeBps is not an integer or is out of range.\n */\nexport function subtractPartnerFee(amount: bigint, partnerFeeBps: number): bigint {\n if (!Number.isInteger(partnerFeeBps)) {\n throw new Error('partnerFeeBps must be an integer');\n }\n\n if (partnerFeeBps < 0 || partnerFeeBps > 10_000) {\n throw new Error('partnerFeeBps must be between 0 and 10,000');\n }\n\n return (amount * BigInt(10_000 - partnerFeeBps)) / 10_000n;\n}\n\n/**\n * Calculates the fee percentage given an input amount and a fee amount.\n *\n * @param inputAmount - The original input amount.\n * @param feeAmount - The fee amount to be calculated as a percentage of the input amount.\n * @returns An object containing the fee percentage and the number of decimal places.\n *\n * @throws {Error} If inputAmount is less than or equal to zero, or if feeAmount is negative.\n */\nexport function calculateFeePercentage(\n inputAmount: bigint,\n feeAmount: bigint,\n): { feePercentage: number; feePercentageDecimals: number } {\n if (inputAmount <= 0n) {\n throw new Error('Input amount must be greater than zero');\n }\n\n if (feeAmount < 0n) {\n throw new Error('Fee amount must be >= zero');\n }\n\n if (feeAmount === 0n) {\n return { feePercentage: 0, feePercentageDecimals: 0 };\n }\n\n const MAX_DECIMALS = 18;\n\n for (let decimals = 0; decimals <= MAX_DECIMALS; decimals++) {\n const scale = 10n ** BigInt(decimals);\n const numerator = feeAmount * 100n * scale;\n\n if (numerator % inputAmount === 0n) {\n const value = numerator / inputAmount;\n\n if (value > BigInt(Number.MAX_SAFE_INTEGER)) {\n throw new Error('feePercentage exceeds Number.MAX_SAFE_INTEGER');\n }\n\n return {\n feePercentage: Number(value),\n feePercentageDecimals: decimals,\n };\n }\n }\n\n // Fallback: highest precision, truncated\n const scale = 10n ** BigInt(MAX_DECIMALS);\n const value = (feeAmount * 100n * scale) / inputAmount;\n\n if (value > BigInt(Number.MAX_SAFE_INTEGER)) {\n throw new Error('feePercentage exceeds Number.MAX_SAFE_INTEGER');\n }\n\n return {\n feePercentage: Number(value),\n feePercentageDecimals: MAX_DECIMALS,\n };\n}\n\n/**\n * Maps Viem errors to corresponding ErrorCode values.\n *\n * @param error - The error thrown by Viem.\n * @returns The corresponding ErrorCode.\n */\nexport function getErrorCodeForViemError(error: unknown): ErrorCode {\n if (error instanceof WaitForTransactionReceiptTimeoutError) {\n return ErrorCode.TIMEOUT;\n }\n\n return ErrorCode.TRANSACTION_REVERTED;\n}\n\n/**\n * Maps `@solana/kit` errors to SDK ErrorCode values.\n *\n * `@solana/kit` throws typed `SolanaError` instances with numeric codes.\n * We use the `isSolanaError` type guard to match specific codes:\n *\n * - Transport / node-health errors → SERVICE_NOT_AVAILABLE\n * (HTTP transport failures, node-unhealthy JSON-RPC responses)\n *\n * - Block-height exceeded → TIMEOUT\n * (the transaction's blockhash has expired — the 150-slot validity\n * window has passed and the tx can no longer land)\n *\n * - Everything else → UNKNOWN\n * (unexpected JSON-RPC errors, malformed responses, internal errors, etc.)\n */\nexport function getErrorCodeForSolanaRpcError(error: unknown): ErrorCode {\n if (\n isSolanaError(error, SOLANA_ERROR__JSON_RPC__SERVER_ERROR_NODE_UNHEALTHY) ||\n isSolanaError(error, SOLANA_ERROR__RPC__TRANSPORT_HTTP_ERROR)\n ) {\n return ErrorCode.SERVICE_NOT_AVAILABLE;\n }\n\n if (isSolanaError(error, SOLANA_ERROR__BLOCK_HEIGHT_EXCEEDED)) {\n return ErrorCode.TIMEOUT;\n }\n\n return ErrorCode.UNKNOWN;\n}\n\n/**\n * Waits for either a timeout to elapse or an abort signal to be triggered.\n *\n * @param timeoutMs - The timeout duration in milliseconds.\n * @param signal - The AbortSignal to listen for abort events.\n *\n * @returns A promise that resolves when either the timeout elapses or the abort signal is triggered.\n */\nexport function waitForTimeoutOrAbort({\n timeoutMs,\n signal,\n}: Readonly<{\n timeoutMs: number;\n signal: AbortSignal;\n}>): Promise<void> {\n return new Promise((resolve) => {\n let settled = false;\n\n const finish = (): void => {\n if (settled) {\n return;\n }\n\n settled = true;\n clearTimeout(timeoutId);\n signal.removeEventListener('abort', onAbort);\n resolve();\n };\n\n const onAbort = (): void => {\n finish();\n };\n\n const timeoutId = setTimeout(() => {\n finish();\n }, timeoutMs);\n\n signal.addEventListener('abort', onAbort, { once: true });\n\n if (signal.aborted) {\n finish();\n }\n });\n}\n\nconst ABORT_TAG: unique symbol = Symbol('aborted');\n\n/**\n * @internal\n *\n * Waits for a promise to resolve or an abort signal to be triggered, whichever comes first.\n *\n * If the promise resolves first, returns an object with status 'ok' and the resolved value.\n * If the abort signal is triggered first, returns an object with status 'aborted'.\n *\n * @param awaitable - The promise to wait for.\n * @param signal - The AbortSignal to listen for abort events.\n * @returns A promise that resolves to an object indicating whether the operation was aborted or completed successfully.\n *\n * @throws Any error thrown by the awaitable promise will be propagated to the caller.\n *\n * @example\n * ```ts\n * const ac = new AbortController();\n * const result = await awaitOrAbort(someAsyncOperation(), ac.signal);\n *\n * if (result.status === 'aborted') {\n * console.log('Operation was aborted');\n * } else {\n * console.log('Operation completed with value:', result.value);\n * }\n * ```\n */\nexport async function awaitOrAbort<T>(\n awaitable: Promise<T>,\n signal: AbortSignal,\n): Promise<{ status: 'aborted' } | { status: 'ok'; value: T }> {\n const maybeAwaitable = await Promise.race([\n awaitable,\n new Promise<typeof ABORT_TAG>((resolve) => {\n signal.addEventListener('abort', () => resolve(ABORT_TAG), { once: true });\n }),\n ]);\n\n if (maybeAwaitable === ABORT_TAG || signal.aborted) {\n return { status: 'aborted' };\n }\n\n return { status: 'ok', value: maybeAwaitable };\n}\n\n/**\n * Build a `FailedTransfer` from a quote.\n *\n * Centralises the boilerplate that every transfer-service handler repeats\n * when it needs to return a failed transfer before a source tx is recorded.\n */\nexport function makeFailedTransferFromQuote(\n quote: Quote,\n options: {\n environment: Environment;\n errorCode: ErrorCode;\n errorReason: string;\n },\n): FailedTransfer {\n return {\n amountIn: quote.amountIn,\n amountOut: quote.amountOut,\n environment: options.environment,\n errorCode: options.errorCode,\n errorReason: options.errorReason,\n failedAtMs: Date.now(),\n fees: quote.fees,\n fromAddress: quote.fromAddress,\n id: quote.id,\n partnerFeeBps: quote.partnerFeeBps,\n sourceAsset: quote.assetIn,\n sourceChain: quote.sourceChain,\n status: 'failed',\n targetAsset: quote.assetOut,\n targetChain: quote.targetChain,\n toAddress: quote.toAddress,\n type: quote.serviceType,\n };\n}\n"],"mappings":"4NAiCA,SAAS,EAAa,EAAyB,CAC7C,GAAM,CAAE,YAAW,UAAW,GAAY,EAAkB,EAAM,QAAQ,CAE1E,GAAI,IAAc,SAChB,MAAM,IAAI,EACR,+CACA,gCAAgC,EAAU,qCAC3C,CAGH,MAAO,CACL,GAAI,OAAO,EAAQ,CACnB,KAAM,EAAM,UACZ,eAAgB,CACd,SAAU,EAAM,aAAa,SAC7B,OAAQ,EAAM,aAAa,OAC3B,KAAM,EAAM,aAAa,KAC1B,CACD,QAAS,CACP,QAAS,CACP,KAAM,CAAC,EAAM,OAAO,CACrB,CACD,OAAQ,CACN,KAAM,CAAC,EAAM,OAAO,CACrB,CACF,CACD,GAAI,EAAM,kBAAkB,WAAa,CACvC,UAAW,CACT,WAAY,CACV,QAAS,EAAM,iBAAiB,UACjC,CACF,CACF,CACF,CAGH,SAAgB,EAAqB,CACnC,SAG8E,CAe9E,OALe,EAAmB,CAChC,MAVgB,EAAa,EAAM,CAWnC,UATgB,EAAK,EAAM,OAAQ,CACnC,MAAO,GACP,WAAY,EACZ,WAAY,IACZ,QAAS,KACV,CAAC,CAKD,CAAC,CAAC,OAAO,EAAc,CAK1B,SAAgB,EAAqB,CAAE,SAA8C,CACnF,OAAO,EAAgB,EAAM,OAAO,CAGtC,SAAgB,EAAuB,EAAkB,EAA+C,CACtG,GAAI,IAAsB,IAAA,GACxB,OAAO,EAGT,GAAI,CAAC,OAAO,UAAU,EAAkB,EAAI,EAAoB,EAC9D,MAAM,IAAI,EACR,4BACA,6DAA6D,IAC9D,CAGH,OAAQ,EAAW,OAAO,IAAS,EAAkB,CAAI,OAiJ3D,SAAgB,EAAsB,CACpC,YACA,UAIiB,CACjB,OAAO,IAAI,QAAS,GAAY,CAC9B,IAAI,EAAU,GAER,MAAqB,CACrB,IAIJ,EAAU,GACV,aAAa,EAAU,CACvB,EAAO,oBAAoB,QAAS,EAAQ,CAC5C,GAAS,GAGL,MAAsB,CAC1B,GAAQ,EAGJ,EAAY,eAAiB,CACjC,GAAQ,EACP,EAAU,CAEb,EAAO,iBAAiB,QAAS,EAAS,CAAE,KAAM,GAAM,CAAC,CAErD,EAAO,SACT,GAAQ,EAEV,CAGJ,MAAM,EAA2B,OAAO,UAAU,CA4BlD,eAAsB,EACpB,EACA,EAC6D,CAC7D,IAAM,EAAiB,MAAM,QAAQ,KAAK,CACxC,EACA,IAAI,QAA2B,GAAY,CACzC,EAAO,iBAAiB,YAAe,EAAQ,EAAU,CAAE,CAAE,KAAM,GAAM,CAAC,EAC1E,CACH,CAAC,CAMF,OAJI,IAAmB,GAAa,EAAO,QAClC,CAAE,OAAQ,UAAW,CAGvB,CAAE,OAAQ,KAAM,MAAO,EAAgB,CAShD,SAAgB,EACd,EACA,EAKgB,CAChB,MAAO,CACL,SAAU,EAAM,SAChB,UAAW,EAAM,UACjB,YAAa,EAAQ,YACrB,UAAW,EAAQ,UACnB,YAAa,EAAQ,YACrB,WAAY,KAAK,KAAK,CACtB,KAAM,EAAM,KACZ,YAAa,EAAM,YACnB,GAAI,EAAM,GACV,cAAe,EAAM,cACrB,YAAa,EAAM,QACnB,YAAa,EAAM,YACnB,OAAQ,SACR,YAAa,EAAM,SACnB,YAAa,EAAM,YACnB,UAAW,EAAM,UACjB,KAAM,EAAM,YACb"}
|
|
1
|
+
{"version":3,"file":"_utils.js","names":[],"sources":["../../src/transfer-service/_utils.ts"],"sourcesContent":["/**\n * @module\n * @internal\n *\n * Internal utility functions for transfer services.\n */\nimport {\n createSolanaRpc,\n isSolanaError,\n SOLANA_ERROR__BLOCK_HEIGHT_EXCEEDED,\n SOLANA_ERROR__JSON_RPC__SERVER_ERROR_NODE_UNHEALTHY,\n SOLANA_ERROR__RPC__TRANSPORT_HTTP_ERROR,\n type Rpc,\n type SolanaRpcApi,\n} from '@solana/kit';\nimport {\n createWalletClient,\n http,\n publicActions,\n WaitForTransactionReceiptTimeoutError,\n type Client,\n type HttpTransport,\n type PublicActions,\n type Chain as ViemChain,\n type WalletRpcSchema,\n} from 'viem';\nimport { splitCaip2ChainId } from '../utils/caip';\nimport type { Environment } from '../constants';\nimport { AbortedError, ErrorCode, InvalidParamsError } from '../errors';\nimport type { Chain } from '../types/chain';\nimport type { Quote } from '../types/quote';\nimport type { FailedTransfer } from '../types/transfer';\n\nfunction getViemChain(chain: Chain): ViemChain {\n const { namespace, reference: chainId } = splitCaip2ChainId(chain.chainId);\n\n if (namespace !== 'eip155') {\n throw new InvalidParamsError(\n 'Can not get Viem chain for unsupported chain',\n `Unsupported chain namespace: ${namespace}. Only eip155 chains are supported.`,\n );\n }\n\n return {\n id: Number(chainId),\n name: chain.chainName,\n nativeCurrency: {\n decimals: chain.networkToken.decimals,\n symbol: chain.networkToken.symbol,\n name: chain.networkToken.name,\n },\n rpcUrls: {\n default: {\n http: [chain.rpcUrl],\n },\n public: {\n http: [chain.rpcUrl],\n },\n },\n ...(chain.utilityAddresses?.multicall && {\n contracts: {\n multicall3: {\n address: chain.utilityAddresses.multicall,\n },\n },\n }),\n };\n}\n\nexport function getEvmClientForChain({\n chain,\n}: {\n chain: Chain;\n}): Client<HttpTransport, ViemChain, undefined, WalletRpcSchema, PublicActions> {\n const chainInfo = getViemChain(chain);\n\n const transport = http(chain.rpcUrl, {\n batch: true,\n retryCount: 6,\n retryDelay: 200,\n timeout: 15_000,\n });\n\n const client = createWalletClient({\n chain: chainInfo,\n transport,\n }).extend(publicActions);\n\n return client;\n}\n\nexport function getSolanaRpcForChain({ chain }: { chain: Chain }): Rpc<SolanaRpcApi> {\n return createSolanaRpc(chain.rpcUrl);\n}\n\nexport function applyFeeUnitsBpsMargin(feeUnits: bigint, feeUnitsMarginBps: number | undefined): bigint {\n if (feeUnitsMarginBps === undefined) {\n return feeUnits;\n }\n\n if (!Number.isInteger(feeUnitsMarginBps) || feeUnitsMarginBps < 0) {\n throw new InvalidParamsError(\n 'Invalid feeUnitsMarginBps',\n `feeUnitsMarginBps must be a non-negative integer, but got ${feeUnitsMarginBps}`,\n );\n }\n\n return (feeUnits * BigInt(10_000 + feeUnitsMarginBps)) / 10_000n;\n}\n\nexport function scaleAmount(amount: bigint, multiplier: number, precisionFactor = 1_000_000): bigint {\n // Verify precisionFactor is a positive integer\n if (!Number.isInteger(precisionFactor) || precisionFactor <= 0) {\n throw new Error('precisionFactor must be a positive integer');\n }\n\n return (amount * BigInt(multiplier * precisionFactor)) / BigInt(precisionFactor);\n}\n\n/**\n * Subtracts the partner fee from the given amount.\n *\n * @param amount - The original amount.\n * @param partnerFeeBps - Fee in basis points (1 bps = 0.01%)\n * @returns The amount after subtracting the partner fee.\n *\n * @throws {Error} If partnerFeeBps is not an integer or is out of range.\n */\nexport function subtractPartnerFee(amount: bigint, partnerFeeBps: number): bigint {\n if (!Number.isInteger(partnerFeeBps)) {\n throw new Error('partnerFeeBps must be an integer');\n }\n\n if (partnerFeeBps < 0 || partnerFeeBps > 10_000) {\n throw new Error('partnerFeeBps must be between 0 and 10,000');\n }\n\n return (amount * BigInt(10_000 - partnerFeeBps)) / 10_000n;\n}\n\n/**\n * Calculates the fee percentage given an input amount and a fee amount.\n *\n * @param inputAmount - The original input amount.\n * @param feeAmount - The fee amount to be calculated as a percentage of the input amount.\n * @returns An object containing the fee percentage and the number of decimal places.\n *\n * @throws {Error} If inputAmount is less than or equal to zero, or if feeAmount is negative.\n */\nexport function calculateFeePercentage(\n inputAmount: bigint,\n feeAmount: bigint,\n): { feePercentage: number; feePercentageDecimals: number } {\n if (inputAmount <= 0n) {\n throw new Error('Input amount must be greater than zero');\n }\n\n if (feeAmount < 0n) {\n throw new Error('Fee amount must be >= zero');\n }\n\n if (feeAmount === 0n) {\n return { feePercentage: 0, feePercentageDecimals: 0 };\n }\n\n const MAX_DECIMALS = 18;\n\n for (let decimals = 0; decimals <= MAX_DECIMALS; decimals++) {\n const scale = 10n ** BigInt(decimals);\n const numerator = feeAmount * 100n * scale;\n\n if (numerator % inputAmount === 0n) {\n const value = numerator / inputAmount;\n\n if (value > BigInt(Number.MAX_SAFE_INTEGER)) {\n throw new Error('feePercentage exceeds Number.MAX_SAFE_INTEGER');\n }\n\n return {\n feePercentage: Number(value),\n feePercentageDecimals: decimals,\n };\n }\n }\n\n // Fallback: highest precision, truncated\n const scale = 10n ** BigInt(MAX_DECIMALS);\n const value = (feeAmount * 100n * scale) / inputAmount;\n\n if (value > BigInt(Number.MAX_SAFE_INTEGER)) {\n throw new Error('feePercentage exceeds Number.MAX_SAFE_INTEGER');\n }\n\n return {\n feePercentage: Number(value),\n feePercentageDecimals: MAX_DECIMALS,\n };\n}\n\n/**\n * Maps Viem errors to corresponding ErrorCode values.\n *\n * @param error - The error thrown by Viem.\n * @returns The corresponding ErrorCode.\n */\nexport function getErrorCodeForViemError(error: unknown): ErrorCode {\n if (error instanceof WaitForTransactionReceiptTimeoutError) {\n return ErrorCode.TIMEOUT;\n }\n\n return ErrorCode.TRANSACTION_REVERTED;\n}\n\n/**\n * Maps `@solana/kit` errors to SDK ErrorCode values.\n *\n * `@solana/kit` throws typed `SolanaError` instances with numeric codes.\n * We use the `isSolanaError` type guard to match specific codes:\n *\n * - Transport / node-health errors → SERVICE_NOT_AVAILABLE\n * (HTTP transport failures, node-unhealthy JSON-RPC responses)\n *\n * - Block-height exceeded → TIMEOUT\n * (the transaction's blockhash has expired — the 150-slot validity\n * window has passed and the tx can no longer land)\n *\n * - Everything else → UNKNOWN\n * (unexpected JSON-RPC errors, malformed responses, internal errors, etc.)\n */\nexport function getErrorCodeForSolanaRpcError(error: unknown): ErrorCode {\n if (\n isSolanaError(error, SOLANA_ERROR__JSON_RPC__SERVER_ERROR_NODE_UNHEALTHY) ||\n isSolanaError(error, SOLANA_ERROR__RPC__TRANSPORT_HTTP_ERROR)\n ) {\n return ErrorCode.SERVICE_NOT_AVAILABLE;\n }\n\n if (isSolanaError(error, SOLANA_ERROR__BLOCK_HEIGHT_EXCEEDED)) {\n return ErrorCode.TIMEOUT;\n }\n\n return ErrorCode.UNKNOWN;\n}\n\n/**\n * Waits for either a timeout to elapse or an abort signal to be triggered.\n *\n * @param timeoutMs - The timeout duration in milliseconds.\n * @param signal - The AbortSignal to listen for abort events.\n *\n * @returns A promise that resolves when either the timeout elapses or the abort signal is triggered.\n */\nexport function waitForTimeoutOrAbort({\n timeoutMs,\n signal,\n}: Readonly<{\n timeoutMs: number;\n signal: AbortSignal;\n}>): Promise<void> {\n return new Promise((resolve) => {\n let settled = false;\n\n const finish = (): void => {\n if (settled) {\n return;\n }\n\n settled = true;\n clearTimeout(timeoutId);\n signal.removeEventListener('abort', onAbort);\n resolve();\n };\n\n const onAbort = (): void => {\n finish();\n };\n\n const timeoutId = setTimeout(() => {\n finish();\n }, timeoutMs);\n\n signal.addEventListener('abort', onAbort, { once: true });\n\n if (signal.aborted) {\n finish();\n }\n });\n}\n\nconst ABORT_TAG: unique symbol = Symbol('aborted');\n\n/**\n * @internal\n *\n * Waits for a promise to resolve or an abort signal to be triggered, whichever comes first.\n *\n * If the promise resolves first, returns an object with status 'ok' and the resolved value.\n * If the abort signal is triggered first, returns an object with status 'aborted'.\n *\n * @param awaitable - The promise to wait for.\n * @param signal - The AbortSignal to listen for abort events.\n * @returns A promise that resolves to an object indicating whether the operation was aborted or completed successfully.\n *\n * @throws Any error thrown by the awaitable promise will be propagated to the caller.\n *\n * @example\n * ```ts\n * const ac = new AbortController();\n * const result = await awaitOrAbort(someAsyncOperation(), ac.signal);\n *\n * if (result.status === 'aborted') {\n * console.log('Operation was aborted');\n * } else {\n * console.log('Operation completed with value:', result.value);\n * }\n * ```\n */\nexport async function awaitOrAbort<T>(\n awaitable: Promise<T>,\n signal: AbortSignal,\n): Promise<{ status: 'aborted' } | { status: 'ok'; value: T }> {\n const maybeAwaitable = await Promise.race([\n awaitable,\n new Promise<typeof ABORT_TAG>((resolve) => {\n signal.addEventListener('abort', () => resolve(ABORT_TAG), { once: true });\n }),\n ]);\n\n if (maybeAwaitable === ABORT_TAG || signal.aborted) {\n return { status: 'aborted' };\n }\n\n return { status: 'ok', value: maybeAwaitable };\n}\n\n/**\n * Build a `FailedTransfer` from a quote.\n *\n * Centralises the boilerplate that every transfer-service handler repeats\n * when it needs to return a failed transfer before a source tx is recorded.\n */\nexport function makeFailedTransferFromQuote(\n quote: Quote,\n options: {\n environment: Environment;\n errorCode: ErrorCode;\n errorReason: string;\n },\n): FailedTransfer {\n return {\n amountIn: quote.amountIn,\n amountOut: quote.amountOut,\n environment: options.environment,\n errorCode: options.errorCode,\n errorReason: options.errorReason,\n failedAtMs: Date.now(),\n fees: quote.fees,\n fromAddress: quote.fromAddress,\n id: quote.id,\n partnerFeeBps: quote.partnerFeeBps,\n sourceAsset: quote.assetIn,\n sourceChain: quote.sourceChain,\n status: 'failed',\n targetAsset: quote.assetOut,\n targetChain: quote.targetChain,\n toAddress: quote.toAddress,\n type: quote.serviceType,\n };\n}\n\nexport async function wait(delayMs: number, signal?: AbortSignal): Promise<void> {\n return new Promise((resolve, reject) => {\n if (delayMs <= 0) {\n return resolve();\n }\n\n const timeoutId = setTimeout(() => {\n cleanup();\n resolve();\n }, delayMs);\n\n const onAbort = () => {\n cleanup();\n reject(new AbortedError());\n };\n\n const cleanup = () => {\n clearTimeout(timeoutId);\n\n if (signal) {\n signal.removeEventListener('abort', onAbort);\n }\n };\n\n if (signal) {\n if (signal.aborted) {\n cleanup();\n\n return reject(new AbortedError());\n }\n\n signal.addEventListener('abort', onAbort);\n }\n });\n}\n"],"mappings":"8OAiCA,SAAS,EAAa,EAAyB,CAC7C,GAAM,CAAE,YAAW,UAAW,GAAY,EAAkB,EAAM,QAAQ,CAE1E,GAAI,IAAc,SAChB,MAAM,IAAI,EACR,+CACA,gCAAgC,EAAU,qCAC3C,CAGH,MAAO,CACL,GAAI,OAAO,EAAQ,CACnB,KAAM,EAAM,UACZ,eAAgB,CACd,SAAU,EAAM,aAAa,SAC7B,OAAQ,EAAM,aAAa,OAC3B,KAAM,EAAM,aAAa,KAC1B,CACD,QAAS,CACP,QAAS,CACP,KAAM,CAAC,EAAM,OAAO,CACrB,CACD,OAAQ,CACN,KAAM,CAAC,EAAM,OAAO,CACrB,CACF,CACD,GAAI,EAAM,kBAAkB,WAAa,CACvC,UAAW,CACT,WAAY,CACV,QAAS,EAAM,iBAAiB,UACjC,CACF,CACF,CACF,CAGH,SAAgB,EAAqB,CACnC,SAG8E,CAe9E,OALe,EAAmB,CAChC,MAVgB,EAAa,EAAM,CAWnC,UATgB,EAAK,EAAM,OAAQ,CACnC,MAAO,GACP,WAAY,EACZ,WAAY,IACZ,QAAS,KACV,CAAC,CAKD,CAAC,CAAC,OAAO,EAAc,CAK1B,SAAgB,EAAqB,CAAE,SAA8C,CACnF,OAAO,EAAgB,EAAM,OAAO,CAGtC,SAAgB,EAAuB,EAAkB,EAA+C,CACtG,GAAI,IAAsB,IAAA,GACxB,OAAO,EAGT,GAAI,CAAC,OAAO,UAAU,EAAkB,EAAI,EAAoB,EAC9D,MAAM,IAAI,EACR,4BACA,6DAA6D,IAC9D,CAGH,OAAQ,EAAW,OAAO,IAAS,EAAkB,CAAI,OAiJ3D,SAAgB,EAAsB,CACpC,YACA,UAIiB,CACjB,OAAO,IAAI,QAAS,GAAY,CAC9B,IAAI,EAAU,GAER,MAAqB,CACrB,IAIJ,EAAU,GACV,aAAa,EAAU,CACvB,EAAO,oBAAoB,QAAS,EAAQ,CAC5C,GAAS,GAGL,MAAsB,CAC1B,GAAQ,EAGJ,EAAY,eAAiB,CACjC,GAAQ,EACP,EAAU,CAEb,EAAO,iBAAiB,QAAS,EAAS,CAAE,KAAM,GAAM,CAAC,CAErD,EAAO,SACT,GAAQ,EAEV,CAGJ,MAAM,EAA2B,OAAO,UAAU,CA4BlD,eAAsB,EACpB,EACA,EAC6D,CAC7D,IAAM,EAAiB,MAAM,QAAQ,KAAK,CACxC,EACA,IAAI,QAA2B,GAAY,CACzC,EAAO,iBAAiB,YAAe,EAAQ,EAAU,CAAE,CAAE,KAAM,GAAM,CAAC,EAC1E,CACH,CAAC,CAMF,OAJI,IAAmB,GAAa,EAAO,QAClC,CAAE,OAAQ,UAAW,CAGvB,CAAE,OAAQ,KAAM,MAAO,EAAgB,CAShD,SAAgB,EACd,EACA,EAKgB,CAChB,MAAO,CACL,SAAU,EAAM,SAChB,UAAW,EAAM,UACjB,YAAa,EAAQ,YACrB,UAAW,EAAQ,UACnB,YAAa,EAAQ,YACrB,WAAY,KAAK,KAAK,CACtB,KAAM,EAAM,KACZ,YAAa,EAAM,YACnB,GAAI,EAAM,GACV,cAAe,EAAM,cACrB,YAAa,EAAM,QACnB,YAAa,EAAM,YACnB,OAAQ,SACR,YAAa,EAAM,SACnB,YAAa,EAAM,YACnB,UAAW,EAAM,UACjB,KAAM,EAAM,YACb,CAGH,eAAsB,EAAK,EAAiB,EAAqC,CAC/E,OAAO,IAAI,SAAS,EAAS,IAAW,CACtC,GAAI,GAAW,EACb,OAAO,GAAS,CAGlB,IAAM,EAAY,eAAiB,CACjC,GAAS,CACT,GAAS,EACR,EAAQ,CAEL,MAAgB,CACpB,GAAS,CACT,EAAO,IAAI,EAAe,EAGtB,MAAgB,CACpB,aAAa,EAAU,CAEnB,GACF,EAAO,oBAAoB,QAAS,EAAQ,EAIhD,GAAI,EAAQ,CACV,GAAI,EAAO,QAGT,OAFA,GAAS,CAEF,EAAO,IAAI,EAAe,CAGnC,EAAO,iBAAiB,QAAS,EAAQ,GAE3C"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
const e=require(`../../../constants.cjs`);function t({environment:t}){return({sourceAsset:n,sourceChainId:r,targetAsset:i,targetChainId:a})=>{if(!(t===e.Environment.PROD||t===e.Environment.TEST))return!1;let o=Object.values(t===e.Environment.PROD?e.AvalancheMainnetBlockchainChainIds:e.AvalancheFujiBlockchainChainIds);return n.type===e.TokenType.NATIVE&&i.type===e.TokenType.NATIVE&&o.includes(r)&&o.includes(a)&&r!==a}}exports.analyzeSupportFactory=t;
|
|
2
|
+
//# sourceMappingURL=analyze-support.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"analyze-support.cjs","names":["Environment","AvalancheMainnetBlockchainChainIds","AvalancheFujiBlockchainChainIds","TokenType"],"sources":["../../../../src/transfer-service/avalanche-cct/_handlers/analyze-support.ts"],"sourcesContent":["import {\n AvalancheFujiBlockchainChainIds,\n AvalancheMainnetBlockchainChainIds,\n Environment,\n TokenType,\n} from '../../../constants';\nimport type { Caip2ChainId } from '../../../types/caip';\nimport type { TransferService } from '../../../types/service';\n\nexport interface AnalyzeSupportOptions {\n environment: Environment;\n}\n\nexport function analyzeSupportFactory({ environment }: AnalyzeSupportOptions): TransferService['analyzeSupport'] {\n return ({ sourceAsset, sourceChainId, targetAsset, targetChainId }) => {\n const isSupportedEnvironment = environment === Environment.PROD || environment === Environment.TEST;\n if (!isSupportedEnvironment) return false;\n\n const validChainIds: readonly Caip2ChainId[] = Object.values(\n environment === Environment.PROD ? AvalancheMainnetBlockchainChainIds : AvalancheFujiBlockchainChainIds,\n );\n\n const isSupported =\n sourceAsset.type === TokenType.NATIVE &&\n targetAsset.type === TokenType.NATIVE &&\n validChainIds.includes(sourceChainId) &&\n validChainIds.includes(targetChainId) &&\n sourceChainId !== targetChainId;\n\n return isSupported;\n };\n}\n"],"mappings":"0CAaA,SAAgB,EAAsB,CAAE,eAAyE,CAC/G,OAAQ,CAAE,cAAa,gBAAe,cAAa,mBAAoB,CAErE,GAAI,EAD2B,IAAgBA,EAAAA,YAAY,MAAQ,IAAgBA,EAAAA,YAAY,MAClE,MAAO,GAEpC,IAAM,EAAyC,OAAO,OACpD,IAAgBA,EAAAA,YAAY,KAAOC,EAAAA,mCAAqCC,EAAAA,gCACzE,CASD,OANE,EAAY,OAASC,EAAAA,UAAU,QAC/B,EAAY,OAASA,EAAAA,UAAU,QAC/B,EAAc,SAAS,EAAc,EACrC,EAAc,SAAS,EAAc,EACrC,IAAkB"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{AvalancheFujiBlockchainChainIds as e,AvalancheMainnetBlockchainChainIds as t,Environment as n,TokenType as r}from"../../../constants.js";function i({environment:i}){return({sourceAsset:a,sourceChainId:o,targetAsset:s,targetChainId:c})=>{if(!(i===n.PROD||i===n.TEST))return!1;let l=Object.values(i===n.PROD?t:e);return a.type===r.NATIVE&&s.type===r.NATIVE&&l.includes(o)&&l.includes(c)&&o!==c}}export{i as analyzeSupportFactory};
|
|
2
|
+
//# sourceMappingURL=analyze-support.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"analyze-support.js","names":[],"sources":["../../../../src/transfer-service/avalanche-cct/_handlers/analyze-support.ts"],"sourcesContent":["import {\n AvalancheFujiBlockchainChainIds,\n AvalancheMainnetBlockchainChainIds,\n Environment,\n TokenType,\n} from '../../../constants';\nimport type { Caip2ChainId } from '../../../types/caip';\nimport type { TransferService } from '../../../types/service';\n\nexport interface AnalyzeSupportOptions {\n environment: Environment;\n}\n\nexport function analyzeSupportFactory({ environment }: AnalyzeSupportOptions): TransferService['analyzeSupport'] {\n return ({ sourceAsset, sourceChainId, targetAsset, targetChainId }) => {\n const isSupportedEnvironment = environment === Environment.PROD || environment === Environment.TEST;\n if (!isSupportedEnvironment) return false;\n\n const validChainIds: readonly Caip2ChainId[] = Object.values(\n environment === Environment.PROD ? AvalancheMainnetBlockchainChainIds : AvalancheFujiBlockchainChainIds,\n );\n\n const isSupported =\n sourceAsset.type === TokenType.NATIVE &&\n targetAsset.type === TokenType.NATIVE &&\n validChainIds.includes(sourceChainId) &&\n validChainIds.includes(targetChainId) &&\n sourceChainId !== targetChainId;\n\n return isSupported;\n };\n}\n"],"mappings":"gJAaA,SAAgB,EAAsB,CAAE,eAAyE,CAC/G,OAAQ,CAAE,cAAa,gBAAe,cAAa,mBAAoB,CAErE,GAAI,EAD2B,IAAgB,EAAY,MAAQ,IAAgB,EAAY,MAClE,MAAO,GAEpC,IAAM,EAAyC,OAAO,OACpD,IAAgB,EAAY,KAAO,EAAqC,EACzE,CASD,OANE,EAAY,OAAS,EAAU,QAC/B,EAAY,OAAS,EAAU,QAC/B,EAAc,SAAS,EAAc,EACrC,EAAc,SAAS,EAAc,EACrC,IAAkB"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
const e=require(`../../../constants.cjs`),t=require(`../../../errors.cjs`),n=require(`../_utils.cjs`),r=require(`../../_utils.cjs`),i=require(`../../_evm-gas.cjs`),a=require(`../_utils/fees.cjs`);function o({ajsContext:o,environment:s,getAtomicUtxos:c,getUtxos:l}){return async(u,d)=>{if(u.serviceType!==e.ServiceType.AVALANCHE_CCT)throw new t.SdkError(t.ErrorReason.INCORRECT_PROVIDER_PROVIDED,t.ErrorCode.INVALID_PARAMS);let f=s===e.Environment.TEST,p=r.getEvmClientForChain({chain:f?e.AVALANCHE_FUJI_CHAIN:e.AVALANCHE_MAINNET_CHAIN}),m=d?.overrides?.maxFeePerGas??(await i.fetchSuggestedGasPrices(p))[d?.overrides?.feeRateTier??`fast`].maxFeePerGas,h=d?.feeUnitsMarginBps,g=n.getChainAlias(u.sourceChain.chainId,f),_=n.getChainAlias(u.targetChain.chainId,f),v=(await c(_,g)).getUTXOs(),y=u.amountIn>0n,b=y&&g===`P`?Math.max((await l(`P`)).getUTXOs().length,1):1,x=v.length+(y?1:0),S={context:o,environment:s,maxFeePerGas:m,numberInputs:b},C={context:o,environment:s,maxFeePerGas:m,numberInputs:x,numberSignatures:1},w=y?await a.getExportFeeInNanoAvax(g,{...S,feeUnitsMarginBps:h}):0n,T=await a.getImportFeeInNanoAvax(_,{...C,feeUnitsMarginBps:h}),E=y?await a.getExportFeeInNanoAvax(g,{...S,feeUnitsMarginBps:void 0}):0n,D=await a.getImportFeeInNanoAvax(_,{...C,feeUnitsMarginBps:void 0}),O=w+T,k=E+D,A=g===`C`,j=A?n.convertNanoAvaxToWei(O):O,M=A?n.convertNanoAvaxToWei(k):k;return{asset:n.getNativeTokenForChainAlias(g),totalFee:j,totalFeeWithoutMargin:M}}}exports.estimateNativeFeeFactory=o;
|
|
2
|
+
//# sourceMappingURL=estimate-native-fee.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"estimate-native-fee.cjs","names":["ServiceType","SdkError","ErrorReason","ErrorCode","Environment","getEvmClientForChain","AVALANCHE_FUJI_CHAIN","AVALANCHE_MAINNET_CHAIN","fetchSuggestedGasPrices","getChainAlias","getExportFeeInNanoAvax","getImportFeeInNanoAvax","convertNanoAvaxToWei","getNativeTokenForChainAlias"],"sources":["../../../../src/transfer-service/avalanche-cct/_handlers/estimate-native-fee.ts"],"sourcesContent":["import type { Context } from '@avalabs/avalanchejs';\nimport type { TransferService } from '../../../types/service';\nimport {\n AVALANCHE_FUJI_CHAIN,\n AVALANCHE_MAINNET_CHAIN,\n Environment,\n ServiceType,\n type AvalancheBlockchainAlias,\n} from '../../../constants';\nimport type { GetAtomicUtxosCallback, GetUtxosCallback } from '../types';\nimport { ErrorCode, ErrorReason, SdkError } from '../../../errors';\nimport { fetchSuggestedGasPrices } from '../../_evm-gas';\nimport { getEvmClientForChain } from '../../_utils';\nimport { getChainAlias, convertNanoAvaxToWei, getNativeTokenForChainAlias } from '../_utils';\nimport { getExportFeeInNanoAvax, getImportFeeInNanoAvax } from '../_utils/fees';\n\nexport interface EstimateNativeFeeOptions {\n ajsContext: Context.Context;\n environment: Environment;\n getAtomicUtxos: GetAtomicUtxosCallback;\n getUtxos: GetUtxosCallback;\n}\n\nexport function estimateNativeFeeFactory({\n ajsContext,\n environment,\n getAtomicUtxos,\n getUtxos,\n}: EstimateNativeFeeOptions): TransferService['estimateNativeFee'] {\n return async (quote, options) => {\n if (quote.serviceType !== ServiceType.AVALANCHE_CCT) {\n throw new SdkError(ErrorReason.INCORRECT_PROVIDER_PROVIDED, ErrorCode.INVALID_PARAMS);\n }\n\n const isTestnet = environment === Environment.TEST;\n const cChain = isTestnet ? AVALANCHE_FUJI_CHAIN : AVALANCHE_MAINNET_CHAIN;\n\n const client = getEvmClientForChain({ chain: cChain });\n\n const maxFeePerGas =\n options?.overrides?.maxFeePerGas ??\n (await fetchSuggestedGasPrices(client))[options?.overrides?.feeRateTier ?? 'fast'].maxFeePerGas;\n const feeUnitsMarginBps = options?.feeUnitsMarginBps;\n\n const sourceChainAlias: AvalancheBlockchainAlias = getChainAlias(quote.sourceChain.chainId, isTestnet);\n const destinationChainAlias: AvalancheBlockchainAlias = getChainAlias(quote.targetChain.chainId, isTestnet);\n const atomicUtxoSet = await getAtomicUtxos(destinationChainAlias, sourceChainAlias);\n const atomicUtxos = atomicUtxoSet.getUTXOs();\n\n const hasExport = quote.amountIn > 0n;\n // Minimum of 1, but default assume the max amount of UTXOs\n // if exporting from P-Chain since each UTXO requires a signature which increases the fee.\n const exportNumberInputs =\n hasExport && sourceChainAlias === 'P' ? Math.max((await getUtxos('P')).getUTXOs().length, 1) : 1;\n const importNumberInputs = atomicUtxos.length + (hasExport ? 1 : 0);\n const numberSignatures = 1;\n\n const feeBaseParams = {\n context: ajsContext,\n environment,\n maxFeePerGas,\n numberInputs: exportNumberInputs,\n };\n\n const importFeeBaseParams = {\n context: ajsContext,\n environment,\n maxFeePerGas,\n numberInputs: importNumberInputs,\n numberSignatures,\n };\n\n const exportFeeInNanoAvax = hasExport\n ? await getExportFeeInNanoAvax(sourceChainAlias, {\n ...feeBaseParams,\n feeUnitsMarginBps,\n })\n : 0n;\n\n const importFeeInNanoAvax = await getImportFeeInNanoAvax(destinationChainAlias, {\n ...importFeeBaseParams,\n feeUnitsMarginBps,\n });\n\n const exportFeeWithoutMarginInNanoAvax = hasExport\n ? await getExportFeeInNanoAvax(sourceChainAlias, {\n ...feeBaseParams,\n feeUnitsMarginBps: undefined,\n })\n : 0n;\n\n const importFeeWithoutMarginInNanoAvax = await getImportFeeInNanoAvax(destinationChainAlias, {\n ...importFeeBaseParams,\n feeUnitsMarginBps: undefined,\n });\n\n const totalFeeInNanoAvax = exportFeeInNanoAvax + importFeeInNanoAvax;\n const totalFeeWithoutMarginInNanoAvax = exportFeeWithoutMarginInNanoAvax + importFeeWithoutMarginInNanoAvax;\n\n const shouldReturnWei = sourceChainAlias === 'C';\n const totalFee = shouldReturnWei ? convertNanoAvaxToWei(totalFeeInNanoAvax) : totalFeeInNanoAvax;\n const totalFeeWithoutMargin = shouldReturnWei\n ? convertNanoAvaxToWei(totalFeeWithoutMarginInNanoAvax)\n : totalFeeWithoutMarginInNanoAvax;\n\n return {\n asset: getNativeTokenForChainAlias(sourceChainAlias),\n totalFee,\n totalFeeWithoutMargin,\n };\n };\n}\n"],"mappings":"oMAuBA,SAAgB,EAAyB,CACvC,aACA,cACA,iBACA,YACiE,CACjE,OAAO,MAAO,EAAO,IAAY,CAC/B,GAAI,EAAM,cAAgBA,EAAAA,YAAY,cACpC,MAAM,IAAIC,EAAAA,SAASC,EAAAA,YAAY,4BAA6BC,EAAAA,UAAU,eAAe,CAGvF,IAAM,EAAY,IAAgBC,EAAAA,YAAY,KAGxC,EAASC,EAAAA,qBAAqB,CAAE,MAFvB,EAAYC,EAAAA,qBAAuBC,EAAAA,wBAEG,CAAC,CAEhD,EACJ,GAAS,WAAW,eACnB,MAAMC,EAAAA,wBAAwB,EAAO,EAAE,GAAS,WAAW,aAAe,QAAQ,aAC/E,EAAoB,GAAS,kBAE7B,EAA6CC,EAAAA,cAAc,EAAM,YAAY,QAAS,EAAU,CAChG,EAAkDA,EAAAA,cAAc,EAAM,YAAY,QAAS,EAAU,CAErG,GADgB,MAAM,EAAe,EAAuB,EAAiB,EACjD,UAAU,CAEtC,EAAY,EAAM,SAAW,GAG7B,EACJ,GAAa,IAAqB,IAAM,KAAK,KAAK,MAAM,EAAS,IAAI,EAAE,UAAU,CAAC,OAAQ,EAAE,CAAG,EAC3F,EAAqB,EAAY,QAAU,EAAY,EAAI,GAG3D,EAAgB,CACpB,QAAS,EACT,cACA,eACA,aAAc,EACf,CAEK,EAAsB,CAC1B,QAAS,EACT,cACA,eACA,aAAc,EACd,mBACD,CAEK,EAAsB,EACxB,MAAMC,EAAAA,uBAAuB,EAAkB,CAC7C,GAAG,EACH,oBACD,CAAC,CACF,GAEE,EAAsB,MAAMC,EAAAA,uBAAuB,EAAuB,CAC9E,GAAG,EACH,oBACD,CAAC,CAEI,EAAmC,EACrC,MAAMD,EAAAA,uBAAuB,EAAkB,CAC7C,GAAG,EACH,kBAAmB,IAAA,GACpB,CAAC,CACF,GAEE,EAAmC,MAAMC,EAAAA,uBAAuB,EAAuB,CAC3F,GAAG,EACH,kBAAmB,IAAA,GACpB,CAAC,CAEI,EAAqB,EAAsB,EAC3C,EAAkC,EAAmC,EAErE,EAAkB,IAAqB,IACvC,EAAW,EAAkBC,EAAAA,qBAAqB,EAAmB,CAAG,EACxE,EAAwB,EAC1BA,EAAAA,qBAAqB,EAAgC,CACrD,EAEJ,MAAO,CACL,MAAOC,EAAAA,4BAA4B,EAAiB,CACpD,WACA,wBACD"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{AVALANCHE_FUJI_CHAIN as e,AVALANCHE_MAINNET_CHAIN as t,Environment as n,ServiceType as r}from"../../../constants.js";import{ErrorCode as i,ErrorReason as a,SdkError as o}from"../../../errors.js";import{convertNanoAvaxToWei as s,getChainAlias as c,getNativeTokenForChainAlias as l}from"../_utils.js";import{getEvmClientForChain as u}from"../../_utils.js";import{fetchSuggestedGasPrices as d}from"../../_evm-gas.js";import{getExportFeeInNanoAvax as f,getImportFeeInNanoAvax as p}from"../_utils/fees.js";function m({ajsContext:m,environment:h,getAtomicUtxos:g,getUtxos:_}){return async(v,y)=>{if(v.serviceType!==r.AVALANCHE_CCT)throw new o(a.INCORRECT_PROVIDER_PROVIDED,i.INVALID_PARAMS);let b=h===n.TEST,x=u({chain:b?e:t}),S=y?.overrides?.maxFeePerGas??(await d(x))[y?.overrides?.feeRateTier??`fast`].maxFeePerGas,C=y?.feeUnitsMarginBps,w=c(v.sourceChain.chainId,b),T=c(v.targetChain.chainId,b),E=(await g(T,w)).getUTXOs(),D=v.amountIn>0n,O=D&&w===`P`?Math.max((await _(`P`)).getUTXOs().length,1):1,k=E.length+(D?1:0),A={context:m,environment:h,maxFeePerGas:S,numberInputs:O},j={context:m,environment:h,maxFeePerGas:S,numberInputs:k,numberSignatures:1},M=D?await f(w,{...A,feeUnitsMarginBps:C}):0n,N=await p(T,{...j,feeUnitsMarginBps:C}),P=D?await f(w,{...A,feeUnitsMarginBps:void 0}):0n,F=await p(T,{...j,feeUnitsMarginBps:void 0}),I=M+N,L=P+F,R=w===`C`,z=R?s(I):I,B=R?s(L):L;return{asset:l(w),totalFee:z,totalFeeWithoutMargin:B}}}export{m as estimateNativeFeeFactory};
|
|
2
|
+
//# sourceMappingURL=estimate-native-fee.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"estimate-native-fee.js","names":[],"sources":["../../../../src/transfer-service/avalanche-cct/_handlers/estimate-native-fee.ts"],"sourcesContent":["import type { Context } from '@avalabs/avalanchejs';\nimport type { TransferService } from '../../../types/service';\nimport {\n AVALANCHE_FUJI_CHAIN,\n AVALANCHE_MAINNET_CHAIN,\n Environment,\n ServiceType,\n type AvalancheBlockchainAlias,\n} from '../../../constants';\nimport type { GetAtomicUtxosCallback, GetUtxosCallback } from '../types';\nimport { ErrorCode, ErrorReason, SdkError } from '../../../errors';\nimport { fetchSuggestedGasPrices } from '../../_evm-gas';\nimport { getEvmClientForChain } from '../../_utils';\nimport { getChainAlias, convertNanoAvaxToWei, getNativeTokenForChainAlias } from '../_utils';\nimport { getExportFeeInNanoAvax, getImportFeeInNanoAvax } from '../_utils/fees';\n\nexport interface EstimateNativeFeeOptions {\n ajsContext: Context.Context;\n environment: Environment;\n getAtomicUtxos: GetAtomicUtxosCallback;\n getUtxos: GetUtxosCallback;\n}\n\nexport function estimateNativeFeeFactory({\n ajsContext,\n environment,\n getAtomicUtxos,\n getUtxos,\n}: EstimateNativeFeeOptions): TransferService['estimateNativeFee'] {\n return async (quote, options) => {\n if (quote.serviceType !== ServiceType.AVALANCHE_CCT) {\n throw new SdkError(ErrorReason.INCORRECT_PROVIDER_PROVIDED, ErrorCode.INVALID_PARAMS);\n }\n\n const isTestnet = environment === Environment.TEST;\n const cChain = isTestnet ? AVALANCHE_FUJI_CHAIN : AVALANCHE_MAINNET_CHAIN;\n\n const client = getEvmClientForChain({ chain: cChain });\n\n const maxFeePerGas =\n options?.overrides?.maxFeePerGas ??\n (await fetchSuggestedGasPrices(client))[options?.overrides?.feeRateTier ?? 'fast'].maxFeePerGas;\n const feeUnitsMarginBps = options?.feeUnitsMarginBps;\n\n const sourceChainAlias: AvalancheBlockchainAlias = getChainAlias(quote.sourceChain.chainId, isTestnet);\n const destinationChainAlias: AvalancheBlockchainAlias = getChainAlias(quote.targetChain.chainId, isTestnet);\n const atomicUtxoSet = await getAtomicUtxos(destinationChainAlias, sourceChainAlias);\n const atomicUtxos = atomicUtxoSet.getUTXOs();\n\n const hasExport = quote.amountIn > 0n;\n // Minimum of 1, but default assume the max amount of UTXOs\n // if exporting from P-Chain since each UTXO requires a signature which increases the fee.\n const exportNumberInputs =\n hasExport && sourceChainAlias === 'P' ? Math.max((await getUtxos('P')).getUTXOs().length, 1) : 1;\n const importNumberInputs = atomicUtxos.length + (hasExport ? 1 : 0);\n const numberSignatures = 1;\n\n const feeBaseParams = {\n context: ajsContext,\n environment,\n maxFeePerGas,\n numberInputs: exportNumberInputs,\n };\n\n const importFeeBaseParams = {\n context: ajsContext,\n environment,\n maxFeePerGas,\n numberInputs: importNumberInputs,\n numberSignatures,\n };\n\n const exportFeeInNanoAvax = hasExport\n ? await getExportFeeInNanoAvax(sourceChainAlias, {\n ...feeBaseParams,\n feeUnitsMarginBps,\n })\n : 0n;\n\n const importFeeInNanoAvax = await getImportFeeInNanoAvax(destinationChainAlias, {\n ...importFeeBaseParams,\n feeUnitsMarginBps,\n });\n\n const exportFeeWithoutMarginInNanoAvax = hasExport\n ? await getExportFeeInNanoAvax(sourceChainAlias, {\n ...feeBaseParams,\n feeUnitsMarginBps: undefined,\n })\n : 0n;\n\n const importFeeWithoutMarginInNanoAvax = await getImportFeeInNanoAvax(destinationChainAlias, {\n ...importFeeBaseParams,\n feeUnitsMarginBps: undefined,\n });\n\n const totalFeeInNanoAvax = exportFeeInNanoAvax + importFeeInNanoAvax;\n const totalFeeWithoutMarginInNanoAvax = exportFeeWithoutMarginInNanoAvax + importFeeWithoutMarginInNanoAvax;\n\n const shouldReturnWei = sourceChainAlias === 'C';\n const totalFee = shouldReturnWei ? convertNanoAvaxToWei(totalFeeInNanoAvax) : totalFeeInNanoAvax;\n const totalFeeWithoutMargin = shouldReturnWei\n ? convertNanoAvaxToWei(totalFeeWithoutMarginInNanoAvax)\n : totalFeeWithoutMarginInNanoAvax;\n\n return {\n asset: getNativeTokenForChainAlias(sourceChainAlias),\n totalFee,\n totalFeeWithoutMargin,\n };\n };\n}\n"],"mappings":"4fAuBA,SAAgB,EAAyB,CACvC,aACA,cACA,iBACA,YACiE,CACjE,OAAO,MAAO,EAAO,IAAY,CAC/B,GAAI,EAAM,cAAgB,EAAY,cACpC,MAAM,IAAI,EAAS,EAAY,4BAA6B,EAAU,eAAe,CAGvF,IAAM,EAAY,IAAgB,EAAY,KAGxC,EAAS,EAAqB,CAAE,MAFvB,EAAY,EAAuB,EAEG,CAAC,CAEhD,EACJ,GAAS,WAAW,eACnB,MAAM,EAAwB,EAAO,EAAE,GAAS,WAAW,aAAe,QAAQ,aAC/E,EAAoB,GAAS,kBAE7B,EAA6C,EAAc,EAAM,YAAY,QAAS,EAAU,CAChG,EAAkD,EAAc,EAAM,YAAY,QAAS,EAAU,CAErG,GADgB,MAAM,EAAe,EAAuB,EAAiB,EACjD,UAAU,CAEtC,EAAY,EAAM,SAAW,GAG7B,EACJ,GAAa,IAAqB,IAAM,KAAK,KAAK,MAAM,EAAS,IAAI,EAAE,UAAU,CAAC,OAAQ,EAAE,CAAG,EAC3F,EAAqB,EAAY,QAAU,EAAY,EAAI,GAG3D,EAAgB,CACpB,QAAS,EACT,cACA,eACA,aAAc,EACf,CAEK,EAAsB,CAC1B,QAAS,EACT,cACA,eACA,aAAc,EACd,mBACD,CAEK,EAAsB,EACxB,MAAM,EAAuB,EAAkB,CAC7C,GAAG,EACH,oBACD,CAAC,CACF,GAEE,EAAsB,MAAM,EAAuB,EAAuB,CAC9E,GAAG,EACH,oBACD,CAAC,CAEI,EAAmC,EACrC,MAAM,EAAuB,EAAkB,CAC7C,GAAG,EACH,kBAAmB,IAAA,GACpB,CAAC,CACF,GAEE,EAAmC,MAAM,EAAuB,EAAuB,CAC3F,GAAG,EACH,kBAAmB,IAAA,GACpB,CAAC,CAEI,EAAqB,EAAsB,EAC3C,EAAkC,EAAmC,EAErE,EAAkB,IAAqB,IACvC,EAAW,EAAkB,EAAqB,EAAmB,CAAG,EACxE,EAAwB,EAC1B,EAAqB,EAAgC,CACrD,EAEJ,MAAO,CACL,MAAO,EAA4B,EAAiB,CACpD,WACA,wBACD"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
const e=require(`../../../constants.cjs`),t=require(`../../../utils/asset-id.cjs`),n=require(`../constants.cjs`),r=({assets:e,limit:t,page:n})=>{let r=(n-1)*t,i=e.slice(r,r+t),a=r+i.length<e.length;return{assets:i,meta:{currentPage:n,hasMore:a,...a?{nextPage:n+1}:{}}}};function i({environment:i}){return async({sourceAsset:a,sourceChainId:o,targetChainId:s,limit:c,page:l})=>{let u=c??100,d=l??1;if(a.type!==e.TokenType.NATIVE||!(i===e.Environment.PROD||i===e.Environment.TEST))return r({assets:[],limit:u,page:d});let f=Object.values(i===e.Environment.PROD?e.AvalancheMainnetBlockchainChainIds:e.AvalancheFujiBlockchainChainIds);if(!f.includes(o)||!f.includes(s)||o===s)return r({assets:[],limit:u,page:d});let p=o===e.AvalancheMainnetBlockchainChainIds.C||o===e.AvalancheFujiBlockchainChainIds.C?n.AVALANCHE_PX_CHAIN_NATIVE_ASSET:n.AVALANCHE_C_CHAIN_NATIVE_ASSET;return r({assets:[{id:t.getAssetId(s,p),...p,bridgeProviders:[e.ServiceType.AVALANCHE_CCT]}],limit:u,page:d})}}exports.getBridgeableAssetsFactory=i;
|
|
2
|
+
//# sourceMappingURL=get-bridgeable-assets.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"get-bridgeable-assets.cjs","names":["TokenType","Environment","AvalancheMainnetBlockchainChainIds","AvalancheFujiBlockchainChainIds","AVALANCHE_PX_CHAIN_NATIVE_ASSET","AVALANCHE_C_CHAIN_NATIVE_ASSET","getAssetId","ServiceType"],"sources":["../../../../src/transfer-service/avalanche-cct/_handlers/get-bridgeable-assets.ts"],"sourcesContent":["import {\n TokenType,\n Environment,\n AvalancheMainnetBlockchainChainIds,\n AvalancheFujiBlockchainChainIds,\n ServiceType,\n} from '../../../constants';\nimport type { BridgeableUiAsset } from '../../../types/asset';\nimport type { Caip2ChainId } from '../../../types/caip';\nimport type { GetBridgeableAssetsProps, GetBridgeableAssetsResult, TransferService } from '../../../types/service';\nimport { getAssetId } from '../../../utils/asset-id';\nimport { AVALANCHE_C_CHAIN_NATIVE_ASSET, AVALANCHE_PX_CHAIN_NATIVE_ASSET } from '../constants';\n\nconst DEFAULT_PAGE = 1;\nconst DEFAULT_LIMIT = 100;\n\nconst paginateAssets = ({\n assets,\n limit,\n page,\n}: {\n assets: readonly BridgeableUiAsset[];\n limit: number;\n page: number;\n}): GetBridgeableAssetsResult => {\n const startIndex = (page - 1) * limit;\n const pageAssets = assets.slice(startIndex, startIndex + limit);\n const hasMore = startIndex + pageAssets.length < assets.length;\n\n return {\n assets: pageAssets,\n meta: {\n currentPage: page,\n hasMore,\n ...(hasMore ? { nextPage: page + 1 } : {}),\n },\n };\n};\n\nexport interface GetBridgeableAssetsOptions {\n environment: Environment;\n}\n\nexport function getBridgeableAssetsFactory({\n environment,\n}: GetBridgeableAssetsOptions): TransferService['getBridgeableAssets'] {\n return async ({\n sourceAsset,\n sourceChainId,\n targetChainId,\n limit,\n page,\n }: GetBridgeableAssetsProps): Promise<GetBridgeableAssetsResult> => {\n const pageLimit = limit ?? DEFAULT_LIMIT;\n const currentPage = page ?? DEFAULT_PAGE;\n\n if (sourceAsset.type !== TokenType.NATIVE)\n return paginateAssets({ assets: [], limit: pageLimit, page: currentPage });\n\n const isSupportedEnvironment = environment === Environment.PROD || environment === Environment.TEST;\n if (!isSupportedEnvironment) return paginateAssets({ assets: [], limit: pageLimit, page: currentPage });\n\n const validChainIds: readonly Caip2ChainId[] = Object.values(\n environment === Environment.PROD ? AvalancheMainnetBlockchainChainIds : AvalancheFujiBlockchainChainIds,\n );\n\n if (\n !validChainIds.includes(sourceChainId) ||\n !validChainIds.includes(targetChainId) ||\n sourceChainId === targetChainId\n ) {\n return paginateAssets({ assets: [], limit: pageLimit, page: currentPage });\n }\n\n const targetNativeAsset =\n sourceChainId === AvalancheMainnetBlockchainChainIds.C || sourceChainId === AvalancheFujiBlockchainChainIds.C\n ? AVALANCHE_PX_CHAIN_NATIVE_ASSET\n : AVALANCHE_C_CHAIN_NATIVE_ASSET;\n\n return paginateAssets({\n assets: [\n {\n id: getAssetId(targetChainId, targetNativeAsset),\n ...targetNativeAsset,\n bridgeProviders: [ServiceType.AVALANCHE_CCT],\n },\n ],\n limit: pageLimit,\n page: currentPage,\n });\n };\n}\n"],"mappings":"iHAgBM,GAAkB,CACtB,SACA,QACA,UAK+B,CAC/B,IAAM,GAAc,EAAO,GAAK,EAC1B,EAAa,EAAO,MAAM,EAAY,EAAa,EAAM,CACzD,EAAU,EAAa,EAAW,OAAS,EAAO,OAExD,MAAO,CACL,OAAQ,EACR,KAAM,CACJ,YAAa,EACb,UACA,GAAI,EAAU,CAAE,SAAU,EAAO,EAAG,CAAG,EAAE,CAC1C,CACF,EAOH,SAAgB,EAA2B,CACzC,eACqE,CACrE,OAAO,MAAO,CACZ,cACA,gBACA,gBACA,QACA,UACkE,CAClE,IAAM,EAAY,GAAS,IACrB,EAAc,GAAQ,EAM5B,GAJI,EAAY,OAASA,EAAAA,UAAU,QAI/B,EAD2B,IAAgBC,EAAAA,YAAY,MAAQ,IAAgBA,EAAAA,YAAY,MAClE,OAAO,EAAe,CAAE,OAAQ,EAAE,CAAE,MAAO,EAAW,KAAM,EAAa,CAAC,CAEvG,IAAM,EAAyC,OAAO,OACpD,IAAgBA,EAAAA,YAAY,KAAOC,EAAAA,mCAAqCC,EAAAA,gCACzE,CAED,GACE,CAAC,EAAc,SAAS,EAAc,EACtC,CAAC,EAAc,SAAS,EAAc,EACtC,IAAkB,EAElB,OAAO,EAAe,CAAE,OAAQ,EAAE,CAAE,MAAO,EAAW,KAAM,EAAa,CAAC,CAG5E,IAAM,EACJ,IAAkBD,EAAAA,mCAAmC,GAAK,IAAkBC,EAAAA,gCAAgC,EACxGC,EAAAA,gCACAC,EAAAA,+BAEN,OAAO,EAAe,CACpB,OAAQ,CACN,CACE,GAAIC,EAAAA,WAAW,EAAe,EAAkB,CAChD,GAAG,EACH,gBAAiB,CAACC,EAAAA,YAAY,cAAc,CAC7C,CACF,CACD,MAAO,EACP,KAAM,EACP,CAAC"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{AvalancheFujiBlockchainChainIds as e,AvalancheMainnetBlockchainChainIds as t,Environment as n,ServiceType as r,TokenType as i}from"../../../constants.js";import{getAssetId as a}from"../../../utils/asset-id.js";import{AVALANCHE_C_CHAIN_NATIVE_ASSET as o,AVALANCHE_PX_CHAIN_NATIVE_ASSET as s}from"../constants.js";const c=({assets:e,limit:t,page:n})=>{let r=(n-1)*t,i=e.slice(r,r+t),a=r+i.length<e.length;return{assets:i,meta:{currentPage:n,hasMore:a,...a?{nextPage:n+1}:{}}}};function l({environment:l}){return async({sourceAsset:u,sourceChainId:d,targetChainId:f,limit:p,page:m})=>{let h=p??100,g=m??1;if(u.type!==i.NATIVE||!(l===n.PROD||l===n.TEST))return c({assets:[],limit:h,page:g});let _=Object.values(l===n.PROD?t:e);if(!_.includes(d)||!_.includes(f)||d===f)return c({assets:[],limit:h,page:g});let v=d===t.C||d===e.C?s:o;return c({assets:[{id:a(f,v),...v,bridgeProviders:[r.AVALANCHE_CCT]}],limit:h,page:g})}}export{l as getBridgeableAssetsFactory};
|
|
2
|
+
//# sourceMappingURL=get-bridgeable-assets.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"get-bridgeable-assets.js","names":[],"sources":["../../../../src/transfer-service/avalanche-cct/_handlers/get-bridgeable-assets.ts"],"sourcesContent":["import {\n TokenType,\n Environment,\n AvalancheMainnetBlockchainChainIds,\n AvalancheFujiBlockchainChainIds,\n ServiceType,\n} from '../../../constants';\nimport type { BridgeableUiAsset } from '../../../types/asset';\nimport type { Caip2ChainId } from '../../../types/caip';\nimport type { GetBridgeableAssetsProps, GetBridgeableAssetsResult, TransferService } from '../../../types/service';\nimport { getAssetId } from '../../../utils/asset-id';\nimport { AVALANCHE_C_CHAIN_NATIVE_ASSET, AVALANCHE_PX_CHAIN_NATIVE_ASSET } from '../constants';\n\nconst DEFAULT_PAGE = 1;\nconst DEFAULT_LIMIT = 100;\n\nconst paginateAssets = ({\n assets,\n limit,\n page,\n}: {\n assets: readonly BridgeableUiAsset[];\n limit: number;\n page: number;\n}): GetBridgeableAssetsResult => {\n const startIndex = (page - 1) * limit;\n const pageAssets = assets.slice(startIndex, startIndex + limit);\n const hasMore = startIndex + pageAssets.length < assets.length;\n\n return {\n assets: pageAssets,\n meta: {\n currentPage: page,\n hasMore,\n ...(hasMore ? { nextPage: page + 1 } : {}),\n },\n };\n};\n\nexport interface GetBridgeableAssetsOptions {\n environment: Environment;\n}\n\nexport function getBridgeableAssetsFactory({\n environment,\n}: GetBridgeableAssetsOptions): TransferService['getBridgeableAssets'] {\n return async ({\n sourceAsset,\n sourceChainId,\n targetChainId,\n limit,\n page,\n }: GetBridgeableAssetsProps): Promise<GetBridgeableAssetsResult> => {\n const pageLimit = limit ?? DEFAULT_LIMIT;\n const currentPage = page ?? DEFAULT_PAGE;\n\n if (sourceAsset.type !== TokenType.NATIVE)\n return paginateAssets({ assets: [], limit: pageLimit, page: currentPage });\n\n const isSupportedEnvironment = environment === Environment.PROD || environment === Environment.TEST;\n if (!isSupportedEnvironment) return paginateAssets({ assets: [], limit: pageLimit, page: currentPage });\n\n const validChainIds: readonly Caip2ChainId[] = Object.values(\n environment === Environment.PROD ? AvalancheMainnetBlockchainChainIds : AvalancheFujiBlockchainChainIds,\n );\n\n if (\n !validChainIds.includes(sourceChainId) ||\n !validChainIds.includes(targetChainId) ||\n sourceChainId === targetChainId\n ) {\n return paginateAssets({ assets: [], limit: pageLimit, page: currentPage });\n }\n\n const targetNativeAsset =\n sourceChainId === AvalancheMainnetBlockchainChainIds.C || sourceChainId === AvalancheFujiBlockchainChainIds.C\n ? AVALANCHE_PX_CHAIN_NATIVE_ASSET\n : AVALANCHE_C_CHAIN_NATIVE_ASSET;\n\n return paginateAssets({\n assets: [\n {\n id: getAssetId(targetChainId, targetNativeAsset),\n ...targetNativeAsset,\n bridgeProviders: [ServiceType.AVALANCHE_CCT],\n },\n ],\n limit: pageLimit,\n page: currentPage,\n });\n };\n}\n"],"mappings":"+TAaA,MAGM,GAAkB,CACtB,SACA,QACA,UAK+B,CAC/B,IAAM,GAAc,EAAO,GAAK,EAC1B,EAAa,EAAO,MAAM,EAAY,EAAa,EAAM,CACzD,EAAU,EAAa,EAAW,OAAS,EAAO,OAExD,MAAO,CACL,OAAQ,EACR,KAAM,CACJ,YAAa,EACb,UACA,GAAI,EAAU,CAAE,SAAU,EAAO,EAAG,CAAG,EAAE,CAC1C,CACF,EAOH,SAAgB,EAA2B,CACzC,eACqE,CACrE,OAAO,MAAO,CACZ,cACA,gBACA,gBACA,QACA,UACkE,CAClE,IAAM,EAAY,GAAS,IACrB,EAAc,GAAQ,EAM5B,GAJI,EAAY,OAAS,EAAU,QAI/B,EAD2B,IAAgB,EAAY,MAAQ,IAAgB,EAAY,MAClE,OAAO,EAAe,CAAE,OAAQ,EAAE,CAAE,MAAO,EAAW,KAAM,EAAa,CAAC,CAEvG,IAAM,EAAyC,OAAO,OACpD,IAAgB,EAAY,KAAO,EAAqC,EACzE,CAED,GACE,CAAC,EAAc,SAAS,EAAc,EACtC,CAAC,EAAc,SAAS,EAAc,EACtC,IAAkB,EAElB,OAAO,EAAe,CAAE,OAAQ,EAAE,CAAE,MAAO,EAAW,KAAM,EAAa,CAAC,CAG5E,IAAM,EACJ,IAAkB,EAAmC,GAAK,IAAkB,EAAgC,EACxG,EACA,EAEN,OAAO,EAAe,CACpB,OAAQ,CACN,CACE,GAAI,EAAW,EAAe,EAAkB,CAChD,GAAG,EACH,gBAAiB,CAAC,EAAY,cAAc,CAC7C,CACF,CACD,MAAO,EACP,KAAM,EACP,CAAC"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
const e=require(`../../../constants.cjs`);function t(){return async({sourceChainId:t})=>{switch(t){case e.AvalancheChainIds.MAINNET:case e.AvalancheChainIds.FUJI:return 1000000000n;default:return 1n}}}exports.getMinimumTransferAmountFactory=t;
|
|
2
|
+
//# sourceMappingURL=get-minimum-transfer-amount.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"get-minimum-transfer-amount.cjs","names":["AvalancheChainIds"],"sources":["../../../../src/transfer-service/avalanche-cct/_handlers/get-minimum-transfer-amount.ts"],"sourcesContent":["import { AvalancheChainIds } from '../../../constants';\nimport type { TransferService } from '../../../types/service';\n\nconst ONE_NANO_AVAX = 1n;\nconst ONE_NANO_AVAX_IN_WEI = 1_000_000_000n;\n\nexport function getMinimumTransferAmountFactory(): TransferService['getMinimumTransferAmount'] {\n return async ({ sourceChainId }) => {\n switch (sourceChainId) {\n case AvalancheChainIds.MAINNET:\n case AvalancheChainIds.FUJI: {\n return ONE_NANO_AVAX_IN_WEI;\n }\n\n default: {\n return ONE_NANO_AVAX;\n }\n }\n };\n}\n"],"mappings":"0CAMA,SAAgB,GAA+E,CAC7F,OAAO,MAAO,CAAE,mBAAoB,CAClC,OAAQ,EAAR,CACE,KAAKA,EAAAA,kBAAkB,QACvB,KAAKA,EAAAA,kBAAkB,KACrB,OAAO,YAGT,QACE,OAAO"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{AvalancheChainIds as e}from"../../../constants.js";function t(){return async({sourceChainId:t})=>{switch(t){case e.MAINNET:case e.FUJI:return 1000000000n;default:return 1n}}}export{t as getMinimumTransferAmountFactory};
|
|
2
|
+
//# sourceMappingURL=get-minimum-transfer-amount.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"get-minimum-transfer-amount.js","names":[],"sources":["../../../../src/transfer-service/avalanche-cct/_handlers/get-minimum-transfer-amount.ts"],"sourcesContent":["import { AvalancheChainIds } from '../../../constants';\nimport type { TransferService } from '../../../types/service';\n\nconst ONE_NANO_AVAX = 1n;\nconst ONE_NANO_AVAX_IN_WEI = 1_000_000_000n;\n\nexport function getMinimumTransferAmountFactory(): TransferService['getMinimumTransferAmount'] {\n return async ({ sourceChainId }) => {\n switch (sourceChainId) {\n case AvalancheChainIds.MAINNET:\n case AvalancheChainIds.FUJI: {\n return ONE_NANO_AVAX_IN_WEI;\n }\n\n default: {\n return ONE_NANO_AVAX;\n }\n }\n };\n}\n"],"mappings":"0DAMA,SAAgB,GAA+E,CAC7F,OAAO,MAAO,CAAE,mBAAoB,CAClC,OAAQ,EAAR,CACE,KAAK,EAAkB,QACvB,KAAK,EAAkB,KACrB,OAAO,YAGT,QACE,OAAO"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
const e=require(`../../../constants.cjs`);function t({environment:t}){return async()=>{if(!(t===e.Environment.PROD||t===e.Environment.TEST))return new Map;let n=t===e.Environment.PROD?Object.values(e.AvalancheMainnetBlockchainChainIds):Object.values(e.AvalancheFujiBlockchainChainIds),r=new Map;return n.forEach(e=>{let t=n.filter(t=>t!==e);r.set(e,new Set(t))}),r}}exports.getSupportedChainsFactory=t;
|
|
2
|
+
//# sourceMappingURL=get-supported-chains.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"get-supported-chains.cjs","names":["Environment","AvalancheMainnetBlockchainChainIds","AvalancheFujiBlockchainChainIds"],"sources":["../../../../src/transfer-service/avalanche-cct/_handlers/get-supported-chains.ts"],"sourcesContent":["import { AvalancheFujiBlockchainChainIds, AvalancheMainnetBlockchainChainIds, Environment } from '../../../constants';\nimport type { Caip2ChainId } from '../../../types/caip';\nimport type { TransferService } from '../../../types/service';\n\nexport interface GetSupportedChainsOptions {\n environment: Environment;\n}\n\nexport function getSupportedChainsFactory({\n environment,\n}: GetSupportedChainsOptions): TransferService['getSupportedChains'] {\n return async () => {\n if (!(environment === Environment.PROD || environment === Environment.TEST)) {\n return new Map();\n }\n\n const chainIds =\n environment === Environment.PROD\n ? Object.values(AvalancheMainnetBlockchainChainIds)\n : Object.values(AvalancheFujiBlockchainChainIds);\n\n const supportedChainsMap = new Map<Caip2ChainId, Set<Caip2ChainId>>();\n\n chainIds.forEach((chainId) => {\n const otherChainIds = chainIds.filter((id) => id !== chainId);\n supportedChainsMap.set(chainId, new Set(otherChainIds));\n });\n\n return supportedChainsMap;\n };\n}\n"],"mappings":"0CAQA,SAAgB,EAA0B,CACxC,eACmE,CACnE,OAAO,SAAY,CACjB,GAAI,EAAE,IAAgBA,EAAAA,YAAY,MAAQ,IAAgBA,EAAAA,YAAY,MACpE,OAAO,IAAI,IAGb,IAAM,EACJ,IAAgBA,EAAAA,YAAY,KACxB,OAAO,OAAOC,EAAAA,mCAAmC,CACjD,OAAO,OAAOC,EAAAA,gCAAgC,CAE9C,EAAqB,IAAI,IAO/B,OALA,EAAS,QAAS,GAAY,CAC5B,IAAM,EAAgB,EAAS,OAAQ,GAAO,IAAO,EAAQ,CAC7D,EAAmB,IAAI,EAAS,IAAI,IAAI,EAAc,CAAC,EACvD,CAEK"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{AvalancheFujiBlockchainChainIds as e,AvalancheMainnetBlockchainChainIds as t,Environment as n}from"../../../constants.js";function r({environment:r}){return async()=>{if(!(r===n.PROD||r===n.TEST))return new Map;let i=r===n.PROD?Object.values(t):Object.values(e),a=new Map;return i.forEach(e=>{let t=i.filter(t=>t!==e);a.set(e,new Set(t))}),a}}export{r as getSupportedChainsFactory};
|
|
2
|
+
//# sourceMappingURL=get-supported-chains.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"get-supported-chains.js","names":[],"sources":["../../../../src/transfer-service/avalanche-cct/_handlers/get-supported-chains.ts"],"sourcesContent":["import { AvalancheFujiBlockchainChainIds, AvalancheMainnetBlockchainChainIds, Environment } from '../../../constants';\nimport type { Caip2ChainId } from '../../../types/caip';\nimport type { TransferService } from '../../../types/service';\n\nexport interface GetSupportedChainsOptions {\n environment: Environment;\n}\n\nexport function getSupportedChainsFactory({\n environment,\n}: GetSupportedChainsOptions): TransferService['getSupportedChains'] {\n return async () => {\n if (!(environment === Environment.PROD || environment === Environment.TEST)) {\n return new Map();\n }\n\n const chainIds =\n environment === Environment.PROD\n ? Object.values(AvalancheMainnetBlockchainChainIds)\n : Object.values(AvalancheFujiBlockchainChainIds);\n\n const supportedChainsMap = new Map<Caip2ChainId, Set<Caip2ChainId>>();\n\n chainIds.forEach((chainId) => {\n const otherChainIds = chainIds.filter((id) => id !== chainId);\n supportedChainsMap.set(chainId, new Set(otherChainIds));\n });\n\n return supportedChainsMap;\n };\n}\n"],"mappings":"iIAQA,SAAgB,EAA0B,CACxC,eACmE,CACnE,OAAO,SAAY,CACjB,GAAI,EAAE,IAAgB,EAAY,MAAQ,IAAgB,EAAY,MACpE,OAAO,IAAI,IAGb,IAAM,EACJ,IAAgB,EAAY,KACxB,OAAO,OAAO,EAAmC,CACjD,OAAO,OAAO,EAAgC,CAE9C,EAAqB,IAAI,IAO/B,OALA,EAAS,QAAS,GAAY,CAC5B,IAAM,EAAgB,EAAS,OAAQ,GAAO,IAAO,EAAQ,CAC7D,EAAmB,IAAI,EAAS,IAAI,IAAI,EAAc,CAAC,EACvD,CAEK"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
require(`../../../_virtual/_rolldown/runtime.cjs`);const e=require(`../../../constants.cjs`),t=require(`../../../errors.cjs`),n=require(`../_utils.cjs`),r=require(`../_type-guards.cjs`);let i=require(`viem`),a=require(`@avalabs/avalanchejs`);function o({clock:o=()=>Math.floor(Date.now()/1e3),environment:s,getAtomicUtxos:c}){return(l,u)=>{let d=new AbortController,f=()=>d.abort();if(s!==e.Environment.PROD&&s!==e.Environment.TEST)return d.signal.aborted||(u(`error`,new t.InvalidParamsError(`Unsupported environment for Avalanche CCT service.`)),u(`done`)),{cancel:f};let p=s===e.Environment.TEST,m=l.fromAddress,h=l.toAddress,g=p?e.AvalancheFujiBlockchainChainIds.C:e.AvalancheMainnetBlockchainChainIds.C,_=l.sourceChain.chainId===g,v=l.targetChain.chainId===g,y=_?(0,i.isAddress)(m):r.isXpAddressFullyValid(m)&&n.xpAddressMatchesNetwork(m,p),b=v?(0,i.isAddress)(h):r.isXpAddressFullyValid(h)&&n.xpAddressMatchesNetwork(h,p);if(!y||!b)return d.signal.aborted||(u(`error`,new t.InvalidParamsError(`Invalid fromAddress or toAddress for the specified environment.`,`Address types must match chain type: C-Chain uses EVM addresses, P/X chains use XP bech32 addresses for the selected environment.`)),u(`done`)),{cancel:f};let x=_||v;return x&&m===h?(d.signal.aborted||(u(`error`,new t.InvalidParamsError(`fromAddress and toAddress must be different when C-Chain is involved.`)),u(`done`)),{cancel:f}):!x&&m!==h?(d.signal.aborted||(u(`error`,new t.InvalidParamsError(`fromAddress and toAddress must be the same for P↔X transfers.`)),u(`done`)),{cancel:f}):((async()=>{let t=n.getChainAlias(l.sourceChain.chainId,p),r=n.getChainAlias(l.targetChain.chainId,p),i=(await c(r,t)).getUTXOs().reduce((e,t)=>e+a.utils.getUtxoInfo(t).amount,0n);if(t===`C`&&l.amount!==0n&&l.amount<1000000000n){d.signal.aborted||u(`done`);return}if(l.amount===0n&&i===0n){d.signal.aborted||u(`done`);return}let s=n.getNativeTokenForChainAlias(t),f=n.getNativeTokenForChainAlias(r),m=n.getOutputAmountForAvalancheCct({amountIn:l.amount,sourceAsset:s,targetAsset:f});if(m===0n){d.signal.aborted||u(`done`);return}let h=n.getOutputAmountForAvalancheCct({amountIn:i,sourceAsset:n.getNativeTokenForChainAlias(`P`),targetAsset:f}),g={aggregator:{id:`avalanche-cct`,name:`Avalanche CCT`},amountIn:l.amount,amountOut:m+h,assetIn:s,assetOut:f,expiresAt:o()+60,fees:[],fromAddress:l.fromAddress,id:crypto.randomUUID(),partnerFeeBps:null,serviceType:e.ServiceType.AVALANCHE_CCT,slippageBps:0,sourceChain:l.sourceChain,targetChain:l.targetChain,toAddress:l.toAddress};d.signal.aborted||(u(`quote`,g),u(`done`))})().catch(e=>{d.signal.aborted||(u(`error`,new t.SdkError(t.ErrorReason.UNKNOWN,t.ErrorCode.UNKNOWN,{cause:e,details:`Failed to stream quotes`})),u(`done`))}),{cancel:f})}}exports.streamQuotesFactory=o;
|
|
2
|
+
//# sourceMappingURL=stream-quotes.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stream-quotes.cjs","names":["Environment","InvalidParamsError","AvalancheFujiBlockchainChainIds","AvalancheMainnetBlockchainChainIds","isXpAddressFullyValid","xpAddressMatchesNetwork","getChainAlias","utils","getNativeTokenForChainAlias","getOutputAmountForAvalancheCct","ServiceType","SdkError","ErrorReason","ErrorCode"],"sources":["../../../../src/transfer-service/avalanche-cct/_handlers/stream-quotes.ts"],"sourcesContent":["import { utils } from '@avalabs/avalanchejs';\nimport { isAddress } from 'viem';\nimport {\n AvalancheFujiBlockchainChainIds,\n AvalancheMainnetBlockchainChainIds,\n Environment,\n ServiceType,\n type AvalancheBlockchainAlias,\n} from '../../../constants';\nimport { ErrorCode, ErrorReason, InvalidParamsError, SdkError } from '../../../errors';\nimport type { TransferService } from '../../../types/service';\nimport type { Quote } from '../../../types/quote';\nimport { isXpAddressFullyValid } from '../_type-guards';\nimport {\n getChainAlias,\n getNativeTokenForChainAlias,\n getOutputAmountForAvalancheCct,\n xpAddressMatchesNetwork,\n} from '../_utils';\nimport type { GetAtomicUtxosCallback } from '../types';\n\nexport interface StreamQuotesOptions {\n clock?: () => number;\n environment: Environment;\n getAtomicUtxos: GetAtomicUtxosCallback;\n}\n\nexport function streamQuotesFactory({\n clock = () => Math.floor(Date.now() / 1000),\n environment,\n getAtomicUtxos,\n}: StreamQuotesOptions): TransferService['streamQuotes'] {\n return (props, handler) => {\n const ac = new AbortController();\n const cancel = () => ac.abort();\n\n if (environment !== Environment.PROD && environment !== Environment.TEST) {\n if (!ac.signal.aborted) {\n handler('error', new InvalidParamsError('Unsupported environment for Avalanche CCT service.'));\n handler('done');\n }\n\n return { cancel };\n }\n\n const isTestnet = environment === Environment.TEST;\n\n const fromAddress = props.fromAddress;\n const toAddress = props.toAddress;\n const cChainId = isTestnet ? AvalancheFujiBlockchainChainIds.C : AvalancheMainnetBlockchainChainIds.C;\n const isSourceChainC = props.sourceChain.chainId === cChainId;\n const isTargetChainC = props.targetChain.chainId === cChainId;\n\n const isFromAddressValid = isSourceChainC\n ? isAddress(fromAddress)\n : isXpAddressFullyValid(fromAddress) && xpAddressMatchesNetwork(fromAddress, isTestnet);\n\n const isToAddressValid = isTargetChainC\n ? isAddress(toAddress)\n : isXpAddressFullyValid(toAddress) && xpAddressMatchesNetwork(toAddress, isTestnet);\n\n if (!isFromAddressValid || !isToAddressValid) {\n if (!ac.signal.aborted) {\n handler(\n 'error',\n new InvalidParamsError(\n 'Invalid fromAddress or toAddress for the specified environment.',\n 'Address types must match chain type: C-Chain uses EVM addresses, P/X chains use XP bech32 addresses for the selected environment.',\n ),\n );\n handler('done');\n }\n\n return {\n cancel,\n };\n }\n\n // Validate addresses equal if both chains are P/X and different if either chain is C.\n const isEitherChainC = isSourceChainC || isTargetChainC;\n\n if (isEitherChainC && fromAddress === toAddress) {\n if (!ac.signal.aborted) {\n handler(\n 'error',\n new InvalidParamsError('fromAddress and toAddress must be different when C-Chain is involved.'),\n );\n handler('done');\n }\n\n return { cancel };\n }\n\n if (!isEitherChainC && fromAddress !== toAddress) {\n if (!ac.signal.aborted) {\n handler('error', new InvalidParamsError('fromAddress and toAddress must be the same for P↔X transfers.'));\n handler('done');\n }\n\n return { cancel };\n }\n\n (async () => {\n const sourceChainAlias: AvalancheBlockchainAlias = getChainAlias(props.sourceChain.chainId, isTestnet);\n const destinationChainAlias: AvalancheBlockchainAlias = getChainAlias(props.targetChain.chainId, isTestnet);\n const atomicUtxoSet = await getAtomicUtxos(destinationChainAlias, sourceChainAlias);\n const atomicUtxos = atomicUtxoSet.getUTXOs();\n const atomicUtxosTotalAmount = atomicUtxos.reduce((total, utxo) => {\n const utxoInfo = utils.getUtxoInfo(utxo);\n\n return total + utxoInfo.amount;\n }, 0n);\n\n // If source is C-Chain, the props amount must be either `0n` or _at least_ one nano AVAX.\n // Otherwise, we should just emit a \"done\" event.\n if (sourceChainAlias === 'C' && props.amount !== 0n && props.amount < 1_000_000_000n) {\n if (!ac.signal.aborted) {\n handler('done');\n }\n\n return;\n }\n\n // Special case for 0 amount transfers where user intends to finish stuck atomic imports.\n if (props.amount === 0n && atomicUtxosTotalAmount === 0n) {\n if (!ac.signal.aborted) {\n handler('done');\n }\n\n return;\n }\n\n const assetIn = getNativeTokenForChainAlias(sourceChainAlias);\n const assetOut = getNativeTokenForChainAlias(destinationChainAlias);\n const amountIn = getOutputAmountForAvalancheCct({\n amountIn: props.amount,\n sourceAsset: assetIn,\n targetAsset: assetOut,\n });\n\n // Emit no quotes if `amountIn` is 0\n // This can happen if the user tries to transfer an amount below 1 nano AVAX from the C-Chain.\n if (amountIn === 0n) {\n if (!ac.signal.aborted) {\n handler('done');\n }\n\n return;\n }\n\n // TODO: Do we need to account for subtracting import fees from these UTXOs\n // in order to give an accurate picture of how much the user will receive on the other side?\n const amountOutFromAtomicUtxos = getOutputAmountForAvalancheCct({\n amountIn: atomicUtxosTotalAmount,\n sourceAsset: getNativeTokenForChainAlias('P'),\n targetAsset: assetOut,\n });\n\n const quote: Quote = {\n aggregator: {\n id: 'avalanche-cct',\n name: 'Avalanche CCT',\n },\n amountIn: props.amount,\n amountOut: amountIn + amountOutFromAtomicUtxos,\n assetIn,\n assetOut,\n expiresAt: clock() + 60, // Expire in 1 minute.\n fees: [],\n fromAddress: props.fromAddress,\n id: crypto.randomUUID(),\n partnerFeeBps: null,\n serviceType: ServiceType.AVALANCHE_CCT,\n slippageBps: 0,\n sourceChain: props.sourceChain,\n targetChain: props.targetChain,\n toAddress: props.toAddress,\n };\n\n if (!ac.signal.aborted) {\n handler('quote', quote);\n handler('done');\n }\n })().catch((error) => {\n if (!ac.signal.aborted) {\n handler(\n 'error',\n new SdkError(ErrorReason.UNKNOWN, ErrorCode.UNKNOWN, { cause: error, details: 'Failed to stream quotes' }),\n );\n handler('done');\n }\n });\n\n return {\n cancel,\n };\n };\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{AvalancheFujiBlockchainChainIds as e,AvalancheMainnetBlockchainChainIds as t,Environment as n,ServiceType as r}from"../../../constants.js";import{ErrorCode as i,ErrorReason as a,InvalidParamsError as o,SdkError as s}from"../../../errors.js";import{getChainAlias as c,getNativeTokenForChainAlias as l,getOutputAmountForAvalancheCct as u,xpAddressMatchesNetwork as d}from"../_utils.js";import{isXpAddressFullyValid as f}from"../_type-guards.js";import{isAddress as p}from"viem";import{utils as m}from"@avalabs/avalanchejs";function h({clock:h=()=>Math.floor(Date.now()/1e3),environment:g,getAtomicUtxos:_}){return(v,y)=>{let b=new AbortController,x=()=>b.abort();if(g!==n.PROD&&g!==n.TEST)return b.signal.aborted||(y(`error`,new o(`Unsupported environment for Avalanche CCT service.`)),y(`done`)),{cancel:x};let S=g===n.TEST,C=v.fromAddress,w=v.toAddress,T=S?e.C:t.C,E=v.sourceChain.chainId===T,D=v.targetChain.chainId===T,O=E?p(C):f(C)&&d(C,S),k=D?p(w):f(w)&&d(w,S);if(!O||!k)return b.signal.aborted||(y(`error`,new o(`Invalid fromAddress or toAddress for the specified environment.`,`Address types must match chain type: C-Chain uses EVM addresses, P/X chains use XP bech32 addresses for the selected environment.`)),y(`done`)),{cancel:x};let A=E||D;return A&&C===w?(b.signal.aborted||(y(`error`,new o(`fromAddress and toAddress must be different when C-Chain is involved.`)),y(`done`)),{cancel:x}):!A&&C!==w?(b.signal.aborted||(y(`error`,new o(`fromAddress and toAddress must be the same for P↔X transfers.`)),y(`done`)),{cancel:x}):((async()=>{let e=c(v.sourceChain.chainId,S),t=c(v.targetChain.chainId,S),n=(await _(t,e)).getUTXOs().reduce((e,t)=>e+m.getUtxoInfo(t).amount,0n);if(e===`C`&&v.amount!==0n&&v.amount<1000000000n){b.signal.aborted||y(`done`);return}if(v.amount===0n&&n===0n){b.signal.aborted||y(`done`);return}let i=l(e),a=l(t),o=u({amountIn:v.amount,sourceAsset:i,targetAsset:a});if(o===0n){b.signal.aborted||y(`done`);return}let s=u({amountIn:n,sourceAsset:l(`P`),targetAsset:a}),d={aggregator:{id:`avalanche-cct`,name:`Avalanche CCT`},amountIn:v.amount,amountOut:o+s,assetIn:i,assetOut:a,expiresAt:h()+60,fees:[],fromAddress:v.fromAddress,id:crypto.randomUUID(),partnerFeeBps:null,serviceType:r.AVALANCHE_CCT,slippageBps:0,sourceChain:v.sourceChain,targetChain:v.targetChain,toAddress:v.toAddress};b.signal.aborted||(y(`quote`,d),y(`done`))})().catch(e=>{b.signal.aborted||(y(`error`,new s(a.UNKNOWN,i.UNKNOWN,{cause:e,details:`Failed to stream quotes`})),y(`done`))}),{cancel:x})}}export{h as streamQuotesFactory};
|
|
2
|
+
//# sourceMappingURL=stream-quotes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stream-quotes.js","names":[],"sources":["../../../../src/transfer-service/avalanche-cct/_handlers/stream-quotes.ts"],"sourcesContent":["import { utils } from '@avalabs/avalanchejs';\nimport { isAddress } from 'viem';\nimport {\n AvalancheFujiBlockchainChainIds,\n AvalancheMainnetBlockchainChainIds,\n Environment,\n ServiceType,\n type AvalancheBlockchainAlias,\n} from '../../../constants';\nimport { ErrorCode, ErrorReason, InvalidParamsError, SdkError } from '../../../errors';\nimport type { TransferService } from '../../../types/service';\nimport type { Quote } from '../../../types/quote';\nimport { isXpAddressFullyValid } from '../_type-guards';\nimport {\n getChainAlias,\n getNativeTokenForChainAlias,\n getOutputAmountForAvalancheCct,\n xpAddressMatchesNetwork,\n} from '../_utils';\nimport type { GetAtomicUtxosCallback } from '../types';\n\nexport interface StreamQuotesOptions {\n clock?: () => number;\n environment: Environment;\n getAtomicUtxos: GetAtomicUtxosCallback;\n}\n\nexport function streamQuotesFactory({\n clock = () => Math.floor(Date.now() / 1000),\n environment,\n getAtomicUtxos,\n}: StreamQuotesOptions): TransferService['streamQuotes'] {\n return (props, handler) => {\n const ac = new AbortController();\n const cancel = () => ac.abort();\n\n if (environment !== Environment.PROD && environment !== Environment.TEST) {\n if (!ac.signal.aborted) {\n handler('error', new InvalidParamsError('Unsupported environment for Avalanche CCT service.'));\n handler('done');\n }\n\n return { cancel };\n }\n\n const isTestnet = environment === Environment.TEST;\n\n const fromAddress = props.fromAddress;\n const toAddress = props.toAddress;\n const cChainId = isTestnet ? AvalancheFujiBlockchainChainIds.C : AvalancheMainnetBlockchainChainIds.C;\n const isSourceChainC = props.sourceChain.chainId === cChainId;\n const isTargetChainC = props.targetChain.chainId === cChainId;\n\n const isFromAddressValid = isSourceChainC\n ? isAddress(fromAddress)\n : isXpAddressFullyValid(fromAddress) && xpAddressMatchesNetwork(fromAddress, isTestnet);\n\n const isToAddressValid = isTargetChainC\n ? isAddress(toAddress)\n : isXpAddressFullyValid(toAddress) && xpAddressMatchesNetwork(toAddress, isTestnet);\n\n if (!isFromAddressValid || !isToAddressValid) {\n if (!ac.signal.aborted) {\n handler(\n 'error',\n new InvalidParamsError(\n 'Invalid fromAddress or toAddress for the specified environment.',\n 'Address types must match chain type: C-Chain uses EVM addresses, P/X chains use XP bech32 addresses for the selected environment.',\n ),\n );\n handler('done');\n }\n\n return {\n cancel,\n };\n }\n\n // Validate addresses equal if both chains are P/X and different if either chain is C.\n const isEitherChainC = isSourceChainC || isTargetChainC;\n\n if (isEitherChainC && fromAddress === toAddress) {\n if (!ac.signal.aborted) {\n handler(\n 'error',\n new InvalidParamsError('fromAddress and toAddress must be different when C-Chain is involved.'),\n );\n handler('done');\n }\n\n return { cancel };\n }\n\n if (!isEitherChainC && fromAddress !== toAddress) {\n if (!ac.signal.aborted) {\n handler('error', new InvalidParamsError('fromAddress and toAddress must be the same for P↔X transfers.'));\n handler('done');\n }\n\n return { cancel };\n }\n\n (async () => {\n const sourceChainAlias: AvalancheBlockchainAlias = getChainAlias(props.sourceChain.chainId, isTestnet);\n const destinationChainAlias: AvalancheBlockchainAlias = getChainAlias(props.targetChain.chainId, isTestnet);\n const atomicUtxoSet = await getAtomicUtxos(destinationChainAlias, sourceChainAlias);\n const atomicUtxos = atomicUtxoSet.getUTXOs();\n const atomicUtxosTotalAmount = atomicUtxos.reduce((total, utxo) => {\n const utxoInfo = utils.getUtxoInfo(utxo);\n\n return total + utxoInfo.amount;\n }, 0n);\n\n // If source is C-Chain, the props amount must be either `0n` or _at least_ one nano AVAX.\n // Otherwise, we should just emit a \"done\" event.\n if (sourceChainAlias === 'C' && props.amount !== 0n && props.amount < 1_000_000_000n) {\n if (!ac.signal.aborted) {\n handler('done');\n }\n\n return;\n }\n\n // Special case for 0 amount transfers where user intends to finish stuck atomic imports.\n if (props.amount === 0n && atomicUtxosTotalAmount === 0n) {\n if (!ac.signal.aborted) {\n handler('done');\n }\n\n return;\n }\n\n const assetIn = getNativeTokenForChainAlias(sourceChainAlias);\n const assetOut = getNativeTokenForChainAlias(destinationChainAlias);\n const amountIn = getOutputAmountForAvalancheCct({\n amountIn: props.amount,\n sourceAsset: assetIn,\n targetAsset: assetOut,\n });\n\n // Emit no quotes if `amountIn` is 0\n // This can happen if the user tries to transfer an amount below 1 nano AVAX from the C-Chain.\n if (amountIn === 0n) {\n if (!ac.signal.aborted) {\n handler('done');\n }\n\n return;\n }\n\n // TODO: Do we need to account for subtracting import fees from these UTXOs\n // in order to give an accurate picture of how much the user will receive on the other side?\n const amountOutFromAtomicUtxos = getOutputAmountForAvalancheCct({\n amountIn: atomicUtxosTotalAmount,\n sourceAsset: getNativeTokenForChainAlias('P'),\n targetAsset: assetOut,\n });\n\n const quote: Quote = {\n aggregator: {\n id: 'avalanche-cct',\n name: 'Avalanche CCT',\n },\n amountIn: props.amount,\n amountOut: amountIn + amountOutFromAtomicUtxos,\n assetIn,\n assetOut,\n expiresAt: clock() + 60, // Expire in 1 minute.\n fees: [],\n fromAddress: props.fromAddress,\n id: crypto.randomUUID(),\n partnerFeeBps: null,\n serviceType: ServiceType.AVALANCHE_CCT,\n slippageBps: 0,\n sourceChain: props.sourceChain,\n targetChain: props.targetChain,\n toAddress: props.toAddress,\n };\n\n if (!ac.signal.aborted) {\n handler('quote', quote);\n handler('done');\n }\n })().catch((error) => {\n if (!ac.signal.aborted) {\n handler(\n 'error',\n new SdkError(ErrorReason.UNKNOWN, ErrorCode.UNKNOWN, { cause: error, details: 'Failed to stream quotes' }),\n );\n handler('done');\n }\n });\n\n return {\n cancel,\n };\n };\n}\n"],"mappings":"ghBA2BA,SAAgB,EAAoB,CAClC,YAAc,KAAK,MAAM,KAAK,KAAK,CAAG,IAAK,CAC3C,cACA,kBACuD,CACvD,OAAQ,EAAO,IAAY,CACzB,IAAM,EAAK,IAAI,gBACT,MAAe,EAAG,OAAO,CAE/B,GAAI,IAAgB,EAAY,MAAQ,IAAgB,EAAY,KAMlE,OALK,EAAG,OAAO,UACb,EAAQ,QAAS,IAAI,EAAmB,qDAAqD,CAAC,CAC9F,EAAQ,OAAO,EAGV,CAAE,SAAQ,CAGnB,IAAM,EAAY,IAAgB,EAAY,KAExC,EAAc,EAAM,YACpB,EAAY,EAAM,UAClB,EAAW,EAAY,EAAgC,EAAI,EAAmC,EAC9F,EAAiB,EAAM,YAAY,UAAY,EAC/C,EAAiB,EAAM,YAAY,UAAY,EAE/C,EAAqB,EACvB,EAAU,EAAY,CACtB,EAAsB,EAAY,EAAI,EAAwB,EAAa,EAAU,CAEnF,EAAmB,EACrB,EAAU,EAAU,CACpB,EAAsB,EAAU,EAAI,EAAwB,EAAW,EAAU,CAErF,GAAI,CAAC,GAAsB,CAAC,EAY1B,OAXK,EAAG,OAAO,UACb,EACE,QACA,IAAI,EACF,kEACA,oIACD,CACF,CACD,EAAQ,OAAO,EAGV,CACL,SACD,CAIH,IAAM,EAAiB,GAAkB,EAkHzC,OAhHI,GAAkB,IAAgB,GAC/B,EAAG,OAAO,UACb,EACE,QACA,IAAI,EAAmB,wEAAwE,CAChG,CACD,EAAQ,OAAO,EAGV,CAAE,SAAQ,EAGf,CAAC,GAAkB,IAAgB,GAChC,EAAG,OAAO,UACb,EAAQ,QAAS,IAAI,EAAmB,gEAAgE,CAAC,CACzG,EAAQ,OAAO,EAGV,CAAE,SAAQ,IAGlB,SAAY,CACX,IAAM,EAA6C,EAAc,EAAM,YAAY,QAAS,EAAU,CAChG,EAAkD,EAAc,EAAM,YAAY,QAAS,EAAU,CAGrG,GAFgB,MAAM,EAAe,EAAuB,EAAiB,EACjD,UAAU,CACD,QAAQ,EAAO,IAGjD,EAFU,EAAM,YAAY,EAAK,CAEhB,OACvB,GAAG,CAIN,GAAI,IAAqB,KAAO,EAAM,SAAW,IAAM,EAAM,OAAS,YAAgB,CAC/E,EAAG,OAAO,SACb,EAAQ,OAAO,CAGjB,OAIF,GAAI,EAAM,SAAW,IAAM,IAA2B,GAAI,CACnD,EAAG,OAAO,SACb,EAAQ,OAAO,CAGjB,OAGF,IAAM,EAAU,EAA4B,EAAiB,CACvD,EAAW,EAA4B,EAAsB,CAC7D,EAAW,EAA+B,CAC9C,SAAU,EAAM,OAChB,YAAa,EACb,YAAa,EACd,CAAC,CAIF,GAAI,IAAa,GAAI,CACd,EAAG,OAAO,SACb,EAAQ,OAAO,CAGjB,OAKF,IAAM,EAA2B,EAA+B,CAC9D,SAAU,EACV,YAAa,EAA4B,IAAI,CAC7C,YAAa,EACd,CAAC,CAEI,EAAe,CACnB,WAAY,CACV,GAAI,gBACJ,KAAM,gBACP,CACD,SAAU,EAAM,OAChB,UAAW,EAAW,EACtB,UACA,WACA,UAAW,GAAO,CAAG,GACrB,KAAM,EAAE,CACR,YAAa,EAAM,YACnB,GAAI,OAAO,YAAY,CACvB,cAAe,KACf,YAAa,EAAY,cACzB,YAAa,EACb,YAAa,EAAM,YACnB,YAAa,EAAM,YACnB,UAAW,EAAM,UAClB,CAEI,EAAG,OAAO,UACb,EAAQ,QAAS,EAAM,CACvB,EAAQ,OAAO,KAEf,CAAC,MAAO,GAAU,CACf,EAAG,OAAO,UACb,EACE,QACA,IAAI,EAAS,EAAY,QAAS,EAAU,QAAS,CAAE,MAAO,EAAO,QAAS,0BAA2B,CAAC,CAC3G,CACD,EAAQ,OAAO,GAEjB,CAEK,CACL,SACD"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
const e=require(`../../../errors.cjs`),t=require(`../_utils.cjs`),n=require(`../../_utils.cjs`),r=require(`../_utils/polling.cjs`);function i({environment:e}){return({transfer:t,updateListener:r})=>{let i=new AbortController,s=()=>{i.abort()};return t.status===`completed`||t.status===`failed`?{cancel:s,result:Promise.resolve(t)}:{cancel:s,result:(async()=>{let s=structuredClone(t);for(;!i.signal.aborted;){let t=s.status;switch(s.status){case`source-pending`:s=await a({currentTransfer:s,environment:e}),i.signal.aborted||r(s);break;case`target-pending`:s=await o({currentTransfer:s,environment:e}),i.signal.aborted||r(s);break;default:return s}s.status===t&&await n.waitForTimeoutOrAbort({timeoutMs:1500,signal:i.signal})}return s})()}}}async function a({currentTransfer:n,environment:i}){let a=t.getEnvironmentIsTestnet(i),o=t.getChainAlias(n.sourceChain.chainId,a);try{return await r.pollPrimaryNetworkTxStatus({chainAlias:o,environment:i,txId:n.source.txHash})?{...n,source:{...n.source,confirmationCount:n.source.requiredConfirmationCount},status:`source-completed`}:{...n,errorCode:e.ErrorCode.TRANSACTION_REVERTED,errorReason:`Source transaction was rejected by Avalanche.`,failedAtMs:Date.now(),status:`failed`}}catch{return n}}async function o({currentTransfer:n,environment:i}){if(!n.target?.txHash)return{...n,errorCode:e.ErrorCode.INVALID_PARAMS,errorReason:`Missing target transaction hash.`,failedAtMs:Date.now(),status:`failed`};let a=t.getEnvironmentIsTestnet(i),o=t.getChainAlias(n.targetChain.chainId,a);try{if(!await r.pollPrimaryNetworkTxStatus({chainAlias:o,environment:i,txId:n.target.txHash}))return{...n,errorCode:e.ErrorCode.TRANSACTION_REVERTED,errorReason:`Target transaction was rejected by Avalanche.`,failedAtMs:Date.now(),status:`failed`};let t=n.source.txHash===n.target.txHash;return{...n,completedAtMs:Date.now(),source:{...n.source,confirmationCount:t?n.source.requiredConfirmationCount:n.source.confirmationCount},status:`completed`,target:{...n.target,confirmationCount:n.target.requiredConfirmationCount}}}catch{return n}}exports.trackTransferFactory=i;
|
|
2
|
+
//# sourceMappingURL=track-transfer.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"track-transfer.cjs","names":["waitForTimeoutOrAbort","getEnvironmentIsTestnet","getChainAlias","pollPrimaryNetworkTxStatus","ErrorCode"],"sources":["../../../../src/transfer-service/avalanche-cct/_handlers/track-transfer.ts"],"sourcesContent":["import { ErrorCode } from '../../../errors';\nimport type { TransferService } from '../../../types/service';\nimport type {\n CompletedTransfer,\n FailedTransfer,\n SourceCompletedTransfer,\n SourcePendingTransfer,\n TargetPendingTransfer,\n Transfer,\n} from '../../../types/transfer';\nimport { waitForTimeoutOrAbort } from '../../_utils';\nimport { getChainAlias, getEnvironmentIsTestnet } from '../_utils';\nimport { pollPrimaryNetworkTxStatus } from '../_utils/polling';\n\nconst TRACKING_POLL_INTERVAL_MS = 1_500;\n\nexport interface TrackTransferFactoryOptions {\n environment: Parameters<typeof pollPrimaryNetworkTxStatus>[0]['environment'];\n}\n\nexport function trackTransferFactory({ environment }: TrackTransferFactoryOptions): TransferService['trackTransfer'] {\n return ({ transfer, updateListener }) => {\n const ac = new AbortController();\n const cancel = () => {\n ac.abort();\n };\n\n if (transfer.status === 'completed' || transfer.status === 'failed') {\n return {\n cancel,\n result: Promise.resolve(transfer),\n };\n }\n\n const executeTracking = async (): Promise<Transfer> => {\n let currentTransfer: Transfer = structuredClone(transfer);\n\n while (!ac.signal.aborted) {\n const statusBeforeTracking = currentTransfer.status;\n\n switch (currentTransfer.status) {\n case 'source-pending': {\n currentTransfer = await _trackSourceTx({ currentTransfer, environment });\n\n if (!ac.signal.aborted) {\n updateListener(currentTransfer);\n }\n\n break;\n }\n case 'target-pending': {\n currentTransfer = await _trackTargetTx({ currentTransfer, environment });\n\n if (!ac.signal.aborted) {\n updateListener(currentTransfer);\n }\n\n break;\n }\n default: {\n return currentTransfer;\n }\n }\n\n const hasStatusChanged = currentTransfer.status !== statusBeforeTracking;\n\n if (!hasStatusChanged) {\n await waitForTimeoutOrAbort({ timeoutMs: TRACKING_POLL_INTERVAL_MS, signal: ac.signal });\n }\n }\n\n return currentTransfer;\n };\n\n return {\n cancel,\n result: executeTracking(),\n };\n };\n}\n\nexport async function _trackSourceTx({\n currentTransfer,\n environment,\n}: {\n currentTransfer: SourcePendingTransfer;\n environment: Parameters<typeof pollPrimaryNetworkTxStatus>[0]['environment'];\n}): Promise<SourcePendingTransfer | SourceCompletedTransfer | FailedTransfer> {\n const isTestnet = getEnvironmentIsTestnet(environment);\n const sourceChainAlias = getChainAlias(currentTransfer.sourceChain.chainId, isTestnet);\n\n try {\n const didSucceed = await pollPrimaryNetworkTxStatus({\n chainAlias: sourceChainAlias,\n environment,\n txId: currentTransfer.source.txHash,\n });\n\n if (!didSucceed) {\n return {\n ...currentTransfer,\n errorCode: ErrorCode.TRANSACTION_REVERTED,\n errorReason: 'Source transaction was rejected by Avalanche.',\n failedAtMs: Date.now(),\n status: 'failed',\n } satisfies FailedTransfer;\n }\n\n return {\n ...currentTransfer,\n source: {\n ...currentTransfer.source,\n confirmationCount: currentTransfer.source.requiredConfirmationCount,\n },\n status: 'source-completed',\n } satisfies SourceCompletedTransfer;\n } catch {\n return currentTransfer;\n }\n}\n\nexport async function _trackTargetTx({\n currentTransfer,\n environment,\n}: {\n currentTransfer: TargetPendingTransfer;\n environment: Parameters<typeof pollPrimaryNetworkTxStatus>[0]['environment'];\n}): Promise<TargetPendingTransfer | CompletedTransfer | FailedTransfer> {\n if (!currentTransfer.target?.txHash) {\n return {\n ...currentTransfer,\n errorCode: ErrorCode.INVALID_PARAMS,\n errorReason: 'Missing target transaction hash.',\n failedAtMs: Date.now(),\n status: 'failed',\n } satisfies FailedTransfer;\n }\n\n const isTestnet = getEnvironmentIsTestnet(environment);\n const destinationChainAlias = getChainAlias(currentTransfer.targetChain.chainId, isTestnet);\n\n try {\n const didSucceed = await pollPrimaryNetworkTxStatus({\n chainAlias: destinationChainAlias,\n environment,\n txId: currentTransfer.target.txHash,\n });\n\n if (!didSucceed) {\n return {\n ...currentTransfer,\n errorCode: ErrorCode.TRANSACTION_REVERTED,\n errorReason: 'Target transaction was rejected by Avalanche.',\n failedAtMs: Date.now(),\n status: 'failed',\n } satisfies FailedTransfer;\n }\n\n const isImportOnlyFlow = currentTransfer.source.txHash === currentTransfer.target.txHash;\n\n return {\n ...currentTransfer,\n completedAtMs: Date.now(),\n source: {\n ...currentTransfer.source,\n confirmationCount: isImportOnlyFlow\n ? currentTransfer.source.requiredConfirmationCount\n : currentTransfer.source.confirmationCount,\n },\n status: 'completed',\n target: {\n ...currentTransfer.target,\n confirmationCount: currentTransfer.target.requiredConfirmationCount,\n },\n } satisfies CompletedTransfer;\n } catch {\n return currentTransfer;\n }\n}\n"],"mappings":"mIAoBA,SAAgB,EAAqB,CAAE,eAA8E,CACnH,OAAQ,CAAE,WAAU,oBAAqB,CACvC,IAAM,EAAK,IAAI,gBACT,MAAe,CACnB,EAAG,OAAO,EAkDZ,OA/CI,EAAS,SAAW,aAAe,EAAS,SAAW,SAClD,CACL,SACA,OAAQ,QAAQ,QAAQ,EAAS,CAClC,CA2CI,CACL,SACA,QA1CsB,SAA+B,CACrD,IAAI,EAA4B,gBAAgB,EAAS,CAEzD,KAAO,CAAC,EAAG,OAAO,SAAS,CACzB,IAAM,EAAuB,EAAgB,OAE7C,OAAQ,EAAgB,OAAxB,CACE,IAAK,iBACH,EAAkB,MAAM,EAAe,CAAE,kBAAiB,cAAa,CAAC,CAEnE,EAAG,OAAO,SACb,EAAe,EAAgB,CAGjC,MAEF,IAAK,iBACH,EAAkB,MAAM,EAAe,CAAE,kBAAiB,cAAa,CAAC,CAEnE,EAAG,OAAO,SACb,EAAe,EAAgB,CAGjC,MAEF,QACE,OAAO,EAIc,EAAgB,SAAW,GAGlD,MAAMA,EAAAA,sBAAsB,CAAE,UAAW,KAA2B,OAAQ,EAAG,OAAQ,CAAC,CAI5F,OAAO,KAKkB,CAC1B,EAIL,eAAsB,EAAe,CACnC,kBACA,eAI4E,CAC5E,IAAM,EAAYC,EAAAA,wBAAwB,EAAY,CAChD,EAAmBC,EAAAA,cAAc,EAAgB,YAAY,QAAS,EAAU,CAEtF,GAAI,CAiBF,OAhBmB,MAAMC,EAAAA,2BAA2B,CAClD,WAAY,EACZ,cACA,KAAM,EAAgB,OAAO,OAC9B,CAAC,CAYK,CACL,GAAG,EACH,OAAQ,CACN,GAAG,EAAgB,OACnB,kBAAmB,EAAgB,OAAO,0BAC3C,CACD,OAAQ,mBACT,CAhBQ,CACL,GAAG,EACH,UAAWC,EAAAA,UAAU,qBACrB,YAAa,gDACb,WAAY,KAAK,KAAK,CACtB,OAAQ,SACT,MAWG,CACN,OAAO,GAIX,eAAsB,EAAe,CACnC,kBACA,eAIsE,CACtE,GAAI,CAAC,EAAgB,QAAQ,OAC3B,MAAO,CACL,GAAG,EACH,UAAWA,EAAAA,UAAU,eACrB,YAAa,mCACb,WAAY,KAAK,KAAK,CACtB,OAAQ,SACT,CAGH,IAAM,EAAYH,EAAAA,wBAAwB,EAAY,CAChD,EAAwBC,EAAAA,cAAc,EAAgB,YAAY,QAAS,EAAU,CAE3F,GAAI,CAOF,GAAI,CANe,MAAMC,EAAAA,2BAA2B,CAClD,WAAY,EACZ,cACA,KAAM,EAAgB,OAAO,OAC9B,CAAC,CAGA,MAAO,CACL,GAAG,EACH,UAAWC,EAAAA,UAAU,qBACrB,YAAa,gDACb,WAAY,KAAK,KAAK,CACtB,OAAQ,SACT,CAGH,IAAM,EAAmB,EAAgB,OAAO,SAAW,EAAgB,OAAO,OAElF,MAAO,CACL,GAAG,EACH,cAAe,KAAK,KAAK,CACzB,OAAQ,CACN,GAAG,EAAgB,OACnB,kBAAmB,EACf,EAAgB,OAAO,0BACvB,EAAgB,OAAO,kBAC5B,CACD,OAAQ,YACR,OAAQ,CACN,GAAG,EAAgB,OACnB,kBAAmB,EAAgB,OAAO,0BAC3C,CACF,MACK,CACN,OAAO"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{ErrorCode as e}from"../../../errors.js";import{getChainAlias as t,getEnvironmentIsTestnet as n}from"../_utils.js";import{waitForTimeoutOrAbort as r}from"../../_utils.js";import{pollPrimaryNetworkTxStatus as i}from"../_utils/polling.js";function a({environment:e}){return({transfer:t,updateListener:n})=>{let i=new AbortController,a=()=>{i.abort()};return t.status===`completed`||t.status===`failed`?{cancel:a,result:Promise.resolve(t)}:{cancel:a,result:(async()=>{let a=structuredClone(t);for(;!i.signal.aborted;){let t=a.status;switch(a.status){case`source-pending`:a=await o({currentTransfer:a,environment:e}),i.signal.aborted||n(a);break;case`target-pending`:a=await s({currentTransfer:a,environment:e}),i.signal.aborted||n(a);break;default:return a}a.status===t&&await r({timeoutMs:1500,signal:i.signal})}return a})()}}}async function o({currentTransfer:r,environment:a}){let o=n(a),s=t(r.sourceChain.chainId,o);try{return await i({chainAlias:s,environment:a,txId:r.source.txHash})?{...r,source:{...r.source,confirmationCount:r.source.requiredConfirmationCount},status:`source-completed`}:{...r,errorCode:e.TRANSACTION_REVERTED,errorReason:`Source transaction was rejected by Avalanche.`,failedAtMs:Date.now(),status:`failed`}}catch{return r}}async function s({currentTransfer:r,environment:a}){if(!r.target?.txHash)return{...r,errorCode:e.INVALID_PARAMS,errorReason:`Missing target transaction hash.`,failedAtMs:Date.now(),status:`failed`};let o=n(a),s=t(r.targetChain.chainId,o);try{if(!await i({chainAlias:s,environment:a,txId:r.target.txHash}))return{...r,errorCode:e.TRANSACTION_REVERTED,errorReason:`Target transaction was rejected by Avalanche.`,failedAtMs:Date.now(),status:`failed`};let t=r.source.txHash===r.target.txHash;return{...r,completedAtMs:Date.now(),source:{...r.source,confirmationCount:t?r.source.requiredConfirmationCount:r.source.confirmationCount},status:`completed`,target:{...r.target,confirmationCount:r.target.requiredConfirmationCount}}}catch{return r}}export{a as trackTransferFactory};
|
|
2
|
+
//# sourceMappingURL=track-transfer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"track-transfer.js","names":[],"sources":["../../../../src/transfer-service/avalanche-cct/_handlers/track-transfer.ts"],"sourcesContent":["import { ErrorCode } from '../../../errors';\nimport type { TransferService } from '../../../types/service';\nimport type {\n CompletedTransfer,\n FailedTransfer,\n SourceCompletedTransfer,\n SourcePendingTransfer,\n TargetPendingTransfer,\n Transfer,\n} from '../../../types/transfer';\nimport { waitForTimeoutOrAbort } from '../../_utils';\nimport { getChainAlias, getEnvironmentIsTestnet } from '../_utils';\nimport { pollPrimaryNetworkTxStatus } from '../_utils/polling';\n\nconst TRACKING_POLL_INTERVAL_MS = 1_500;\n\nexport interface TrackTransferFactoryOptions {\n environment: Parameters<typeof pollPrimaryNetworkTxStatus>[0]['environment'];\n}\n\nexport function trackTransferFactory({ environment }: TrackTransferFactoryOptions): TransferService['trackTransfer'] {\n return ({ transfer, updateListener }) => {\n const ac = new AbortController();\n const cancel = () => {\n ac.abort();\n };\n\n if (transfer.status === 'completed' || transfer.status === 'failed') {\n return {\n cancel,\n result: Promise.resolve(transfer),\n };\n }\n\n const executeTracking = async (): Promise<Transfer> => {\n let currentTransfer: Transfer = structuredClone(transfer);\n\n while (!ac.signal.aborted) {\n const statusBeforeTracking = currentTransfer.status;\n\n switch (currentTransfer.status) {\n case 'source-pending': {\n currentTransfer = await _trackSourceTx({ currentTransfer, environment });\n\n if (!ac.signal.aborted) {\n updateListener(currentTransfer);\n }\n\n break;\n }\n case 'target-pending': {\n currentTransfer = await _trackTargetTx({ currentTransfer, environment });\n\n if (!ac.signal.aborted) {\n updateListener(currentTransfer);\n }\n\n break;\n }\n default: {\n return currentTransfer;\n }\n }\n\n const hasStatusChanged = currentTransfer.status !== statusBeforeTracking;\n\n if (!hasStatusChanged) {\n await waitForTimeoutOrAbort({ timeoutMs: TRACKING_POLL_INTERVAL_MS, signal: ac.signal });\n }\n }\n\n return currentTransfer;\n };\n\n return {\n cancel,\n result: executeTracking(),\n };\n };\n}\n\nexport async function _trackSourceTx({\n currentTransfer,\n environment,\n}: {\n currentTransfer: SourcePendingTransfer;\n environment: Parameters<typeof pollPrimaryNetworkTxStatus>[0]['environment'];\n}): Promise<SourcePendingTransfer | SourceCompletedTransfer | FailedTransfer> {\n const isTestnet = getEnvironmentIsTestnet(environment);\n const sourceChainAlias = getChainAlias(currentTransfer.sourceChain.chainId, isTestnet);\n\n try {\n const didSucceed = await pollPrimaryNetworkTxStatus({\n chainAlias: sourceChainAlias,\n environment,\n txId: currentTransfer.source.txHash,\n });\n\n if (!didSucceed) {\n return {\n ...currentTransfer,\n errorCode: ErrorCode.TRANSACTION_REVERTED,\n errorReason: 'Source transaction was rejected by Avalanche.',\n failedAtMs: Date.now(),\n status: 'failed',\n } satisfies FailedTransfer;\n }\n\n return {\n ...currentTransfer,\n source: {\n ...currentTransfer.source,\n confirmationCount: currentTransfer.source.requiredConfirmationCount,\n },\n status: 'source-completed',\n } satisfies SourceCompletedTransfer;\n } catch {\n return currentTransfer;\n }\n}\n\nexport async function _trackTargetTx({\n currentTransfer,\n environment,\n}: {\n currentTransfer: TargetPendingTransfer;\n environment: Parameters<typeof pollPrimaryNetworkTxStatus>[0]['environment'];\n}): Promise<TargetPendingTransfer | CompletedTransfer | FailedTransfer> {\n if (!currentTransfer.target?.txHash) {\n return {\n ...currentTransfer,\n errorCode: ErrorCode.INVALID_PARAMS,\n errorReason: 'Missing target transaction hash.',\n failedAtMs: Date.now(),\n status: 'failed',\n } satisfies FailedTransfer;\n }\n\n const isTestnet = getEnvironmentIsTestnet(environment);\n const destinationChainAlias = getChainAlias(currentTransfer.targetChain.chainId, isTestnet);\n\n try {\n const didSucceed = await pollPrimaryNetworkTxStatus({\n chainAlias: destinationChainAlias,\n environment,\n txId: currentTransfer.target.txHash,\n });\n\n if (!didSucceed) {\n return {\n ...currentTransfer,\n errorCode: ErrorCode.TRANSACTION_REVERTED,\n errorReason: 'Target transaction was rejected by Avalanche.',\n failedAtMs: Date.now(),\n status: 'failed',\n } satisfies FailedTransfer;\n }\n\n const isImportOnlyFlow = currentTransfer.source.txHash === currentTransfer.target.txHash;\n\n return {\n ...currentTransfer,\n completedAtMs: Date.now(),\n source: {\n ...currentTransfer.source,\n confirmationCount: isImportOnlyFlow\n ? currentTransfer.source.requiredConfirmationCount\n : currentTransfer.source.confirmationCount,\n },\n status: 'completed',\n target: {\n ...currentTransfer.target,\n confirmationCount: currentTransfer.target.requiredConfirmationCount,\n },\n } satisfies CompletedTransfer;\n } catch {\n return currentTransfer;\n }\n}\n"],"mappings":"mPAoBA,SAAgB,EAAqB,CAAE,eAA8E,CACnH,OAAQ,CAAE,WAAU,oBAAqB,CACvC,IAAM,EAAK,IAAI,gBACT,MAAe,CACnB,EAAG,OAAO,EAkDZ,OA/CI,EAAS,SAAW,aAAe,EAAS,SAAW,SAClD,CACL,SACA,OAAQ,QAAQ,QAAQ,EAAS,CAClC,CA2CI,CACL,SACA,QA1CsB,SAA+B,CACrD,IAAI,EAA4B,gBAAgB,EAAS,CAEzD,KAAO,CAAC,EAAG,OAAO,SAAS,CACzB,IAAM,EAAuB,EAAgB,OAE7C,OAAQ,EAAgB,OAAxB,CACE,IAAK,iBACH,EAAkB,MAAM,EAAe,CAAE,kBAAiB,cAAa,CAAC,CAEnE,EAAG,OAAO,SACb,EAAe,EAAgB,CAGjC,MAEF,IAAK,iBACH,EAAkB,MAAM,EAAe,CAAE,kBAAiB,cAAa,CAAC,CAEnE,EAAG,OAAO,SACb,EAAe,EAAgB,CAGjC,MAEF,QACE,OAAO,EAIc,EAAgB,SAAW,GAGlD,MAAM,EAAsB,CAAE,UAAW,KAA2B,OAAQ,EAAG,OAAQ,CAAC,CAI5F,OAAO,KAKkB,CAC1B,EAIL,eAAsB,EAAe,CACnC,kBACA,eAI4E,CAC5E,IAAM,EAAY,EAAwB,EAAY,CAChD,EAAmB,EAAc,EAAgB,YAAY,QAAS,EAAU,CAEtF,GAAI,CAiBF,OAhBmB,MAAM,EAA2B,CAClD,WAAY,EACZ,cACA,KAAM,EAAgB,OAAO,OAC9B,CAAC,CAYK,CACL,GAAG,EACH,OAAQ,CACN,GAAG,EAAgB,OACnB,kBAAmB,EAAgB,OAAO,0BAC3C,CACD,OAAQ,mBACT,CAhBQ,CACL,GAAG,EACH,UAAW,EAAU,qBACrB,YAAa,gDACb,WAAY,KAAK,KAAK,CACtB,OAAQ,SACT,MAWG,CACN,OAAO,GAIX,eAAsB,EAAe,CACnC,kBACA,eAIsE,CACtE,GAAI,CAAC,EAAgB,QAAQ,OAC3B,MAAO,CACL,GAAG,EACH,UAAW,EAAU,eACrB,YAAa,mCACb,WAAY,KAAK,KAAK,CACtB,OAAQ,SACT,CAGH,IAAM,EAAY,EAAwB,EAAY,CAChD,EAAwB,EAAc,EAAgB,YAAY,QAAS,EAAU,CAE3F,GAAI,CAOF,GAAI,CANe,MAAM,EAA2B,CAClD,WAAY,EACZ,cACA,KAAM,EAAgB,OAAO,OAC9B,CAAC,CAGA,MAAO,CACL,GAAG,EACH,UAAW,EAAU,qBACrB,YAAa,gDACb,WAAY,KAAK,KAAK,CACtB,OAAQ,SACT,CAGH,IAAM,EAAmB,EAAgB,OAAO,SAAW,EAAgB,OAAO,OAElF,MAAO,CACL,GAAG,EACH,cAAe,KAAK,KAAK,CACzB,OAAQ,CACN,GAAG,EAAgB,OACnB,kBAAmB,EACf,EAAgB,OAAO,0BACvB,EAAgB,OAAO,kBAC5B,CACD,OAAQ,YACR,OAAQ,CACN,GAAG,EAAgB,OACnB,kBAAmB,EAAgB,OAAO,0BAC3C,CACF,MACK,CACN,OAAO"}
|