@avalabs/fusion-sdk 0.21.0 → 0.23.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.
Files changed (101) hide show
  1. package/dist/constants.cjs +1 -1
  2. package/dist/constants.cjs.map +1 -1
  3. package/dist/constants.d.cts +9 -1
  4. package/dist/constants.d.ts +9 -1
  5. package/dist/constants.js +1 -1
  6. package/dist/constants.js.map +1 -1
  7. package/dist/mod.cjs +1 -1
  8. package/dist/mod.d.cts +5 -1
  9. package/dist/mod.d.ts +5 -1
  10. package/dist/mod.js +1 -1
  11. package/dist/transfer-manager.cjs +1 -1
  12. package/dist/transfer-manager.cjs.map +1 -1
  13. package/dist/transfer-manager.js +1 -1
  14. package/dist/transfer-manager.js.map +1 -1
  15. package/dist/transfer-service/_evm-approval.cjs +2 -0
  16. package/dist/transfer-service/_evm-approval.cjs.map +1 -0
  17. package/dist/transfer-service/_evm-approval.d.cts +23 -0
  18. package/dist/transfer-service/_evm-approval.d.ts +23 -0
  19. package/dist/transfer-service/_evm-approval.js +2 -0
  20. package/dist/transfer-service/_evm-approval.js.map +1 -0
  21. package/dist/transfer-service/_utils.cjs +1 -1
  22. package/dist/transfer-service/_utils.cjs.map +1 -1
  23. package/dist/transfer-service/_utils.d.ts +1 -0
  24. package/dist/transfer-service/_utils.js +1 -1
  25. package/dist/transfer-service/_utils.js.map +1 -1
  26. package/dist/transfer-service/avalanche-cct/_handlers/estimate-native-fee.cjs +1 -1
  27. package/dist/transfer-service/avalanche-cct/_handlers/estimate-native-fee.js +1 -1
  28. package/dist/transfer-service/avalanche-cct/_handlers/track-transfer.cjs +1 -1
  29. package/dist/transfer-service/avalanche-cct/_handlers/track-transfer.js +1 -1
  30. package/dist/transfer-service/avalanche-cct/_handlers/transfer-asset.cjs +1 -1
  31. package/dist/transfer-service/avalanche-cct/_handlers/transfer-asset.js +1 -1
  32. package/dist/transfer-service/avalanche-cct/_utils/fees.cjs +1 -1
  33. package/dist/transfer-service/avalanche-cct/_utils/fees.js +1 -1
  34. package/dist/transfer-service/avalanche-cct/_utils/polling.cjs +1 -1
  35. package/dist/transfer-service/avalanche-cct/_utils/polling.js +1 -1
  36. package/dist/transfer-service/avalanche-evm/_handlers/estimate-native-fee.cjs +1 -1
  37. package/dist/transfer-service/avalanche-evm/_handlers/estimate-native-fee.js +1 -1
  38. package/dist/transfer-service/markr/_api.cjs +1 -1
  39. package/dist/transfer-service/markr/_api.cjs.map +1 -1
  40. package/dist/transfer-service/markr/_api.js +1 -1
  41. package/dist/transfer-service/markr/_api.js.map +1 -1
  42. package/dist/transfer-service/markr/_handlers/estimate-native-fee.cjs +1 -1
  43. package/dist/transfer-service/markr/_handlers/estimate-native-fee.js +1 -1
  44. package/dist/transfer-service/markr/_handlers/transfer-asset.cjs +1 -1
  45. package/dist/transfer-service/markr/_handlers/transfer-asset.cjs.map +1 -1
  46. package/dist/transfer-service/markr/_handlers/transfer-asset.js +1 -1
  47. package/dist/transfer-service/markr/_handlers/transfer-asset.js.map +1 -1
  48. package/dist/transfer-service/markr/_schema.cjs +1 -1
  49. package/dist/transfer-service/markr/_schema.cjs.map +1 -1
  50. package/dist/transfer-service/markr/_schema.js +1 -1
  51. package/dist/transfer-service/markr/_schema.js.map +1 -1
  52. package/dist/transfer-service/markr/_utils.cjs +1 -1
  53. package/dist/transfer-service/markr/_utils.cjs.map +1 -1
  54. package/dist/transfer-service/markr/_utils.js +1 -1
  55. package/dist/transfer-service/markr/_utils.js.map +1 -1
  56. package/dist/transfer-service/markr/markr-service.cjs +1 -1
  57. package/dist/transfer-service/markr/markr-service.cjs.map +1 -1
  58. package/dist/transfer-service/markr/markr-service.d.cts +26 -0
  59. package/dist/transfer-service/markr/markr-service.d.ts +26 -0
  60. package/dist/transfer-service/markr/markr-service.js +1 -1
  61. package/dist/transfer-service/markr/markr-service.js.map +1 -1
  62. package/dist/transfer-service/markr/recurring/_api.cjs +2 -0
  63. package/dist/transfer-service/markr/recurring/_api.cjs.map +1 -0
  64. package/dist/transfer-service/markr/recurring/_api.js +2 -0
  65. package/dist/transfer-service/markr/recurring/_api.js.map +1 -0
  66. package/dist/transfer-service/markr/recurring/_chain-info.cjs +2 -0
  67. package/dist/transfer-service/markr/recurring/_chain-info.cjs.map +1 -0
  68. package/dist/transfer-service/markr/recurring/_chain-info.js +2 -0
  69. package/dist/transfer-service/markr/recurring/_chain-info.js.map +1 -0
  70. package/dist/transfer-service/markr/recurring/_eligibility.cjs +2 -0
  71. package/dist/transfer-service/markr/recurring/_eligibility.cjs.map +1 -0
  72. package/dist/transfer-service/markr/recurring/_eligibility.js +2 -0
  73. package/dist/transfer-service/markr/recurring/_eligibility.js.map +1 -0
  74. package/dist/transfer-service/markr/recurring/_frequency.cjs +2 -0
  75. package/dist/transfer-service/markr/recurring/_frequency.cjs.map +1 -0
  76. package/dist/transfer-service/markr/recurring/_frequency.d.cts +17 -0
  77. package/dist/transfer-service/markr/recurring/_frequency.d.ts +17 -0
  78. package/dist/transfer-service/markr/recurring/_frequency.js +2 -0
  79. package/dist/transfer-service/markr/recurring/_frequency.js.map +1 -0
  80. package/dist/transfer-service/markr/recurring/_namespace.cjs +2 -0
  81. package/dist/transfer-service/markr/recurring/_namespace.cjs.map +1 -0
  82. package/dist/transfer-service/markr/recurring/_namespace.js +2 -0
  83. package/dist/transfer-service/markr/recurring/_namespace.js.map +1 -0
  84. package/dist/transfer-service/markr/recurring/_schema.cjs +2 -0
  85. package/dist/transfer-service/markr/recurring/_schema.cjs.map +1 -0
  86. package/dist/transfer-service/markr/recurring/_schema.js +2 -0
  87. package/dist/transfer-service/markr/recurring/_schema.js.map +1 -0
  88. package/dist/transfer-service/markr/recurring/index.d.ts +2 -0
  89. package/dist/transfer-service/markr/recurring/types.cjs +2 -0
  90. package/dist/transfer-service/markr/recurring/types.cjs.map +1 -0
  91. package/dist/transfer-service/markr/recurring/types.d.cts +455 -0
  92. package/dist/transfer-service/markr/recurring/types.d.ts +455 -0
  93. package/dist/transfer-service/markr/recurring/types.js +2 -0
  94. package/dist/transfer-service/markr/recurring/types.js.map +1 -0
  95. package/dist/transfer-service/wrap-unwrap/_handlers/transfer-asset.cjs +1 -1
  96. package/dist/transfer-service/wrap-unwrap/_handlers/transfer-asset.js +1 -1
  97. package/dist/types/transfer-manager.d.cts +16 -0
  98. package/dist/types/transfer-manager.d.ts +16 -0
  99. package/dist/types/transfer.d.cts +8 -0
  100. package/dist/types/transfer.d.ts +8 -0
  101. package/package.json +3 -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 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
+ {"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';\nimport type { MarkrService } from './transfer-service/markr/markr-service';\nimport type { RecurringNamespace } from './transfer-service/markr/recurring/types';\n\n/**\n * Builds the `TransferManager.recurring` capability surface by delegating\n * each call to whichever underlying service implements recurring (today:\n * Markr). The delegate captures the services map by reference so a future\n * call sees whatever is currently initialized.\n *\n * Throws `ServiceUnavailableError` from every method when no recurring-\n * capable service is registered — same failure shape as `transferAsset`,\n * `estimateNativeFee`, and `trackTransfer` when the relevant service is\n * absent.\n */\nconst createRecurringDelegate = (services: Map<ServiceType, TransferService>): RecurringNamespace => {\n const requireMarkrService = (): MarkrService => {\n const service = services.get(ServiceType.MARKR);\n // The `'recurring' in service` guard documents the invariant in code:\n // `initializeServices` registers a `MarkrService` (which extends\n // `TransferService` with `.recurring`) for `ServiceType.MARKR`. The check\n // also gives us a clear `ServiceUnavailableError` instead of a runtime\n // `Cannot read property 'X' of undefined` if a future refactor ever\n // registers a plain `TransferService` for the Markr slot.\n if (!service || !('recurring' in service)) {\n throw new ServiceUnavailableError(\n ErrorReason.SERVICE_TYPE_NOT_CONFIGURED,\n 'Recurring swaps require the Markr service, which was not initialized.',\n );\n }\n return service as MarkrService;\n };\n\n // `async` on the Promise-returning methods so a sync throw from\n // `requireMarkrService()` becomes a Promise rejection (consumers expect\n // `manager.recurring.quote(...)` to return a Promise, not to throw before\n // returning one). The sync methods (`checkEligibility`,\n // `getRecurringChainInfo`) keep their natural sync shape — sync throws\n // are the contract there.\n return {\n quote: async (props) => requireMarkrService().recurring.quote(props),\n executeFirstFill: async (props) => requireMarkrService().recurring.executeFirstFill(props),\n listOrders: async (props) => requireMarkrService().recurring.listOrders(props),\n executeCancellation: async (props) => requireMarkrService().recurring.executeCancellation(props),\n executePause: async (props) => requireMarkrService().recurring.executePause(props),\n executeUnpause: async (props) => requireMarkrService().recurring.executeUnpause(props),\n checkEligibility: (props) => requireMarkrService().recurring.checkEligibility(props),\n getRecurringChainInfo: () => requireMarkrService().recurring.getRecurringChainInfo(),\n };\n};\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 recurring: createRecurringDelegate(services),\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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"}
@@ -0,0 +1,2 @@
1
+ require(`../_virtual/_rolldown/runtime.cjs`);const e=require(`../errors.cjs`),t=require(`./_utils.cjs`),n=require(`./_evm-errors.cjs`);let r=require(`viem`);var i=class extends e.SdkError{constructor(){super(`ERC20 approval transaction was reverted.`,e.ErrorCode.TRANSACTION_REVERTED),this.name=`ApprovalRevertedError`}};async function a({chainIdHex:e,client:i,gasSettings:a,owner:o,requiredAllowance:s,spender:c,token:l}){if(await i.readContract({address:l,abi:r.erc20Abi,functionName:`allowance`,args:[o,c]})>=s)return;let u=(0,r.encodeFunctionData)({abi:r.erc20Abi,functionName:`approve`,args:[c,s]});return{chainId:e,data:u,from:o,gas:t.applyFeeUnitsBpsMargin(await n.estimateGasWithRevert(i,{account:o,to:l,data:u},r.erc20Abi,`Failed to estimate gas for ERC20 approval transaction.`),a?.estimateGasMarginBps),to:l,value:0n,...t.maybe1559(a)}}async function o({client:e,evmSigner:t,onStepChange:n,request:r,step:a}){n?.(a);let o=await t.sign(r,async t=>e.sendRawTransaction({serializedTransaction:t}),a);if((await e.waitForTransactionReceipt({hash:o})).status===`reverted`)throw new i}exports.ApprovalRevertedError=i,exports.buildErc20ApprovalRequest=a,exports.signApprovalAndAssertConfirmed=o;
2
+ //# sourceMappingURL=_evm-approval.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"_evm-approval.cjs","names":["SdkError","ErrorCode","erc20Abi","applyFeeUnitsBpsMargin","estimateGasWithRevert","maybe1559"],"sources":["../../src/transfer-service/_evm-approval.ts"],"sourcesContent":["/**\n * @module\n * @internal\n *\n * Shared EVM allowance + approval helpers reused by the regular\n * `transferAsset` path and the recurring `executeFirstFill` path. Captures the\n * \"read on-chain allowance, build an `approve(spender, amount)` TX when short,\n * sign + wait + revert-check\" subroutines that both call sites need —\n * orchestration (one-click batch attempt, fallback to sequential, final swap\n * sign) stays at each call site because the surrounding contract differs\n * (return type, gas estimation flavor, native-token short-circuit, etc.).\n */\nimport { encodeFunctionData, erc20Abi, type Address as EvmAddress } from 'viem';\nimport { ErrorCode, SdkError } from '../errors';\nimport type { GasSettings } from '../types/service';\nimport type { EvmSigner, EvmTransactionRequest, Hex } from '../types/signer';\nimport type { TransferStepDetails } from '../types/transfer';\nimport { applyFeeUnitsBpsMargin, maybe1559 } from './_utils';\nimport type { EvmSourceClient } from './_utils';\nimport { estimateGasWithRevert } from './_evm-errors';\n\n/**\n * Thrown by {@link signApprovalAndAssertConfirmed} when the approval TX is\n * mined as reverted (i.e. broadcast succeeded, but the on-chain receipt's\n * `status === 'reverted'`).\n *\n * Distinct class so callers can `instanceof`-discriminate this specific\n * confirmed-then-reverted signal from other failures (signer rejection, RPC\n * timeout on the receipt poll, etc.) — the regular `transferAsset` path\n * converts this to a failed `Transfer`; the recurring path lets it bubble.\n *\n * Extends `SdkError` (with `ErrorCode.TRANSACTION_REVERTED`) so existing\n * error-code-based consumers still observe the documented semantics.\n */\nexport class ApprovalRevertedError extends SdkError {\n constructor() {\n super('ERC20 approval transaction was reverted.', ErrorCode.TRANSACTION_REVERTED);\n this.name = 'ApprovalRevertedError';\n }\n}\n\n/**\n * Reads `allowance(token → spender)` for `owner` and, if short of\n * `requiredAllowance`, builds an `approve(spender, requiredAllowance)`\n * {@link EvmTransactionRequest} with a gas estimate (plus\n * `gasSettings.estimateGasMarginBps` margin) and optional 1559 overrides\n * already applied.\n *\n * Returns `undefined` when the existing allowance already covers — caller\n * skips the approval step entirely.\n *\n * Native-token short-circuits live at the call site (this helper only runs\n * for ERC-20 inputs).\n */\nexport async function buildErc20ApprovalRequest({\n chainIdHex,\n client,\n gasSettings,\n owner,\n requiredAllowance,\n spender,\n token,\n}: {\n chainIdHex: Hex;\n client: EvmSourceClient;\n gasSettings?: GasSettings;\n owner: EvmAddress;\n requiredAllowance: bigint;\n spender: EvmAddress;\n token: EvmAddress;\n}): Promise<EvmTransactionRequest | undefined> {\n const allowance = await client.readContract({\n address: token,\n abi: erc20Abi,\n functionName: 'allowance',\n args: [owner, spender],\n });\n\n if (allowance >= requiredAllowance) {\n return undefined;\n }\n\n const data = encodeFunctionData({\n abi: erc20Abi,\n functionName: 'approve',\n args: [spender, requiredAllowance],\n });\n\n const gasEstimate = await estimateGasWithRevert(\n client,\n { account: owner, to: token, data },\n erc20Abi,\n 'Failed to estimate gas for ERC20 approval transaction.',\n );\n\n return {\n chainId: chainIdHex,\n data,\n from: owner,\n gas: applyFeeUnitsBpsMargin(gasEstimate, gasSettings?.estimateGasMarginBps),\n to: token,\n value: 0n,\n ...maybe1559(gasSettings),\n };\n}\n\n/**\n * Signs the given approval `EvmTransactionRequest`, dispatches it via the\n * chain's RPC, and waits for the receipt. Throws {@link ApprovalRevertedError}\n * (an `SdkError` subclass with `ErrorCode.TRANSACTION_REVERTED`) when the\n * approval TX is mined as reverted — callers may `instanceof`-discriminate\n * to convert into a service-specific failure envelope (e.g.\n * `makeFailedTransferFromQuote`). Other errors (signer rejection, RPC\n * timeouts on the receipt poll, etc.) propagate unchanged.\n *\n * Fires `onStepChange(step)` before signing so consumers can advance their\n * step-tracking UI; omit for paths that don't surface per-step progress\n * (e.g. the recurring namespace).\n */\nexport async function signApprovalAndAssertConfirmed({\n client,\n evmSigner,\n onStepChange,\n request,\n step,\n}: {\n client: EvmSourceClient;\n evmSigner: EvmSigner;\n onStepChange?: (step: TransferStepDetails) => void;\n request: EvmTransactionRequest;\n step: TransferStepDetails;\n}): Promise<void> {\n onStepChange?.(step);\n\n const approvalTxHash = await evmSigner.sign(\n request,\n async (signedTxHash) => client.sendRawTransaction({ serializedTransaction: signedTxHash }),\n step,\n );\n\n const receipt = await client.waitForTransactionReceipt({ hash: approvalTxHash });\n\n if (receipt.status === 'reverted') {\n throw new ApprovalRevertedError();\n }\n}\n"],"mappings":"6JAkCA,IAAa,EAAb,cAA2CA,EAAAA,QAAS,CAClD,aAAc,CACZ,MAAM,2CAA4CC,EAAAA,UAAU,qBAAqB,CACjF,KAAK,KAAO,0BAiBhB,eAAsB,EAA0B,CAC9C,aACA,SACA,cACA,QACA,oBACA,UACA,SAS6C,CAQ7C,GAPkB,MAAM,EAAO,aAAa,CAC1C,QAAS,EACT,IAAKC,EAAAA,SACL,aAAc,YACd,KAAM,CAAC,EAAO,EAAQ,CACvB,CAAC,EAEe,EACf,OAGF,IAAM,GAAA,EAAA,EAAA,oBAA0B,CAC9B,IAAKA,EAAAA,SACL,aAAc,UACd,KAAM,CAAC,EAAS,EAAkB,CACnC,CAAC,CASF,MAAO,CACL,QAAS,EACT,OACA,KAAM,EACN,IAAKC,EAAAA,uBAXa,MAAMC,EAAAA,sBACxB,EACA,CAAE,QAAS,EAAO,GAAI,EAAO,OAAM,CACnCF,EAAAA,SACA,yDACD,CAM0C,GAAa,qBAAqB,CAC3E,GAAI,EACJ,MAAO,GACP,GAAGG,EAAAA,UAAU,EAAY,CAC1B,CAgBH,eAAsB,EAA+B,CACnD,SACA,YACA,eACA,UACA,QAOgB,CAChB,IAAe,EAAK,CAEpB,IAAM,EAAiB,MAAM,EAAU,KACrC,EACA,KAAO,IAAiB,EAAO,mBAAmB,CAAE,sBAAuB,EAAc,CAAC,CAC1F,EACD,CAID,IAFgB,MAAM,EAAO,0BAA0B,CAAE,KAAM,EAAgB,CAAC,EAEpE,SAAW,WACrB,MAAM,IAAI"}
@@ -0,0 +1,23 @@
1
+ import { SdkError } from "../errors.cjs";
2
+ import { Address } from "viem";
3
+
4
+ //#region src/transfer-service/_evm-approval.d.ts
5
+ /**
6
+ * Thrown by {@link signApprovalAndAssertConfirmed} when the approval TX is
7
+ * mined as reverted (i.e. broadcast succeeded, but the on-chain receipt's
8
+ * `status === 'reverted'`).
9
+ *
10
+ * Distinct class so callers can `instanceof`-discriminate this specific
11
+ * confirmed-then-reverted signal from other failures (signer rejection, RPC
12
+ * timeout on the receipt poll, etc.) — the regular `transferAsset` path
13
+ * converts this to a failed `Transfer`; the recurring path lets it bubble.
14
+ *
15
+ * Extends `SdkError` (with `ErrorCode.TRANSACTION_REVERTED`) so existing
16
+ * error-code-based consumers still observe the documented semantics.
17
+ */
18
+ declare class ApprovalRevertedError extends SdkError {
19
+ constructor();
20
+ }
21
+ //#endregion
22
+ export { ApprovalRevertedError };
23
+ //# sourceMappingURL=_evm-approval.d.cts.map
@@ -0,0 +1,23 @@
1
+ import { SdkError } from "../errors.js";
2
+ import { Address } from "viem";
3
+
4
+ //#region src/transfer-service/_evm-approval.d.ts
5
+ /**
6
+ * Thrown by {@link signApprovalAndAssertConfirmed} when the approval TX is
7
+ * mined as reverted (i.e. broadcast succeeded, but the on-chain receipt's
8
+ * `status === 'reverted'`).
9
+ *
10
+ * Distinct class so callers can `instanceof`-discriminate this specific
11
+ * confirmed-then-reverted signal from other failures (signer rejection, RPC
12
+ * timeout on the receipt poll, etc.) — the regular `transferAsset` path
13
+ * converts this to a failed `Transfer`; the recurring path lets it bubble.
14
+ *
15
+ * Extends `SdkError` (with `ErrorCode.TRANSACTION_REVERTED`) so existing
16
+ * error-code-based consumers still observe the documented semantics.
17
+ */
18
+ declare class ApprovalRevertedError extends SdkError {
19
+ constructor();
20
+ }
21
+ //#endregion
22
+ export { ApprovalRevertedError };
23
+ //# sourceMappingURL=_evm-approval.d.ts.map
@@ -0,0 +1,2 @@
1
+ import{ErrorCode as e,SdkError as t}from"../errors.js";import{applyFeeUnitsBpsMargin as n,maybe1559 as r}from"./_utils.js";import{estimateGasWithRevert as i}from"./_evm-errors.js";import{encodeFunctionData as a,erc20Abi as o}from"viem";var s=class extends t{constructor(){super(`ERC20 approval transaction was reverted.`,e.TRANSACTION_REVERTED),this.name=`ApprovalRevertedError`}};async function c({chainIdHex:e,client:t,gasSettings:s,owner:c,requiredAllowance:l,spender:u,token:d}){if(await t.readContract({address:d,abi:o,functionName:`allowance`,args:[c,u]})>=l)return;let f=a({abi:o,functionName:`approve`,args:[u,l]});return{chainId:e,data:f,from:c,gas:n(await i(t,{account:c,to:d,data:f},o,`Failed to estimate gas for ERC20 approval transaction.`),s?.estimateGasMarginBps),to:d,value:0n,...r(s)}}async function l({client:e,evmSigner:t,onStepChange:n,request:r,step:i}){n?.(i);let a=await t.sign(r,async t=>e.sendRawTransaction({serializedTransaction:t}),i);if((await e.waitForTransactionReceipt({hash:a})).status===`reverted`)throw new s}export{s as ApprovalRevertedError,c as buildErc20ApprovalRequest,l as signApprovalAndAssertConfirmed};
2
+ //# sourceMappingURL=_evm-approval.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"_evm-approval.js","names":[],"sources":["../../src/transfer-service/_evm-approval.ts"],"sourcesContent":["/**\n * @module\n * @internal\n *\n * Shared EVM allowance + approval helpers reused by the regular\n * `transferAsset` path and the recurring `executeFirstFill` path. Captures the\n * \"read on-chain allowance, build an `approve(spender, amount)` TX when short,\n * sign + wait + revert-check\" subroutines that both call sites need —\n * orchestration (one-click batch attempt, fallback to sequential, final swap\n * sign) stays at each call site because the surrounding contract differs\n * (return type, gas estimation flavor, native-token short-circuit, etc.).\n */\nimport { encodeFunctionData, erc20Abi, type Address as EvmAddress } from 'viem';\nimport { ErrorCode, SdkError } from '../errors';\nimport type { GasSettings } from '../types/service';\nimport type { EvmSigner, EvmTransactionRequest, Hex } from '../types/signer';\nimport type { TransferStepDetails } from '../types/transfer';\nimport { applyFeeUnitsBpsMargin, maybe1559 } from './_utils';\nimport type { EvmSourceClient } from './_utils';\nimport { estimateGasWithRevert } from './_evm-errors';\n\n/**\n * Thrown by {@link signApprovalAndAssertConfirmed} when the approval TX is\n * mined as reverted (i.e. broadcast succeeded, but the on-chain receipt's\n * `status === 'reverted'`).\n *\n * Distinct class so callers can `instanceof`-discriminate this specific\n * confirmed-then-reverted signal from other failures (signer rejection, RPC\n * timeout on the receipt poll, etc.) — the regular `transferAsset` path\n * converts this to a failed `Transfer`; the recurring path lets it bubble.\n *\n * Extends `SdkError` (with `ErrorCode.TRANSACTION_REVERTED`) so existing\n * error-code-based consumers still observe the documented semantics.\n */\nexport class ApprovalRevertedError extends SdkError {\n constructor() {\n super('ERC20 approval transaction was reverted.', ErrorCode.TRANSACTION_REVERTED);\n this.name = 'ApprovalRevertedError';\n }\n}\n\n/**\n * Reads `allowance(token → spender)` for `owner` and, if short of\n * `requiredAllowance`, builds an `approve(spender, requiredAllowance)`\n * {@link EvmTransactionRequest} with a gas estimate (plus\n * `gasSettings.estimateGasMarginBps` margin) and optional 1559 overrides\n * already applied.\n *\n * Returns `undefined` when the existing allowance already covers — caller\n * skips the approval step entirely.\n *\n * Native-token short-circuits live at the call site (this helper only runs\n * for ERC-20 inputs).\n */\nexport async function buildErc20ApprovalRequest({\n chainIdHex,\n client,\n gasSettings,\n owner,\n requiredAllowance,\n spender,\n token,\n}: {\n chainIdHex: Hex;\n client: EvmSourceClient;\n gasSettings?: GasSettings;\n owner: EvmAddress;\n requiredAllowance: bigint;\n spender: EvmAddress;\n token: EvmAddress;\n}): Promise<EvmTransactionRequest | undefined> {\n const allowance = await client.readContract({\n address: token,\n abi: erc20Abi,\n functionName: 'allowance',\n args: [owner, spender],\n });\n\n if (allowance >= requiredAllowance) {\n return undefined;\n }\n\n const data = encodeFunctionData({\n abi: erc20Abi,\n functionName: 'approve',\n args: [spender, requiredAllowance],\n });\n\n const gasEstimate = await estimateGasWithRevert(\n client,\n { account: owner, to: token, data },\n erc20Abi,\n 'Failed to estimate gas for ERC20 approval transaction.',\n );\n\n return {\n chainId: chainIdHex,\n data,\n from: owner,\n gas: applyFeeUnitsBpsMargin(gasEstimate, gasSettings?.estimateGasMarginBps),\n to: token,\n value: 0n,\n ...maybe1559(gasSettings),\n };\n}\n\n/**\n * Signs the given approval `EvmTransactionRequest`, dispatches it via the\n * chain's RPC, and waits for the receipt. Throws {@link ApprovalRevertedError}\n * (an `SdkError` subclass with `ErrorCode.TRANSACTION_REVERTED`) when the\n * approval TX is mined as reverted — callers may `instanceof`-discriminate\n * to convert into a service-specific failure envelope (e.g.\n * `makeFailedTransferFromQuote`). Other errors (signer rejection, RPC\n * timeouts on the receipt poll, etc.) propagate unchanged.\n *\n * Fires `onStepChange(step)` before signing so consumers can advance their\n * step-tracking UI; omit for paths that don't surface per-step progress\n * (e.g. the recurring namespace).\n */\nexport async function signApprovalAndAssertConfirmed({\n client,\n evmSigner,\n onStepChange,\n request,\n step,\n}: {\n client: EvmSourceClient;\n evmSigner: EvmSigner;\n onStepChange?: (step: TransferStepDetails) => void;\n request: EvmTransactionRequest;\n step: TransferStepDetails;\n}): Promise<void> {\n onStepChange?.(step);\n\n const approvalTxHash = await evmSigner.sign(\n request,\n async (signedTxHash) => client.sendRawTransaction({ serializedTransaction: signedTxHash }),\n step,\n );\n\n const receipt = await client.waitForTransactionReceipt({ hash: approvalTxHash });\n\n if (receipt.status === 'reverted') {\n throw new ApprovalRevertedError();\n }\n}\n"],"mappings":"4OAkCA,IAAa,EAAb,cAA2C,CAAS,CAClD,aAAc,CACZ,MAAM,2CAA4C,EAAU,qBAAqB,CACjF,KAAK,KAAO,0BAiBhB,eAAsB,EAA0B,CAC9C,aACA,SACA,cACA,QACA,oBACA,UACA,SAS6C,CAQ7C,GAPkB,MAAM,EAAO,aAAa,CAC1C,QAAS,EACT,IAAK,EACL,aAAc,YACd,KAAM,CAAC,EAAO,EAAQ,CACvB,CAAC,EAEe,EACf,OAGF,IAAM,EAAO,EAAmB,CAC9B,IAAK,EACL,aAAc,UACd,KAAM,CAAC,EAAS,EAAkB,CACnC,CAAC,CASF,MAAO,CACL,QAAS,EACT,OACA,KAAM,EACN,IAAK,EAXa,MAAM,EACxB,EACA,CAAE,QAAS,EAAO,GAAI,EAAO,OAAM,CACnC,EACA,yDACD,CAM0C,GAAa,qBAAqB,CAC3E,GAAI,EACJ,MAAO,GACP,GAAG,EAAU,EAAY,CAC1B,CAgBH,eAAsB,EAA+B,CACnD,SACA,YACA,eACA,UACA,QAOgB,CAChB,IAAe,EAAK,CAEpB,IAAM,EAAiB,MAAM,EAAU,KACrC,EACA,KAAO,IAAiB,EAAO,mBAAmB,CAAE,sBAAuB,EAAc,CAAC,CAC1F,EACD,CAID,IAFgB,MAAM,EAAO,0BAA0B,CAAE,KAAM,EAAgB,CAAC,EAEpE,SAAW,WACrB,MAAM,IAAI"}
@@ -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}}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;
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(e){return e?.maxFeePerGas===void 0?{}:{maxFeePerGas:e.maxFeePerGas,maxPriorityFeePerGas:e.maxPriorityFeePerGas}}function c(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 l({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 u=Symbol(`aborted`);async function d(e,t){let n=await Promise.race([e,new Promise(e=>{t.addEventListener(`abort`,()=>e(u),{once:!0})})]);return n===u||t.aborted?{status:`aborted`}:{status:`ok`,value:n}}function f(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 p(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=c,exports.awaitOrAbort=d,exports.getEvmClientForChain=a,exports.getSolanaRpcForChain=o,exports.makeFailedTransferFromQuote=f,exports.maybe1559=s,exports.wait=p,exports.waitForTimeoutOrAbort=l;
2
2
  //# sourceMappingURL=_utils.cjs.map
@@ -1 +1 @@
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
+ {"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 { GasSettings } from '../types/service';\nimport type { EvmTransactionRequest } from '../types/signer';\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\n/**\n * Concrete viem client returned by {@link getEvmClientForChain}. Exported so\n * helpers like {@link buildErc20ApprovalRequest} and\n * {@link signApprovalAndAssertConfirmed} can structurally type the `client`\n * arg without rebuilding the viem-types tower.\n */\nexport type EvmSourceClient = Client<HttpTransport, ViemChain, undefined, WalletRpcSchema, PublicActions>;\n\nexport function getEvmClientForChain({ chain }: { chain: Chain }): EvmSourceClient {\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\n/**\n * Pulls the EIP-1559 fee fields out of {@link GasSettings} as a spread-ready\n * object suitable for inclusion in an {@link EvmTransactionRequest} literal.\n * Returns an empty object when `gasSettings?.maxFeePerGas` is `undefined`\n * (legacy / wallet-default gas pricing) so the consumer's wallet picks the\n * fee tier — matches the convention used across every EVM signing path.\n */\nexport function maybe1559(\n gasSettings: GasSettings | undefined,\n): Pick<EvmTransactionRequest, 'maxFeePerGas' | 'maxPriorityFeePerGas'> {\n return gasSettings?.maxFeePerGas !== undefined\n ? { maxFeePerGas: gasSettings.maxFeePerGas, maxPriorityFeePerGas: gasSettings.maxPriorityFeePerGas }\n : {};\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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"}
@@ -0,0 +1 @@
1
+ export { };
@@ -1,2 +1,2 @@
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};
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){return e?.maxFeePerGas===void 0?{}:{maxFeePerGas:e.maxFeePerGas,maxPriorityFeePerGas:e.maxPriorityFeePerGas}}function d(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 f({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 p=Symbol(`aborted`);async function m(e,t){let n=await Promise.race([e,new Promise(e=>{t.addEventListener(`abort`,()=>e(p),{once:!0})})]);return n===p||t.aborted?{status:`aborted`}:{status:`ok`,value:n}}function h(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 g(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{d as applyFeeUnitsBpsMargin,m as awaitOrAbort,c as getEvmClientForChain,l as getSolanaRpcForChain,h as makeFailedTransferFromQuote,u as maybe1559,g as wait,f 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 { 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
+ {"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 { GasSettings } from '../types/service';\nimport type { EvmTransactionRequest } from '../types/signer';\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\n/**\n * Concrete viem client returned by {@link getEvmClientForChain}. Exported so\n * helpers like {@link buildErc20ApprovalRequest} and\n * {@link signApprovalAndAssertConfirmed} can structurally type the `client`\n * arg without rebuilding the viem-types tower.\n */\nexport type EvmSourceClient = Client<HttpTransport, ViemChain, undefined, WalletRpcSchema, PublicActions>;\n\nexport function getEvmClientForChain({ chain }: { chain: Chain }): EvmSourceClient {\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\n/**\n * Pulls the EIP-1559 fee fields out of {@link GasSettings} as a spread-ready\n * object suitable for inclusion in an {@link EvmTransactionRequest} literal.\n * Returns an empty object when `gasSettings?.maxFeePerGas` is `undefined`\n * (legacy / wallet-default gas pricing) so the consumer's wallet picks the\n * fee tier — matches the convention used across every EVM signing path.\n */\nexport function maybe1559(\n gasSettings: GasSettings | undefined,\n): Pick<EvmTransactionRequest, 'maxFeePerGas' | 'maxPriorityFeePerGas'> {\n return gasSettings?.maxFeePerGas !== undefined\n ? { maxFeePerGas: gasSettings.maxFeePerGas, maxPriorityFeePerGas: gasSettings.maxPriorityFeePerGas }\n : {};\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
- 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;
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=n.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=r.getChainAlias(u.sourceChain.chainId,f),_=r.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?r.convertNanoAvaxToWei(O):O,M=A?r.convertNanoAvaxToWei(k):k;return{asset:r.getNativeTokenForChainAlias(g),totalFee:j,totalFeeWithoutMargin:M}}}exports.estimateNativeFeeFactory=o;
2
2
  //# sourceMappingURL=estimate-native-fee.cjs.map
@@ -1,2 +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};
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{getEvmClientForChain as s}from"../../_utils.js";import{convertNanoAvaxToWei as c,getChainAlias as l,getNativeTokenForChainAlias 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=s({chain:b?e:t}),S=y?.overrides?.maxFeePerGas??(await d(x))[y?.overrides?.feeRateTier??`fast`].maxFeePerGas,C=y?.feeUnitsMarginBps,w=l(v.sourceChain.chainId,b),T=l(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?c(I):I,B=R?c(L):L;return{asset:u(w),totalFee:z,totalFeeWithoutMargin:B}}}export{m as estimateNativeFeeFactory};
2
2
  //# sourceMappingURL=estimate-native-fee.js.map
@@ -1,2 +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;
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:n,updateListener:r})=>{let i=new AbortController,s=()=>{i.abort()};return n.status===`completed`||n.status===`failed`?{cancel:s,result:Promise.resolve(n)}:{cancel:s,result:(async()=>{let s=structuredClone(n);for(;!i.signal.aborted;){let n=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===n&&await t.waitForTimeoutOrAbort({timeoutMs:1500,signal:i.signal})}return s})()}}}async function a({currentTransfer:t,environment:i}){let a=n.getEnvironmentIsTestnet(i),o=n.getChainAlias(t.sourceChain.chainId,a);try{return await r.pollPrimaryNetworkTxStatus({chainAlias:o,environment:i,txId:t.source.txHash})?{...t,source:{...t.source,confirmationCount:t.source.requiredConfirmationCount},status:`source-completed`}:{...t,errorCode:e.ErrorCode.TRANSACTION_REVERTED,errorReason:`Source transaction was rejected by Avalanche.`,failedAtMs:Date.now(),status:`failed`}}catch{return t}}async function o({currentTransfer:t,environment:i}){if(!t.target?.txHash)return{...t,errorCode:e.ErrorCode.INVALID_PARAMS,errorReason:`Missing target transaction hash.`,failedAtMs:Date.now(),status:`failed`};let a=n.getEnvironmentIsTestnet(i),o=n.getChainAlias(t.targetChain.chainId,a);try{if(!await r.pollPrimaryNetworkTxStatus({chainAlias:o,environment:i,txId:t.target.txHash}))return{...t,errorCode:e.ErrorCode.TRANSACTION_REVERTED,errorReason:`Target transaction was rejected by Avalanche.`,failedAtMs:Date.now(),status:`failed`};let n=t.source.txHash===t.target.txHash;return{...t,completedAtMs:Date.now(),source:{...t.source,confirmationCount:n?t.source.requiredConfirmationCount:t.source.confirmationCount},status:`completed`,target:{...t.target,confirmationCount:t.target.requiredConfirmationCount}}}catch{return t}}exports.trackTransferFactory=i;
2
2
  //# sourceMappingURL=track-transfer.cjs.map
@@ -1,2 +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};
1
+ import{ErrorCode as e}from"../../../errors.js";import{waitForTimeoutOrAbort as t}from"../../_utils.js";import{getChainAlias as n,getEnvironmentIsTestnet as r}from"../_utils.js";import{pollPrimaryNetworkTxStatus as i}from"../_utils/polling.js";function a({environment:e}){return({transfer:n,updateListener:r})=>{let i=new AbortController,a=()=>{i.abort()};return n.status===`completed`||n.status===`failed`?{cancel:a,result:Promise.resolve(n)}:{cancel:a,result:(async()=>{let a=structuredClone(n);for(;!i.signal.aborted;){let n=a.status;switch(a.status){case`source-pending`:a=await o({currentTransfer:a,environment:e}),i.signal.aborted||r(a);break;case`target-pending`:a=await s({currentTransfer:a,environment:e}),i.signal.aborted||r(a);break;default:return a}a.status===n&&await t({timeoutMs:1500,signal:i.signal})}return a})()}}}async function o({currentTransfer:t,environment:a}){let o=r(a),s=n(t.sourceChain.chainId,o);try{return await i({chainAlias:s,environment:a,txId:t.source.txHash})?{...t,source:{...t.source,confirmationCount:t.source.requiredConfirmationCount},status:`source-completed`}:{...t,errorCode:e.TRANSACTION_REVERTED,errorReason:`Source transaction was rejected by Avalanche.`,failedAtMs:Date.now(),status:`failed`}}catch{return t}}async function s({currentTransfer:t,environment:a}){if(!t.target?.txHash)return{...t,errorCode:e.INVALID_PARAMS,errorReason:`Missing target transaction hash.`,failedAtMs:Date.now(),status:`failed`};let o=r(a),s=n(t.targetChain.chainId,o);try{if(!await i({chainAlias:s,environment:a,txId:t.target.txHash}))return{...t,errorCode:e.TRANSACTION_REVERTED,errorReason:`Target transaction was rejected by Avalanche.`,failedAtMs:Date.now(),status:`failed`};let n=t.source.txHash===t.target.txHash;return{...t,completedAtMs:Date.now(),source:{...t.source,confirmationCount:n?t.source.requiredConfirmationCount:t.source.confirmationCount},status:`completed`,target:{...t.target,confirmationCount:t.target.requiredConfirmationCount}}}catch{return t}}export{a as trackTransferFactory};
2
2
  //# sourceMappingURL=track-transfer.js.map
@@ -1,2 +1,2 @@
1
- const e=require(`../../../constants.cjs`),t=require(`../../../errors.cjs`),n=require(`../constants.cjs`),r=require(`../_utils.cjs`),i=require(`../../_transfer-utilities.cjs`),a=require(`../../_utils.cjs`),o=require(`../_utils/p-chain.cjs`),s=require(`../_utils/polling.cjs`),c=require(`../_utils/transactions.cjs`),l=require(`../_utils/fees.cjs`),u=require(`../_utils/addresses.cjs`);function d({ajsContext:n,avalancheSendTx:a,environment:o,getCoreEthAddress:c,getAtomicUtxos:l,getUtxos:d,getWalletAddressesForChainAlias:m,getWalletChangeAddressForChainAlias:_}){return async({onStepChange:v,quote:y})=>{if(y.serviceType!==e.ServiceType.AVALANCHE_CCT)throw new t.SdkError(t.ErrorReason.INCORRECT_PROVIDER_PROVIDED,t.ErrorCode.INVALID_PARAMS);let b=r.getEnvironmentIsTestnet(o),x=r.getChainAlias(y.sourceChain.chainId,b),S=r.getChainAlias(y.targetChain.chainId,b),C=u.getExportFromAddressEvm(y.fromAddress,x),w=x===`C`?void 0:u.assertXpAddress(y.fromAddress),T=await u.getExportToAddress({destinationChainAlias:S,getCoreEthAddress:c,quoteToAddress:y.toAddress}),E=u.getImportToAddress(y.toAddress,S),D=S===`C`?T:u.assertXpAddress(y.toAddress),O=y.amountIn>0n,k=O?2:1,A=Date.now(),j=f(y,o),M;if(O){v?.({currentSignature:1,currentSignatureReason:e.TransferSignatureReason.AvalancheCrossChainExport,quote:y,requiredSignatures:k});let c=await r.tryOrThrow(()=>h({ajsContext:n,environment:o,getUtxos:d,getWalletAddressesForChainAlias:m,getWalletChangeAddressForChainAlias:_,quoteAmountIn:y.amountIn,sourceChainAlias:x,destinationChainAlias:S,fromAddress:C,requiredFromAddress:w,toAddress:T}),e=>new t.SdkError(`Failed to build Avalanche export transaction.`,t.ErrorCode.UNKNOWN,{cause:e}));M=await r.tryOrThrow(()=>a({baseFeeInNanoAvax:c.baseFeeInNanoAvax,chainAlias:x,txType:`export`,unsignedTx:c.unsignedTx}),e=>new t.SdkError(`Failed to sign/send Avalanche export transaction.`,t.ErrorCode.SIGNING_FAILED,{cause:e}));let l;try{l=await s.pollPrimaryNetworkTxStatus({chainAlias:x,environment:o,txId:M})}catch{return i.sourcePendingTransferFromQuote(y,{environment:o,requiredConfirmationCount:1,startedAtMs:A,txHash:M})}if(!l)return p({errorCode:t.ErrorCode.TRANSACTION_REVERTED,errorReason:`Export transaction was not accepted by Avalanche.`,sourceStartedAtMs:A,sourceTxHash:M,transferBase:j})}let N=await r.tryOrThrow(async()=>(await l(S,x)).getUTXOs(),e=>new t.SdkError(`Failed to fetch Avalanche atomic UTXOs.`,t.ErrorCode.UNKNOWN,{cause:e}));if(N.length===0)return p({errorCode:t.ErrorCode.INVALID_PARAMS,errorReason:`No atomic UTXOs available to import for this route.`,sourceStartedAtMs:A,sourceTxHash:M,transferBase:j});v?.({currentSignature:O?2:1,currentSignatureReason:e.TransferSignatureReason.AvalancheCrossChainImport,quote:y,requiredSignatures:k});let P=await r.tryOrThrow(()=>g({ajsContext:n,atomicUtxos:N,destinationChainAlias:S,environment:o,getWalletAddressesForChainAlias:m,getWalletChangeAddressForChainAlias:_,sourceChainAlias:x,requiredFromAddress:D,toAddress:E}),e=>new t.SdkError(`Failed to build Avalanche import transaction.`,t.ErrorCode.UNKNOWN,{cause:e})),F=await r.tryOrThrow(()=>a({baseFeeInNanoAvax:P.baseFeeInNanoAvax,chainAlias:S,txType:`import`,unsignedTx:P.unsignedTx}),e=>new t.SdkError(`Failed to sign/send Avalanche import transaction.`,t.ErrorCode.SIGNING_FAILED,{cause:e}));return{...j,source:{confirmationCount:M?1:0,requiredConfirmationCount:1,startedAtMs:A,txHash:M??F},status:`target-pending`,target:{confirmationCount:0,requiredConfirmationCount:1,startedAtMs:Date.now(),txHash:F}}}}function f(e,t){return{amountIn:e.amountIn,amountOut:e.amountOut,environment:t,fees:e.fees,fromAddress:e.fromAddress,id:e.id,partnerFeeBps:e.partnerFeeBps,sourceAsset:e.assetIn,sourceChain:e.sourceChain,targetAsset:e.assetOut,targetChain:e.targetChain,toAddress:e.toAddress,type:e.serviceType}}function p({errorCode:e,errorReason:t,sourceStartedAtMs:n,sourceTxHash:r,transferBase:i}){return{...i,errorCode:e,errorReason:t,failedAtMs:Date.now(),...r?{source:{confirmationCount:0,requiredConfirmationCount:1,startedAtMs:n,txHash:r}}:{},status:`failed`}}function m(e,t){return e===`C`?t/n.WEI_PER_NANO_AVAX_BIGINT:t}async function h({ajsContext:n,destinationChainAlias:r,environment:i,fromAddress:s,getUtxos:d,getWalletAddressesForChainAlias:f,getWalletChangeAddressForChainAlias:p,quoteAmountIn:h,requiredFromAddress:g,sourceChainAlias:_,toAddress:v}){let y=m(_,h);switch(_){case`C`:{if(r===`C`)throw new t.InvalidParamsError(`Source and destination chain aliases must be different.`);if(!s)throw new t.InvalidParamsError(`fromAddress must be an EVM address when exporting from C-Chain.`);let o=a.getEvmClientForChain({chain:i===e.Environment.TEST?e.AVALANCHE_FUJI_CHAIN:e.AVALANCHE_MAINNET_CHAIN}),[u,d]=await Promise.all([o.getTransactionCount({address:s}),l.getCChainBaseFeeInNanoAvax(i)]);return{baseFeeInNanoAvax:d,unsignedTx:c.exportTx({amountInNanoAvax:y,baseFeeInNanoAvax:d,context:n,destinationChainAlias:r,fromAddress:s,nonce:BigInt(u),sourceChainAlias:_,toAddress:v})}}case`P`:{if(r===`P`)throw new t.InvalidParamsError(`Source and destination chain aliases must be different.`);let[e,a,s,l]=await Promise.all([u.getWalletChangeAddress({chainAlias:_,getWalletChangeAddressForChainAlias:p}),o.getFeeState(i),u.getWalletFromAddresses({chainAlias:_,getWalletAddressesForChainAlias:f,requiredAddress:g}),d(`P`)]);return{baseFeeInNanoAvax:a.price,unsignedTx:c.exportTx({amountInNanoAvax:y,changeAddress:e,context:n,destinationChainAlias:r,feeState:a,fromAddresses:s,sourceChainAlias:_,toAddress:v,utxos:l.getUTXOs()})}}case`X`:{if(r===`X`)throw new t.InvalidParamsError(`Source and destination chain aliases must be different.`);let[e,i,a]=await Promise.all([u.getWalletChangeAddress({chainAlias:_,getWalletChangeAddressForChainAlias:p}),u.getWalletFromAddresses({chainAlias:_,getWalletAddressesForChainAlias:f,requiredAddress:g}),d(`X`)]);return{baseFeeInNanoAvax:n.baseTxFee,unsignedTx:c.exportTx({amountInNanoAvax:y,changeAddress:e,context:n,destinationChainAlias:r,fromAddresses:i,sourceChainAlias:_,toAddress:v,utxos:a.getUTXOs()})}}}}async function g({ajsContext:e,atomicUtxos:n,destinationChainAlias:r,environment:i,getWalletAddressesForChainAlias:a,getWalletChangeAddressForChainAlias:s,requiredFromAddress:d,sourceChainAlias:f,toAddress:p}){switch(r){case`C`:{if(f===`C`)throw new t.InvalidParamsError(`Source and destination chain aliases must be different.`);let[o,s]=await Promise.all([l.getCChainBaseFeeInNanoAvax(i),u.getWalletFromAddresses({chainAlias:r,getWalletAddressesForChainAlias:a,requiredAddress:d})]);return{baseFeeInNanoAvax:o,unsignedTx:c.importTx({atomicUtxos:n,baseFeeInNanoAvax:o,context:e,destinationChainAlias:r,fromAddresses:s,sourceChainAlias:f,toAddress:u.getImportToAddress(p,`C`)})}}case`P`:{if(f===`P`)throw new t.InvalidParamsError(`Source and destination chain aliases must be different.`);let[s,l]=await Promise.all([o.getFeeState(i),u.getWalletFromAddresses({chainAlias:r,getWalletAddressesForChainAlias:a,requiredAddress:d})]);return{baseFeeInNanoAvax:s.price,unsignedTx:c.importTx({atomicUtxos:n,context:e,destinationChainAlias:r,feeState:s,fromAddresses:l,sourceChainAlias:f,toAddress:u.getImportToAddress(p,`P`)})}}case`X`:{if(f===`X`)throw new t.InvalidParamsError(`Source and destination chain aliases must be different.`);let[i,o]=await Promise.all([u.getWalletChangeAddress({chainAlias:r,getWalletChangeAddressForChainAlias:s}),u.getWalletFromAddresses({chainAlias:r,getWalletAddressesForChainAlias:a,requiredAddress:d})]);return{baseFeeInNanoAvax:e.baseTxFee,unsignedTx:c.importTx({atomicUtxos:n,changeAddress:i,context:e,destinationChainAlias:r,fromAddresses:o,sourceChainAlias:f,toAddress:u.getImportToAddress(p,`X`)})}}}}exports.transferAssetFactory=d;
1
+ const e=require(`../../../constants.cjs`),t=require(`../../../errors.cjs`),n=require(`../../_utils.cjs`),r=require(`../constants.cjs`),i=require(`../_utils.cjs`),a=require(`../../_transfer-utilities.cjs`),o=require(`../_utils/p-chain.cjs`),s=require(`../_utils/polling.cjs`),c=require(`../_utils/transactions.cjs`),l=require(`../_utils/fees.cjs`),u=require(`../_utils/addresses.cjs`);function d({ajsContext:n,avalancheSendTx:r,environment:o,getCoreEthAddress:c,getAtomicUtxos:l,getUtxos:d,getWalletAddressesForChainAlias:m,getWalletChangeAddressForChainAlias:_}){return async({onStepChange:v,quote:y})=>{if(y.serviceType!==e.ServiceType.AVALANCHE_CCT)throw new t.SdkError(t.ErrorReason.INCORRECT_PROVIDER_PROVIDED,t.ErrorCode.INVALID_PARAMS);let b=i.getEnvironmentIsTestnet(o),x=i.getChainAlias(y.sourceChain.chainId,b),S=i.getChainAlias(y.targetChain.chainId,b),C=u.getExportFromAddressEvm(y.fromAddress,x),w=x===`C`?void 0:u.assertXpAddress(y.fromAddress),T=await u.getExportToAddress({destinationChainAlias:S,getCoreEthAddress:c,quoteToAddress:y.toAddress}),E=u.getImportToAddress(y.toAddress,S),D=S===`C`?T:u.assertXpAddress(y.toAddress),O=y.amountIn>0n,k=O?2:1,A=Date.now(),j=f(y,o),M;if(O){v?.({currentSignature:1,currentSignatureReason:e.TransferSignatureReason.AvalancheCrossChainExport,quote:y,requiredSignatures:k});let c=await i.tryOrThrow(()=>h({ajsContext:n,environment:o,getUtxos:d,getWalletAddressesForChainAlias:m,getWalletChangeAddressForChainAlias:_,quoteAmountIn:y.amountIn,sourceChainAlias:x,destinationChainAlias:S,fromAddress:C,requiredFromAddress:w,toAddress:T}),e=>new t.SdkError(`Failed to build Avalanche export transaction.`,t.ErrorCode.UNKNOWN,{cause:e}));M=await i.tryOrThrow(()=>r({baseFeeInNanoAvax:c.baseFeeInNanoAvax,chainAlias:x,txType:`export`,unsignedTx:c.unsignedTx}),e=>new t.SdkError(`Failed to sign/send Avalanche export transaction.`,t.ErrorCode.SIGNING_FAILED,{cause:e}));let l;try{l=await s.pollPrimaryNetworkTxStatus({chainAlias:x,environment:o,txId:M})}catch{return a.sourcePendingTransferFromQuote(y,{environment:o,requiredConfirmationCount:1,startedAtMs:A,txHash:M})}if(!l)return p({errorCode:t.ErrorCode.TRANSACTION_REVERTED,errorReason:`Export transaction was not accepted by Avalanche.`,sourceStartedAtMs:A,sourceTxHash:M,transferBase:j})}let N=await i.tryOrThrow(async()=>(await l(S,x)).getUTXOs(),e=>new t.SdkError(`Failed to fetch Avalanche atomic UTXOs.`,t.ErrorCode.UNKNOWN,{cause:e}));if(N.length===0)return p({errorCode:t.ErrorCode.INVALID_PARAMS,errorReason:`No atomic UTXOs available to import for this route.`,sourceStartedAtMs:A,sourceTxHash:M,transferBase:j});v?.({currentSignature:O?2:1,currentSignatureReason:e.TransferSignatureReason.AvalancheCrossChainImport,quote:y,requiredSignatures:k});let P=await i.tryOrThrow(()=>g({ajsContext:n,atomicUtxos:N,destinationChainAlias:S,environment:o,getWalletAddressesForChainAlias:m,getWalletChangeAddressForChainAlias:_,sourceChainAlias:x,requiredFromAddress:D,toAddress:E}),e=>new t.SdkError(`Failed to build Avalanche import transaction.`,t.ErrorCode.UNKNOWN,{cause:e})),F=await i.tryOrThrow(()=>r({baseFeeInNanoAvax:P.baseFeeInNanoAvax,chainAlias:S,txType:`import`,unsignedTx:P.unsignedTx}),e=>new t.SdkError(`Failed to sign/send Avalanche import transaction.`,t.ErrorCode.SIGNING_FAILED,{cause:e}));return{...j,source:{confirmationCount:M?1:0,requiredConfirmationCount:1,startedAtMs:A,txHash:M??F},status:`target-pending`,target:{confirmationCount:0,requiredConfirmationCount:1,startedAtMs:Date.now(),txHash:F}}}}function f(e,t){return{amountIn:e.amountIn,amountOut:e.amountOut,environment:t,fees:e.fees,fromAddress:e.fromAddress,id:e.id,partnerFeeBps:e.partnerFeeBps,sourceAsset:e.assetIn,sourceChain:e.sourceChain,targetAsset:e.assetOut,targetChain:e.targetChain,toAddress:e.toAddress,type:e.serviceType}}function p({errorCode:e,errorReason:t,sourceStartedAtMs:n,sourceTxHash:r,transferBase:i}){return{...i,errorCode:e,errorReason:t,failedAtMs:Date.now(),...r?{source:{confirmationCount:0,requiredConfirmationCount:1,startedAtMs:n,txHash:r}}:{},status:`failed`}}function m(e,t){return e===`C`?t/r.WEI_PER_NANO_AVAX_BIGINT:t}async function h({ajsContext:r,destinationChainAlias:i,environment:a,fromAddress:s,getUtxos:d,getWalletAddressesForChainAlias:f,getWalletChangeAddressForChainAlias:p,quoteAmountIn:h,requiredFromAddress:g,sourceChainAlias:_,toAddress:v}){let y=m(_,h);switch(_){case`C`:{if(i===`C`)throw new t.InvalidParamsError(`Source and destination chain aliases must be different.`);if(!s)throw new t.InvalidParamsError(`fromAddress must be an EVM address when exporting from C-Chain.`);let o=n.getEvmClientForChain({chain:a===e.Environment.TEST?e.AVALANCHE_FUJI_CHAIN:e.AVALANCHE_MAINNET_CHAIN}),[u,d]=await Promise.all([o.getTransactionCount({address:s}),l.getCChainBaseFeeInNanoAvax(a)]);return{baseFeeInNanoAvax:d,unsignedTx:c.exportTx({amountInNanoAvax:y,baseFeeInNanoAvax:d,context:r,destinationChainAlias:i,fromAddress:s,nonce:BigInt(u),sourceChainAlias:_,toAddress:v})}}case`P`:{if(i===`P`)throw new t.InvalidParamsError(`Source and destination chain aliases must be different.`);let[e,n,s,l]=await Promise.all([u.getWalletChangeAddress({chainAlias:_,getWalletChangeAddressForChainAlias:p}),o.getFeeState(a),u.getWalletFromAddresses({chainAlias:_,getWalletAddressesForChainAlias:f,requiredAddress:g}),d(`P`)]);return{baseFeeInNanoAvax:n.price,unsignedTx:c.exportTx({amountInNanoAvax:y,changeAddress:e,context:r,destinationChainAlias:i,feeState:n,fromAddresses:s,sourceChainAlias:_,toAddress:v,utxos:l.getUTXOs()})}}case`X`:{if(i===`X`)throw new t.InvalidParamsError(`Source and destination chain aliases must be different.`);let[e,n,a]=await Promise.all([u.getWalletChangeAddress({chainAlias:_,getWalletChangeAddressForChainAlias:p}),u.getWalletFromAddresses({chainAlias:_,getWalletAddressesForChainAlias:f,requiredAddress:g}),d(`X`)]);return{baseFeeInNanoAvax:r.baseTxFee,unsignedTx:c.exportTx({amountInNanoAvax:y,changeAddress:e,context:r,destinationChainAlias:i,fromAddresses:n,sourceChainAlias:_,toAddress:v,utxos:a.getUTXOs()})}}}}async function g({ajsContext:e,atomicUtxos:n,destinationChainAlias:r,environment:i,getWalletAddressesForChainAlias:a,getWalletChangeAddressForChainAlias:s,requiredFromAddress:d,sourceChainAlias:f,toAddress:p}){switch(r){case`C`:{if(f===`C`)throw new t.InvalidParamsError(`Source and destination chain aliases must be different.`);let[o,s]=await Promise.all([l.getCChainBaseFeeInNanoAvax(i),u.getWalletFromAddresses({chainAlias:r,getWalletAddressesForChainAlias:a,requiredAddress:d})]);return{baseFeeInNanoAvax:o,unsignedTx:c.importTx({atomicUtxos:n,baseFeeInNanoAvax:o,context:e,destinationChainAlias:r,fromAddresses:s,sourceChainAlias:f,toAddress:u.getImportToAddress(p,`C`)})}}case`P`:{if(f===`P`)throw new t.InvalidParamsError(`Source and destination chain aliases must be different.`);let[s,l]=await Promise.all([o.getFeeState(i),u.getWalletFromAddresses({chainAlias:r,getWalletAddressesForChainAlias:a,requiredAddress:d})]);return{baseFeeInNanoAvax:s.price,unsignedTx:c.importTx({atomicUtxos:n,context:e,destinationChainAlias:r,feeState:s,fromAddresses:l,sourceChainAlias:f,toAddress:u.getImportToAddress(p,`P`)})}}case`X`:{if(f===`X`)throw new t.InvalidParamsError(`Source and destination chain aliases must be different.`);let[i,o]=await Promise.all([u.getWalletChangeAddress({chainAlias:r,getWalletChangeAddressForChainAlias:s}),u.getWalletFromAddresses({chainAlias:r,getWalletAddressesForChainAlias:a,requiredAddress:d})]);return{baseFeeInNanoAvax:e.baseTxFee,unsignedTx:c.importTx({atomicUtxos:n,changeAddress:i,context:e,destinationChainAlias:r,fromAddresses:o,sourceChainAlias:f,toAddress:u.getImportToAddress(p,`X`)})}}}}exports.transferAssetFactory=d;
2
2
  //# sourceMappingURL=transfer-asset.cjs.map
@@ -1,2 +1,2 @@
1
- import{AVALANCHE_FUJI_CHAIN as e,AVALANCHE_MAINNET_CHAIN as t,Environment as n,ServiceType as r,TransferSignatureReason as i}from"../../../constants.js";import{ErrorCode as a,ErrorReason as o,InvalidParamsError as s,SdkError as c}from"../../../errors.js";import{WEI_PER_NANO_AVAX_BIGINT as l}from"../constants.js";import{getChainAlias as u,getEnvironmentIsTestnet as d,tryOrThrow as f}from"../_utils.js";import{sourcePendingTransferFromQuote as p}from"../../_transfer-utilities.js";import{getEvmClientForChain as m}from"../../_utils.js";import{getFeeState as h}from"../_utils/p-chain.js";import{pollPrimaryNetworkTxStatus as g}from"../_utils/polling.js";import{exportTx as _,importTx as v}from"../_utils/transactions.js";import{getCChainBaseFeeInNanoAvax as y}from"../_utils/fees.js";import{assertXpAddress as b,getExportFromAddressEvm as x,getExportToAddress as S,getImportToAddress as C,getWalletChangeAddress as w,getWalletFromAddresses as T}from"../_utils/addresses.js";function E({ajsContext:e,avalancheSendTx:t,environment:n,getCoreEthAddress:s,getAtomicUtxos:l,getUtxos:m,getWalletAddressesForChainAlias:h,getWalletChangeAddressForChainAlias:_}){return async({onStepChange:v,quote:y})=>{if(y.serviceType!==r.AVALANCHE_CCT)throw new c(o.INCORRECT_PROVIDER_PROVIDED,a.INVALID_PARAMS);let w=d(n),T=u(y.sourceChain.chainId,w),E=u(y.targetChain.chainId,w),k=x(y.fromAddress,T),M=T===`C`?void 0:b(y.fromAddress),N=await S({destinationChainAlias:E,getCoreEthAddress:s,quoteToAddress:y.toAddress}),P=C(y.toAddress,E),F=E===`C`?N:b(y.toAddress),I=y.amountIn>0n,L=I?2:1,R=Date.now(),z=D(y,n),B;if(I){v?.({currentSignature:1,currentSignatureReason:i.AvalancheCrossChainExport,quote:y,requiredSignatures:L});let r=await f(()=>A({ajsContext:e,environment:n,getUtxos:m,getWalletAddressesForChainAlias:h,getWalletChangeAddressForChainAlias:_,quoteAmountIn:y.amountIn,sourceChainAlias:T,destinationChainAlias:E,fromAddress:k,requiredFromAddress:M,toAddress:N}),e=>new c(`Failed to build Avalanche export transaction.`,a.UNKNOWN,{cause:e}));B=await f(()=>t({baseFeeInNanoAvax:r.baseFeeInNanoAvax,chainAlias:T,txType:`export`,unsignedTx:r.unsignedTx}),e=>new c(`Failed to sign/send Avalanche export transaction.`,a.SIGNING_FAILED,{cause:e}));let o;try{o=await g({chainAlias:T,environment:n,txId:B})}catch{return p(y,{environment:n,requiredConfirmationCount:1,startedAtMs:R,txHash:B})}if(!o)return O({errorCode:a.TRANSACTION_REVERTED,errorReason:`Export transaction was not accepted by Avalanche.`,sourceStartedAtMs:R,sourceTxHash:B,transferBase:z})}let V=await f(async()=>(await l(E,T)).getUTXOs(),e=>new c(`Failed to fetch Avalanche atomic UTXOs.`,a.UNKNOWN,{cause:e}));if(V.length===0)return O({errorCode:a.INVALID_PARAMS,errorReason:`No atomic UTXOs available to import for this route.`,sourceStartedAtMs:R,sourceTxHash:B,transferBase:z});v?.({currentSignature:I?2:1,currentSignatureReason:i.AvalancheCrossChainImport,quote:y,requiredSignatures:L});let H=await f(()=>j({ajsContext:e,atomicUtxos:V,destinationChainAlias:E,environment:n,getWalletAddressesForChainAlias:h,getWalletChangeAddressForChainAlias:_,sourceChainAlias:T,requiredFromAddress:F,toAddress:P}),e=>new c(`Failed to build Avalanche import transaction.`,a.UNKNOWN,{cause:e})),U=await f(()=>t({baseFeeInNanoAvax:H.baseFeeInNanoAvax,chainAlias:E,txType:`import`,unsignedTx:H.unsignedTx}),e=>new c(`Failed to sign/send Avalanche import transaction.`,a.SIGNING_FAILED,{cause:e}));return{...z,source:{confirmationCount:B?1:0,requiredConfirmationCount:1,startedAtMs:R,txHash:B??U},status:`target-pending`,target:{confirmationCount:0,requiredConfirmationCount:1,startedAtMs:Date.now(),txHash:U}}}}function D(e,t){return{amountIn:e.amountIn,amountOut:e.amountOut,environment:t,fees:e.fees,fromAddress:e.fromAddress,id:e.id,partnerFeeBps:e.partnerFeeBps,sourceAsset:e.assetIn,sourceChain:e.sourceChain,targetAsset:e.assetOut,targetChain:e.targetChain,toAddress:e.toAddress,type:e.serviceType}}function O({errorCode:e,errorReason:t,sourceStartedAtMs:n,sourceTxHash:r,transferBase:i}){return{...i,errorCode:e,errorReason:t,failedAtMs:Date.now(),...r?{source:{confirmationCount:0,requiredConfirmationCount:1,startedAtMs:n,txHash:r}}:{},status:`failed`}}function k(e,t){return e===`C`?t/l:t}async function A({ajsContext:r,destinationChainAlias:i,environment:a,fromAddress:o,getUtxos:c,getWalletAddressesForChainAlias:l,getWalletChangeAddressForChainAlias:u,quoteAmountIn:d,requiredFromAddress:f,sourceChainAlias:p,toAddress:g}){let v=k(p,d);switch(p){case`C`:{if(i===`C`)throw new s(`Source and destination chain aliases must be different.`);if(!o)throw new s(`fromAddress must be an EVM address when exporting from C-Chain.`);let c=m({chain:a===n.TEST?e:t}),[l,u]=await Promise.all([c.getTransactionCount({address:o}),y(a)]);return{baseFeeInNanoAvax:u,unsignedTx:_({amountInNanoAvax:v,baseFeeInNanoAvax:u,context:r,destinationChainAlias:i,fromAddress:o,nonce:BigInt(l),sourceChainAlias:p,toAddress:g})}}case`P`:{if(i===`P`)throw new s(`Source and destination chain aliases must be different.`);let[e,t,n,o]=await Promise.all([w({chainAlias:p,getWalletChangeAddressForChainAlias:u}),h(a),T({chainAlias:p,getWalletAddressesForChainAlias:l,requiredAddress:f}),c(`P`)]);return{baseFeeInNanoAvax:t.price,unsignedTx:_({amountInNanoAvax:v,changeAddress:e,context:r,destinationChainAlias:i,feeState:t,fromAddresses:n,sourceChainAlias:p,toAddress:g,utxos:o.getUTXOs()})}}case`X`:{if(i===`X`)throw new s(`Source and destination chain aliases must be different.`);let[e,t,n]=await Promise.all([w({chainAlias:p,getWalletChangeAddressForChainAlias:u}),T({chainAlias:p,getWalletAddressesForChainAlias:l,requiredAddress:f}),c(`X`)]);return{baseFeeInNanoAvax:r.baseTxFee,unsignedTx:_({amountInNanoAvax:v,changeAddress:e,context:r,destinationChainAlias:i,fromAddresses:t,sourceChainAlias:p,toAddress:g,utxos:n.getUTXOs()})}}}}async function j({ajsContext:e,atomicUtxos:t,destinationChainAlias:n,environment:r,getWalletAddressesForChainAlias:i,getWalletChangeAddressForChainAlias:a,requiredFromAddress:o,sourceChainAlias:c,toAddress:l}){switch(n){case`C`:{if(c===`C`)throw new s(`Source and destination chain aliases must be different.`);let[a,u]=await Promise.all([y(r),T({chainAlias:n,getWalletAddressesForChainAlias:i,requiredAddress:o})]);return{baseFeeInNanoAvax:a,unsignedTx:v({atomicUtxos:t,baseFeeInNanoAvax:a,context:e,destinationChainAlias:n,fromAddresses:u,sourceChainAlias:c,toAddress:C(l,`C`)})}}case`P`:{if(c===`P`)throw new s(`Source and destination chain aliases must be different.`);let[a,u]=await Promise.all([h(r),T({chainAlias:n,getWalletAddressesForChainAlias:i,requiredAddress:o})]);return{baseFeeInNanoAvax:a.price,unsignedTx:v({atomicUtxos:t,context:e,destinationChainAlias:n,feeState:a,fromAddresses:u,sourceChainAlias:c,toAddress:C(l,`P`)})}}case`X`:{if(c===`X`)throw new s(`Source and destination chain aliases must be different.`);let[r,u]=await Promise.all([w({chainAlias:n,getWalletChangeAddressForChainAlias:a}),T({chainAlias:n,getWalletAddressesForChainAlias:i,requiredAddress:o})]);return{baseFeeInNanoAvax:e.baseTxFee,unsignedTx:v({atomicUtxos:t,changeAddress:r,context:e,destinationChainAlias:n,fromAddresses:u,sourceChainAlias:c,toAddress:C(l,`X`)})}}}}export{E as transferAssetFactory};
1
+ import{AVALANCHE_FUJI_CHAIN as e,AVALANCHE_MAINNET_CHAIN as t,Environment as n,ServiceType as r,TransferSignatureReason as i}from"../../../constants.js";import{ErrorCode as a,ErrorReason as o,InvalidParamsError as s,SdkError as c}from"../../../errors.js";import{getEvmClientForChain as l}from"../../_utils.js";import{WEI_PER_NANO_AVAX_BIGINT as u}from"../constants.js";import{getChainAlias as d,getEnvironmentIsTestnet as f,tryOrThrow as p}from"../_utils.js";import{sourcePendingTransferFromQuote as m}from"../../_transfer-utilities.js";import{getFeeState as h}from"../_utils/p-chain.js";import{pollPrimaryNetworkTxStatus as g}from"../_utils/polling.js";import{exportTx as _,importTx as v}from"../_utils/transactions.js";import{getCChainBaseFeeInNanoAvax as y}from"../_utils/fees.js";import{assertXpAddress as b,getExportFromAddressEvm as x,getExportToAddress as S,getImportToAddress as C,getWalletChangeAddress as w,getWalletFromAddresses as T}from"../_utils/addresses.js";function E({ajsContext:e,avalancheSendTx:t,environment:n,getCoreEthAddress:s,getAtomicUtxos:l,getUtxos:u,getWalletAddressesForChainAlias:h,getWalletChangeAddressForChainAlias:_}){return async({onStepChange:v,quote:y})=>{if(y.serviceType!==r.AVALANCHE_CCT)throw new c(o.INCORRECT_PROVIDER_PROVIDED,a.INVALID_PARAMS);let w=f(n),T=d(y.sourceChain.chainId,w),E=d(y.targetChain.chainId,w),k=x(y.fromAddress,T),M=T===`C`?void 0:b(y.fromAddress),N=await S({destinationChainAlias:E,getCoreEthAddress:s,quoteToAddress:y.toAddress}),P=C(y.toAddress,E),F=E===`C`?N:b(y.toAddress),I=y.amountIn>0n,L=I?2:1,R=Date.now(),z=D(y,n),B;if(I){v?.({currentSignature:1,currentSignatureReason:i.AvalancheCrossChainExport,quote:y,requiredSignatures:L});let r=await p(()=>A({ajsContext:e,environment:n,getUtxos:u,getWalletAddressesForChainAlias:h,getWalletChangeAddressForChainAlias:_,quoteAmountIn:y.amountIn,sourceChainAlias:T,destinationChainAlias:E,fromAddress:k,requiredFromAddress:M,toAddress:N}),e=>new c(`Failed to build Avalanche export transaction.`,a.UNKNOWN,{cause:e}));B=await p(()=>t({baseFeeInNanoAvax:r.baseFeeInNanoAvax,chainAlias:T,txType:`export`,unsignedTx:r.unsignedTx}),e=>new c(`Failed to sign/send Avalanche export transaction.`,a.SIGNING_FAILED,{cause:e}));let o;try{o=await g({chainAlias:T,environment:n,txId:B})}catch{return m(y,{environment:n,requiredConfirmationCount:1,startedAtMs:R,txHash:B})}if(!o)return O({errorCode:a.TRANSACTION_REVERTED,errorReason:`Export transaction was not accepted by Avalanche.`,sourceStartedAtMs:R,sourceTxHash:B,transferBase:z})}let V=await p(async()=>(await l(E,T)).getUTXOs(),e=>new c(`Failed to fetch Avalanche atomic UTXOs.`,a.UNKNOWN,{cause:e}));if(V.length===0)return O({errorCode:a.INVALID_PARAMS,errorReason:`No atomic UTXOs available to import for this route.`,sourceStartedAtMs:R,sourceTxHash:B,transferBase:z});v?.({currentSignature:I?2:1,currentSignatureReason:i.AvalancheCrossChainImport,quote:y,requiredSignatures:L});let H=await p(()=>j({ajsContext:e,atomicUtxos:V,destinationChainAlias:E,environment:n,getWalletAddressesForChainAlias:h,getWalletChangeAddressForChainAlias:_,sourceChainAlias:T,requiredFromAddress:F,toAddress:P}),e=>new c(`Failed to build Avalanche import transaction.`,a.UNKNOWN,{cause:e})),U=await p(()=>t({baseFeeInNanoAvax:H.baseFeeInNanoAvax,chainAlias:E,txType:`import`,unsignedTx:H.unsignedTx}),e=>new c(`Failed to sign/send Avalanche import transaction.`,a.SIGNING_FAILED,{cause:e}));return{...z,source:{confirmationCount:B?1:0,requiredConfirmationCount:1,startedAtMs:R,txHash:B??U},status:`target-pending`,target:{confirmationCount:0,requiredConfirmationCount:1,startedAtMs:Date.now(),txHash:U}}}}function D(e,t){return{amountIn:e.amountIn,amountOut:e.amountOut,environment:t,fees:e.fees,fromAddress:e.fromAddress,id:e.id,partnerFeeBps:e.partnerFeeBps,sourceAsset:e.assetIn,sourceChain:e.sourceChain,targetAsset:e.assetOut,targetChain:e.targetChain,toAddress:e.toAddress,type:e.serviceType}}function O({errorCode:e,errorReason:t,sourceStartedAtMs:n,sourceTxHash:r,transferBase:i}){return{...i,errorCode:e,errorReason:t,failedAtMs:Date.now(),...r?{source:{confirmationCount:0,requiredConfirmationCount:1,startedAtMs:n,txHash:r}}:{},status:`failed`}}function k(e,t){return e===`C`?t/u:t}async function A({ajsContext:r,destinationChainAlias:i,environment:a,fromAddress:o,getUtxos:c,getWalletAddressesForChainAlias:u,getWalletChangeAddressForChainAlias:d,quoteAmountIn:f,requiredFromAddress:p,sourceChainAlias:m,toAddress:g}){let v=k(m,f);switch(m){case`C`:{if(i===`C`)throw new s(`Source and destination chain aliases must be different.`);if(!o)throw new s(`fromAddress must be an EVM address when exporting from C-Chain.`);let c=l({chain:a===n.TEST?e:t}),[u,d]=await Promise.all([c.getTransactionCount({address:o}),y(a)]);return{baseFeeInNanoAvax:d,unsignedTx:_({amountInNanoAvax:v,baseFeeInNanoAvax:d,context:r,destinationChainAlias:i,fromAddress:o,nonce:BigInt(u),sourceChainAlias:m,toAddress:g})}}case`P`:{if(i===`P`)throw new s(`Source and destination chain aliases must be different.`);let[e,t,n,o]=await Promise.all([w({chainAlias:m,getWalletChangeAddressForChainAlias:d}),h(a),T({chainAlias:m,getWalletAddressesForChainAlias:u,requiredAddress:p}),c(`P`)]);return{baseFeeInNanoAvax:t.price,unsignedTx:_({amountInNanoAvax:v,changeAddress:e,context:r,destinationChainAlias:i,feeState:t,fromAddresses:n,sourceChainAlias:m,toAddress:g,utxos:o.getUTXOs()})}}case`X`:{if(i===`X`)throw new s(`Source and destination chain aliases must be different.`);let[e,t,n]=await Promise.all([w({chainAlias:m,getWalletChangeAddressForChainAlias:d}),T({chainAlias:m,getWalletAddressesForChainAlias:u,requiredAddress:p}),c(`X`)]);return{baseFeeInNanoAvax:r.baseTxFee,unsignedTx:_({amountInNanoAvax:v,changeAddress:e,context:r,destinationChainAlias:i,fromAddresses:t,sourceChainAlias:m,toAddress:g,utxos:n.getUTXOs()})}}}}async function j({ajsContext:e,atomicUtxos:t,destinationChainAlias:n,environment:r,getWalletAddressesForChainAlias:i,getWalletChangeAddressForChainAlias:a,requiredFromAddress:o,sourceChainAlias:c,toAddress:l}){switch(n){case`C`:{if(c===`C`)throw new s(`Source and destination chain aliases must be different.`);let[a,u]=await Promise.all([y(r),T({chainAlias:n,getWalletAddressesForChainAlias:i,requiredAddress:o})]);return{baseFeeInNanoAvax:a,unsignedTx:v({atomicUtxos:t,baseFeeInNanoAvax:a,context:e,destinationChainAlias:n,fromAddresses:u,sourceChainAlias:c,toAddress:C(l,`C`)})}}case`P`:{if(c===`P`)throw new s(`Source and destination chain aliases must be different.`);let[a,u]=await Promise.all([h(r),T({chainAlias:n,getWalletAddressesForChainAlias:i,requiredAddress:o})]);return{baseFeeInNanoAvax:a.price,unsignedTx:v({atomicUtxos:t,context:e,destinationChainAlias:n,feeState:a,fromAddresses:u,sourceChainAlias:c,toAddress:C(l,`P`)})}}case`X`:{if(c===`X`)throw new s(`Source and destination chain aliases must be different.`);let[r,u]=await Promise.all([w({chainAlias:n,getWalletChangeAddressForChainAlias:a}),T({chainAlias:n,getWalletAddressesForChainAlias:i,requiredAddress:o})]);return{baseFeeInNanoAvax:e.baseTxFee,unsignedTx:v({atomicUtxos:t,changeAddress:r,context:e,destinationChainAlias:n,fromAddresses:u,sourceChainAlias:c,toAddress:C(l,`X`)})}}}}export{E as transferAssetFactory};
2
2
  //# sourceMappingURL=transfer-asset.js.map
@@ -1,2 +1,2 @@
1
- require(`../../../_virtual/_rolldown/runtime.cjs`);const e=require(`../../../constants.cjs`),t=require(`../../../errors.cjs`),n=require(`../constants.cjs`),r=require(`../../_utils.cjs`),i=require(`./p-chain.cjs`),a=require(`../../_evm-gas.cjs`);let o=require(`@avalabs/avalanchejs`);function s(e,n){if(!Number.isInteger(e)||e<=0)throw new t.InvalidParamsError(`Expected a positive integer greater than 0 for ${n}, but received: ${e}`)}function c(e=1,t=1){return s(e,`numberInputs`),s(t,`numberSignatures`),78n+BigInt(e)*90n+1n*60n+BigInt(t)*1000n+10000n}function l(e,t){return s(e,`numberInputs`),o.Common.dimensionsToGas(o.Common.createDimensions({bandwidth:161*e+254,dbRead:e,dbWrite:2+e,compute:200*e}),t)}function u(e,t){return s(e,`numberInputs`),o.Common.dimensionsToGas(o.Common.createDimensions({bandwidth:161*e+174,dbRead:e,dbWrite:1+e,compute:200*e}),t)}function d(e,t){let i=(r.applyFeeUnitsBpsMargin(e,t)+n.WEI_PER_NANO_AVAX_BIGINT-1n)/n.WEI_PER_NANO_AVAX_BIGINT;return i<=0n?1n:i}async function f(t){let n=(await a.fetchSuggestedGasPrices(r.getEvmClientForChain({chain:t===e.Environment.TEST?e.AVALANCHE_FUJI_CHAIN:e.AVALANCHE_MAINNET_CHAIN}))).fast.maxFeePerGas;return d(n,void 0)}function p({feeUnitsMarginBps:e,maxFeePerGas:t}){return d(t,e)*11230n}function m({feeUnitsMarginBps:e,maxFeePerGas:t,numberInputs:n,numberSignatures:r}){return d(t,e)*c(n,r)}async function h({context:e,environment:t,numberInputs:n}){let{price:r}=await i.getFeeState(t);return r*l(n,e.platformFeeConfig.weights)}async function g({context:e,environment:t,numberInputs:n}){let{price:r}=await i.getFeeState(t);return r*u(n,e.platformFeeConfig.weights)}function _({context:e}){return e.baseTxFee}function v({context:e}){return e.baseTxFee}async function y(e,n){let{context:r,environment:i,feeUnitsMarginBps:a,maxFeePerGas:o,numberInputs:s}=n;switch(e){case`C`:return p({feeUnitsMarginBps:a,maxFeePerGas:o});case`P`:return await h({context:r,environment:i,numberInputs:s});case`X`:return _({context:r});default:throw new t.InvalidParamsError(`Unsupported chain alias: ${e}`)}}async function b(e,n){let{context:r,environment:i,feeUnitsMarginBps:a,maxFeePerGas:o,numberInputs:s,numberSignatures:c}=n;switch(e){case`C`:return m({feeUnitsMarginBps:a,maxFeePerGas:o,numberInputs:s,numberSignatures:c});case`P`:return await g({context:r,environment:i,numberInputs:s});case`X`:return v({context:r});default:throw new t.InvalidParamsError(`Unsupported chain alias: ${e}`)}}exports.getCChainBaseFeeInNanoAvax=f,exports.getExportFeeInNanoAvax=y,exports.getImportFeeInNanoAvax=b;
1
+ require(`../../../_virtual/_rolldown/runtime.cjs`);const e=require(`../../../constants.cjs`),t=require(`../../../errors.cjs`),n=require(`../../_utils.cjs`),r=require(`../constants.cjs`),i=require(`./p-chain.cjs`),a=require(`../../_evm-gas.cjs`);let o=require(`@avalabs/avalanchejs`);function s(e,n){if(!Number.isInteger(e)||e<=0)throw new t.InvalidParamsError(`Expected a positive integer greater than 0 for ${n}, but received: ${e}`)}function c(e=1,t=1){return s(e,`numberInputs`),s(t,`numberSignatures`),78n+BigInt(e)*90n+1n*60n+BigInt(t)*1000n+10000n}function l(e,t){return s(e,`numberInputs`),o.Common.dimensionsToGas(o.Common.createDimensions({bandwidth:161*e+254,dbRead:e,dbWrite:2+e,compute:200*e}),t)}function u(e,t){return s(e,`numberInputs`),o.Common.dimensionsToGas(o.Common.createDimensions({bandwidth:161*e+174,dbRead:e,dbWrite:1+e,compute:200*e}),t)}function d(e,t){let i=(n.applyFeeUnitsBpsMargin(e,t)+r.WEI_PER_NANO_AVAX_BIGINT-1n)/r.WEI_PER_NANO_AVAX_BIGINT;return i<=0n?1n:i}async function f(t){let r=(await a.fetchSuggestedGasPrices(n.getEvmClientForChain({chain:t===e.Environment.TEST?e.AVALANCHE_FUJI_CHAIN:e.AVALANCHE_MAINNET_CHAIN}))).fast.maxFeePerGas;return d(r,void 0)}function p({feeUnitsMarginBps:e,maxFeePerGas:t}){return d(t,e)*11230n}function m({feeUnitsMarginBps:e,maxFeePerGas:t,numberInputs:n,numberSignatures:r}){return d(t,e)*c(n,r)}async function h({context:e,environment:t,numberInputs:n}){let{price:r}=await i.getFeeState(t);return r*l(n,e.platformFeeConfig.weights)}async function g({context:e,environment:t,numberInputs:n}){let{price:r}=await i.getFeeState(t);return r*u(n,e.platformFeeConfig.weights)}function _({context:e}){return e.baseTxFee}function v({context:e}){return e.baseTxFee}async function y(e,n){let{context:r,environment:i,feeUnitsMarginBps:a,maxFeePerGas:o,numberInputs:s}=n;switch(e){case`C`:return p({feeUnitsMarginBps:a,maxFeePerGas:o});case`P`:return await h({context:r,environment:i,numberInputs:s});case`X`:return _({context:r});default:throw new t.InvalidParamsError(`Unsupported chain alias: ${e}`)}}async function b(e,n){let{context:r,environment:i,feeUnitsMarginBps:a,maxFeePerGas:o,numberInputs:s,numberSignatures:c}=n;switch(e){case`C`:return m({feeUnitsMarginBps:a,maxFeePerGas:o,numberInputs:s,numberSignatures:c});case`P`:return await g({context:r,environment:i,numberInputs:s});case`X`:return v({context:r});default:throw new t.InvalidParamsError(`Unsupported chain alias: ${e}`)}}exports.getCChainBaseFeeInNanoAvax=f,exports.getExportFeeInNanoAvax=y,exports.getImportFeeInNanoAvax=b;
2
2
  //# sourceMappingURL=fees.cjs.map
@@ -1,2 +1,2 @@
1
- import{AVALANCHE_FUJI_CHAIN as e,AVALANCHE_MAINNET_CHAIN as t,Environment as n}from"../../../constants.js";import{InvalidParamsError as r}from"../../../errors.js";import{WEI_PER_NANO_AVAX_BIGINT as i}from"../constants.js";import{applyFeeUnitsBpsMargin as a,getEvmClientForChain as o}from"../../_utils.js";import{getFeeState as s}from"./p-chain.js";import{fetchSuggestedGasPrices as c}from"../../_evm-gas.js";import{Common as l}from"@avalabs/avalanchejs";function u(e,t){if(!Number.isInteger(e)||e<=0)throw new r(`Expected a positive integer greater than 0 for ${t}, but received: ${e}`)}function d(e=1,t=1){return u(e,`numberInputs`),u(t,`numberSignatures`),78n+BigInt(e)*90n+1n*60n+BigInt(t)*1000n+10000n}function f(e,t){return u(e,`numberInputs`),l.dimensionsToGas(l.createDimensions({bandwidth:161*e+254,dbRead:e,dbWrite:2+e,compute:200*e}),t)}function p(e,t){return u(e,`numberInputs`),l.dimensionsToGas(l.createDimensions({bandwidth:161*e+174,dbRead:e,dbWrite:1+e,compute:200*e}),t)}function m(e,t){let n=(a(e,t)+i-1n)/i;return n<=0n?1n:n}async function h(r){let i=(await c(o({chain:r===n.TEST?e:t}))).fast.maxFeePerGas;return m(i,void 0)}function g({feeUnitsMarginBps:e,maxFeePerGas:t}){return m(t,e)*11230n}function _({feeUnitsMarginBps:e,maxFeePerGas:t,numberInputs:n,numberSignatures:r}){return m(t,e)*d(n,r)}async function v({context:e,environment:t,numberInputs:n}){let{price:r}=await s(t);return r*f(n,e.platformFeeConfig.weights)}async function y({context:e,environment:t,numberInputs:n}){let{price:r}=await s(t);return r*p(n,e.platformFeeConfig.weights)}function b({context:e}){return e.baseTxFee}function x({context:e}){return e.baseTxFee}async function S(e,t){let{context:n,environment:i,feeUnitsMarginBps:a,maxFeePerGas:o,numberInputs:s}=t;switch(e){case`C`:return g({feeUnitsMarginBps:a,maxFeePerGas:o});case`P`:return await v({context:n,environment:i,numberInputs:s});case`X`:return b({context:n});default:throw new r(`Unsupported chain alias: ${e}`)}}async function C(e,t){let{context:n,environment:i,feeUnitsMarginBps:a,maxFeePerGas:o,numberInputs:s,numberSignatures:c}=t;switch(e){case`C`:return _({feeUnitsMarginBps:a,maxFeePerGas:o,numberInputs:s,numberSignatures:c});case`P`:return await y({context:n,environment:i,numberInputs:s});case`X`:return x({context:n});default:throw new r(`Unsupported chain alias: ${e}`)}}export{h as getCChainBaseFeeInNanoAvax,S as getExportFeeInNanoAvax,C as getImportFeeInNanoAvax};
1
+ import{AVALANCHE_FUJI_CHAIN as e,AVALANCHE_MAINNET_CHAIN as t,Environment as n}from"../../../constants.js";import{InvalidParamsError as r}from"../../../errors.js";import{applyFeeUnitsBpsMargin as i,getEvmClientForChain as a}from"../../_utils.js";import{WEI_PER_NANO_AVAX_BIGINT as o}from"../constants.js";import{getFeeState as s}from"./p-chain.js";import{fetchSuggestedGasPrices as c}from"../../_evm-gas.js";import{Common as l}from"@avalabs/avalanchejs";function u(e,t){if(!Number.isInteger(e)||e<=0)throw new r(`Expected a positive integer greater than 0 for ${t}, but received: ${e}`)}function d(e=1,t=1){return u(e,`numberInputs`),u(t,`numberSignatures`),78n+BigInt(e)*90n+1n*60n+BigInt(t)*1000n+10000n}function f(e,t){return u(e,`numberInputs`),l.dimensionsToGas(l.createDimensions({bandwidth:161*e+254,dbRead:e,dbWrite:2+e,compute:200*e}),t)}function p(e,t){return u(e,`numberInputs`),l.dimensionsToGas(l.createDimensions({bandwidth:161*e+174,dbRead:e,dbWrite:1+e,compute:200*e}),t)}function m(e,t){let n=(i(e,t)+o-1n)/o;return n<=0n?1n:n}async function h(r){let i=(await c(a({chain:r===n.TEST?e:t}))).fast.maxFeePerGas;return m(i,void 0)}function g({feeUnitsMarginBps:e,maxFeePerGas:t}){return m(t,e)*11230n}function _({feeUnitsMarginBps:e,maxFeePerGas:t,numberInputs:n,numberSignatures:r}){return m(t,e)*d(n,r)}async function v({context:e,environment:t,numberInputs:n}){let{price:r}=await s(t);return r*f(n,e.platformFeeConfig.weights)}async function y({context:e,environment:t,numberInputs:n}){let{price:r}=await s(t);return r*p(n,e.platformFeeConfig.weights)}function b({context:e}){return e.baseTxFee}function x({context:e}){return e.baseTxFee}async function S(e,t){let{context:n,environment:i,feeUnitsMarginBps:a,maxFeePerGas:o,numberInputs:s}=t;switch(e){case`C`:return g({feeUnitsMarginBps:a,maxFeePerGas:o});case`P`:return await v({context:n,environment:i,numberInputs:s});case`X`:return b({context:n});default:throw new r(`Unsupported chain alias: ${e}`)}}async function C(e,t){let{context:n,environment:i,feeUnitsMarginBps:a,maxFeePerGas:o,numberInputs:s,numberSignatures:c}=t;switch(e){case`C`:return _({feeUnitsMarginBps:a,maxFeePerGas:o,numberInputs:s,numberSignatures:c});case`P`:return await y({context:n,environment:i,numberInputs:s});case`X`:return x({context:n});default:throw new r(`Unsupported chain alias: ${e}`)}}export{h as getCChainBaseFeeInNanoAvax,S as getExportFeeInNanoAvax,C as getImportFeeInNanoAvax};
2
2
  //# sourceMappingURL=fees.js.map
@@ -1,2 +1,2 @@
1
- const e=require(`../../../errors.cjs`),t=require(`../_utils.cjs`),n=require(`../../_utils.cjs`);function r(n,r){switch(r){case`C`:return e=>t.getAvalancheProvider(n,r).getAtomicTxStatus(e);case`P`:return e=>t.getAvalancheProvider(n,r).getTxStatus({txID:e});case`X`:return e=>t.getAvalancheProvider(n,r).getTxStatus({txID:e});default:throw new e.InvalidParamsError(`Unsupported chain alias: ${r}`,`Can not get transaction status function for unsupported chain alias.`)}}async function i({chainAlias:t,count:a=13,environment:o,signal:s,txId:c}){if(a<0)return!1;try{let{status:e}=await r(o,t)(c);switch(e){case`Accepted`:case`Committed`:return!0;case`Dropped`:case`Rejected`:return!1;default:break}return await n.wait(1500*1.2**(13-a),s),await i({chainAlias:t,count:a-1,environment:o,signal:s,txId:c})}catch(t){throw new e.SdkError(`Failed to poll transaction status from Avalanche.`,e.ErrorCode.UNKNOWN,{cause:t})}}exports.pollPrimaryNetworkTxStatus=i;
1
+ const e=require(`../../../errors.cjs`),t=require(`../../_utils.cjs`),n=require(`../_utils.cjs`);function r(t,r){switch(r){case`C`:return e=>n.getAvalancheProvider(t,r).getAtomicTxStatus(e);case`P`:return e=>n.getAvalancheProvider(t,r).getTxStatus({txID:e});case`X`:return e=>n.getAvalancheProvider(t,r).getTxStatus({txID:e});default:throw new e.InvalidParamsError(`Unsupported chain alias: ${r}`,`Can not get transaction status function for unsupported chain alias.`)}}async function i({chainAlias:n,count:a=13,environment:o,signal:s,txId:c}){if(a<0)return!1;try{let{status:e}=await r(o,n)(c);switch(e){case`Accepted`:case`Committed`:return!0;case`Dropped`:case`Rejected`:return!1;default:break}return await t.wait(1500*1.2**(13-a),s),await i({chainAlias:n,count:a-1,environment:o,signal:s,txId:c})}catch(t){throw new e.SdkError(`Failed to poll transaction status from Avalanche.`,e.ErrorCode.UNKNOWN,{cause:t})}}exports.pollPrimaryNetworkTxStatus=i;
2
2
  //# sourceMappingURL=polling.cjs.map
@@ -1,2 +1,2 @@
1
- import{ErrorCode as e,InvalidParamsError as t,SdkError as n}from"../../../errors.js";import{getAvalancheProvider as r}from"../_utils.js";import{wait as i}from"../../_utils.js";function a(e,n){switch(n){case`C`:return t=>r(e,n).getAtomicTxStatus(t);case`P`:return t=>r(e,n).getTxStatus({txID:t});case`X`:return t=>r(e,n).getTxStatus({txID:t});default:throw new t(`Unsupported chain alias: ${n}`,`Can not get transaction status function for unsupported chain alias.`)}}async function o({chainAlias:t,count:r=13,environment:s,signal:c,txId:l}){if(r<0)return!1;try{let{status:e}=await a(s,t)(l);switch(e){case`Accepted`:case`Committed`:return!0;case`Dropped`:case`Rejected`:return!1;default:break}return await i(1500*1.2**(13-r),c),await o({chainAlias:t,count:r-1,environment:s,signal:c,txId:l})}catch(t){throw new n(`Failed to poll transaction status from Avalanche.`,e.UNKNOWN,{cause:t})}}export{o as pollPrimaryNetworkTxStatus};
1
+ import{ErrorCode as e,InvalidParamsError as t,SdkError as n}from"../../../errors.js";import{wait as r}from"../../_utils.js";import{getAvalancheProvider as i}from"../_utils.js";function a(e,n){switch(n){case`C`:return t=>i(e,n).getAtomicTxStatus(t);case`P`:return t=>i(e,n).getTxStatus({txID:t});case`X`:return t=>i(e,n).getTxStatus({txID:t});default:throw new t(`Unsupported chain alias: ${n}`,`Can not get transaction status function for unsupported chain alias.`)}}async function o({chainAlias:t,count:i=13,environment:s,signal:c,txId:l}){if(i<0)return!1;try{let{status:e}=await a(s,t)(l);switch(e){case`Accepted`:case`Committed`:return!0;case`Dropped`:case`Rejected`:return!1;default:break}return await r(1500*1.2**(13-i),c),await o({chainAlias:t,count:i-1,environment:s,signal:c,txId:l})}catch(t){throw new n(`Failed to poll transaction status from Avalanche.`,e.UNKNOWN,{cause:t})}}export{o as pollPrimaryNetworkTxStatus};
2
2
  //# sourceMappingURL=polling.js.map