@avalabs/fusion-sdk 0.6.0 → 0.7.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 (91) hide show
  1. package/dist/constants.cjs +1 -1
  2. package/dist/constants.cjs.map +1 -1
  3. package/dist/constants.js +1 -1
  4. package/dist/constants.js.map +1 -1
  5. package/dist/mod.d.cts +3 -3
  6. package/dist/mod.d.ts +3 -3
  7. package/dist/transfer-manager.cjs +1 -1
  8. package/dist/transfer-manager.cjs.map +1 -1
  9. package/dist/transfer-manager.js +1 -1
  10. package/dist/transfer-manager.js.map +1 -1
  11. package/dist/transfer-service/avalanche-evm/_handlers/get-bridgeable-assets.cjs +2 -0
  12. package/dist/transfer-service/avalanche-evm/_handlers/get-bridgeable-assets.cjs.map +1 -0
  13. package/dist/transfer-service/avalanche-evm/_handlers/get-bridgeable-assets.js +2 -0
  14. package/dist/transfer-service/avalanche-evm/_handlers/get-bridgeable-assets.js.map +1 -0
  15. package/dist/transfer-service/avalanche-evm/avalanche-evm-service.cjs +1 -1
  16. package/dist/transfer-service/avalanche-evm/avalanche-evm-service.cjs.map +1 -1
  17. package/dist/transfer-service/avalanche-evm/avalanche-evm-service.js +1 -1
  18. package/dist/transfer-service/avalanche-evm/avalanche-evm-service.js.map +1 -1
  19. package/dist/transfer-service/lombard/_utils/asset.cjs +1 -1
  20. package/dist/transfer-service/lombard/_utils/asset.cjs.map +1 -1
  21. package/dist/transfer-service/lombard/_utils/asset.js +1 -1
  22. package/dist/transfer-service/lombard/_utils/asset.js.map +1 -1
  23. package/dist/transfer-service/lombard/btc-to-btcb/_handlers/get-bridgeable-assets.cjs +2 -0
  24. package/dist/transfer-service/lombard/btc-to-btcb/_handlers/get-bridgeable-assets.cjs.map +1 -0
  25. package/dist/transfer-service/lombard/btc-to-btcb/_handlers/get-bridgeable-assets.js +2 -0
  26. package/dist/transfer-service/lombard/btc-to-btcb/_handlers/get-bridgeable-assets.js.map +1 -0
  27. package/dist/transfer-service/lombard/btc-to-btcb-service.cjs +1 -1
  28. package/dist/transfer-service/lombard/btc-to-btcb-service.cjs.map +1 -1
  29. package/dist/transfer-service/lombard/btc-to-btcb-service.js +1 -1
  30. package/dist/transfer-service/lombard/btc-to-btcb-service.js.map +1 -1
  31. package/dist/transfer-service/lombard/btcb-to-btc/_handlers/get-bridgeable-assets.cjs +2 -0
  32. package/dist/transfer-service/lombard/btcb-to-btc/_handlers/get-bridgeable-assets.cjs.map +1 -0
  33. package/dist/transfer-service/lombard/btcb-to-btc/_handlers/get-bridgeable-assets.js +2 -0
  34. package/dist/transfer-service/lombard/btcb-to-btc/_handlers/get-bridgeable-assets.js.map +1 -0
  35. package/dist/transfer-service/lombard/btcb-to-btc-service.cjs +1 -1
  36. package/dist/transfer-service/lombard/btcb-to-btc-service.cjs.map +1 -1
  37. package/dist/transfer-service/lombard/btcb-to-btc-service.js +1 -1
  38. package/dist/transfer-service/lombard/btcb-to-btc-service.js.map +1 -1
  39. package/dist/transfer-service/lombard/constants.cjs +1 -1
  40. package/dist/transfer-service/lombard/constants.cjs.map +1 -1
  41. package/dist/transfer-service/lombard/constants.js +1 -1
  42. package/dist/transfer-service/lombard/constants.js.map +1 -1
  43. package/dist/transfer-service/markr/_api.cjs +1 -1
  44. package/dist/transfer-service/markr/_api.js +1 -1
  45. package/dist/transfer-service/markr/_handlers/analyze-support.cjs +1 -1
  46. package/dist/transfer-service/markr/_handlers/analyze-support.cjs.map +1 -1
  47. package/dist/transfer-service/markr/_handlers/analyze-support.js +1 -1
  48. package/dist/transfer-service/markr/_handlers/analyze-support.js.map +1 -1
  49. package/dist/transfer-service/markr/_handlers/get-bridgeable-assets.cjs +2 -0
  50. package/dist/transfer-service/markr/_handlers/get-bridgeable-assets.cjs.map +1 -0
  51. package/dist/transfer-service/markr/_handlers/get-bridgeable-assets.js +2 -0
  52. package/dist/transfer-service/markr/_handlers/get-bridgeable-assets.js.map +1 -0
  53. package/dist/transfer-service/markr/_handlers/track-transfer.cjs +1 -1
  54. package/dist/transfer-service/markr/_handlers/track-transfer.cjs.map +1 -1
  55. package/dist/transfer-service/markr/_handlers/track-transfer.js +1 -1
  56. package/dist/transfer-service/markr/_handlers/track-transfer.js.map +1 -1
  57. package/dist/transfer-service/markr/_utils.cjs +1 -1
  58. package/dist/transfer-service/markr/_utils.cjs.map +1 -1
  59. package/dist/transfer-service/markr/_utils.js +1 -1
  60. package/dist/transfer-service/markr/_utils.js.map +1 -1
  61. package/dist/transfer-service/markr/constants.cjs +1 -1
  62. package/dist/transfer-service/markr/constants.cjs.map +1 -1
  63. package/dist/transfer-service/markr/constants.js +1 -1
  64. package/dist/transfer-service/markr/constants.js.map +1 -1
  65. package/dist/transfer-service/markr/markr-service.cjs +1 -1
  66. package/dist/transfer-service/markr/markr-service.cjs.map +1 -1
  67. package/dist/transfer-service/markr/markr-service.js +1 -1
  68. package/dist/transfer-service/markr/markr-service.js.map +1 -1
  69. package/dist/transfer-service/wrap-unwrap/_handlers/get-bridgeable-assets.cjs +2 -0
  70. package/dist/transfer-service/wrap-unwrap/_handlers/get-bridgeable-assets.cjs.map +1 -0
  71. package/dist/transfer-service/wrap-unwrap/_handlers/get-bridgeable-assets.js +2 -0
  72. package/dist/transfer-service/wrap-unwrap/_handlers/get-bridgeable-assets.js.map +1 -0
  73. package/dist/transfer-service/wrap-unwrap/constants.cjs +1 -1
  74. package/dist/transfer-service/wrap-unwrap/constants.cjs.map +1 -1
  75. package/dist/transfer-service/wrap-unwrap/constants.js +1 -1
  76. package/dist/transfer-service/wrap-unwrap/constants.js.map +1 -1
  77. package/dist/transfer-service/wrap-unwrap/wrap-unwrap-service.cjs +1 -1
  78. package/dist/transfer-service/wrap-unwrap/wrap-unwrap-service.cjs.map +1 -1
  79. package/dist/transfer-service/wrap-unwrap/wrap-unwrap-service.js +1 -1
  80. package/dist/transfer-service/wrap-unwrap/wrap-unwrap-service.js.map +1 -1
  81. package/dist/types/asset.d.cts +6 -1
  82. package/dist/types/asset.d.ts +6 -1
  83. package/dist/types/service.d.cts +15 -2
  84. package/dist/types/service.d.ts +15 -2
  85. package/dist/types/transfer-manager.d.cts +17 -1
  86. package/dist/types/transfer-manager.d.ts +17 -1
  87. package/dist/utils/asset-id.cjs +2 -0
  88. package/dist/utils/asset-id.cjs.map +1 -0
  89. package/dist/utils/asset-id.js +2 -0
  90. package/dist/utils/asset-id.js.map +1 -0
  91. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"track-transfer.cjs","names":["isSolanaNamespace","trackSameChainEvmTransfer","ErrorCode","getSolanaRpcForChain","SOLANA_TX_TIMEOUT_MS","waitForTimeoutOrAbort","SOLANA_POLLING_INTERVAL_MS","getErrorCodeForSolanaRpcError","isEvmNamespace","getEvmClientForChain","awaitOrAbort","getErrorCodeForViemError","markrGetCrossChainStatus"],"sources":["../../../../src/transfer-service/markr/_handlers/track-transfer.ts"],"sourcesContent":["import { assertIsSignature, type Signature } from '@solana/kit';\nimport { isHash } from 'viem';\nimport { isEvmNamespace, isSolanaNamespace } from '../../../_utils/chain';\nimport { ErrorCode } from '../../../errors';\nimport type { TransferService, TrackTransferProps } from '../../../types/service';\nimport type {\n CompletedTransfer,\n FailedTransfer,\n SourceCompletedTransfer,\n SourcePendingTransfer,\n TargetPendingTransfer,\n Transfer,\n} from '../../../types/transfer';\nimport {\n awaitOrAbort,\n getErrorCodeForSolanaRpcError,\n getErrorCodeForViemError,\n getEvmClientForChain,\n getSolanaRpcForChain,\n waitForTimeoutOrAbort,\n} from '../../_utils';\nimport { trackSameChainEvmTransfer } from '../../_tracking-utilities';\nimport { markrGetCrossChainStatus, type ApiOptions } from '../_api';\nimport type { CrossChainStatusResponse } from '../_schema';\nimport { SOLANA_POLLING_INTERVAL_MS, SOLANA_TX_TIMEOUT_MS } from '../constants';\nimport type { Caip2ChainId } from '../../../mod';\n\nconst CROSS_CHAIN_POLLING_INTERVAL_MS = 3_000;\n\ntype InFlightTransfer = SourcePendingTransfer | SourceCompletedTransfer | TargetPendingTransfer;\n\nexport interface TrackTransferFactoryConfig {\n apiOptions: ApiOptions;\n}\n\nexport function trackTransferFactory({ apiOptions }: TrackTransferFactoryConfig): TransferService['trackTransfer'] {\n return ({ transfer, updateListener }) => {\n if (transfer.sourceChain.chainId === transfer.targetChain.chainId) {\n if (isSolanaNamespace(transfer.sourceChain.chainId)) {\n return _trackSameChainSolanaTransfer({ transfer, updateListener });\n }\n return trackSameChainEvmTransfer({ transfer, updateListener });\n }\n\n return _trackCrossChainTransfer({ transfer, updateListener }, apiOptions);\n };\n}\n\nexport function _trackSameChainSolanaTransfer({ transfer, updateListener }: TrackTransferProps): {\n cancel: () => void;\n result: Promise<Transfer>;\n} {\n const ac = new AbortController();\n const cancel = () => ac.abort();\n\n if (transfer.status !== 'source-pending') {\n return { cancel, result: Promise.resolve(transfer) };\n }\n\n return { cancel, result: _pollSolanaSignatureStatus(transfer, updateListener, ac.signal) };\n}\n\nasync function _pollSolanaSignatureStatus(\n transfer: SourcePendingTransfer,\n updateListener: (transfer: Transfer) => void,\n signal: AbortSignal,\n): Promise<Transfer> {\n const { txHash } = transfer.source;\n\n try {\n assertIsSignature(txHash);\n } catch {\n const failed: FailedTransfer = {\n ...transfer,\n errorCode: ErrorCode.INVALID_PARAMS,\n failedAtMs: Date.now(),\n status: 'failed',\n };\n updateListener(failed);\n return failed;\n }\n\n const rpc = getSolanaRpcForChain({ chain: transfer.sourceChain });\n const startTime = Date.now();\n\n while (!signal.aborted) {\n if (Date.now() - startTime > SOLANA_TX_TIMEOUT_MS) {\n const failed: FailedTransfer = {\n ...transfer,\n errorCode: ErrorCode.TIMEOUT,\n failedAtMs: Date.now(),\n status: 'failed',\n };\n updateListener(failed);\n return failed;\n }\n\n try {\n const { value } = await rpc.getSignatureStatuses([txHash], { searchTransactionHistory: true }).send();\n const status = value[0];\n\n if (!status) {\n await waitForTimeoutOrAbort({ timeoutMs: SOLANA_POLLING_INTERVAL_MS, signal });\n continue;\n }\n\n if (status.err !== null) {\n const failed: FailedTransfer = {\n ...transfer,\n errorCode: ErrorCode.TRANSACTION_REVERTED,\n failedAtMs: Date.now(),\n status: 'failed',\n };\n updateListener(failed);\n return failed;\n }\n\n if (status.confirmationStatus === 'finalized') {\n const completed: CompletedTransfer = {\n ...transfer,\n completedAtMs: Date.now(),\n source: {\n ...transfer.source,\n confirmationCount: transfer.source.requiredConfirmationCount,\n },\n status: 'completed',\n target: null,\n };\n updateListener(completed);\n return completed;\n }\n\n const confirmations = Number(status.confirmations ?? 0);\n const cappedCount = Math.min(confirmations, transfer.source.requiredConfirmationCount - 1);\n\n if (cappedCount !== transfer.source.confirmationCount) {\n transfer = {\n ...transfer,\n source: {\n ...transfer.source,\n confirmationCount: cappedCount,\n },\n };\n updateListener(transfer);\n }\n\n await waitForTimeoutOrAbort({ timeoutMs: SOLANA_POLLING_INTERVAL_MS, signal });\n } catch (error) {\n const failed: FailedTransfer = {\n ...transfer,\n errorCode: getErrorCodeForSolanaRpcError(error),\n failedAtMs: Date.now(),\n status: 'failed',\n };\n updateListener(failed);\n return failed;\n }\n }\n\n return transfer;\n}\n\nexport function _trackCrossChainTransfer(\n { transfer, updateListener }: TrackTransferProps,\n apiOptions: ApiOptions,\n): { cancel: () => void; result: Promise<Transfer> } {\n const ac = new AbortController();\n const cancel = () => {\n ac.abort();\n };\n\n const executeTracking = async (): Promise<Transfer> => {\n let currentTransfer: Transfer = structuredClone(transfer);\n while (!ac.signal.aborted) {\n const updatedTransfer = await _getMarkrCrossChainTxStatus(currentTransfer, apiOptions, ac.signal);\n\n if (ac.signal.aborted) {\n break;\n }\n\n currentTransfer = updatedTransfer;\n\n updateListener(updatedTransfer);\n\n if (updatedTransfer.status === 'completed' || updatedTransfer.status === 'failed') {\n return updatedTransfer;\n }\n\n // Wait before polling again.\n await new Promise((resolve) => {\n const timeoutId = setTimeout(resolve, CROSS_CHAIN_POLLING_INTERVAL_MS);\n ac.signal.addEventListener('abort', () => clearTimeout(timeoutId), { once: true });\n });\n }\n\n return currentTransfer;\n };\n\n return {\n cancel,\n result: executeTracking(),\n };\n}\n\nexport async function _getMarkrCrossChainTxStatus(\n transfer: Transfer,\n apiOptions: ApiOptions,\n signal: AbortSignal,\n): Promise<Transfer> {\n if (transfer.status === 'completed' || transfer.status === 'failed') {\n return transfer;\n }\n\n // We only support tracking EVM or Solana source transactions.\n if (!_isValidSourceTxHash(transfer.source.txHash, transfer.sourceChain.chainId)) {\n const failedTransfer: FailedTransfer = {\n ...transfer,\n errorCode: ErrorCode.INVALID_PARAMS,\n errorReason: 'Invalid source transaction hash',\n failedAtMs: Date.now(),\n status: 'failed',\n };\n return failedTransfer;\n }\n\n // If transfer is `source-pending`, we first confirm source-chain finality before\n // querying Markr's cross-chain status endpoint.\n // Once source finality is confirmed, we mark the transfer as source-completed and\n // defer Markr polling to subsequent iterations.\n if (transfer.status === 'source-pending') {\n if (isEvmNamespace(transfer.sourceChain.chainId)) {\n const sourceTxHash = transfer.source.txHash;\n\n if (!isHash(sourceTxHash)) {\n const failedTransfer: FailedTransfer = {\n ...transfer,\n errorCode: ErrorCode.INVALID_PARAMS,\n errorReason: 'Invalid source transaction hash',\n failedAtMs: Date.now(),\n status: 'failed',\n };\n\n return failedTransfer;\n }\n\n const client = getEvmClientForChain({ chain: transfer.sourceChain });\n\n try {\n const receiptResult = await awaitOrAbort(\n client.waitForTransactionReceipt({\n hash: sourceTxHash,\n }),\n signal,\n );\n\n if (receiptResult.status === 'aborted') {\n return transfer;\n }\n\n const receipt = receiptResult.value;\n\n if (receipt.status === 'reverted') {\n const failedTransfer: FailedTransfer = {\n ...transfer,\n errorCode: ErrorCode.TRANSACTION_REVERTED,\n errorReason: 'Source transaction was reverted',\n failedAtMs: Date.now(),\n status: 'failed',\n };\n return failedTransfer;\n }\n\n const finalityResult = await _waitForEvmSourceFinalization(client, receipt.blockNumber, signal);\n if (finalityResult.status === 'aborted') {\n return transfer;\n }\n\n return _toSourceCompletedTransfer(transfer);\n } catch (error) {\n const failedTransfer: FailedTransfer = {\n ...transfer,\n errorCode: getErrorCodeForViemError(error),\n errorReason: 'Failed to confirm source transaction finality',\n failedAtMs: Date.now(),\n status: 'failed',\n };\n return failedTransfer;\n }\n }\n\n if (isSolanaNamespace(transfer.sourceChain.chainId)) {\n const sourceTxHash = transfer.source.txHash;\n\n try {\n assertIsSignature(sourceTxHash);\n } catch {\n const failedTransfer: FailedTransfer = {\n ...transfer,\n errorCode: ErrorCode.INVALID_PARAMS,\n errorReason: 'Invalid source transaction hash',\n failedAtMs: Date.now(),\n status: 'failed',\n };\n return failedTransfer;\n }\n\n const finalityResult = await _waitForSolanaSourceFinalization(transfer.sourceChain, sourceTxHash, signal);\n\n if (finalityResult.status === 'aborted') {\n return transfer;\n }\n\n if (finalityResult.status === 'failed') {\n const failedTransfer: FailedTransfer = {\n ...transfer,\n errorCode: finalityResult.errorCode,\n errorReason: 'Failed to confirm source transaction finality',\n failedAtMs: Date.now(),\n status: 'failed',\n };\n return failedTransfer;\n }\n\n return _toSourceCompletedTransfer(transfer);\n }\n }\n\n try {\n const statusResponse = await markrGetCrossChainStatus(apiOptions, transfer.source.txHash, { signal });\n const transferWithMarkrMetadata = _withMarkrTrackingMetadata(transfer, statusResponse);\n\n switch (statusResponse.status) {\n case 'failed': {\n const failedTransfer: FailedTransfer = {\n ...transferWithMarkrMetadata,\n errorCode: ErrorCode.TRANSACTION_REVERTED,\n errorReason: 'Transaction execution failed.',\n failedAtMs: _getLastStatusActivityTime(statusResponse),\n status: 'failed',\n };\n\n return failedTransfer;\n }\n\n case 'pending': {\n return _isMarkrSourceFinalized(statusResponse.sourceChain.finalized)\n ? _toSourceCompletedTransfer(transferWithMarkrMetadata)\n : transferWithMarkrMetadata;\n }\n\n case 'committed':\n case 'pending_execution': {\n return _toTargetPendingTransfer(transferWithMarkrMetadata, statusResponse);\n }\n\n case 'completed': {\n return _toCompletedTransfer(transferWithMarkrMetadata, statusResponse);\n }\n\n case 'unknown':\n default: {\n return _deriveTransferFromUnknownStatus(transferWithMarkrMetadata, statusResponse);\n }\n }\n } catch (error) {\n // TODO: Clean this console.error up before v1 release.\n // This is just here for now to try to track down tracking issues.\n console.error('[Unified Asset Transfer] Error fetching cross-chain status from Markr API', {\n error,\n now: Date.now(),\n });\n\n const failedTransfer: FailedTransfer = {\n ...transfer,\n errorCode: ErrorCode.UNKNOWN,\n errorReason: 'Failed to fetch cross-chain tx status',\n failedAtMs: Date.now(),\n status: 'failed',\n };\n return failedTransfer;\n }\n}\n\nasync function _waitForEvmSourceFinalization(\n client: ReturnType<typeof getEvmClientForChain>,\n txBlockNumber: bigint,\n signal: AbortSignal,\n): Promise<{ status: 'aborted' } | { status: 'ok' }> {\n while (!signal.aborted) {\n const finalizedBlockResult = await awaitOrAbort(client.getBlock({ blockTag: 'finalized' }), signal);\n\n if (finalizedBlockResult.status === 'aborted') {\n return { status: 'aborted' };\n }\n\n if (finalizedBlockResult.value.number >= txBlockNumber) {\n return { status: 'ok' };\n }\n\n await waitForTimeoutOrAbort({\n timeoutMs: CROSS_CHAIN_POLLING_INTERVAL_MS,\n signal,\n });\n }\n\n return { status: 'aborted' };\n}\n\nasync function _waitForSolanaSourceFinalization(\n chain: SourcePendingTransfer['sourceChain'],\n txHash: Signature,\n signal: AbortSignal,\n): Promise<{ status: 'aborted' } | { status: 'ok' } | { status: 'failed'; errorCode: ErrorCode }> {\n const rpc = getSolanaRpcForChain({ chain });\n const startTime = Date.now();\n\n while (!signal.aborted) {\n if (Date.now() - startTime > SOLANA_TX_TIMEOUT_MS) {\n return {\n status: 'failed',\n errorCode: ErrorCode.TIMEOUT,\n };\n }\n\n try {\n const { value } = await rpc.getSignatureStatuses([txHash], { searchTransactionHistory: true }).send();\n const txStatus = value[0];\n\n if (!txStatus) {\n await waitForTimeoutOrAbort({ timeoutMs: SOLANA_POLLING_INTERVAL_MS, signal });\n continue;\n }\n\n if (txStatus.err !== null) {\n return {\n status: 'failed',\n errorCode: ErrorCode.TRANSACTION_REVERTED,\n };\n }\n\n if (txStatus.confirmationStatus === 'finalized') {\n return { status: 'ok' };\n }\n\n await waitForTimeoutOrAbort({ timeoutMs: SOLANA_POLLING_INTERVAL_MS, signal });\n } catch (error) {\n return {\n status: 'failed',\n errorCode: getErrorCodeForSolanaRpcError(error),\n };\n }\n }\n\n return { status: 'aborted' };\n}\n\nfunction _isValidSourceTxHash(txHash: string, sourceChainId: Caip2ChainId): boolean {\n if (isEvmNamespace(sourceChainId)) {\n return isHash(txHash);\n }\n\n if (isSolanaNamespace(sourceChainId)) {\n try {\n assertIsSignature(txHash);\n return true;\n } catch {\n return false;\n }\n }\n\n return false;\n}\n\nfunction _isMarkrSourceFinalized(finalized: CrossChainStatusResponse['sourceChain']['finalized']): boolean {\n return finalized === true || typeof finalized === 'string';\n}\n\nfunction _toSourceCompletedTransfer(transfer: InFlightTransfer): SourceCompletedTransfer {\n return {\n ...transfer,\n source: {\n ...transfer.source,\n confirmationCount: 2,\n requiredConfirmationCount: 2,\n },\n status: 'source-completed',\n };\n}\n\nfunction _withMarkrTrackingMetadata(\n transfer: InFlightTransfer,\n statusResponse: CrossChainStatusResponse,\n): InFlightTransfer {\n const metadata: Record<string, unknown> = { ...(transfer.metadata ?? {}) };\n\n if (statusResponse.destinationChain.bridgeHash) {\n metadata.bridgeHash = statusResponse.destinationChain.bridgeHash;\n }\n\n if (statusResponse.debug) {\n metadata.debug = statusResponse.debug;\n }\n\n if (Object.keys(metadata).length === 0) {\n return transfer;\n }\n\n return {\n ...transfer,\n metadata,\n };\n}\n\nfunction _toTargetPendingTransfer(\n transfer: InFlightTransfer,\n statusResponse: CrossChainStatusResponse,\n): TargetPendingTransfer {\n const { timestamp, transactionHash } = statusResponse.destinationChain;\n\n return {\n ...transfer,\n source: {\n ...transfer.source,\n confirmationCount: 2,\n requiredConfirmationCount: 2,\n },\n status: 'target-pending',\n target: {\n confirmationCount: transactionHash ? 1 : 0,\n requiredConfirmationCount: 2,\n startedAtMs: timestamp ? new Date(timestamp).getTime() : Date.now(),\n txHash: transactionHash ?? undefined,\n },\n };\n}\n\nfunction _toCompletedTransfer(transfer: InFlightTransfer, statusResponse: CrossChainStatusResponse): CompletedTransfer {\n const { timestamp, transactionHash } = statusResponse.destinationChain;\n\n return {\n ...transfer,\n completedAtMs: _getLastStatusActivityTime(statusResponse),\n status: 'completed',\n source: {\n ...transfer.source,\n confirmationCount: 2,\n requiredConfirmationCount: 2,\n },\n target: transactionHash\n ? {\n txHash: transactionHash,\n confirmationCount: 2,\n requiredConfirmationCount: 2,\n startedAtMs: timestamp ? new Date(timestamp).getTime() : Date.now(),\n }\n : null,\n };\n}\n\nfunction _deriveTransferFromUnknownStatus(\n transfer: InFlightTransfer,\n statusResponse: CrossChainStatusResponse,\n): Transfer {\n if (statusResponse.progress.executed === true) {\n return _toCompletedTransfer(transfer, statusResponse);\n }\n\n if (statusResponse.progress.committed === true) {\n return _toTargetPendingTransfer(transfer, statusResponse);\n }\n\n if (_isMarkrSourceFinalized(statusResponse.sourceChain.finalized)) {\n return _toSourceCompletedTransfer(transfer);\n }\n\n return {\n ...transfer,\n source: {\n ...transfer.source,\n confirmationCount: 0,\n requiredConfirmationCount: 2,\n },\n status: 'source-pending',\n };\n}\n\nfunction _getLastStatusActivityTime(response: CrossChainStatusResponse): number {\n if (response.destinationChain.finalized) {\n return new Date(response.destinationChain.finalized).getTime();\n }\n\n if (response.destinationChain.timestamp) {\n return new Date(response.destinationChain.timestamp).getTime();\n }\n\n if (response.sourceChain.finalized) {\n if (typeof response.sourceChain.finalized === 'boolean' && response.sourceChain.finalized === true) {\n // Handle case where finalized is returned as boolean `true` instead of a timestamp.\n return new Date(response.sourceChain.timestamp).getTime();\n }\n return new Date(response.sourceChain.finalized).getTime();\n }\n\n return new Date(response.sourceChain.timestamp).getTime();\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"track-transfer.cjs","names":["isSolanaNamespace","trackSameChainEvmTransfer","ErrorCode","getSolanaRpcForChain","SOLANA_TX_TIMEOUT_MS","waitForTimeoutOrAbort","SOLANA_POLLING_INTERVAL_MS","getErrorCodeForSolanaRpcError","isEvmNamespace","getEvmClientForChain","awaitOrAbort","getErrorCodeForViemError","markrGetCrossChainStatus","CROSS_CHAIN_POLLING_INTERVAL_MS","FINALITY_MS_BY_CHAIN_ID","FINALITY_MS_BY_CHAIN_NAME_ALIAS","FINALITY_TIER_MAX_FINALITY_MS"],"sources":["../../../../src/transfer-service/markr/_handlers/track-transfer.ts"],"sourcesContent":["import { assertIsSignature, type Signature } from '@solana/kit';\nimport { isHash } from 'viem';\nimport { isEvmNamespace, isSolanaNamespace } from '../../../_utils/chain';\nimport { ErrorCode } from '../../../errors';\nimport type { TransferService, TrackTransferProps } from '../../../types/service';\nimport type {\n CompletedTransfer,\n FailedTransfer,\n SourceCompletedTransfer,\n SourcePendingTransfer,\n TargetPendingTransfer,\n Transfer,\n} from '../../../types/transfer';\nimport {\n awaitOrAbort,\n getErrorCodeForSolanaRpcError,\n getErrorCodeForViemError,\n getEvmClientForChain,\n getSolanaRpcForChain,\n waitForTimeoutOrAbort,\n} from '../../_utils';\nimport { trackSameChainEvmTransfer } from '../../_tracking-utilities';\nimport { markrGetCrossChainStatus, type ApiOptions } from '../_api';\nimport type { CrossChainStatusResponse } from '../_schema';\nimport {\n CROSS_CHAIN_POLLING_INTERVAL_MS,\n FINALITY_MS_BY_CHAIN_ID,\n FINALITY_MS_BY_CHAIN_NAME_ALIAS,\n FINALITY_TIER_MAX_FINALITY_MS,\n SOLANA_POLLING_INTERVAL_MS,\n SOLANA_TX_TIMEOUT_MS,\n} from '../constants';\nimport type { Caip2ChainId } from '../../../mod';\n\ntype FinalityTier = keyof typeof CROSS_CHAIN_POLLING_INTERVAL_MS;\n\ntype InFlightTransfer = SourcePendingTransfer | SourceCompletedTransfer | TargetPendingTransfer;\n\nexport interface TrackTransferFactoryConfig {\n apiOptions: ApiOptions;\n}\n\nexport function trackTransferFactory({ apiOptions }: TrackTransferFactoryConfig): TransferService['trackTransfer'] {\n return ({ transfer, updateListener }) => {\n if (transfer.sourceChain.chainId === transfer.targetChain.chainId) {\n if (isSolanaNamespace(transfer.sourceChain.chainId)) {\n return _trackSameChainSolanaTransfer({ transfer, updateListener });\n }\n return trackSameChainEvmTransfer({ transfer, updateListener });\n }\n\n return _trackCrossChainTransfer({ transfer, updateListener }, apiOptions);\n };\n}\n\nexport function _trackSameChainSolanaTransfer({ transfer, updateListener }: TrackTransferProps): {\n cancel: () => void;\n result: Promise<Transfer>;\n} {\n const ac = new AbortController();\n const cancel = () => ac.abort();\n\n if (transfer.status !== 'source-pending') {\n return { cancel, result: Promise.resolve(transfer) };\n }\n\n return { cancel, result: _pollSolanaSignatureStatus(transfer, updateListener, ac.signal) };\n}\n\nasync function _pollSolanaSignatureStatus(\n transfer: SourcePendingTransfer,\n updateListener: (transfer: Transfer) => void,\n signal: AbortSignal,\n): Promise<Transfer> {\n const { txHash } = transfer.source;\n\n try {\n assertIsSignature(txHash);\n } catch {\n const failed: FailedTransfer = {\n ...transfer,\n errorCode: ErrorCode.INVALID_PARAMS,\n failedAtMs: Date.now(),\n status: 'failed',\n };\n updateListener(failed);\n return failed;\n }\n\n const rpc = getSolanaRpcForChain({ chain: transfer.sourceChain });\n const startTime = Date.now();\n\n while (!signal.aborted) {\n if (Date.now() - startTime > SOLANA_TX_TIMEOUT_MS) {\n const failed: FailedTransfer = {\n ...transfer,\n errorCode: ErrorCode.TIMEOUT,\n failedAtMs: Date.now(),\n status: 'failed',\n };\n updateListener(failed);\n return failed;\n }\n\n try {\n const { value } = await rpc.getSignatureStatuses([txHash], { searchTransactionHistory: true }).send();\n const status = value[0];\n\n if (!status) {\n await waitForTimeoutOrAbort({ timeoutMs: SOLANA_POLLING_INTERVAL_MS, signal });\n continue;\n }\n\n if (status.err !== null) {\n const failed: FailedTransfer = {\n ...transfer,\n errorCode: ErrorCode.TRANSACTION_REVERTED,\n failedAtMs: Date.now(),\n status: 'failed',\n };\n updateListener(failed);\n return failed;\n }\n\n if (status.confirmationStatus === 'finalized') {\n const completed: CompletedTransfer = {\n ...transfer,\n completedAtMs: Date.now(),\n source: {\n ...transfer.source,\n confirmationCount: transfer.source.requiredConfirmationCount,\n },\n status: 'completed',\n target: null,\n };\n updateListener(completed);\n return completed;\n }\n\n const confirmations = Number(status.confirmations ?? 0);\n const cappedCount = Math.min(confirmations, transfer.source.requiredConfirmationCount - 1);\n\n if (cappedCount !== transfer.source.confirmationCount) {\n transfer = {\n ...transfer,\n source: {\n ...transfer.source,\n confirmationCount: cappedCount,\n },\n };\n updateListener(transfer);\n }\n\n await waitForTimeoutOrAbort({ timeoutMs: SOLANA_POLLING_INTERVAL_MS, signal });\n } catch (error) {\n const failed: FailedTransfer = {\n ...transfer,\n errorCode: getErrorCodeForSolanaRpcError(error),\n failedAtMs: Date.now(),\n status: 'failed',\n };\n updateListener(failed);\n return failed;\n }\n }\n\n return transfer;\n}\n\nexport function _trackCrossChainTransfer(\n { transfer, updateListener }: TrackTransferProps,\n apiOptions: ApiOptions,\n): { cancel: () => void; result: Promise<Transfer> } {\n const ac = new AbortController();\n const cancel = () => {\n ac.abort();\n };\n\n const executeTracking = async (): Promise<Transfer> => {\n let currentTransfer: Transfer = structuredClone(transfer);\n while (!ac.signal.aborted) {\n const updatedTransfer = await _getMarkrCrossChainTxStatus(currentTransfer, apiOptions, ac.signal);\n\n if (ac.signal.aborted) {\n break;\n }\n\n currentTransfer = updatedTransfer;\n\n updateListener(updatedTransfer);\n\n if (updatedTransfer.status === 'completed' || updatedTransfer.status === 'failed') {\n return updatedTransfer;\n }\n\n const pollingIntervalMs = _getPollingIntervalMsForTransfer(updatedTransfer);\n\n // Wait before polling again.\n await new Promise((resolve) => {\n const timeoutId = setTimeout(resolve, pollingIntervalMs);\n ac.signal.addEventListener('abort', () => clearTimeout(timeoutId), { once: true });\n });\n }\n\n return currentTransfer;\n };\n\n return {\n cancel,\n result: executeTracking(),\n };\n}\n\nexport async function _getMarkrCrossChainTxStatus(\n transfer: Transfer,\n apiOptions: ApiOptions,\n signal: AbortSignal,\n): Promise<Transfer> {\n if (transfer.status === 'completed' || transfer.status === 'failed') {\n return transfer;\n }\n\n // We only support tracking EVM or Solana source transactions.\n if (!_isValidSourceTxHash(transfer.source.txHash, transfer.sourceChain.chainId)) {\n const failedTransfer: FailedTransfer = {\n ...transfer,\n errorCode: ErrorCode.INVALID_PARAMS,\n errorReason: 'Invalid source transaction hash',\n failedAtMs: Date.now(),\n status: 'failed',\n };\n return failedTransfer;\n }\n\n // If transfer is `source-pending`, we first confirm source-chain finality before\n // querying Markr's cross-chain status endpoint.\n // Once source finality is confirmed, we mark the transfer as source-completed and\n // defer Markr polling to subsequent iterations.\n if (transfer.status === 'source-pending') {\n if (isEvmNamespace(transfer.sourceChain.chainId)) {\n const sourceTxHash = transfer.source.txHash;\n\n if (!isHash(sourceTxHash)) {\n const failedTransfer: FailedTransfer = {\n ...transfer,\n errorCode: ErrorCode.INVALID_PARAMS,\n errorReason: 'Invalid source transaction hash',\n failedAtMs: Date.now(),\n status: 'failed',\n };\n\n return failedTransfer;\n }\n\n const client = getEvmClientForChain({ chain: transfer.sourceChain });\n\n try {\n const receiptResult = await awaitOrAbort(\n client.waitForTransactionReceipt({\n hash: sourceTxHash,\n }),\n signal,\n );\n\n if (receiptResult.status === 'aborted') {\n return transfer;\n }\n\n const receipt = receiptResult.value;\n\n if (receipt.status === 'reverted') {\n const failedTransfer: FailedTransfer = {\n ...transfer,\n errorCode: ErrorCode.TRANSACTION_REVERTED,\n errorReason: 'Source transaction was reverted',\n failedAtMs: Date.now(),\n status: 'failed',\n };\n return failedTransfer;\n }\n\n const finalityResult = await _waitForEvmSourceFinalization(\n client,\n transfer.sourceChain.chainId,\n transfer.sourceChain.chainName,\n receipt.blockNumber,\n signal,\n );\n if (finalityResult.status === 'aborted') {\n return transfer;\n }\n\n return _toSourceCompletedTransfer(transfer);\n } catch (error) {\n const failedTransfer: FailedTransfer = {\n ...transfer,\n errorCode: getErrorCodeForViemError(error),\n errorReason: 'Failed to confirm source transaction finality',\n failedAtMs: Date.now(),\n status: 'failed',\n };\n return failedTransfer;\n }\n }\n\n if (isSolanaNamespace(transfer.sourceChain.chainId)) {\n const sourceTxHash = transfer.source.txHash;\n\n try {\n assertIsSignature(sourceTxHash);\n } catch {\n const failedTransfer: FailedTransfer = {\n ...transfer,\n errorCode: ErrorCode.INVALID_PARAMS,\n errorReason: 'Invalid source transaction hash',\n failedAtMs: Date.now(),\n status: 'failed',\n };\n return failedTransfer;\n }\n\n const finalityResult = await _waitForSolanaSourceFinalization(transfer.sourceChain, sourceTxHash, signal);\n\n if (finalityResult.status === 'aborted') {\n return transfer;\n }\n\n if (finalityResult.status === 'failed') {\n const failedTransfer: FailedTransfer = {\n ...transfer,\n errorCode: finalityResult.errorCode,\n errorReason: 'Failed to confirm source transaction finality',\n failedAtMs: Date.now(),\n status: 'failed',\n };\n return failedTransfer;\n }\n\n return _toSourceCompletedTransfer(transfer);\n }\n }\n\n try {\n const statusResponse = await markrGetCrossChainStatus(apiOptions, transfer.source.txHash, { signal });\n const transferWithMarkrMetadata = _withMarkrTrackingMetadata(transfer, statusResponse);\n\n switch (statusResponse.status) {\n case 'failed': {\n const failedTransfer: FailedTransfer = {\n ...transferWithMarkrMetadata,\n errorCode: ErrorCode.TRANSACTION_REVERTED,\n errorReason: 'Transaction execution failed.',\n failedAtMs: _getLastStatusActivityTime(statusResponse),\n status: 'failed',\n };\n\n return failedTransfer;\n }\n\n case 'pending': {\n return _isMarkrSourceFinalized(statusResponse.sourceChain.finalized)\n ? _toSourceCompletedTransfer(transferWithMarkrMetadata)\n : transferWithMarkrMetadata;\n }\n\n case 'committed':\n case 'pending_execution': {\n return _toTargetPendingTransfer(transferWithMarkrMetadata, statusResponse);\n }\n\n case 'completed': {\n return _toCompletedTransfer(transferWithMarkrMetadata, statusResponse);\n }\n\n case 'unknown':\n default: {\n return _deriveTransferFromUnknownStatus(transferWithMarkrMetadata, statusResponse);\n }\n }\n } catch (error) {\n // TODO: Clean this console.error up before v1 release.\n // This is just here for now to try to track down tracking issues.\n console.error('[Unified Asset Transfer] Error fetching cross-chain status from Markr API', {\n error,\n now: Date.now(),\n });\n\n const failedTransfer: FailedTransfer = {\n ...transfer,\n errorCode: ErrorCode.UNKNOWN,\n errorReason: 'Failed to fetch cross-chain tx status',\n failedAtMs: Date.now(),\n status: 'failed',\n };\n return failedTransfer;\n }\n}\n\nasync function _waitForEvmSourceFinalization(\n client: ReturnType<typeof getEvmClientForChain>,\n chainId: Caip2ChainId,\n chainName: string,\n txBlockNumber: bigint,\n signal: AbortSignal,\n): Promise<{ status: 'aborted' } | { status: 'ok' }> {\n const pollingIntervalMs = _getCrossChainPollingIntervalMs(chainId, chainName);\n\n while (!signal.aborted) {\n const finalizedBlockResult = await awaitOrAbort(client.getBlock({ blockTag: 'finalized' }), signal);\n\n if (finalizedBlockResult.status === 'aborted') {\n return { status: 'aborted' };\n }\n\n if (finalizedBlockResult.value.number >= txBlockNumber) {\n return { status: 'ok' };\n }\n\n await waitForTimeoutOrAbort({\n timeoutMs: pollingIntervalMs,\n signal,\n });\n }\n\n return { status: 'aborted' };\n}\n\nfunction _getCrossChainPollingIntervalMs(chainId: Caip2ChainId, chainName: string): number {\n const knownFinalityMs = _getKnownFinalityMs(chainId, chainName);\n const finalityTier = _toFinalityTier(knownFinalityMs);\n return CROSS_CHAIN_POLLING_INTERVAL_MS[finalityTier];\n}\n\nfunction _getPollingIntervalMsForTransfer(transfer: Transfer): number {\n if (transfer.status === 'source-pending') {\n return _getCrossChainPollingIntervalMs(transfer.sourceChain.chainId, transfer.sourceChain.chainName);\n }\n\n return _getCrossChainPollingIntervalMs(transfer.targetChain.chainId, transfer.targetChain.chainName);\n}\n\nfunction _getKnownFinalityMs(chainId: Caip2ChainId, chainName: string): number | undefined {\n const chainIdFinalityMs = FINALITY_MS_BY_CHAIN_ID[chainId];\n if (chainIdFinalityMs !== undefined) {\n return chainIdFinalityMs;\n }\n\n const normalizedName = _normalizeChainName(chainName);\n const matchingAlias = FINALITY_MS_BY_CHAIN_NAME_ALIAS.find(({ aliases }) =>\n aliases.some((alias) => normalizedName.includes(alias)),\n );\n\n return matchingAlias?.finalityMs;\n}\n\nfunction _normalizeChainName(chainName: string): string {\n return chainName.toLowerCase().replace(/[^a-z0-9]/g, '');\n}\n\nfunction _toFinalityTier(knownFinalityMs: number | undefined): FinalityTier {\n if (knownFinalityMs === undefined) {\n return 'medium';\n }\n\n if (knownFinalityMs <= FINALITY_TIER_MAX_FINALITY_MS.fast) {\n return 'fast';\n }\n\n if (knownFinalityMs <= FINALITY_TIER_MAX_FINALITY_MS.medium) {\n return 'medium';\n }\n\n if (knownFinalityMs <= FINALITY_TIER_MAX_FINALITY_MS.slow) {\n return 'slow';\n }\n\n return 'verySlow';\n}\n\nasync function _waitForSolanaSourceFinalization(\n chain: SourcePendingTransfer['sourceChain'],\n txHash: Signature,\n signal: AbortSignal,\n): Promise<{ status: 'aborted' } | { status: 'ok' } | { status: 'failed'; errorCode: ErrorCode }> {\n const rpc = getSolanaRpcForChain({ chain });\n const startTime = Date.now();\n\n while (!signal.aborted) {\n if (Date.now() - startTime > SOLANA_TX_TIMEOUT_MS) {\n return {\n status: 'failed',\n errorCode: ErrorCode.TIMEOUT,\n };\n }\n\n try {\n const { value } = await rpc.getSignatureStatuses([txHash], { searchTransactionHistory: true }).send();\n const txStatus = value[0];\n\n if (!txStatus) {\n await waitForTimeoutOrAbort({ timeoutMs: SOLANA_POLLING_INTERVAL_MS, signal });\n continue;\n }\n\n if (txStatus.err !== null) {\n return {\n status: 'failed',\n errorCode: ErrorCode.TRANSACTION_REVERTED,\n };\n }\n\n if (txStatus.confirmationStatus === 'finalized') {\n return { status: 'ok' };\n }\n\n await waitForTimeoutOrAbort({ timeoutMs: SOLANA_POLLING_INTERVAL_MS, signal });\n } catch (error) {\n return {\n status: 'failed',\n errorCode: getErrorCodeForSolanaRpcError(error),\n };\n }\n }\n\n return { status: 'aborted' };\n}\n\nfunction _isValidSourceTxHash(txHash: string, sourceChainId: Caip2ChainId): boolean {\n if (isEvmNamespace(sourceChainId)) {\n return isHash(txHash);\n }\n\n if (isSolanaNamespace(sourceChainId)) {\n try {\n assertIsSignature(txHash);\n return true;\n } catch {\n return false;\n }\n }\n\n return false;\n}\n\nfunction _isMarkrSourceFinalized(finalized: CrossChainStatusResponse['sourceChain']['finalized']): boolean {\n return finalized === true || typeof finalized === 'string';\n}\n\nfunction _toSourceCompletedTransfer(transfer: InFlightTransfer): SourceCompletedTransfer {\n return {\n ...transfer,\n source: {\n ...transfer.source,\n confirmationCount: 2,\n requiredConfirmationCount: 2,\n },\n status: 'source-completed',\n };\n}\n\nfunction _withMarkrTrackingMetadata(\n transfer: InFlightTransfer,\n statusResponse: CrossChainStatusResponse,\n): InFlightTransfer {\n const metadata: Record<string, unknown> = { ...(transfer.metadata ?? {}) };\n\n if (statusResponse.destinationChain.bridgeHash) {\n metadata.bridgeHash = statusResponse.destinationChain.bridgeHash;\n }\n\n if (statusResponse.debug) {\n metadata.debug = statusResponse.debug;\n }\n\n if (Object.keys(metadata).length === 0) {\n return transfer;\n }\n\n return {\n ...transfer,\n metadata,\n };\n}\n\nfunction _toTargetPendingTransfer(\n transfer: InFlightTransfer,\n statusResponse: CrossChainStatusResponse,\n): TargetPendingTransfer {\n const { timestamp, transactionHash } = statusResponse.destinationChain;\n\n return {\n ...transfer,\n source: {\n ...transfer.source,\n confirmationCount: 2,\n requiredConfirmationCount: 2,\n },\n status: 'target-pending',\n target: {\n confirmationCount: transactionHash ? 1 : 0,\n requiredConfirmationCount: 2,\n startedAtMs: timestamp ? new Date(timestamp).getTime() : Date.now(),\n txHash: transactionHash ?? undefined,\n },\n };\n}\n\nfunction _toCompletedTransfer(transfer: InFlightTransfer, statusResponse: CrossChainStatusResponse): CompletedTransfer {\n const { timestamp, transactionHash } = statusResponse.destinationChain;\n\n return {\n ...transfer,\n completedAtMs: _getLastStatusActivityTime(statusResponse),\n status: 'completed',\n source: {\n ...transfer.source,\n confirmationCount: 2,\n requiredConfirmationCount: 2,\n },\n target: transactionHash\n ? {\n txHash: transactionHash,\n confirmationCount: 2,\n requiredConfirmationCount: 2,\n startedAtMs: timestamp ? new Date(timestamp).getTime() : Date.now(),\n }\n : null,\n };\n}\n\nfunction _deriveTransferFromUnknownStatus(\n transfer: InFlightTransfer,\n statusResponse: CrossChainStatusResponse,\n): Transfer {\n if (statusResponse.progress.executed === true) {\n return _toCompletedTransfer(transfer, statusResponse);\n }\n\n if (statusResponse.progress.committed === true) {\n return _toTargetPendingTransfer(transfer, statusResponse);\n }\n\n if (_isMarkrSourceFinalized(statusResponse.sourceChain.finalized)) {\n return _toSourceCompletedTransfer(transfer);\n }\n\n return {\n ...transfer,\n source: {\n ...transfer.source,\n confirmationCount: 0,\n requiredConfirmationCount: 2,\n },\n status: 'source-pending',\n };\n}\n\nfunction _getLastStatusActivityTime(response: CrossChainStatusResponse): number {\n if (response.destinationChain.finalized) {\n return new Date(response.destinationChain.finalized).getTime();\n }\n\n if (response.destinationChain.timestamp) {\n return new Date(response.destinationChain.timestamp).getTime();\n }\n\n if (response.sourceChain.finalized) {\n if (typeof response.sourceChain.finalized === 'boolean' && response.sourceChain.finalized === true) {\n // Handle case where finalized is returned as boolean `true` instead of a timestamp.\n return new Date(response.sourceChain.timestamp).getTime();\n }\n return new Date(response.sourceChain.finalized).getTime();\n }\n\n return new Date(response.sourceChain.timestamp).getTime();\n}\n"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- import{ErrorCode as e}from"../../../errors.js";import{isEvmNamespace as t,isSolanaNamespace as n}from"../../../_utils/chain.js";import{awaitOrAbort as r,getErrorCodeForSolanaRpcError as i,getErrorCodeForViemError as a,getEvmClientForChain as o,getSolanaRpcForChain as s,waitForTimeoutOrAbort as c}from"../../_utils.js";import{markrGetCrossChainStatus as l}from"../_api.js";import{trackSameChainEvmTransfer as u}from"../../_tracking-utilities.js";import{SOLANA_POLLING_INTERVAL_MS as d,SOLANA_TX_TIMEOUT_MS as f}from"../constants.js";import{isHash as p}from"viem";import{assertIsSignature as m}from"@solana/kit";const h=3e3;function g({apiOptions:e}){return({transfer:t,updateListener:r})=>t.sourceChain.chainId===t.targetChain.chainId?n(t.sourceChain.chainId)?_({transfer:t,updateListener:r}):u({transfer:t,updateListener:r}):y({transfer:t,updateListener:r},e)}function _({transfer:e,updateListener:t}){let n=new AbortController,r=()=>n.abort();return e.status===`source-pending`?{cancel:r,result:v(e,t,n.signal)}:{cancel:r,result:Promise.resolve(e)}}async function v(t,n,r){let{txHash:a}=t.source;try{m(a)}catch{let r={...t,errorCode:e.INVALID_PARAMS,failedAtMs:Date.now(),status:`failed`};return n(r),r}let o=s({chain:t.sourceChain}),l=Date.now();for(;!r.aborted;){if(Date.now()-l>f){let r={...t,errorCode:e.TIMEOUT,failedAtMs:Date.now(),status:`failed`};return n(r),r}try{let{value:i}=await o.getSignatureStatuses([a],{searchTransactionHistory:!0}).send(),s=i[0];if(!s){await c({timeoutMs:d,signal:r});continue}if(s.err!==null){let r={...t,errorCode:e.TRANSACTION_REVERTED,failedAtMs:Date.now(),status:`failed`};return n(r),r}if(s.confirmationStatus===`finalized`){let e={...t,completedAtMs:Date.now(),source:{...t.source,confirmationCount:t.source.requiredConfirmationCount},status:`completed`,target:null};return n(e),e}let l=Number(s.confirmations??0),u=Math.min(l,t.source.requiredConfirmationCount-1);u!==t.source.confirmationCount&&(t={...t,source:{...t.source,confirmationCount:u}},n(t)),await c({timeoutMs:d,signal:r})}catch(e){let r={...t,errorCode:i(e),failedAtMs:Date.now(),status:`failed`};return n(r),r}}return t}function y({transfer:e,updateListener:t},n){let r=new AbortController;return{cancel:()=>{r.abort()},result:(async()=>{let i=structuredClone(e);for(;!r.signal.aborted;){let e=await b(i,n,r.signal);if(r.signal.aborted)break;if(i=e,t(e),e.status===`completed`||e.status===`failed`)return e;await new Promise(e=>{let t=setTimeout(e,h);r.signal.addEventListener(`abort`,()=>clearTimeout(t),{once:!0})})}return i})()}}async function b(i,s,c){if(i.status===`completed`||i.status===`failed`)return i;if(!C(i.source.txHash,i.sourceChain.chainId))return{...i,errorCode:e.INVALID_PARAMS,errorReason:`Invalid source transaction hash`,failedAtMs:Date.now(),status:`failed`};if(i.status===`source-pending`){if(t(i.sourceChain.chainId)){let t=i.source.txHash;if(!p(t))return{...i,errorCode:e.INVALID_PARAMS,errorReason:`Invalid source transaction hash`,failedAtMs:Date.now(),status:`failed`};let n=o({chain:i.sourceChain});try{let a=await r(n.waitForTransactionReceipt({hash:t}),c);if(a.status===`aborted`)return i;let o=a.value;return o.status===`reverted`?{...i,errorCode:e.TRANSACTION_REVERTED,errorReason:`Source transaction was reverted`,failedAtMs:Date.now(),status:`failed`}:(await x(n,o.blockNumber,c)).status===`aborted`?i:T(i)}catch(e){return{...i,errorCode:a(e),errorReason:`Failed to confirm source transaction finality`,failedAtMs:Date.now(),status:`failed`}}}if(n(i.sourceChain.chainId)){let t=i.source.txHash;try{m(t)}catch{return{...i,errorCode:e.INVALID_PARAMS,errorReason:`Invalid source transaction hash`,failedAtMs:Date.now(),status:`failed`}}let n=await S(i.sourceChain,t,c);return n.status===`aborted`?i:n.status===`failed`?{...i,errorCode:n.errorCode,errorReason:`Failed to confirm source transaction finality`,failedAtMs:Date.now(),status:`failed`}:T(i)}}try{let t=await l(s,i.source.txHash,{signal:c}),n=E(i,t);switch(t.status){case`failed`:return{...n,errorCode:e.TRANSACTION_REVERTED,errorReason:`Transaction execution failed.`,failedAtMs:A(t),status:`failed`};case`pending`:return w(t.sourceChain.finalized)?T(n):n;case`committed`:case`pending_execution`:return D(n,t);case`completed`:return O(n,t);default:return k(n,t)}}catch(t){return console.error(`[Unified Asset Transfer] Error fetching cross-chain status from Markr API`,{error:t,now:Date.now()}),{...i,errorCode:e.UNKNOWN,errorReason:`Failed to fetch cross-chain tx status`,failedAtMs:Date.now(),status:`failed`}}}async function x(e,t,n){for(;!n.aborted;){let i=await r(e.getBlock({blockTag:`finalized`}),n);if(i.status===`aborted`)return{status:`aborted`};if(i.value.number>=t)return{status:`ok`};await c({timeoutMs:h,signal:n})}return{status:`aborted`}}async function S(t,n,r){let a=s({chain:t}),o=Date.now();for(;!r.aborted;){if(Date.now()-o>f)return{status:`failed`,errorCode:e.TIMEOUT};try{let{value:t}=await a.getSignatureStatuses([n],{searchTransactionHistory:!0}).send(),i=t[0];if(!i){await c({timeoutMs:d,signal:r});continue}if(i.err!==null)return{status:`failed`,errorCode:e.TRANSACTION_REVERTED};if(i.confirmationStatus===`finalized`)return{status:`ok`};await c({timeoutMs:d,signal:r})}catch(e){return{status:`failed`,errorCode:i(e)}}}return{status:`aborted`}}function C(e,r){if(t(r))return p(e);if(n(r))try{return m(e),!0}catch{return!1}return!1}function w(e){return e===!0||typeof e==`string`}function T(e){return{...e,source:{...e.source,confirmationCount:2,requiredConfirmationCount:2},status:`source-completed`}}function E(e,t){let n={...e.metadata??{}};return t.destinationChain.bridgeHash&&(n.bridgeHash=t.destinationChain.bridgeHash),t.debug&&(n.debug=t.debug),Object.keys(n).length===0?e:{...e,metadata:n}}function D(e,t){let{timestamp:n,transactionHash:r}=t.destinationChain;return{...e,source:{...e.source,confirmationCount:2,requiredConfirmationCount:2},status:`target-pending`,target:{confirmationCount:r?1:0,requiredConfirmationCount:2,startedAtMs:n?new Date(n).getTime():Date.now(),txHash:r??void 0}}}function O(e,t){let{timestamp:n,transactionHash:r}=t.destinationChain;return{...e,completedAtMs:A(t),status:`completed`,source:{...e.source,confirmationCount:2,requiredConfirmationCount:2},target:r?{txHash:r,confirmationCount:2,requiredConfirmationCount:2,startedAtMs:n?new Date(n).getTime():Date.now()}:null}}function k(e,t){return t.progress.executed===!0?O(e,t):t.progress.committed===!0?D(e,t):w(t.sourceChain.finalized)?T(e):{...e,source:{...e.source,confirmationCount:0,requiredConfirmationCount:2},status:`source-pending`}}function A(e){return e.destinationChain.finalized?new Date(e.destinationChain.finalized).getTime():e.destinationChain.timestamp?new Date(e.destinationChain.timestamp).getTime():e.sourceChain.finalized?typeof e.sourceChain.finalized==`boolean`&&e.sourceChain.finalized===!0?new Date(e.sourceChain.timestamp).getTime():new Date(e.sourceChain.finalized).getTime():new Date(e.sourceChain.timestamp).getTime()}export{g as trackTransferFactory};
1
+ import{ErrorCode as e}from"../../../errors.js";import{isEvmNamespace as t,isSolanaNamespace as n}from"../../../_utils/chain.js";import{awaitOrAbort as r,getErrorCodeForSolanaRpcError as i,getErrorCodeForViemError as a,getEvmClientForChain as o,getSolanaRpcForChain as s,waitForTimeoutOrAbort as c}from"../../_utils.js";import{markrGetCrossChainStatus as l}from"../_api.js";import{trackSameChainEvmTransfer as u}from"../../_tracking-utilities.js";import{CROSS_CHAIN_POLLING_INTERVAL_MS as d,FINALITY_MS_BY_CHAIN_ID as f,FINALITY_MS_BY_CHAIN_NAME_ALIAS as p,FINALITY_TIER_MAX_FINALITY_MS as m,SOLANA_POLLING_INTERVAL_MS as h,SOLANA_TX_TIMEOUT_MS as g}from"../constants.js";import{isHash as _}from"viem";import{assertIsSignature as v}from"@solana/kit";function y({apiOptions:e}){return({transfer:t,updateListener:r})=>t.sourceChain.chainId===t.targetChain.chainId?n(t.sourceChain.chainId)?b({transfer:t,updateListener:r}):u({transfer:t,updateListener:r}):S({transfer:t,updateListener:r},e)}function b({transfer:e,updateListener:t}){let n=new AbortController,r=()=>n.abort();return e.status===`source-pending`?{cancel:r,result:x(e,t,n.signal)}:{cancel:r,result:Promise.resolve(e)}}async function x(t,n,r){let{txHash:a}=t.source;try{v(a)}catch{let r={...t,errorCode:e.INVALID_PARAMS,failedAtMs:Date.now(),status:`failed`};return n(r),r}let o=s({chain:t.sourceChain}),l=Date.now();for(;!r.aborted;){if(Date.now()-l>g){let r={...t,errorCode:e.TIMEOUT,failedAtMs:Date.now(),status:`failed`};return n(r),r}try{let{value:i}=await o.getSignatureStatuses([a],{searchTransactionHistory:!0}).send(),s=i[0];if(!s){await c({timeoutMs:h,signal:r});continue}if(s.err!==null){let r={...t,errorCode:e.TRANSACTION_REVERTED,failedAtMs:Date.now(),status:`failed`};return n(r),r}if(s.confirmationStatus===`finalized`){let e={...t,completedAtMs:Date.now(),source:{...t.source,confirmationCount:t.source.requiredConfirmationCount},status:`completed`,target:null};return n(e),e}let l=Number(s.confirmations??0),u=Math.min(l,t.source.requiredConfirmationCount-1);u!==t.source.confirmationCount&&(t={...t,source:{...t.source,confirmationCount:u}},n(t)),await c({timeoutMs:h,signal:r})}catch(e){let r={...t,errorCode:i(e),failedAtMs:Date.now(),status:`failed`};return n(r),r}}return t}function S({transfer:e,updateListener:t},n){let r=new AbortController;return{cancel:()=>{r.abort()},result:(async()=>{let i=structuredClone(e);for(;!r.signal.aborted;){let e=await C(i,n,r.signal);if(r.signal.aborted)break;if(i=e,t(e),e.status===`completed`||e.status===`failed`)return e;let a=E(e);await new Promise(e=>{let t=setTimeout(e,a);r.signal.addEventListener(`abort`,()=>clearTimeout(t),{once:!0})})}return i})()}}async function C(i,s,c){if(i.status===`completed`||i.status===`failed`)return i;if(!j(i.source.txHash,i.sourceChain.chainId))return{...i,errorCode:e.INVALID_PARAMS,errorReason:`Invalid source transaction hash`,failedAtMs:Date.now(),status:`failed`};if(i.status===`source-pending`){if(t(i.sourceChain.chainId)){let t=i.source.txHash;if(!_(t))return{...i,errorCode:e.INVALID_PARAMS,errorReason:`Invalid source transaction hash`,failedAtMs:Date.now(),status:`failed`};let n=o({chain:i.sourceChain});try{let a=await r(n.waitForTransactionReceipt({hash:t}),c);if(a.status===`aborted`)return i;let o=a.value;return o.status===`reverted`?{...i,errorCode:e.TRANSACTION_REVERTED,errorReason:`Source transaction was reverted`,failedAtMs:Date.now(),status:`failed`}:(await w(n,i.sourceChain.chainId,i.sourceChain.chainName,o.blockNumber,c)).status===`aborted`?i:N(i)}catch(e){return{...i,errorCode:a(e),errorReason:`Failed to confirm source transaction finality`,failedAtMs:Date.now(),status:`failed`}}}if(n(i.sourceChain.chainId)){let t=i.source.txHash;try{v(t)}catch{return{...i,errorCode:e.INVALID_PARAMS,errorReason:`Invalid source transaction hash`,failedAtMs:Date.now(),status:`failed`}}let n=await A(i.sourceChain,t,c);return n.status===`aborted`?i:n.status===`failed`?{...i,errorCode:n.errorCode,errorReason:`Failed to confirm source transaction finality`,failedAtMs:Date.now(),status:`failed`}:N(i)}}try{let t=await l(s,i.source.txHash,{signal:c}),n=P(i,t);switch(t.status){case`failed`:return{...n,errorCode:e.TRANSACTION_REVERTED,errorReason:`Transaction execution failed.`,failedAtMs:R(t),status:`failed`};case`pending`:return M(t.sourceChain.finalized)?N(n):n;case`committed`:case`pending_execution`:return F(n,t);case`completed`:return I(n,t);default:return L(n,t)}}catch(t){return console.error(`[Unified Asset Transfer] Error fetching cross-chain status from Markr API`,{error:t,now:Date.now()}),{...i,errorCode:e.UNKNOWN,errorReason:`Failed to fetch cross-chain tx status`,failedAtMs:Date.now(),status:`failed`}}}async function w(e,t,n,i,a){let o=T(t,n);for(;!a.aborted;){let t=await r(e.getBlock({blockTag:`finalized`}),a);if(t.status===`aborted`)return{status:`aborted`};if(t.value.number>=i)return{status:`ok`};await c({timeoutMs:o,signal:a})}return{status:`aborted`}}function T(e,t){return d[k(D(e,t))]}function E(e){return e.status===`source-pending`?T(e.sourceChain.chainId,e.sourceChain.chainName):T(e.targetChain.chainId,e.targetChain.chainName)}function D(e,t){let n=f[e];if(n!==void 0)return n;let r=O(t);return p.find(({aliases:e})=>e.some(e=>r.includes(e)))?.finalityMs}function O(e){return e.toLowerCase().replace(/[^a-z0-9]/g,``)}function k(e){return e===void 0?`medium`:e<=m.fast?`fast`:e<=m.medium?`medium`:e<=m.slow?`slow`:`verySlow`}async function A(t,n,r){let a=s({chain:t}),o=Date.now();for(;!r.aborted;){if(Date.now()-o>g)return{status:`failed`,errorCode:e.TIMEOUT};try{let{value:t}=await a.getSignatureStatuses([n],{searchTransactionHistory:!0}).send(),i=t[0];if(!i){await c({timeoutMs:h,signal:r});continue}if(i.err!==null)return{status:`failed`,errorCode:e.TRANSACTION_REVERTED};if(i.confirmationStatus===`finalized`)return{status:`ok`};await c({timeoutMs:h,signal:r})}catch(e){return{status:`failed`,errorCode:i(e)}}}return{status:`aborted`}}function j(e,r){if(t(r))return _(e);if(n(r))try{return v(e),!0}catch{return!1}return!1}function M(e){return e===!0||typeof e==`string`}function N(e){return{...e,source:{...e.source,confirmationCount:2,requiredConfirmationCount:2},status:`source-completed`}}function P(e,t){let n={...e.metadata??{}};return t.destinationChain.bridgeHash&&(n.bridgeHash=t.destinationChain.bridgeHash),t.debug&&(n.debug=t.debug),Object.keys(n).length===0?e:{...e,metadata:n}}function F(e,t){let{timestamp:n,transactionHash:r}=t.destinationChain;return{...e,source:{...e.source,confirmationCount:2,requiredConfirmationCount:2},status:`target-pending`,target:{confirmationCount:r?1:0,requiredConfirmationCount:2,startedAtMs:n?new Date(n).getTime():Date.now(),txHash:r??void 0}}}function I(e,t){let{timestamp:n,transactionHash:r}=t.destinationChain;return{...e,completedAtMs:R(t),status:`completed`,source:{...e.source,confirmationCount:2,requiredConfirmationCount:2},target:r?{txHash:r,confirmationCount:2,requiredConfirmationCount:2,startedAtMs:n?new Date(n).getTime():Date.now()}:null}}function L(e,t){return t.progress.executed===!0?I(e,t):t.progress.committed===!0?F(e,t):M(t.sourceChain.finalized)?N(e):{...e,source:{...e.source,confirmationCount:0,requiredConfirmationCount:2},status:`source-pending`}}function R(e){return e.destinationChain.finalized?new Date(e.destinationChain.finalized).getTime():e.destinationChain.timestamp?new Date(e.destinationChain.timestamp).getTime():e.sourceChain.finalized?typeof e.sourceChain.finalized==`boolean`&&e.sourceChain.finalized===!0?new Date(e.sourceChain.timestamp).getTime():new Date(e.sourceChain.finalized).getTime():new Date(e.sourceChain.timestamp).getTime()}export{y as trackTransferFactory};
2
2
  //# sourceMappingURL=track-transfer.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"track-transfer.js","names":[],"sources":["../../../../src/transfer-service/markr/_handlers/track-transfer.ts"],"sourcesContent":["import { assertIsSignature, type Signature } from '@solana/kit';\nimport { isHash } from 'viem';\nimport { isEvmNamespace, isSolanaNamespace } from '../../../_utils/chain';\nimport { ErrorCode } from '../../../errors';\nimport type { TransferService, TrackTransferProps } from '../../../types/service';\nimport type {\n CompletedTransfer,\n FailedTransfer,\n SourceCompletedTransfer,\n SourcePendingTransfer,\n TargetPendingTransfer,\n Transfer,\n} from '../../../types/transfer';\nimport {\n awaitOrAbort,\n getErrorCodeForSolanaRpcError,\n getErrorCodeForViemError,\n getEvmClientForChain,\n getSolanaRpcForChain,\n waitForTimeoutOrAbort,\n} from '../../_utils';\nimport { trackSameChainEvmTransfer } from '../../_tracking-utilities';\nimport { markrGetCrossChainStatus, type ApiOptions } from '../_api';\nimport type { CrossChainStatusResponse } from '../_schema';\nimport { SOLANA_POLLING_INTERVAL_MS, SOLANA_TX_TIMEOUT_MS } from '../constants';\nimport type { Caip2ChainId } from '../../../mod';\n\nconst CROSS_CHAIN_POLLING_INTERVAL_MS = 3_000;\n\ntype InFlightTransfer = SourcePendingTransfer | SourceCompletedTransfer | TargetPendingTransfer;\n\nexport interface TrackTransferFactoryConfig {\n apiOptions: ApiOptions;\n}\n\nexport function trackTransferFactory({ apiOptions }: TrackTransferFactoryConfig): TransferService['trackTransfer'] {\n return ({ transfer, updateListener }) => {\n if (transfer.sourceChain.chainId === transfer.targetChain.chainId) {\n if (isSolanaNamespace(transfer.sourceChain.chainId)) {\n return _trackSameChainSolanaTransfer({ transfer, updateListener });\n }\n return trackSameChainEvmTransfer({ transfer, updateListener });\n }\n\n return _trackCrossChainTransfer({ transfer, updateListener }, apiOptions);\n };\n}\n\nexport function _trackSameChainSolanaTransfer({ transfer, updateListener }: TrackTransferProps): {\n cancel: () => void;\n result: Promise<Transfer>;\n} {\n const ac = new AbortController();\n const cancel = () => ac.abort();\n\n if (transfer.status !== 'source-pending') {\n return { cancel, result: Promise.resolve(transfer) };\n }\n\n return { cancel, result: _pollSolanaSignatureStatus(transfer, updateListener, ac.signal) };\n}\n\nasync function _pollSolanaSignatureStatus(\n transfer: SourcePendingTransfer,\n updateListener: (transfer: Transfer) => void,\n signal: AbortSignal,\n): Promise<Transfer> {\n const { txHash } = transfer.source;\n\n try {\n assertIsSignature(txHash);\n } catch {\n const failed: FailedTransfer = {\n ...transfer,\n errorCode: ErrorCode.INVALID_PARAMS,\n failedAtMs: Date.now(),\n status: 'failed',\n };\n updateListener(failed);\n return failed;\n }\n\n const rpc = getSolanaRpcForChain({ chain: transfer.sourceChain });\n const startTime = Date.now();\n\n while (!signal.aborted) {\n if (Date.now() - startTime > SOLANA_TX_TIMEOUT_MS) {\n const failed: FailedTransfer = {\n ...transfer,\n errorCode: ErrorCode.TIMEOUT,\n failedAtMs: Date.now(),\n status: 'failed',\n };\n updateListener(failed);\n return failed;\n }\n\n try {\n const { value } = await rpc.getSignatureStatuses([txHash], { searchTransactionHistory: true }).send();\n const status = value[0];\n\n if (!status) {\n await waitForTimeoutOrAbort({ timeoutMs: SOLANA_POLLING_INTERVAL_MS, signal });\n continue;\n }\n\n if (status.err !== null) {\n const failed: FailedTransfer = {\n ...transfer,\n errorCode: ErrorCode.TRANSACTION_REVERTED,\n failedAtMs: Date.now(),\n status: 'failed',\n };\n updateListener(failed);\n return failed;\n }\n\n if (status.confirmationStatus === 'finalized') {\n const completed: CompletedTransfer = {\n ...transfer,\n completedAtMs: Date.now(),\n source: {\n ...transfer.source,\n confirmationCount: transfer.source.requiredConfirmationCount,\n },\n status: 'completed',\n target: null,\n };\n updateListener(completed);\n return completed;\n }\n\n const confirmations = Number(status.confirmations ?? 0);\n const cappedCount = Math.min(confirmations, transfer.source.requiredConfirmationCount - 1);\n\n if (cappedCount !== transfer.source.confirmationCount) {\n transfer = {\n ...transfer,\n source: {\n ...transfer.source,\n confirmationCount: cappedCount,\n },\n };\n updateListener(transfer);\n }\n\n await waitForTimeoutOrAbort({ timeoutMs: SOLANA_POLLING_INTERVAL_MS, signal });\n } catch (error) {\n const failed: FailedTransfer = {\n ...transfer,\n errorCode: getErrorCodeForSolanaRpcError(error),\n failedAtMs: Date.now(),\n status: 'failed',\n };\n updateListener(failed);\n return failed;\n }\n }\n\n return transfer;\n}\n\nexport function _trackCrossChainTransfer(\n { transfer, updateListener }: TrackTransferProps,\n apiOptions: ApiOptions,\n): { cancel: () => void; result: Promise<Transfer> } {\n const ac = new AbortController();\n const cancel = () => {\n ac.abort();\n };\n\n const executeTracking = async (): Promise<Transfer> => {\n let currentTransfer: Transfer = structuredClone(transfer);\n while (!ac.signal.aborted) {\n const updatedTransfer = await _getMarkrCrossChainTxStatus(currentTransfer, apiOptions, ac.signal);\n\n if (ac.signal.aborted) {\n break;\n }\n\n currentTransfer = updatedTransfer;\n\n updateListener(updatedTransfer);\n\n if (updatedTransfer.status === 'completed' || updatedTransfer.status === 'failed') {\n return updatedTransfer;\n }\n\n // Wait before polling again.\n await new Promise((resolve) => {\n const timeoutId = setTimeout(resolve, CROSS_CHAIN_POLLING_INTERVAL_MS);\n ac.signal.addEventListener('abort', () => clearTimeout(timeoutId), { once: true });\n });\n }\n\n return currentTransfer;\n };\n\n return {\n cancel,\n result: executeTracking(),\n };\n}\n\nexport async function _getMarkrCrossChainTxStatus(\n transfer: Transfer,\n apiOptions: ApiOptions,\n signal: AbortSignal,\n): Promise<Transfer> {\n if (transfer.status === 'completed' || transfer.status === 'failed') {\n return transfer;\n }\n\n // We only support tracking EVM or Solana source transactions.\n if (!_isValidSourceTxHash(transfer.source.txHash, transfer.sourceChain.chainId)) {\n const failedTransfer: FailedTransfer = {\n ...transfer,\n errorCode: ErrorCode.INVALID_PARAMS,\n errorReason: 'Invalid source transaction hash',\n failedAtMs: Date.now(),\n status: 'failed',\n };\n return failedTransfer;\n }\n\n // If transfer is `source-pending`, we first confirm source-chain finality before\n // querying Markr's cross-chain status endpoint.\n // Once source finality is confirmed, we mark the transfer as source-completed and\n // defer Markr polling to subsequent iterations.\n if (transfer.status === 'source-pending') {\n if (isEvmNamespace(transfer.sourceChain.chainId)) {\n const sourceTxHash = transfer.source.txHash;\n\n if (!isHash(sourceTxHash)) {\n const failedTransfer: FailedTransfer = {\n ...transfer,\n errorCode: ErrorCode.INVALID_PARAMS,\n errorReason: 'Invalid source transaction hash',\n failedAtMs: Date.now(),\n status: 'failed',\n };\n\n return failedTransfer;\n }\n\n const client = getEvmClientForChain({ chain: transfer.sourceChain });\n\n try {\n const receiptResult = await awaitOrAbort(\n client.waitForTransactionReceipt({\n hash: sourceTxHash,\n }),\n signal,\n );\n\n if (receiptResult.status === 'aborted') {\n return transfer;\n }\n\n const receipt = receiptResult.value;\n\n if (receipt.status === 'reverted') {\n const failedTransfer: FailedTransfer = {\n ...transfer,\n errorCode: ErrorCode.TRANSACTION_REVERTED,\n errorReason: 'Source transaction was reverted',\n failedAtMs: Date.now(),\n status: 'failed',\n };\n return failedTransfer;\n }\n\n const finalityResult = await _waitForEvmSourceFinalization(client, receipt.blockNumber, signal);\n if (finalityResult.status === 'aborted') {\n return transfer;\n }\n\n return _toSourceCompletedTransfer(transfer);\n } catch (error) {\n const failedTransfer: FailedTransfer = {\n ...transfer,\n errorCode: getErrorCodeForViemError(error),\n errorReason: 'Failed to confirm source transaction finality',\n failedAtMs: Date.now(),\n status: 'failed',\n };\n return failedTransfer;\n }\n }\n\n if (isSolanaNamespace(transfer.sourceChain.chainId)) {\n const sourceTxHash = transfer.source.txHash;\n\n try {\n assertIsSignature(sourceTxHash);\n } catch {\n const failedTransfer: FailedTransfer = {\n ...transfer,\n errorCode: ErrorCode.INVALID_PARAMS,\n errorReason: 'Invalid source transaction hash',\n failedAtMs: Date.now(),\n status: 'failed',\n };\n return failedTransfer;\n }\n\n const finalityResult = await _waitForSolanaSourceFinalization(transfer.sourceChain, sourceTxHash, signal);\n\n if (finalityResult.status === 'aborted') {\n return transfer;\n }\n\n if (finalityResult.status === 'failed') {\n const failedTransfer: FailedTransfer = {\n ...transfer,\n errorCode: finalityResult.errorCode,\n errorReason: 'Failed to confirm source transaction finality',\n failedAtMs: Date.now(),\n status: 'failed',\n };\n return failedTransfer;\n }\n\n return _toSourceCompletedTransfer(transfer);\n }\n }\n\n try {\n const statusResponse = await markrGetCrossChainStatus(apiOptions, transfer.source.txHash, { signal });\n const transferWithMarkrMetadata = _withMarkrTrackingMetadata(transfer, statusResponse);\n\n switch (statusResponse.status) {\n case 'failed': {\n const failedTransfer: FailedTransfer = {\n ...transferWithMarkrMetadata,\n errorCode: ErrorCode.TRANSACTION_REVERTED,\n errorReason: 'Transaction execution failed.',\n failedAtMs: _getLastStatusActivityTime(statusResponse),\n status: 'failed',\n };\n\n return failedTransfer;\n }\n\n case 'pending': {\n return _isMarkrSourceFinalized(statusResponse.sourceChain.finalized)\n ? _toSourceCompletedTransfer(transferWithMarkrMetadata)\n : transferWithMarkrMetadata;\n }\n\n case 'committed':\n case 'pending_execution': {\n return _toTargetPendingTransfer(transferWithMarkrMetadata, statusResponse);\n }\n\n case 'completed': {\n return _toCompletedTransfer(transferWithMarkrMetadata, statusResponse);\n }\n\n case 'unknown':\n default: {\n return _deriveTransferFromUnknownStatus(transferWithMarkrMetadata, statusResponse);\n }\n }\n } catch (error) {\n // TODO: Clean this console.error up before v1 release.\n // This is just here for now to try to track down tracking issues.\n console.error('[Unified Asset Transfer] Error fetching cross-chain status from Markr API', {\n error,\n now: Date.now(),\n });\n\n const failedTransfer: FailedTransfer = {\n ...transfer,\n errorCode: ErrorCode.UNKNOWN,\n errorReason: 'Failed to fetch cross-chain tx status',\n failedAtMs: Date.now(),\n status: 'failed',\n };\n return failedTransfer;\n }\n}\n\nasync function _waitForEvmSourceFinalization(\n client: ReturnType<typeof getEvmClientForChain>,\n txBlockNumber: bigint,\n signal: AbortSignal,\n): Promise<{ status: 'aborted' } | { status: 'ok' }> {\n while (!signal.aborted) {\n const finalizedBlockResult = await awaitOrAbort(client.getBlock({ blockTag: 'finalized' }), signal);\n\n if (finalizedBlockResult.status === 'aborted') {\n return { status: 'aborted' };\n }\n\n if (finalizedBlockResult.value.number >= txBlockNumber) {\n return { status: 'ok' };\n }\n\n await waitForTimeoutOrAbort({\n timeoutMs: CROSS_CHAIN_POLLING_INTERVAL_MS,\n signal,\n });\n }\n\n return { status: 'aborted' };\n}\n\nasync function _waitForSolanaSourceFinalization(\n chain: SourcePendingTransfer['sourceChain'],\n txHash: Signature,\n signal: AbortSignal,\n): Promise<{ status: 'aborted' } | { status: 'ok' } | { status: 'failed'; errorCode: ErrorCode }> {\n const rpc = getSolanaRpcForChain({ chain });\n const startTime = Date.now();\n\n while (!signal.aborted) {\n if (Date.now() - startTime > SOLANA_TX_TIMEOUT_MS) {\n return {\n status: 'failed',\n errorCode: ErrorCode.TIMEOUT,\n };\n }\n\n try {\n const { value } = await rpc.getSignatureStatuses([txHash], { searchTransactionHistory: true }).send();\n const txStatus = value[0];\n\n if (!txStatus) {\n await waitForTimeoutOrAbort({ timeoutMs: SOLANA_POLLING_INTERVAL_MS, signal });\n continue;\n }\n\n if (txStatus.err !== null) {\n return {\n status: 'failed',\n errorCode: ErrorCode.TRANSACTION_REVERTED,\n };\n }\n\n if (txStatus.confirmationStatus === 'finalized') {\n return { status: 'ok' };\n }\n\n await waitForTimeoutOrAbort({ timeoutMs: SOLANA_POLLING_INTERVAL_MS, signal });\n } catch (error) {\n return {\n status: 'failed',\n errorCode: getErrorCodeForSolanaRpcError(error),\n };\n }\n }\n\n return { status: 'aborted' };\n}\n\nfunction _isValidSourceTxHash(txHash: string, sourceChainId: Caip2ChainId): boolean {\n if (isEvmNamespace(sourceChainId)) {\n return isHash(txHash);\n }\n\n if (isSolanaNamespace(sourceChainId)) {\n try {\n assertIsSignature(txHash);\n return true;\n } catch {\n return false;\n }\n }\n\n return false;\n}\n\nfunction _isMarkrSourceFinalized(finalized: CrossChainStatusResponse['sourceChain']['finalized']): boolean {\n return finalized === true || typeof finalized === 'string';\n}\n\nfunction _toSourceCompletedTransfer(transfer: InFlightTransfer): SourceCompletedTransfer {\n return {\n ...transfer,\n source: {\n ...transfer.source,\n confirmationCount: 2,\n requiredConfirmationCount: 2,\n },\n status: 'source-completed',\n };\n}\n\nfunction _withMarkrTrackingMetadata(\n transfer: InFlightTransfer,\n statusResponse: CrossChainStatusResponse,\n): InFlightTransfer {\n const metadata: Record<string, unknown> = { ...(transfer.metadata ?? {}) };\n\n if (statusResponse.destinationChain.bridgeHash) {\n metadata.bridgeHash = statusResponse.destinationChain.bridgeHash;\n }\n\n if (statusResponse.debug) {\n metadata.debug = statusResponse.debug;\n }\n\n if (Object.keys(metadata).length === 0) {\n return transfer;\n }\n\n return {\n ...transfer,\n metadata,\n };\n}\n\nfunction _toTargetPendingTransfer(\n transfer: InFlightTransfer,\n statusResponse: CrossChainStatusResponse,\n): TargetPendingTransfer {\n const { timestamp, transactionHash } = statusResponse.destinationChain;\n\n return {\n ...transfer,\n source: {\n ...transfer.source,\n confirmationCount: 2,\n requiredConfirmationCount: 2,\n },\n status: 'target-pending',\n target: {\n confirmationCount: transactionHash ? 1 : 0,\n requiredConfirmationCount: 2,\n startedAtMs: timestamp ? new Date(timestamp).getTime() : Date.now(),\n txHash: transactionHash ?? undefined,\n },\n };\n}\n\nfunction _toCompletedTransfer(transfer: InFlightTransfer, statusResponse: CrossChainStatusResponse): CompletedTransfer {\n const { timestamp, transactionHash } = statusResponse.destinationChain;\n\n return {\n ...transfer,\n completedAtMs: _getLastStatusActivityTime(statusResponse),\n status: 'completed',\n source: {\n ...transfer.source,\n confirmationCount: 2,\n requiredConfirmationCount: 2,\n },\n target: transactionHash\n ? {\n txHash: transactionHash,\n confirmationCount: 2,\n requiredConfirmationCount: 2,\n startedAtMs: timestamp ? new Date(timestamp).getTime() : Date.now(),\n }\n : null,\n };\n}\n\nfunction _deriveTransferFromUnknownStatus(\n transfer: InFlightTransfer,\n statusResponse: CrossChainStatusResponse,\n): Transfer {\n if (statusResponse.progress.executed === true) {\n return _toCompletedTransfer(transfer, statusResponse);\n }\n\n if (statusResponse.progress.committed === true) {\n return _toTargetPendingTransfer(transfer, statusResponse);\n }\n\n if (_isMarkrSourceFinalized(statusResponse.sourceChain.finalized)) {\n return _toSourceCompletedTransfer(transfer);\n }\n\n return {\n ...transfer,\n source: {\n ...transfer.source,\n confirmationCount: 0,\n requiredConfirmationCount: 2,\n },\n status: 'source-pending',\n };\n}\n\nfunction _getLastStatusActivityTime(response: CrossChainStatusResponse): number {\n if (response.destinationChain.finalized) {\n return new Date(response.destinationChain.finalized).getTime();\n }\n\n if (response.destinationChain.timestamp) {\n return new Date(response.destinationChain.timestamp).getTime();\n }\n\n if (response.sourceChain.finalized) {\n if (typeof response.sourceChain.finalized === 'boolean' && response.sourceChain.finalized === true) {\n // Handle case where finalized is returned as boolean `true` instead of a timestamp.\n return new Date(response.sourceChain.timestamp).getTime();\n }\n return new Date(response.sourceChain.finalized).getTime();\n }\n\n return new Date(response.sourceChain.timestamp).getTime();\n}\n"],"mappings":"mmBA2BA,MAAM,EAAkC,IAQxC,SAAgB,EAAqB,CAAE,cAA4E,CACjH,OAAQ,CAAE,WAAU,oBACd,EAAS,YAAY,UAAY,EAAS,YAAY,QACpD,EAAkB,EAAS,YAAY,QAAQ,CAC1C,EAA8B,CAAE,WAAU,iBAAgB,CAAC,CAE7D,EAA0B,CAAE,WAAU,iBAAgB,CAAC,CAGzD,EAAyB,CAAE,WAAU,iBAAgB,CAAE,EAAW,CAI7E,SAAgB,EAA8B,CAAE,WAAU,kBAGxD,CACA,IAAM,EAAK,IAAI,gBACT,MAAe,EAAG,OAAO,CAM/B,OAJI,EAAS,SAAW,iBAIjB,CAAE,SAAQ,OAAQ,EAA2B,EAAU,EAAgB,EAAG,OAAO,CAAE,CAHjF,CAAE,SAAQ,OAAQ,QAAQ,QAAQ,EAAS,CAAE,CAMxD,eAAe,EACb,EACA,EACA,EACmB,CACnB,GAAM,CAAE,UAAW,EAAS,OAE5B,GAAI,CACF,EAAkB,EAAO,MACnB,CACN,IAAM,EAAyB,CAC7B,GAAG,EACH,UAAW,EAAU,eACrB,WAAY,KAAK,KAAK,CACtB,OAAQ,SACT,CAED,OADA,EAAe,EAAO,CACf,EAGT,IAAM,EAAM,EAAqB,CAAE,MAAO,EAAS,YAAa,CAAC,CAC3D,EAAY,KAAK,KAAK,CAE5B,KAAO,CAAC,EAAO,SAAS,CACtB,GAAI,KAAK,KAAK,CAAG,EAAY,EAAsB,CACjD,IAAM,EAAyB,CAC7B,GAAG,EACH,UAAW,EAAU,QACrB,WAAY,KAAK,KAAK,CACtB,OAAQ,SACT,CAED,OADA,EAAe,EAAO,CACf,EAGT,GAAI,CACF,GAAM,CAAE,SAAU,MAAM,EAAI,qBAAqB,CAAC,EAAO,CAAE,CAAE,yBAA0B,GAAM,CAAC,CAAC,MAAM,CAC/F,EAAS,EAAM,GAErB,GAAI,CAAC,EAAQ,CACX,MAAM,EAAsB,CAAE,UAAW,EAA4B,SAAQ,CAAC,CAC9E,SAGF,GAAI,EAAO,MAAQ,KAAM,CACvB,IAAM,EAAyB,CAC7B,GAAG,EACH,UAAW,EAAU,qBACrB,WAAY,KAAK,KAAK,CACtB,OAAQ,SACT,CAED,OADA,EAAe,EAAO,CACf,EAGT,GAAI,EAAO,qBAAuB,YAAa,CAC7C,IAAM,EAA+B,CACnC,GAAG,EACH,cAAe,KAAK,KAAK,CACzB,OAAQ,CACN,GAAG,EAAS,OACZ,kBAAmB,EAAS,OAAO,0BACpC,CACD,OAAQ,YACR,OAAQ,KACT,CAED,OADA,EAAe,EAAU,CAClB,EAGT,IAAM,EAAgB,OAAO,EAAO,eAAiB,EAAE,CACjD,EAAc,KAAK,IAAI,EAAe,EAAS,OAAO,0BAA4B,EAAE,CAEtF,IAAgB,EAAS,OAAO,oBAClC,EAAW,CACT,GAAG,EACH,OAAQ,CACN,GAAG,EAAS,OACZ,kBAAmB,EACpB,CACF,CACD,EAAe,EAAS,EAG1B,MAAM,EAAsB,CAAE,UAAW,EAA4B,SAAQ,CAAC,OACvE,EAAO,CACd,IAAM,EAAyB,CAC7B,GAAG,EACH,UAAW,EAA8B,EAAM,CAC/C,WAAY,KAAK,KAAK,CACtB,OAAQ,SACT,CAED,OADA,EAAe,EAAO,CACf,GAIX,OAAO,EAGT,SAAgB,EACd,CAAE,WAAU,kBACZ,EACmD,CACnD,IAAM,EAAK,IAAI,gBAgCf,MAAO,CACL,WAhCmB,CACnB,EAAG,OAAO,EAgCV,QA7BsB,SAA+B,CACrD,IAAI,EAA4B,gBAAgB,EAAS,CACzD,KAAO,CAAC,EAAG,OAAO,SAAS,CACzB,IAAM,EAAkB,MAAM,EAA4B,EAAiB,EAAY,EAAG,OAAO,CAEjG,GAAI,EAAG,OAAO,QACZ,MAOF,GAJA,EAAkB,EAElB,EAAe,EAAgB,CAE3B,EAAgB,SAAW,aAAe,EAAgB,SAAW,SACvE,OAAO,EAIT,MAAM,IAAI,QAAS,GAAY,CAC7B,IAAM,EAAY,WAAW,EAAS,EAAgC,CACtE,EAAG,OAAO,iBAAiB,YAAe,aAAa,EAAU,CAAE,CAAE,KAAM,GAAM,CAAC,EAClF,CAGJ,OAAO,KAKkB,CAC1B,CAGH,eAAsB,EACpB,EACA,EACA,EACmB,CACnB,GAAI,EAAS,SAAW,aAAe,EAAS,SAAW,SACzD,OAAO,EAIT,GAAI,CAAC,EAAqB,EAAS,OAAO,OAAQ,EAAS,YAAY,QAAQ,CAQ7E,MAPuC,CACrC,GAAG,EACH,UAAW,EAAU,eACrB,YAAa,kCACb,WAAY,KAAK,KAAK,CACtB,OAAQ,SACT,CAQH,GAAI,EAAS,SAAW,iBAAkB,CACxC,GAAI,EAAe,EAAS,YAAY,QAAQ,CAAE,CAChD,IAAM,EAAe,EAAS,OAAO,OAErC,GAAI,CAAC,EAAO,EAAa,CASvB,MARuC,CACrC,GAAG,EACH,UAAW,EAAU,eACrB,YAAa,kCACb,WAAY,KAAK,KAAK,CACtB,OAAQ,SACT,CAKH,IAAM,EAAS,EAAqB,CAAE,MAAO,EAAS,YAAa,CAAC,CAEpE,GAAI,CACF,IAAM,EAAgB,MAAM,EAC1B,EAAO,0BAA0B,CAC/B,KAAM,EACP,CAAC,CACF,EACD,CAED,GAAI,EAAc,SAAW,UAC3B,OAAO,EAGT,IAAM,EAAU,EAAc,MAkB9B,OAhBI,EAAQ,SAAW,WACkB,CACrC,GAAG,EACH,UAAW,EAAU,qBACrB,YAAa,kCACb,WAAY,KAAK,KAAK,CACtB,OAAQ,SACT,EAIoB,MAAM,EAA8B,EAAQ,EAAQ,YAAa,EAAO,EAC5E,SAAW,UACrB,EAGF,EAA2B,EAAS,OACpC,EAAO,CAQd,MAPuC,CACrC,GAAG,EACH,UAAW,EAAyB,EAAM,CAC1C,YAAa,gDACb,WAAY,KAAK,KAAK,CACtB,OAAQ,SACT,EAKL,GAAI,EAAkB,EAAS,YAAY,QAAQ,CAAE,CACnD,IAAM,EAAe,EAAS,OAAO,OAErC,GAAI,CACF,EAAkB,EAAa,MACzB,CAQN,MAPuC,CACrC,GAAG,EACH,UAAW,EAAU,eACrB,YAAa,kCACb,WAAY,KAAK,KAAK,CACtB,OAAQ,SACT,CAIH,IAAM,EAAiB,MAAM,EAAiC,EAAS,YAAa,EAAc,EAAO,CAiBzG,OAfI,EAAe,SAAW,UACrB,EAGL,EAAe,SAAW,SACW,CACrC,GAAG,EACH,UAAW,EAAe,UAC1B,YAAa,gDACb,WAAY,KAAK,KAAK,CACtB,OAAQ,SACT,CAII,EAA2B,EAAS,EAI/C,GAAI,CACF,IAAM,EAAiB,MAAM,EAAyB,EAAY,EAAS,OAAO,OAAQ,CAAE,SAAQ,CAAC,CAC/F,EAA4B,EAA2B,EAAU,EAAe,CAEtF,OAAQ,EAAe,OAAvB,CACE,IAAK,SASH,MARuC,CACrC,GAAG,EACH,UAAW,EAAU,qBACrB,YAAa,gCACb,WAAY,EAA2B,EAAe,CACtD,OAAQ,SACT,CAKH,IAAK,UACH,OAAO,EAAwB,EAAe,YAAY,UAAU,CAChE,EAA2B,EAA0B,CACrD,EAGN,IAAK,YACL,IAAK,oBACH,OAAO,EAAyB,EAA2B,EAAe,CAG5E,IAAK,YACH,OAAO,EAAqB,EAA2B,EAAe,CAIxE,QACE,OAAO,EAAiC,EAA2B,EAAe,QAG/E,EAAO,CAed,OAZA,QAAQ,MAAM,4EAA6E,CACzF,QACA,IAAK,KAAK,KAAK,CAChB,CAAC,CAEqC,CACrC,GAAG,EACH,UAAW,EAAU,QACrB,YAAa,wCACb,WAAY,KAAK,KAAK,CACtB,OAAQ,SACT,EAKL,eAAe,EACb,EACA,EACA,EACmD,CACnD,KAAO,CAAC,EAAO,SAAS,CACtB,IAAM,EAAuB,MAAM,EAAa,EAAO,SAAS,CAAE,SAAU,YAAa,CAAC,CAAE,EAAO,CAEnG,GAAI,EAAqB,SAAW,UAClC,MAAO,CAAE,OAAQ,UAAW,CAG9B,GAAI,EAAqB,MAAM,QAAU,EACvC,MAAO,CAAE,OAAQ,KAAM,CAGzB,MAAM,EAAsB,CAC1B,UAAW,EACX,SACD,CAAC,CAGJ,MAAO,CAAE,OAAQ,UAAW,CAG9B,eAAe,EACb,EACA,EACA,EACgG,CAChG,IAAM,EAAM,EAAqB,CAAE,QAAO,CAAC,CACrC,EAAY,KAAK,KAAK,CAE5B,KAAO,CAAC,EAAO,SAAS,CACtB,GAAI,KAAK,KAAK,CAAG,EAAY,EAC3B,MAAO,CACL,OAAQ,SACR,UAAW,EAAU,QACtB,CAGH,GAAI,CACF,GAAM,CAAE,SAAU,MAAM,EAAI,qBAAqB,CAAC,EAAO,CAAE,CAAE,yBAA0B,GAAM,CAAC,CAAC,MAAM,CAC/F,EAAW,EAAM,GAEvB,GAAI,CAAC,EAAU,CACb,MAAM,EAAsB,CAAE,UAAW,EAA4B,SAAQ,CAAC,CAC9E,SAGF,GAAI,EAAS,MAAQ,KACnB,MAAO,CACL,OAAQ,SACR,UAAW,EAAU,qBACtB,CAGH,GAAI,EAAS,qBAAuB,YAClC,MAAO,CAAE,OAAQ,KAAM,CAGzB,MAAM,EAAsB,CAAE,UAAW,EAA4B,SAAQ,CAAC,OACvE,EAAO,CACd,MAAO,CACL,OAAQ,SACR,UAAW,EAA8B,EAAM,CAChD,EAIL,MAAO,CAAE,OAAQ,UAAW,CAG9B,SAAS,EAAqB,EAAgB,EAAsC,CAClF,GAAI,EAAe,EAAc,CAC/B,OAAO,EAAO,EAAO,CAGvB,GAAI,EAAkB,EAAc,CAClC,GAAI,CAEF,OADA,EAAkB,EAAO,CAClB,QACD,CACN,MAAO,GAIX,MAAO,GAGT,SAAS,EAAwB,EAA0E,CACzG,OAAO,IAAc,IAAQ,OAAO,GAAc,SAGpD,SAAS,EAA2B,EAAqD,CACvF,MAAO,CACL,GAAG,EACH,OAAQ,CACN,GAAG,EAAS,OACZ,kBAAmB,EACnB,0BAA2B,EAC5B,CACD,OAAQ,mBACT,CAGH,SAAS,EACP,EACA,EACkB,CAClB,IAAM,EAAoC,CAAE,GAAI,EAAS,UAAY,EAAE,CAAG,CAc1E,OAZI,EAAe,iBAAiB,aAClC,EAAS,WAAa,EAAe,iBAAiB,YAGpD,EAAe,QACjB,EAAS,MAAQ,EAAe,OAG9B,OAAO,KAAK,EAAS,CAAC,SAAW,EAC5B,EAGF,CACL,GAAG,EACH,WACD,CAGH,SAAS,EACP,EACA,EACuB,CACvB,GAAM,CAAE,YAAW,mBAAoB,EAAe,iBAEtD,MAAO,CACL,GAAG,EACH,OAAQ,CACN,GAAG,EAAS,OACZ,kBAAmB,EACnB,0BAA2B,EAC5B,CACD,OAAQ,iBACR,OAAQ,CACN,kBAAmB,EAAkB,EAAI,EACzC,0BAA2B,EAC3B,YAAa,EAAY,IAAI,KAAK,EAAU,CAAC,SAAS,CAAG,KAAK,KAAK,CACnE,OAAQ,GAAmB,IAAA,GAC5B,CACF,CAGH,SAAS,EAAqB,EAA4B,EAA6D,CACrH,GAAM,CAAE,YAAW,mBAAoB,EAAe,iBAEtD,MAAO,CACL,GAAG,EACH,cAAe,EAA2B,EAAe,CACzD,OAAQ,YACR,OAAQ,CACN,GAAG,EAAS,OACZ,kBAAmB,EACnB,0BAA2B,EAC5B,CACD,OAAQ,EACJ,CACE,OAAQ,EACR,kBAAmB,EACnB,0BAA2B,EAC3B,YAAa,EAAY,IAAI,KAAK,EAAU,CAAC,SAAS,CAAG,KAAK,KAAK,CACpE,CACD,KACL,CAGH,SAAS,EACP,EACA,EACU,CAaV,OAZI,EAAe,SAAS,WAAa,GAChC,EAAqB,EAAU,EAAe,CAGnD,EAAe,SAAS,YAAc,GACjC,EAAyB,EAAU,EAAe,CAGvD,EAAwB,EAAe,YAAY,UAAU,CACxD,EAA2B,EAAS,CAGtC,CACL,GAAG,EACH,OAAQ,CACN,GAAG,EAAS,OACZ,kBAAmB,EACnB,0BAA2B,EAC5B,CACD,OAAQ,iBACT,CAGH,SAAS,EAA2B,EAA4C,CAiB9E,OAhBI,EAAS,iBAAiB,UACrB,IAAI,KAAK,EAAS,iBAAiB,UAAU,CAAC,SAAS,CAG5D,EAAS,iBAAiB,UACrB,IAAI,KAAK,EAAS,iBAAiB,UAAU,CAAC,SAAS,CAG5D,EAAS,YAAY,UACnB,OAAO,EAAS,YAAY,WAAc,WAAa,EAAS,YAAY,YAAc,GAErF,IAAI,KAAK,EAAS,YAAY,UAAU,CAAC,SAAS,CAEpD,IAAI,KAAK,EAAS,YAAY,UAAU,CAAC,SAAS,CAGpD,IAAI,KAAK,EAAS,YAAY,UAAU,CAAC,SAAS"}
1
+ {"version":3,"file":"track-transfer.js","names":[],"sources":["../../../../src/transfer-service/markr/_handlers/track-transfer.ts"],"sourcesContent":["import { assertIsSignature, type Signature } from '@solana/kit';\nimport { isHash } from 'viem';\nimport { isEvmNamespace, isSolanaNamespace } from '../../../_utils/chain';\nimport { ErrorCode } from '../../../errors';\nimport type { TransferService, TrackTransferProps } from '../../../types/service';\nimport type {\n CompletedTransfer,\n FailedTransfer,\n SourceCompletedTransfer,\n SourcePendingTransfer,\n TargetPendingTransfer,\n Transfer,\n} from '../../../types/transfer';\nimport {\n awaitOrAbort,\n getErrorCodeForSolanaRpcError,\n getErrorCodeForViemError,\n getEvmClientForChain,\n getSolanaRpcForChain,\n waitForTimeoutOrAbort,\n} from '../../_utils';\nimport { trackSameChainEvmTransfer } from '../../_tracking-utilities';\nimport { markrGetCrossChainStatus, type ApiOptions } from '../_api';\nimport type { CrossChainStatusResponse } from '../_schema';\nimport {\n CROSS_CHAIN_POLLING_INTERVAL_MS,\n FINALITY_MS_BY_CHAIN_ID,\n FINALITY_MS_BY_CHAIN_NAME_ALIAS,\n FINALITY_TIER_MAX_FINALITY_MS,\n SOLANA_POLLING_INTERVAL_MS,\n SOLANA_TX_TIMEOUT_MS,\n} from '../constants';\nimport type { Caip2ChainId } from '../../../mod';\n\ntype FinalityTier = keyof typeof CROSS_CHAIN_POLLING_INTERVAL_MS;\n\ntype InFlightTransfer = SourcePendingTransfer | SourceCompletedTransfer | TargetPendingTransfer;\n\nexport interface TrackTransferFactoryConfig {\n apiOptions: ApiOptions;\n}\n\nexport function trackTransferFactory({ apiOptions }: TrackTransferFactoryConfig): TransferService['trackTransfer'] {\n return ({ transfer, updateListener }) => {\n if (transfer.sourceChain.chainId === transfer.targetChain.chainId) {\n if (isSolanaNamespace(transfer.sourceChain.chainId)) {\n return _trackSameChainSolanaTransfer({ transfer, updateListener });\n }\n return trackSameChainEvmTransfer({ transfer, updateListener });\n }\n\n return _trackCrossChainTransfer({ transfer, updateListener }, apiOptions);\n };\n}\n\nexport function _trackSameChainSolanaTransfer({ transfer, updateListener }: TrackTransferProps): {\n cancel: () => void;\n result: Promise<Transfer>;\n} {\n const ac = new AbortController();\n const cancel = () => ac.abort();\n\n if (transfer.status !== 'source-pending') {\n return { cancel, result: Promise.resolve(transfer) };\n }\n\n return { cancel, result: _pollSolanaSignatureStatus(transfer, updateListener, ac.signal) };\n}\n\nasync function _pollSolanaSignatureStatus(\n transfer: SourcePendingTransfer,\n updateListener: (transfer: Transfer) => void,\n signal: AbortSignal,\n): Promise<Transfer> {\n const { txHash } = transfer.source;\n\n try {\n assertIsSignature(txHash);\n } catch {\n const failed: FailedTransfer = {\n ...transfer,\n errorCode: ErrorCode.INVALID_PARAMS,\n failedAtMs: Date.now(),\n status: 'failed',\n };\n updateListener(failed);\n return failed;\n }\n\n const rpc = getSolanaRpcForChain({ chain: transfer.sourceChain });\n const startTime = Date.now();\n\n while (!signal.aborted) {\n if (Date.now() - startTime > SOLANA_TX_TIMEOUT_MS) {\n const failed: FailedTransfer = {\n ...transfer,\n errorCode: ErrorCode.TIMEOUT,\n failedAtMs: Date.now(),\n status: 'failed',\n };\n updateListener(failed);\n return failed;\n }\n\n try {\n const { value } = await rpc.getSignatureStatuses([txHash], { searchTransactionHistory: true }).send();\n const status = value[0];\n\n if (!status) {\n await waitForTimeoutOrAbort({ timeoutMs: SOLANA_POLLING_INTERVAL_MS, signal });\n continue;\n }\n\n if (status.err !== null) {\n const failed: FailedTransfer = {\n ...transfer,\n errorCode: ErrorCode.TRANSACTION_REVERTED,\n failedAtMs: Date.now(),\n status: 'failed',\n };\n updateListener(failed);\n return failed;\n }\n\n if (status.confirmationStatus === 'finalized') {\n const completed: CompletedTransfer = {\n ...transfer,\n completedAtMs: Date.now(),\n source: {\n ...transfer.source,\n confirmationCount: transfer.source.requiredConfirmationCount,\n },\n status: 'completed',\n target: null,\n };\n updateListener(completed);\n return completed;\n }\n\n const confirmations = Number(status.confirmations ?? 0);\n const cappedCount = Math.min(confirmations, transfer.source.requiredConfirmationCount - 1);\n\n if (cappedCount !== transfer.source.confirmationCount) {\n transfer = {\n ...transfer,\n source: {\n ...transfer.source,\n confirmationCount: cappedCount,\n },\n };\n updateListener(transfer);\n }\n\n await waitForTimeoutOrAbort({ timeoutMs: SOLANA_POLLING_INTERVAL_MS, signal });\n } catch (error) {\n const failed: FailedTransfer = {\n ...transfer,\n errorCode: getErrorCodeForSolanaRpcError(error),\n failedAtMs: Date.now(),\n status: 'failed',\n };\n updateListener(failed);\n return failed;\n }\n }\n\n return transfer;\n}\n\nexport function _trackCrossChainTransfer(\n { transfer, updateListener }: TrackTransferProps,\n apiOptions: ApiOptions,\n): { cancel: () => void; result: Promise<Transfer> } {\n const ac = new AbortController();\n const cancel = () => {\n ac.abort();\n };\n\n const executeTracking = async (): Promise<Transfer> => {\n let currentTransfer: Transfer = structuredClone(transfer);\n while (!ac.signal.aborted) {\n const updatedTransfer = await _getMarkrCrossChainTxStatus(currentTransfer, apiOptions, ac.signal);\n\n if (ac.signal.aborted) {\n break;\n }\n\n currentTransfer = updatedTransfer;\n\n updateListener(updatedTransfer);\n\n if (updatedTransfer.status === 'completed' || updatedTransfer.status === 'failed') {\n return updatedTransfer;\n }\n\n const pollingIntervalMs = _getPollingIntervalMsForTransfer(updatedTransfer);\n\n // Wait before polling again.\n await new Promise((resolve) => {\n const timeoutId = setTimeout(resolve, pollingIntervalMs);\n ac.signal.addEventListener('abort', () => clearTimeout(timeoutId), { once: true });\n });\n }\n\n return currentTransfer;\n };\n\n return {\n cancel,\n result: executeTracking(),\n };\n}\n\nexport async function _getMarkrCrossChainTxStatus(\n transfer: Transfer,\n apiOptions: ApiOptions,\n signal: AbortSignal,\n): Promise<Transfer> {\n if (transfer.status === 'completed' || transfer.status === 'failed') {\n return transfer;\n }\n\n // We only support tracking EVM or Solana source transactions.\n if (!_isValidSourceTxHash(transfer.source.txHash, transfer.sourceChain.chainId)) {\n const failedTransfer: FailedTransfer = {\n ...transfer,\n errorCode: ErrorCode.INVALID_PARAMS,\n errorReason: 'Invalid source transaction hash',\n failedAtMs: Date.now(),\n status: 'failed',\n };\n return failedTransfer;\n }\n\n // If transfer is `source-pending`, we first confirm source-chain finality before\n // querying Markr's cross-chain status endpoint.\n // Once source finality is confirmed, we mark the transfer as source-completed and\n // defer Markr polling to subsequent iterations.\n if (transfer.status === 'source-pending') {\n if (isEvmNamespace(transfer.sourceChain.chainId)) {\n const sourceTxHash = transfer.source.txHash;\n\n if (!isHash(sourceTxHash)) {\n const failedTransfer: FailedTransfer = {\n ...transfer,\n errorCode: ErrorCode.INVALID_PARAMS,\n errorReason: 'Invalid source transaction hash',\n failedAtMs: Date.now(),\n status: 'failed',\n };\n\n return failedTransfer;\n }\n\n const client = getEvmClientForChain({ chain: transfer.sourceChain });\n\n try {\n const receiptResult = await awaitOrAbort(\n client.waitForTransactionReceipt({\n hash: sourceTxHash,\n }),\n signal,\n );\n\n if (receiptResult.status === 'aborted') {\n return transfer;\n }\n\n const receipt = receiptResult.value;\n\n if (receipt.status === 'reverted') {\n const failedTransfer: FailedTransfer = {\n ...transfer,\n errorCode: ErrorCode.TRANSACTION_REVERTED,\n errorReason: 'Source transaction was reverted',\n failedAtMs: Date.now(),\n status: 'failed',\n };\n return failedTransfer;\n }\n\n const finalityResult = await _waitForEvmSourceFinalization(\n client,\n transfer.sourceChain.chainId,\n transfer.sourceChain.chainName,\n receipt.blockNumber,\n signal,\n );\n if (finalityResult.status === 'aborted') {\n return transfer;\n }\n\n return _toSourceCompletedTransfer(transfer);\n } catch (error) {\n const failedTransfer: FailedTransfer = {\n ...transfer,\n errorCode: getErrorCodeForViemError(error),\n errorReason: 'Failed to confirm source transaction finality',\n failedAtMs: Date.now(),\n status: 'failed',\n };\n return failedTransfer;\n }\n }\n\n if (isSolanaNamespace(transfer.sourceChain.chainId)) {\n const sourceTxHash = transfer.source.txHash;\n\n try {\n assertIsSignature(sourceTxHash);\n } catch {\n const failedTransfer: FailedTransfer = {\n ...transfer,\n errorCode: ErrorCode.INVALID_PARAMS,\n errorReason: 'Invalid source transaction hash',\n failedAtMs: Date.now(),\n status: 'failed',\n };\n return failedTransfer;\n }\n\n const finalityResult = await _waitForSolanaSourceFinalization(transfer.sourceChain, sourceTxHash, signal);\n\n if (finalityResult.status === 'aborted') {\n return transfer;\n }\n\n if (finalityResult.status === 'failed') {\n const failedTransfer: FailedTransfer = {\n ...transfer,\n errorCode: finalityResult.errorCode,\n errorReason: 'Failed to confirm source transaction finality',\n failedAtMs: Date.now(),\n status: 'failed',\n };\n return failedTransfer;\n }\n\n return _toSourceCompletedTransfer(transfer);\n }\n }\n\n try {\n const statusResponse = await markrGetCrossChainStatus(apiOptions, transfer.source.txHash, { signal });\n const transferWithMarkrMetadata = _withMarkrTrackingMetadata(transfer, statusResponse);\n\n switch (statusResponse.status) {\n case 'failed': {\n const failedTransfer: FailedTransfer = {\n ...transferWithMarkrMetadata,\n errorCode: ErrorCode.TRANSACTION_REVERTED,\n errorReason: 'Transaction execution failed.',\n failedAtMs: _getLastStatusActivityTime(statusResponse),\n status: 'failed',\n };\n\n return failedTransfer;\n }\n\n case 'pending': {\n return _isMarkrSourceFinalized(statusResponse.sourceChain.finalized)\n ? _toSourceCompletedTransfer(transferWithMarkrMetadata)\n : transferWithMarkrMetadata;\n }\n\n case 'committed':\n case 'pending_execution': {\n return _toTargetPendingTransfer(transferWithMarkrMetadata, statusResponse);\n }\n\n case 'completed': {\n return _toCompletedTransfer(transferWithMarkrMetadata, statusResponse);\n }\n\n case 'unknown':\n default: {\n return _deriveTransferFromUnknownStatus(transferWithMarkrMetadata, statusResponse);\n }\n }\n } catch (error) {\n // TODO: Clean this console.error up before v1 release.\n // This is just here for now to try to track down tracking issues.\n console.error('[Unified Asset Transfer] Error fetching cross-chain status from Markr API', {\n error,\n now: Date.now(),\n });\n\n const failedTransfer: FailedTransfer = {\n ...transfer,\n errorCode: ErrorCode.UNKNOWN,\n errorReason: 'Failed to fetch cross-chain tx status',\n failedAtMs: Date.now(),\n status: 'failed',\n };\n return failedTransfer;\n }\n}\n\nasync function _waitForEvmSourceFinalization(\n client: ReturnType<typeof getEvmClientForChain>,\n chainId: Caip2ChainId,\n chainName: string,\n txBlockNumber: bigint,\n signal: AbortSignal,\n): Promise<{ status: 'aborted' } | { status: 'ok' }> {\n const pollingIntervalMs = _getCrossChainPollingIntervalMs(chainId, chainName);\n\n while (!signal.aborted) {\n const finalizedBlockResult = await awaitOrAbort(client.getBlock({ blockTag: 'finalized' }), signal);\n\n if (finalizedBlockResult.status === 'aborted') {\n return { status: 'aborted' };\n }\n\n if (finalizedBlockResult.value.number >= txBlockNumber) {\n return { status: 'ok' };\n }\n\n await waitForTimeoutOrAbort({\n timeoutMs: pollingIntervalMs,\n signal,\n });\n }\n\n return { status: 'aborted' };\n}\n\nfunction _getCrossChainPollingIntervalMs(chainId: Caip2ChainId, chainName: string): number {\n const knownFinalityMs = _getKnownFinalityMs(chainId, chainName);\n const finalityTier = _toFinalityTier(knownFinalityMs);\n return CROSS_CHAIN_POLLING_INTERVAL_MS[finalityTier];\n}\n\nfunction _getPollingIntervalMsForTransfer(transfer: Transfer): number {\n if (transfer.status === 'source-pending') {\n return _getCrossChainPollingIntervalMs(transfer.sourceChain.chainId, transfer.sourceChain.chainName);\n }\n\n return _getCrossChainPollingIntervalMs(transfer.targetChain.chainId, transfer.targetChain.chainName);\n}\n\nfunction _getKnownFinalityMs(chainId: Caip2ChainId, chainName: string): number | undefined {\n const chainIdFinalityMs = FINALITY_MS_BY_CHAIN_ID[chainId];\n if (chainIdFinalityMs !== undefined) {\n return chainIdFinalityMs;\n }\n\n const normalizedName = _normalizeChainName(chainName);\n const matchingAlias = FINALITY_MS_BY_CHAIN_NAME_ALIAS.find(({ aliases }) =>\n aliases.some((alias) => normalizedName.includes(alias)),\n );\n\n return matchingAlias?.finalityMs;\n}\n\nfunction _normalizeChainName(chainName: string): string {\n return chainName.toLowerCase().replace(/[^a-z0-9]/g, '');\n}\n\nfunction _toFinalityTier(knownFinalityMs: number | undefined): FinalityTier {\n if (knownFinalityMs === undefined) {\n return 'medium';\n }\n\n if (knownFinalityMs <= FINALITY_TIER_MAX_FINALITY_MS.fast) {\n return 'fast';\n }\n\n if (knownFinalityMs <= FINALITY_TIER_MAX_FINALITY_MS.medium) {\n return 'medium';\n }\n\n if (knownFinalityMs <= FINALITY_TIER_MAX_FINALITY_MS.slow) {\n return 'slow';\n }\n\n return 'verySlow';\n}\n\nasync function _waitForSolanaSourceFinalization(\n chain: SourcePendingTransfer['sourceChain'],\n txHash: Signature,\n signal: AbortSignal,\n): Promise<{ status: 'aborted' } | { status: 'ok' } | { status: 'failed'; errorCode: ErrorCode }> {\n const rpc = getSolanaRpcForChain({ chain });\n const startTime = Date.now();\n\n while (!signal.aborted) {\n if (Date.now() - startTime > SOLANA_TX_TIMEOUT_MS) {\n return {\n status: 'failed',\n errorCode: ErrorCode.TIMEOUT,\n };\n }\n\n try {\n const { value } = await rpc.getSignatureStatuses([txHash], { searchTransactionHistory: true }).send();\n const txStatus = value[0];\n\n if (!txStatus) {\n await waitForTimeoutOrAbort({ timeoutMs: SOLANA_POLLING_INTERVAL_MS, signal });\n continue;\n }\n\n if (txStatus.err !== null) {\n return {\n status: 'failed',\n errorCode: ErrorCode.TRANSACTION_REVERTED,\n };\n }\n\n if (txStatus.confirmationStatus === 'finalized') {\n return { status: 'ok' };\n }\n\n await waitForTimeoutOrAbort({ timeoutMs: SOLANA_POLLING_INTERVAL_MS, signal });\n } catch (error) {\n return {\n status: 'failed',\n errorCode: getErrorCodeForSolanaRpcError(error),\n };\n }\n }\n\n return { status: 'aborted' };\n}\n\nfunction _isValidSourceTxHash(txHash: string, sourceChainId: Caip2ChainId): boolean {\n if (isEvmNamespace(sourceChainId)) {\n return isHash(txHash);\n }\n\n if (isSolanaNamespace(sourceChainId)) {\n try {\n assertIsSignature(txHash);\n return true;\n } catch {\n return false;\n }\n }\n\n return false;\n}\n\nfunction _isMarkrSourceFinalized(finalized: CrossChainStatusResponse['sourceChain']['finalized']): boolean {\n return finalized === true || typeof finalized === 'string';\n}\n\nfunction _toSourceCompletedTransfer(transfer: InFlightTransfer): SourceCompletedTransfer {\n return {\n ...transfer,\n source: {\n ...transfer.source,\n confirmationCount: 2,\n requiredConfirmationCount: 2,\n },\n status: 'source-completed',\n };\n}\n\nfunction _withMarkrTrackingMetadata(\n transfer: InFlightTransfer,\n statusResponse: CrossChainStatusResponse,\n): InFlightTransfer {\n const metadata: Record<string, unknown> = { ...(transfer.metadata ?? {}) };\n\n if (statusResponse.destinationChain.bridgeHash) {\n metadata.bridgeHash = statusResponse.destinationChain.bridgeHash;\n }\n\n if (statusResponse.debug) {\n metadata.debug = statusResponse.debug;\n }\n\n if (Object.keys(metadata).length === 0) {\n return transfer;\n }\n\n return {\n ...transfer,\n metadata,\n };\n}\n\nfunction _toTargetPendingTransfer(\n transfer: InFlightTransfer,\n statusResponse: CrossChainStatusResponse,\n): TargetPendingTransfer {\n const { timestamp, transactionHash } = statusResponse.destinationChain;\n\n return {\n ...transfer,\n source: {\n ...transfer.source,\n confirmationCount: 2,\n requiredConfirmationCount: 2,\n },\n status: 'target-pending',\n target: {\n confirmationCount: transactionHash ? 1 : 0,\n requiredConfirmationCount: 2,\n startedAtMs: timestamp ? new Date(timestamp).getTime() : Date.now(),\n txHash: transactionHash ?? undefined,\n },\n };\n}\n\nfunction _toCompletedTransfer(transfer: InFlightTransfer, statusResponse: CrossChainStatusResponse): CompletedTransfer {\n const { timestamp, transactionHash } = statusResponse.destinationChain;\n\n return {\n ...transfer,\n completedAtMs: _getLastStatusActivityTime(statusResponse),\n status: 'completed',\n source: {\n ...transfer.source,\n confirmationCount: 2,\n requiredConfirmationCount: 2,\n },\n target: transactionHash\n ? {\n txHash: transactionHash,\n confirmationCount: 2,\n requiredConfirmationCount: 2,\n startedAtMs: timestamp ? new Date(timestamp).getTime() : Date.now(),\n }\n : null,\n };\n}\n\nfunction _deriveTransferFromUnknownStatus(\n transfer: InFlightTransfer,\n statusResponse: CrossChainStatusResponse,\n): Transfer {\n if (statusResponse.progress.executed === true) {\n return _toCompletedTransfer(transfer, statusResponse);\n }\n\n if (statusResponse.progress.committed === true) {\n return _toTargetPendingTransfer(transfer, statusResponse);\n }\n\n if (_isMarkrSourceFinalized(statusResponse.sourceChain.finalized)) {\n return _toSourceCompletedTransfer(transfer);\n }\n\n return {\n ...transfer,\n source: {\n ...transfer.source,\n confirmationCount: 0,\n requiredConfirmationCount: 2,\n },\n status: 'source-pending',\n };\n}\n\nfunction _getLastStatusActivityTime(response: CrossChainStatusResponse): number {\n if (response.destinationChain.finalized) {\n return new Date(response.destinationChain.finalized).getTime();\n }\n\n if (response.destinationChain.timestamp) {\n return new Date(response.destinationChain.timestamp).getTime();\n }\n\n if (response.sourceChain.finalized) {\n if (typeof response.sourceChain.finalized === 'boolean' && response.sourceChain.finalized === true) {\n // Handle case where finalized is returned as boolean `true` instead of a timestamp.\n return new Date(response.sourceChain.timestamp).getTime();\n }\n return new Date(response.sourceChain.finalized).getTime();\n }\n\n return new Date(response.sourceChain.timestamp).getTime();\n}\n"],"mappings":"6uBA0CA,SAAgB,EAAqB,CAAE,cAA4E,CACjH,OAAQ,CAAE,WAAU,oBACd,EAAS,YAAY,UAAY,EAAS,YAAY,QACpD,EAAkB,EAAS,YAAY,QAAQ,CAC1C,EAA8B,CAAE,WAAU,iBAAgB,CAAC,CAE7D,EAA0B,CAAE,WAAU,iBAAgB,CAAC,CAGzD,EAAyB,CAAE,WAAU,iBAAgB,CAAE,EAAW,CAI7E,SAAgB,EAA8B,CAAE,WAAU,kBAGxD,CACA,IAAM,EAAK,IAAI,gBACT,MAAe,EAAG,OAAO,CAM/B,OAJI,EAAS,SAAW,iBAIjB,CAAE,SAAQ,OAAQ,EAA2B,EAAU,EAAgB,EAAG,OAAO,CAAE,CAHjF,CAAE,SAAQ,OAAQ,QAAQ,QAAQ,EAAS,CAAE,CAMxD,eAAe,EACb,EACA,EACA,EACmB,CACnB,GAAM,CAAE,UAAW,EAAS,OAE5B,GAAI,CACF,EAAkB,EAAO,MACnB,CACN,IAAM,EAAyB,CAC7B,GAAG,EACH,UAAW,EAAU,eACrB,WAAY,KAAK,KAAK,CACtB,OAAQ,SACT,CAED,OADA,EAAe,EAAO,CACf,EAGT,IAAM,EAAM,EAAqB,CAAE,MAAO,EAAS,YAAa,CAAC,CAC3D,EAAY,KAAK,KAAK,CAE5B,KAAO,CAAC,EAAO,SAAS,CACtB,GAAI,KAAK,KAAK,CAAG,EAAY,EAAsB,CACjD,IAAM,EAAyB,CAC7B,GAAG,EACH,UAAW,EAAU,QACrB,WAAY,KAAK,KAAK,CACtB,OAAQ,SACT,CAED,OADA,EAAe,EAAO,CACf,EAGT,GAAI,CACF,GAAM,CAAE,SAAU,MAAM,EAAI,qBAAqB,CAAC,EAAO,CAAE,CAAE,yBAA0B,GAAM,CAAC,CAAC,MAAM,CAC/F,EAAS,EAAM,GAErB,GAAI,CAAC,EAAQ,CACX,MAAM,EAAsB,CAAE,UAAW,EAA4B,SAAQ,CAAC,CAC9E,SAGF,GAAI,EAAO,MAAQ,KAAM,CACvB,IAAM,EAAyB,CAC7B,GAAG,EACH,UAAW,EAAU,qBACrB,WAAY,KAAK,KAAK,CACtB,OAAQ,SACT,CAED,OADA,EAAe,EAAO,CACf,EAGT,GAAI,EAAO,qBAAuB,YAAa,CAC7C,IAAM,EAA+B,CACnC,GAAG,EACH,cAAe,KAAK,KAAK,CACzB,OAAQ,CACN,GAAG,EAAS,OACZ,kBAAmB,EAAS,OAAO,0BACpC,CACD,OAAQ,YACR,OAAQ,KACT,CAED,OADA,EAAe,EAAU,CAClB,EAGT,IAAM,EAAgB,OAAO,EAAO,eAAiB,EAAE,CACjD,EAAc,KAAK,IAAI,EAAe,EAAS,OAAO,0BAA4B,EAAE,CAEtF,IAAgB,EAAS,OAAO,oBAClC,EAAW,CACT,GAAG,EACH,OAAQ,CACN,GAAG,EAAS,OACZ,kBAAmB,EACpB,CACF,CACD,EAAe,EAAS,EAG1B,MAAM,EAAsB,CAAE,UAAW,EAA4B,SAAQ,CAAC,OACvE,EAAO,CACd,IAAM,EAAyB,CAC7B,GAAG,EACH,UAAW,EAA8B,EAAM,CAC/C,WAAY,KAAK,KAAK,CACtB,OAAQ,SACT,CAED,OADA,EAAe,EAAO,CACf,GAIX,OAAO,EAGT,SAAgB,EACd,CAAE,WAAU,kBACZ,EACmD,CACnD,IAAM,EAAK,IAAI,gBAkCf,MAAO,CACL,WAlCmB,CACnB,EAAG,OAAO,EAkCV,QA/BsB,SAA+B,CACrD,IAAI,EAA4B,gBAAgB,EAAS,CACzD,KAAO,CAAC,EAAG,OAAO,SAAS,CACzB,IAAM,EAAkB,MAAM,EAA4B,EAAiB,EAAY,EAAG,OAAO,CAEjG,GAAI,EAAG,OAAO,QACZ,MAOF,GAJA,EAAkB,EAElB,EAAe,EAAgB,CAE3B,EAAgB,SAAW,aAAe,EAAgB,SAAW,SACvE,OAAO,EAGT,IAAM,EAAoB,EAAiC,EAAgB,CAG3E,MAAM,IAAI,QAAS,GAAY,CAC7B,IAAM,EAAY,WAAW,EAAS,EAAkB,CACxD,EAAG,OAAO,iBAAiB,YAAe,aAAa,EAAU,CAAE,CAAE,KAAM,GAAM,CAAC,EAClF,CAGJ,OAAO,KAKkB,CAC1B,CAGH,eAAsB,EACpB,EACA,EACA,EACmB,CACnB,GAAI,EAAS,SAAW,aAAe,EAAS,SAAW,SACzD,OAAO,EAIT,GAAI,CAAC,EAAqB,EAAS,OAAO,OAAQ,EAAS,YAAY,QAAQ,CAQ7E,MAPuC,CACrC,GAAG,EACH,UAAW,EAAU,eACrB,YAAa,kCACb,WAAY,KAAK,KAAK,CACtB,OAAQ,SACT,CAQH,GAAI,EAAS,SAAW,iBAAkB,CACxC,GAAI,EAAe,EAAS,YAAY,QAAQ,CAAE,CAChD,IAAM,EAAe,EAAS,OAAO,OAErC,GAAI,CAAC,EAAO,EAAa,CASvB,MARuC,CACrC,GAAG,EACH,UAAW,EAAU,eACrB,YAAa,kCACb,WAAY,KAAK,KAAK,CACtB,OAAQ,SACT,CAKH,IAAM,EAAS,EAAqB,CAAE,MAAO,EAAS,YAAa,CAAC,CAEpE,GAAI,CACF,IAAM,EAAgB,MAAM,EAC1B,EAAO,0BAA0B,CAC/B,KAAM,EACP,CAAC,CACF,EACD,CAED,GAAI,EAAc,SAAW,UAC3B,OAAO,EAGT,IAAM,EAAU,EAAc,MAwB9B,OAtBI,EAAQ,SAAW,WACkB,CACrC,GAAG,EACH,UAAW,EAAU,qBACrB,YAAa,kCACb,WAAY,KAAK,KAAK,CACtB,OAAQ,SACT,EAIoB,MAAM,EAC3B,EACA,EAAS,YAAY,QACrB,EAAS,YAAY,UACrB,EAAQ,YACR,EACD,EACkB,SAAW,UACrB,EAGF,EAA2B,EAAS,OACpC,EAAO,CAQd,MAPuC,CACrC,GAAG,EACH,UAAW,EAAyB,EAAM,CAC1C,YAAa,gDACb,WAAY,KAAK,KAAK,CACtB,OAAQ,SACT,EAKL,GAAI,EAAkB,EAAS,YAAY,QAAQ,CAAE,CACnD,IAAM,EAAe,EAAS,OAAO,OAErC,GAAI,CACF,EAAkB,EAAa,MACzB,CAQN,MAPuC,CACrC,GAAG,EACH,UAAW,EAAU,eACrB,YAAa,kCACb,WAAY,KAAK,KAAK,CACtB,OAAQ,SACT,CAIH,IAAM,EAAiB,MAAM,EAAiC,EAAS,YAAa,EAAc,EAAO,CAiBzG,OAfI,EAAe,SAAW,UACrB,EAGL,EAAe,SAAW,SACW,CACrC,GAAG,EACH,UAAW,EAAe,UAC1B,YAAa,gDACb,WAAY,KAAK,KAAK,CACtB,OAAQ,SACT,CAII,EAA2B,EAAS,EAI/C,GAAI,CACF,IAAM,EAAiB,MAAM,EAAyB,EAAY,EAAS,OAAO,OAAQ,CAAE,SAAQ,CAAC,CAC/F,EAA4B,EAA2B,EAAU,EAAe,CAEtF,OAAQ,EAAe,OAAvB,CACE,IAAK,SASH,MARuC,CACrC,GAAG,EACH,UAAW,EAAU,qBACrB,YAAa,gCACb,WAAY,EAA2B,EAAe,CACtD,OAAQ,SACT,CAKH,IAAK,UACH,OAAO,EAAwB,EAAe,YAAY,UAAU,CAChE,EAA2B,EAA0B,CACrD,EAGN,IAAK,YACL,IAAK,oBACH,OAAO,EAAyB,EAA2B,EAAe,CAG5E,IAAK,YACH,OAAO,EAAqB,EAA2B,EAAe,CAIxE,QACE,OAAO,EAAiC,EAA2B,EAAe,QAG/E,EAAO,CAed,OAZA,QAAQ,MAAM,4EAA6E,CACzF,QACA,IAAK,KAAK,KAAK,CAChB,CAAC,CAEqC,CACrC,GAAG,EACH,UAAW,EAAU,QACrB,YAAa,wCACb,WAAY,KAAK,KAAK,CACtB,OAAQ,SACT,EAKL,eAAe,EACb,EACA,EACA,EACA,EACA,EACmD,CACnD,IAAM,EAAoB,EAAgC,EAAS,EAAU,CAE7E,KAAO,CAAC,EAAO,SAAS,CACtB,IAAM,EAAuB,MAAM,EAAa,EAAO,SAAS,CAAE,SAAU,YAAa,CAAC,CAAE,EAAO,CAEnG,GAAI,EAAqB,SAAW,UAClC,MAAO,CAAE,OAAQ,UAAW,CAG9B,GAAI,EAAqB,MAAM,QAAU,EACvC,MAAO,CAAE,OAAQ,KAAM,CAGzB,MAAM,EAAsB,CAC1B,UAAW,EACX,SACD,CAAC,CAGJ,MAAO,CAAE,OAAQ,UAAW,CAG9B,SAAS,EAAgC,EAAuB,EAA2B,CAGzF,OAAO,EADc,EADG,EAAoB,EAAS,EAAU,CACV,EAIvD,SAAS,EAAiC,EAA4B,CAKpE,OAJI,EAAS,SAAW,iBACf,EAAgC,EAAS,YAAY,QAAS,EAAS,YAAY,UAAU,CAG/F,EAAgC,EAAS,YAAY,QAAS,EAAS,YAAY,UAAU,CAGtG,SAAS,EAAoB,EAAuB,EAAuC,CACzF,IAAM,EAAoB,EAAwB,GAClD,GAAI,IAAsB,IAAA,GACxB,OAAO,EAGT,IAAM,EAAiB,EAAoB,EAAU,CAKrD,OAJsB,EAAgC,MAAM,CAAE,aAC5D,EAAQ,KAAM,GAAU,EAAe,SAAS,EAAM,CAAC,CACxD,EAEqB,WAGxB,SAAS,EAAoB,EAA2B,CACtD,OAAO,EAAU,aAAa,CAAC,QAAQ,aAAc,GAAG,CAG1D,SAAS,EAAgB,EAAmD,CAiB1E,OAhBI,IAAoB,IAAA,GACf,SAGL,GAAmB,EAA8B,KAC5C,OAGL,GAAmB,EAA8B,OAC5C,SAGL,GAAmB,EAA8B,KAC5C,OAGF,WAGT,eAAe,EACb,EACA,EACA,EACgG,CAChG,IAAM,EAAM,EAAqB,CAAE,QAAO,CAAC,CACrC,EAAY,KAAK,KAAK,CAE5B,KAAO,CAAC,EAAO,SAAS,CACtB,GAAI,KAAK,KAAK,CAAG,EAAY,EAC3B,MAAO,CACL,OAAQ,SACR,UAAW,EAAU,QACtB,CAGH,GAAI,CACF,GAAM,CAAE,SAAU,MAAM,EAAI,qBAAqB,CAAC,EAAO,CAAE,CAAE,yBAA0B,GAAM,CAAC,CAAC,MAAM,CAC/F,EAAW,EAAM,GAEvB,GAAI,CAAC,EAAU,CACb,MAAM,EAAsB,CAAE,UAAW,EAA4B,SAAQ,CAAC,CAC9E,SAGF,GAAI,EAAS,MAAQ,KACnB,MAAO,CACL,OAAQ,SACR,UAAW,EAAU,qBACtB,CAGH,GAAI,EAAS,qBAAuB,YAClC,MAAO,CAAE,OAAQ,KAAM,CAGzB,MAAM,EAAsB,CAAE,UAAW,EAA4B,SAAQ,CAAC,OACvE,EAAO,CACd,MAAO,CACL,OAAQ,SACR,UAAW,EAA8B,EAAM,CAChD,EAIL,MAAO,CAAE,OAAQ,UAAW,CAG9B,SAAS,EAAqB,EAAgB,EAAsC,CAClF,GAAI,EAAe,EAAc,CAC/B,OAAO,EAAO,EAAO,CAGvB,GAAI,EAAkB,EAAc,CAClC,GAAI,CAEF,OADA,EAAkB,EAAO,CAClB,QACD,CACN,MAAO,GAIX,MAAO,GAGT,SAAS,EAAwB,EAA0E,CACzG,OAAO,IAAc,IAAQ,OAAO,GAAc,SAGpD,SAAS,EAA2B,EAAqD,CACvF,MAAO,CACL,GAAG,EACH,OAAQ,CACN,GAAG,EAAS,OACZ,kBAAmB,EACnB,0BAA2B,EAC5B,CACD,OAAQ,mBACT,CAGH,SAAS,EACP,EACA,EACkB,CAClB,IAAM,EAAoC,CAAE,GAAI,EAAS,UAAY,EAAE,CAAG,CAc1E,OAZI,EAAe,iBAAiB,aAClC,EAAS,WAAa,EAAe,iBAAiB,YAGpD,EAAe,QACjB,EAAS,MAAQ,EAAe,OAG9B,OAAO,KAAK,EAAS,CAAC,SAAW,EAC5B,EAGF,CACL,GAAG,EACH,WACD,CAGH,SAAS,EACP,EACA,EACuB,CACvB,GAAM,CAAE,YAAW,mBAAoB,EAAe,iBAEtD,MAAO,CACL,GAAG,EACH,OAAQ,CACN,GAAG,EAAS,OACZ,kBAAmB,EACnB,0BAA2B,EAC5B,CACD,OAAQ,iBACR,OAAQ,CACN,kBAAmB,EAAkB,EAAI,EACzC,0BAA2B,EAC3B,YAAa,EAAY,IAAI,KAAK,EAAU,CAAC,SAAS,CAAG,KAAK,KAAK,CACnE,OAAQ,GAAmB,IAAA,GAC5B,CACF,CAGH,SAAS,EAAqB,EAA4B,EAA6D,CACrH,GAAM,CAAE,YAAW,mBAAoB,EAAe,iBAEtD,MAAO,CACL,GAAG,EACH,cAAe,EAA2B,EAAe,CACzD,OAAQ,YACR,OAAQ,CACN,GAAG,EAAS,OACZ,kBAAmB,EACnB,0BAA2B,EAC5B,CACD,OAAQ,EACJ,CACE,OAAQ,EACR,kBAAmB,EACnB,0BAA2B,EAC3B,YAAa,EAAY,IAAI,KAAK,EAAU,CAAC,SAAS,CAAG,KAAK,KAAK,CACpE,CACD,KACL,CAGH,SAAS,EACP,EACA,EACU,CAaV,OAZI,EAAe,SAAS,WAAa,GAChC,EAAqB,EAAU,EAAe,CAGnD,EAAe,SAAS,YAAc,GACjC,EAAyB,EAAU,EAAe,CAGvD,EAAwB,EAAe,YAAY,UAAU,CACxD,EAA2B,EAAS,CAGtC,CACL,GAAG,EACH,OAAQ,CACN,GAAG,EAAS,OACZ,kBAAmB,EACnB,0BAA2B,EAC5B,CACD,OAAQ,iBACT,CAGH,SAAS,EAA2B,EAA4C,CAiB9E,OAhBI,EAAS,iBAAiB,UACrB,IAAI,KAAK,EAAS,iBAAiB,UAAU,CAAC,SAAS,CAG5D,EAAS,iBAAiB,UACrB,IAAI,KAAK,EAAS,iBAAiB,UAAU,CAAC,SAAS,CAG5D,EAAS,YAAY,UACnB,OAAO,EAAS,YAAY,WAAc,WAAa,EAAS,YAAY,YAAc,GAErF,IAAI,KAAK,EAAS,YAAY,UAAU,CAAC,SAAS,CAEpD,IAAI,KAAK,EAAS,YAAY,UAAU,CAAC,SAAS,CAGpD,IAAI,KAAK,EAAS,YAAY,UAAU,CAAC,SAAS"}
@@ -1,2 +1,2 @@
1
- require(`../../_virtual/_rolldown/runtime.cjs`);const e=require(`../../constants.cjs`),t=require(`../../errors.cjs`),n=require(`../../utils/caip.cjs`),r=require(`../../utils/evm-address.cjs`),i=require(`../../_utils/chain.cjs`),a=require(`./_api.cjs`),o=require(`../../_utils/math.cjs`),s=require(`../../utils/sol-address.cjs`);let c=require(`viem`);async function l(e,r=!1){let i=new Map;try{let t=(await a.markrGetInfoChains(e)).filter(e=>e.chainType===`evm`||e.chainType===`svm`);for(let e of t){let t=typeof e.chainId==`number`?n.eip155ChainIdToCaip2(e.chainId):e.chainId,a=e.enabled_services.includes(`cross-chain-quote`)&&e.enabled_services.includes(`cross-chain-swap`),o=e.enabled_services.includes(`quote`)&&e.enabled_services.includes(`swap`),s=new Set;for(let r of e.lanes){let e=typeof r==`number`?n.eip155ChainIdToCaip2(r):r;e!==t&&s.add(e)}let c=r?!1:a,l=c?s:new Set;!o&&l.size===0||i.set(t,{chainId:e.chainId,crossChainSwapEnabled:c,crossChainTargetChainIds:l,swapEnabled:o,tokenList:e.enabled_services.includes(`token-list`)})}}catch(e){throw new t.SdkError(t.ErrorReason.UNKNOWN,t.ErrorCode.INITIALIZATION_FAILED,{cause:e,details:`Failed to fetch supported chains from Markr API.`})}return i}async function u(e,t){let n=new Map;for(let[r,i]of t.entries())if(typeof i.chainId==`number`&&i.tokenList&&(i.crossChainSwapEnabled||i.swapEnabled))try{let t=a.markrGetTokenList(e,i.chainId);n.set(r,t)}catch{}return n}function d(t){return t===e.ERC_ZERO_ADDRESS||t===e.SOL_MINT_ADDRESS}function f(t,n){return t.type===e.TokenType.NATIVE?i.isSolanaNamespace(n)?e.SOL_MINT_ADDRESS:e.ERC_ZERO_ADDRESS:t.address}function p({amountOut:e,assetOut:t,slippageBps:n}){let r=o.calculateMinimumAmountOut({amountOut:e,assetOut:t,slippageBps:n});return e>0n&&r===0n?1n:r}function m(t,n,r){let i=t.amountOut*BigInt(r)/10000n,a=t.amountOut-i,o=[...g(t.fees),{type:`partner`,name:`Core Fee`,amount:i,chainId:n.targetChain.chainId,token:_(n.targetAsset)}];return{aggregator:{id:t.aggregator.id,logoUrl:t.aggregator.logo_url,name:t.aggregator.name},amountIn:t.amountIn,amountOut:a,assetIn:n.sourceAsset,assetOut:n.targetAsset,expiresAt:t.expiredAt,fees:o,fromAddress:n.fromAddress,gasEstimate:t.gasEstimate,id:t.uuid,partnerFeeBps:r,serviceType:e.ServiceType.MARKR,slippageBps:n.slippageBps??t.recommendedSlippage,sourceChain:n.sourceChain,targetChain:n.targetChain,toAddress:n.toAddress}}async function h(e){try{return(await a.markrGetPartnerInfo(e)).fee}catch(e){throw new t.SdkError(t.ErrorReason.UNKNOWN,t.ErrorCode.INITIALIZATION_FAILED,{cause:e,details:`Failed to fetch partner info from Markr API.`})}}function g(t){if(!t)return[];let i=[];for(let a of t){let t=typeof a.token.chainId==`number`?n.eip155ChainIdToCaip2(a.token.chainId):a.token.chainId,o;d(a.token.address)?o={type:e.TokenType.NATIVE}:r.isEvmAddress(a.token.address)?o={type:e.TokenType.ERC20,address:a.token.address}:s.isSolAddress(a.token.address)&&(o={type:e.TokenType.SPL,address:a.token.address}),o&&i.push({type:a.type,name:a.name,amount:a.amount,chainId:t,token:o})}return i}function _(t){return t.type===e.TokenType.NATIVE?{type:e.TokenType.NATIVE}:t.type===e.TokenType.SPL?{type:e.TokenType.SPL,address:t.address}:{type:e.TokenType.ERC20,address:t.address}}async function v(e){return e?(await Promise.resolve().then(()=>require(`./_abis/cross-chain-swap-wrapper-abi.cjs`))).MARKR_CROSS_CHAIN_SWAP_WRAPPER_ABI:(await Promise.resolve().then(()=>require(`./_abis/swap-wrapper-abi.cjs`))).MARKR_SWAP_WRAPPER_ABI}function y(e){if(e instanceof c.BaseError){let t=e.data;if((0,c.isHex)(t))return t;let n;if(e.walk(e=>{let t=e.data;return!n&&(0,c.isHex)(t)&&(n=t),!1}),n)return n;let r=e.cause?.data;if((0,c.isHex)(r))return r}if(!e||typeof e!=`object`)return;let t=e;if((0,c.isHex)(t.data))return t.data;if((0,c.isHex)(t.error?.data))return t.error.data;if((0,c.isHex)(t.cause?.data))return t.cause.data;if((0,c.isHex)(t.response?.data))return t.response.data;if((0,c.isHex)(t.body?.error?.data))return t.body.error.data}function b(e,t){let n=y(t);if(!n)return null;try{let t=(0,c.decodeErrorResult)({abi:e,data:n}),r=t.args.length>0?`(${t.args.map(String).join(`, `)})`:`()`;return`${t.errorName}${r}`}catch{let t=n.slice(0,10).toLowerCase();for(let n of e)if(n.type===`error`&&(0,c.toFunctionSelector)(`${n.name}(${n.inputs.map(e=>e.type).join(`,`)})`).toLowerCase()===t)return`${n.name}()`}return null}exports.assetToAddressString=f,exports.calculateMarkrMinimumAmountOut=p,exports.decodeMarkrRevertError=b,exports.getMarkrSwapWrapperAbi=v,exports.getPartnerFeeBps=h,exports.getSupportedChains=l,exports.getSupportedTokens=u,exports.isTokenAddressNative=d,exports.quoteFromMarkrQuoteResponseData=m;
1
+ require(`../../_virtual/_rolldown/runtime.cjs`);const e=require(`../../constants.cjs`),t=require(`../../errors.cjs`),n=require(`../../utils/caip.cjs`),r=require(`../../utils/evm-address.cjs`),i=require(`../../_utils/chain.cjs`),a=require(`../../_utils/math.cjs`),o=require(`./_api.cjs`),s=require(`../../utils/sol-address.cjs`);let c=require(`viem`);function l(e,t,n){let r=e.get(t),i=e.get(n);return!r||!i?!1:t===n?r.swapEnabled:r.crossChainSwapEnabled&&r.crossChainTargetChainIds.has(n)}async function u(e,r=!1){let i=new Map;try{let t=(await o.markrGetInfoChains(e)).filter(e=>e.chainType===`evm`||e.chainType===`svm`);for(let e of t){let t=typeof e.chainId==`number`?n.eip155ChainIdToCaip2(e.chainId):e.chainId,a=e.enabled_services.includes(`cross-chain-quote`)&&e.enabled_services.includes(`cross-chain-swap`),o=e.enabled_services.includes(`quote`)&&e.enabled_services.includes(`swap`),s=new Set;for(let r of e.lanes){let e=typeof r==`number`?n.eip155ChainIdToCaip2(r):r;e!==t&&s.add(e)}let c=r?!1:a,l=c?s:new Set;!o&&l.size===0||i.set(t,{chainId:e.chainId,crossChainSwapEnabled:c,crossChainTargetChainIds:l,swapEnabled:o,tokenList:e.enabled_services.includes(`token-list`)})}}catch(e){throw new t.SdkError(t.ErrorReason.UNKNOWN,t.ErrorCode.INITIALIZATION_FAILED,{cause:e,details:`Failed to fetch supported chains from Markr API.`})}return i}async function d(e,t){let n=new Map;for(let[r,i]of t.entries())if(typeof i.chainId==`number`&&i.tokenList&&(i.crossChainSwapEnabled||i.swapEnabled))try{let t=o.markrGetTokenList(e,i.chainId);n.set(r,t)}catch{}return n}function f(t){return t===e.ERC_ZERO_ADDRESS||t===e.SOL_MINT_ADDRESS}function p(t,n){return t.type===e.TokenType.NATIVE?i.isSolanaNamespace(n)?e.SOL_MINT_ADDRESS:e.ERC_ZERO_ADDRESS:t.address}function m({amountOut:e,assetOut:t,slippageBps:n}){let r=a.calculateMinimumAmountOut({amountOut:e,assetOut:t,slippageBps:n});return e>0n&&r===0n?1n:r}function h(t,n,r){let i=t.amountOut*BigInt(r)/10000n,a=t.amountOut-i,o=[..._(t.fees),{type:`partner`,name:`Core Fee`,amount:i,chainId:n.targetChain.chainId,token:v(n.targetAsset)}];return{aggregator:{id:t.aggregator.id,logoUrl:t.aggregator.logo_url,name:t.aggregator.name},amountIn:t.amountIn,amountOut:a,assetIn:n.sourceAsset,assetOut:n.targetAsset,expiresAt:t.expiredAt,fees:o,fromAddress:n.fromAddress,gasEstimate:t.gasEstimate,id:t.uuid,partnerFeeBps:r,serviceType:e.ServiceType.MARKR,slippageBps:n.slippageBps??t.recommendedSlippage,sourceChain:n.sourceChain,targetChain:n.targetChain,toAddress:n.toAddress}}async function g(e){try{return(await o.markrGetPartnerInfo(e)).fee}catch(e){throw new t.SdkError(t.ErrorReason.UNKNOWN,t.ErrorCode.INITIALIZATION_FAILED,{cause:e,details:`Failed to fetch partner info from Markr API.`})}}function _(t){if(!t)return[];let i=[];for(let a of t){let t=typeof a.token.chainId==`number`?n.eip155ChainIdToCaip2(a.token.chainId):a.token.chainId,o;f(a.token.address)?o={type:e.TokenType.NATIVE}:r.isEvmAddress(a.token.address)?o={type:e.TokenType.ERC20,address:a.token.address}:s.isSolAddress(a.token.address)&&(o={type:e.TokenType.SPL,address:a.token.address}),o&&i.push({type:a.type,name:a.name,amount:a.amount,chainId:t,token:o})}return i}function v(t){return t.type===e.TokenType.NATIVE?{type:e.TokenType.NATIVE}:t.type===e.TokenType.SPL?{type:e.TokenType.SPL,address:t.address}:{type:e.TokenType.ERC20,address:t.address}}async function y(e){return e?(await Promise.resolve().then(()=>require(`./_abis/cross-chain-swap-wrapper-abi.cjs`))).MARKR_CROSS_CHAIN_SWAP_WRAPPER_ABI:(await Promise.resolve().then(()=>require(`./_abis/swap-wrapper-abi.cjs`))).MARKR_SWAP_WRAPPER_ABI}function b(e){if(e instanceof c.BaseError){let t=e.data;if((0,c.isHex)(t))return t;let n;if(e.walk(e=>{let t=e.data;return!n&&(0,c.isHex)(t)&&(n=t),!1}),n)return n;let r=e.cause?.data;if((0,c.isHex)(r))return r}if(!e||typeof e!=`object`)return;let t=e;if((0,c.isHex)(t.data))return t.data;if((0,c.isHex)(t.error?.data))return t.error.data;if((0,c.isHex)(t.cause?.data))return t.cause.data;if((0,c.isHex)(t.response?.data))return t.response.data;if((0,c.isHex)(t.body?.error?.data))return t.body.error.data}function x(e,t){let n=b(t);if(!n)return null;try{let t=(0,c.decodeErrorResult)({abi:e,data:n}),r=t.args.length>0?`(${t.args.map(String).join(`, `)})`:`()`;return`${t.errorName}${r}`}catch{let t=n.slice(0,10).toLowerCase();for(let n of e)if(n.type===`error`&&(0,c.toFunctionSelector)(`${n.name}(${n.inputs.map(e=>e.type).join(`,`)})`).toLowerCase()===t)return`${n.name}()`}return null}exports.assetToAddressString=p,exports.calculateMarkrMinimumAmountOut=m,exports.decodeMarkrRevertError=x,exports.getMarkrSwapWrapperAbi=y,exports.getPartnerFeeBps=g,exports.getSupportedChains=u,exports.getSupportedTokens=d,exports.isRouteSupported=l,exports.isTokenAddressNative=f,exports.quoteFromMarkrQuoteResponseData=h;
2
2
  //# sourceMappingURL=_utils.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"_utils.cjs","names":["markrGetInfoChains","eip155ChainIdToCaip2","SdkError","ErrorReason","ErrorCode","markrGetTokenList","ERC_ZERO_ADDRESS","SOL_MINT_ADDRESS","TokenType","isSolanaNamespace","calculateMinimumAmountOut","ServiceType","markrGetPartnerInfo","isEvmAddress","isSolAddress","BaseError"],"sources":["../../../src/transfer-service/markr/_utils.ts"],"sourcesContent":["import { ErrorCode, ErrorReason, SdkError } from '../../errors';\nimport { BaseError, decodeErrorResult, type Hex, isHex, toFunctionSelector } from 'viem';\nimport {\n type QuoteResponseData,\n type SupportedChainsResponseItemEvm,\n type SupportedChainsResponseItemSvm,\n type TokenListResponse,\n} from './_schema';\nimport { ERC_ZERO_ADDRESS, SOL_MINT_ADDRESS, ServiceType, TokenType } from '../../constants';\nimport { isSolanaNamespace } from '../../_utils/chain';\nimport { calculateMinimumAmountOut } from '../../_utils/math';\nimport { eip155ChainIdToCaip2 } from '../../utils/caip';\nimport type { Asset } from '../../types/asset';\nimport type { Caip2ChainId } from '../../types/caip';\nimport type { Quote, QuoteFee, QuoteFees, QuoteFeeToken, QuoterProps } from '../../types/quote';\nimport { markrGetInfoChains, markrGetPartnerInfo, markrGetTokenList, type ApiOptions } from './_api';\nimport { isEvmAddress } from '../../utils/evm-address';\nimport { isSolAddress } from '../../utils/sol-address';\n\nexport type SupportedChainsMap = Map<\n Caip2ChainId,\n {\n /** `number` for EVM, `Caip2ChainId` for SVM */\n chainId: number | Caip2ChainId;\n crossChainSwapEnabled: boolean;\n crossChainTargetChainIds: ReadonlySet<Caip2ChainId>;\n swapEnabled: boolean;\n tokenList: boolean;\n }\n>;\n\nexport async function getSupportedChains(\n apiOptions: ApiOptions,\n disableCrossChainSwaps = false,\n): Promise<SupportedChainsMap> {\n const supportedChains: SupportedChainsMap = new Map();\n\n try {\n const chains = await markrGetInfoChains(apiOptions);\n const filteredSupportedChains = chains.filter(\n (chain): chain is SupportedChainsResponseItemEvm | SupportedChainsResponseItemSvm => {\n // Only include chains types that we support in the SDK (EVM and Solana for now).\n return chain.chainType === 'evm' || chain.chainType === 'svm';\n },\n );\n\n for (const chain of filteredSupportedChains) {\n const key: Caip2ChainId = typeof chain.chainId === 'number' ? eip155ChainIdToCaip2(chain.chainId) : chain.chainId;\n\n const isCrossChainSwapEnabled =\n chain.enabled_services.includes('cross-chain-quote') && chain.enabled_services.includes('cross-chain-swap');\n const isSwapEnabled = chain.enabled_services.includes('quote') && chain.enabled_services.includes('swap');\n const normalizedLaneChainIds = new Set<Caip2ChainId>();\n\n for (const lane of chain.lanes) {\n const laneChainId = typeof lane === 'number' ? eip155ChainIdToCaip2(lane) : lane;\n\n if (laneChainId !== key) {\n normalizedLaneChainIds.add(laneChainId);\n }\n }\n\n const crossChainSwapEnabled = disableCrossChainSwaps ? false : isCrossChainSwapEnabled;\n const crossChainTargetChainIds = crossChainSwapEnabled ? normalizedLaneChainIds : new Set<Caip2ChainId>();\n\n if (!isSwapEnabled && crossChainTargetChainIds.size === 0) {\n continue;\n }\n\n supportedChains.set(key, {\n chainId: chain.chainId,\n crossChainSwapEnabled,\n crossChainTargetChainIds,\n swapEnabled: isSwapEnabled,\n tokenList: chain.enabled_services.includes('token-list'),\n });\n }\n } catch (error) {\n throw new SdkError(ErrorReason.UNKNOWN, ErrorCode.INITIALIZATION_FAILED, {\n cause: error,\n details: 'Failed to fetch supported chains from Markr API.',\n });\n }\n\n return supportedChains;\n}\n\nexport async function getSupportedTokens(\n apiOptions: ApiOptions,\n supportedChains: SupportedChainsMap,\n): Promise<Map<Caip2ChainId, Promise<TokenListResponse>>> {\n // Parallel fetch token lists for all supported chains.\n const supportedTokens: Map<Caip2ChainId, Promise<TokenListResponse>> = new Map();\n\n for (const [caip2ChainId, chainInfo] of supportedChains.entries()) {\n // Only fetch token list for EVM chains that support swaps.\n if (\n typeof chainInfo.chainId === 'number' &&\n chainInfo.tokenList &&\n (chainInfo.crossChainSwapEnabled || chainInfo.swapEnabled)\n ) {\n try {\n const tokenListPromise = markrGetTokenList(apiOptions, chainInfo.chainId);\n supportedTokens.set(caip2ChainId, tokenListPromise);\n } catch {\n // Ignore errors for individual token list fetches.\n // TODO: Logger?\n }\n }\n }\n\n return supportedTokens;\n}\n\n/**\n * Determine if the provided token address represents the native token for its chain.\n *\n * Markr represents EVM native tokens as the zero address and Solana native SOL\n * as the wrapped SOL mint address.\n */\nexport function isTokenAddressNative(address: string): boolean {\n return address === ERC_ZERO_ADDRESS || address === SOL_MINT_ADDRESS;\n}\n\n/**\n * Convert an `Asset` to the address string expected by the Markr API.\n *\n * For NATIVE assets the representation depends on the chain:\n * - EVM chains: `0x0000...0000` (ERC zero address)\n * - Solana chains: `So11111111111111111111111111111111111111112` (wrapped SOL mint)\n *\n * @param asset The asset to convert.\n * @param chainId CAIP-2 chain ID used to disambiguate NATIVE assets across chain types.\n */\nexport function assetToAddressString(asset: Asset, chainId: Caip2ChainId): string {\n if (asset.type === TokenType.NATIVE) {\n if (isSolanaNamespace(chainId)) {\n return SOL_MINT_ADDRESS;\n }\n\n return ERC_ZERO_ADDRESS;\n }\n\n return asset.address;\n}\n\n/**\n * Markr rejects `minAmountOut=0` for non-zero quotes.\n *\n * For very small quotes, integer truncation after slippage can produce `0`.\n * Clamp to `1` in that edge case to satisfy Markr API validation while\n * preserving normal slippage behavior for larger quotes.\n */\nexport function calculateMarkrMinimumAmountOut({\n amountOut,\n assetOut,\n slippageBps,\n}: Pick<Quote, 'amountOut' | 'assetOut' | 'slippageBps'>): bigint {\n const minAmountOut = calculateMinimumAmountOut({ amountOut, assetOut, slippageBps });\n\n if (amountOut > 0n && minAmountOut === 0n) {\n return 1n;\n }\n\n return minAmountOut;\n}\n\nexport function quoteFromMarkrQuoteResponseData(\n data: QuoteResponseData,\n quoterProps: QuoterProps,\n partnerFeeBps: number,\n): Quote {\n const partnerFee: bigint = (data.amountOut * BigInt(partnerFeeBps)) / 10_000n;\n const amountOutAfterFees: bigint = data.amountOut - partnerFee;\n\n const fees: QuoteFees = [\n ...mapMarkrQuoteResponseDataFeesToQuoteFees(data.fees),\n // Add the partner fee as a QuoteFee component for Markr quotes.\n {\n type: 'partner',\n name: 'Core Fee',\n amount: partnerFee,\n chainId: quoterProps.targetChain.chainId,\n token: assetToFeeToken(quoterProps.targetAsset),\n },\n ];\n\n return {\n aggregator: {\n id: data.aggregator.id,\n logoUrl: data.aggregator.logo_url,\n name: data.aggregator.name,\n },\n amountIn: data.amountIn,\n amountOut: amountOutAfterFees,\n assetIn: quoterProps.sourceAsset,\n assetOut: quoterProps.targetAsset,\n expiresAt: data.expiredAt, // Markr returns `expiredAt` as Unix time in seconds; use as-is.\n fees,\n fromAddress: quoterProps.fromAddress,\n /**\n * This gasEstimate is rough or may be missing.\n * Consumers should use TransferManager.estimateGas for a more accurate estimate.\n */\n gasEstimate: data.gasEstimate,\n id: data.uuid,\n partnerFeeBps,\n serviceType: ServiceType.MARKR,\n slippageBps: quoterProps.slippageBps ?? data.recommendedSlippage,\n sourceChain: quoterProps.sourceChain,\n targetChain: quoterProps.targetChain,\n toAddress: quoterProps.toAddress,\n } satisfies Quote;\n}\n\nexport async function getPartnerFeeBps(apiOptions: ApiOptions): Promise<number> {\n try {\n const partnerInfo = await markrGetPartnerInfo(apiOptions);\n return partnerInfo.fee;\n } catch (error) {\n throw new SdkError(ErrorReason.UNKNOWN, ErrorCode.INITIALIZATION_FAILED, {\n cause: error,\n details: 'Failed to fetch partner info from Markr API.',\n });\n }\n}\n\nexport function mapMarkrQuoteResponseDataFeesToQuoteFees(markrFees: QuoteResponseData['fees']): QuoteFees {\n if (!markrFees) {\n return [];\n }\n\n const fees: QuoteFee[] = [];\n\n for (const fee of markrFees) {\n const chainId = typeof fee.token.chainId === 'number' ? eip155ChainIdToCaip2(fee.token.chainId) : fee.token.chainId;\n\n let token: QuoteFeeToken | undefined;\n\n if (isTokenAddressNative(fee.token.address)) {\n token = { type: TokenType.NATIVE };\n } else if (isEvmAddress(fee.token.address)) {\n token = { type: TokenType.ERC20, address: fee.token.address };\n } else if (isSolAddress(fee.token.address)) {\n token = { type: TokenType.SPL, address: fee.token.address };\n }\n\n if (!token) {\n // Skip fee if we can't determine token type.\n continue;\n }\n\n fees.push({\n type: fee.type,\n name: fee.name,\n amount: fee.amount,\n chainId,\n token,\n });\n }\n\n return fees;\n}\n\nfunction assetToFeeToken(asset: Asset): QuoteFeeToken {\n if (asset.type === TokenType.NATIVE) {\n return { type: TokenType.NATIVE };\n }\n\n if (asset.type === TokenType.SPL) {\n return { type: TokenType.SPL, address: asset.address };\n }\n\n return { type: TokenType.ERC20, address: asset.address };\n}\n\nexport type MarkrRouterAbi =\n | (typeof import('./_abis/swap-wrapper-abi'))['MARKR_SWAP_WRAPPER_ABI']\n | (typeof import('./_abis/cross-chain-swap-wrapper-abi'))['MARKR_CROSS_CHAIN_SWAP_WRAPPER_ABI'];\n\nexport async function getMarkrSwapWrapperAbi(crossChain: boolean): Promise<MarkrRouterAbi> {\n if (crossChain) {\n return (await import('./_abis/cross-chain-swap-wrapper-abi')).MARKR_CROSS_CHAIN_SWAP_WRAPPER_ABI;\n }\n\n return (await import('./_abis/swap-wrapper-abi')).MARKR_SWAP_WRAPPER_ABI;\n}\n\nexport function extractHexDataFromError(error: unknown): Hex | undefined {\n if (error instanceof BaseError) {\n const directData = (error as { data?: unknown }).data;\n if (isHex(directData)) {\n return directData;\n }\n\n let walkedData: Hex | undefined;\n error.walk((walkedError) => {\n const nestedData = (walkedError as { data?: unknown }).data;\n if (!walkedData && isHex(nestedData)) {\n walkedData = nestedData;\n }\n return false;\n });\n\n if (walkedData) {\n return walkedData;\n }\n\n const causeData = (error as { cause?: { data?: unknown } }).cause?.data;\n if (isHex(causeData)) {\n return causeData;\n }\n }\n\n if (!error || typeof error !== 'object') {\n return undefined;\n }\n\n const genericError = error as {\n data?: unknown;\n error?: { data?: unknown };\n cause?: { data?: unknown };\n response?: { data?: unknown };\n body?: { error?: { data?: unknown } };\n };\n\n if (isHex(genericError.data)) {\n return genericError.data;\n }\n\n if (isHex(genericError.error?.data)) {\n return genericError.error.data;\n }\n\n if (isHex(genericError.cause?.data)) {\n return genericError.cause.data;\n }\n\n if (isHex(genericError.response?.data)) {\n return genericError.response.data;\n }\n\n if (isHex(genericError.body?.error?.data)) {\n return genericError.body.error.data;\n }\n\n return undefined;\n}\n\nexport function decodeMarkrRevertError(abi: MarkrRouterAbi, error: unknown): string | null {\n const revertData = extractHexDataFromError(error);\n\n if (!revertData) {\n return null;\n }\n\n try {\n const decoded = decodeErrorResult({ abi, data: revertData });\n const decodedArgs = decoded.args.length > 0 ? `(${decoded.args.map(String).join(', ')})` : '()';\n\n return `${decoded.errorName}${decodedArgs}`;\n } catch {\n const selector = revertData.slice(0, 10).toLowerCase();\n\n for (const abiItem of abi) {\n if (abiItem.type !== 'error') {\n continue;\n }\n\n const signature = `${abiItem.name}(${abiItem.inputs.map((input) => input.type).join(',')})`;\n if (toFunctionSelector(signature).toLowerCase() === selector) {\n return `${abiItem.name}()`;\n }\n }\n }\n\n return null;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"_utils.cjs","names":["markrGetInfoChains","eip155ChainIdToCaip2","SdkError","ErrorReason","ErrorCode","markrGetTokenList","ERC_ZERO_ADDRESS","SOL_MINT_ADDRESS","TokenType","isSolanaNamespace","calculateMinimumAmountOut","ServiceType","markrGetPartnerInfo","isEvmAddress","isSolAddress","BaseError"],"sources":["../../../src/transfer-service/markr/_utils.ts"],"sourcesContent":["import { ErrorCode, ErrorReason, SdkError } from '../../errors';\nimport { BaseError, decodeErrorResult, type Hex, isHex, toFunctionSelector } from 'viem';\nimport {\n type QuoteResponseData,\n type SupportedChainsResponseItemEvm,\n type SupportedChainsResponseItemSvm,\n type TokenListResponse,\n} from './_schema';\nimport { ERC_ZERO_ADDRESS, SOL_MINT_ADDRESS, ServiceType, TokenType } from '../../constants';\nimport { isSolanaNamespace } from '../../_utils/chain';\nimport { calculateMinimumAmountOut } from '../../_utils/math';\nimport { eip155ChainIdToCaip2 } from '../../utils/caip';\nimport type { Asset } from '../../types/asset';\nimport type { Caip2ChainId } from '../../types/caip';\nimport type { Quote, QuoteFee, QuoteFees, QuoteFeeToken, QuoterProps } from '../../types/quote';\nimport { markrGetInfoChains, markrGetPartnerInfo, markrGetTokenList, type ApiOptions } from './_api';\nimport { isEvmAddress } from '../../utils/evm-address';\nimport { isSolAddress } from '../../utils/sol-address';\n\nexport type SupportedChainsMap = Map<\n Caip2ChainId,\n {\n /** `number` for EVM, `Caip2ChainId` for SVM */\n chainId: number | Caip2ChainId;\n crossChainSwapEnabled: boolean;\n crossChainTargetChainIds: ReadonlySet<Caip2ChainId>;\n swapEnabled: boolean;\n tokenList: boolean;\n }\n>;\n\n/**\n * Checks whether the given source → target chain route is supported by Markr.\n */\nexport function isRouteSupported(\n supportedChains: SupportedChainsMap,\n sourceChainId: Caip2ChainId,\n targetChainId: Caip2ChainId,\n): boolean {\n const sourceChain = supportedChains.get(sourceChainId);\n const targetChain = supportedChains.get(targetChainId);\n\n if (!sourceChain || !targetChain) return false;\n\n if (sourceChainId === targetChainId) {\n return sourceChain.swapEnabled;\n }\n\n return sourceChain.crossChainSwapEnabled && sourceChain.crossChainTargetChainIds.has(targetChainId);\n}\n\nexport async function getSupportedChains(\n apiOptions: ApiOptions,\n disableCrossChainSwaps = false,\n): Promise<SupportedChainsMap> {\n const supportedChains: SupportedChainsMap = new Map();\n\n try {\n const chains = await markrGetInfoChains(apiOptions);\n const filteredSupportedChains = chains.filter(\n (chain): chain is SupportedChainsResponseItemEvm | SupportedChainsResponseItemSvm => {\n // Only include chains types that we support in the SDK (EVM and Solana for now).\n return chain.chainType === 'evm' || chain.chainType === 'svm';\n },\n );\n\n for (const chain of filteredSupportedChains) {\n const key: Caip2ChainId = typeof chain.chainId === 'number' ? eip155ChainIdToCaip2(chain.chainId) : chain.chainId;\n\n const isCrossChainSwapEnabled =\n chain.enabled_services.includes('cross-chain-quote') && chain.enabled_services.includes('cross-chain-swap');\n const isSwapEnabled = chain.enabled_services.includes('quote') && chain.enabled_services.includes('swap');\n const normalizedLaneChainIds = new Set<Caip2ChainId>();\n\n for (const lane of chain.lanes) {\n const laneChainId = typeof lane === 'number' ? eip155ChainIdToCaip2(lane) : lane;\n\n if (laneChainId !== key) {\n normalizedLaneChainIds.add(laneChainId);\n }\n }\n\n const crossChainSwapEnabled = disableCrossChainSwaps ? false : isCrossChainSwapEnabled;\n const crossChainTargetChainIds = crossChainSwapEnabled ? normalizedLaneChainIds : new Set<Caip2ChainId>();\n\n if (!isSwapEnabled && crossChainTargetChainIds.size === 0) {\n continue;\n }\n\n supportedChains.set(key, {\n chainId: chain.chainId,\n crossChainSwapEnabled,\n crossChainTargetChainIds,\n swapEnabled: isSwapEnabled,\n tokenList: chain.enabled_services.includes('token-list'),\n });\n }\n } catch (error) {\n throw new SdkError(ErrorReason.UNKNOWN, ErrorCode.INITIALIZATION_FAILED, {\n cause: error,\n details: 'Failed to fetch supported chains from Markr API.',\n });\n }\n\n return supportedChains;\n}\n\nexport async function getSupportedTokens(\n apiOptions: ApiOptions,\n supportedChains: SupportedChainsMap,\n): Promise<Map<Caip2ChainId, Promise<TokenListResponse>>> {\n // Parallel fetch token lists for all supported chains.\n const supportedTokens: Map<Caip2ChainId, Promise<TokenListResponse>> = new Map();\n\n for (const [caip2ChainId, chainInfo] of supportedChains.entries()) {\n // Only fetch token list for EVM chains that support swaps.\n if (\n typeof chainInfo.chainId === 'number' &&\n chainInfo.tokenList &&\n (chainInfo.crossChainSwapEnabled || chainInfo.swapEnabled)\n ) {\n try {\n const tokenListPromise = markrGetTokenList(apiOptions, chainInfo.chainId);\n supportedTokens.set(caip2ChainId, tokenListPromise);\n } catch {\n // Ignore errors for individual token list fetches.\n // TODO: Logger?\n }\n }\n }\n\n return supportedTokens;\n}\n\n/**\n * Determine if the provided token address represents the native token for its chain.\n *\n * Markr represents EVM native tokens as the zero address and Solana native SOL\n * as the wrapped SOL mint address.\n */\nexport function isTokenAddressNative(address: string): boolean {\n return address === ERC_ZERO_ADDRESS || address === SOL_MINT_ADDRESS;\n}\n\n/**\n * Convert an `Asset` to the address string expected by the Markr API.\n *\n * For NATIVE assets the representation depends on the chain:\n * - EVM chains: `0x0000...0000` (ERC zero address)\n * - Solana chains: `So11111111111111111111111111111111111111112` (wrapped SOL mint)\n *\n * @param asset The asset to convert.\n * @param chainId CAIP-2 chain ID used to disambiguate NATIVE assets across chain types.\n */\nexport function assetToAddressString(asset: Asset, chainId: Caip2ChainId): string {\n if (asset.type === TokenType.NATIVE) {\n if (isSolanaNamespace(chainId)) {\n return SOL_MINT_ADDRESS;\n }\n\n return ERC_ZERO_ADDRESS;\n }\n\n return asset.address;\n}\n\n/**\n * Markr rejects `minAmountOut=0` for non-zero quotes.\n *\n * For very small quotes, integer truncation after slippage can produce `0`.\n * Clamp to `1` in that edge case to satisfy Markr API validation while\n * preserving normal slippage behavior for larger quotes.\n */\nexport function calculateMarkrMinimumAmountOut({\n amountOut,\n assetOut,\n slippageBps,\n}: Pick<Quote, 'amountOut' | 'assetOut' | 'slippageBps'>): bigint {\n const minAmountOut = calculateMinimumAmountOut({ amountOut, assetOut, slippageBps });\n\n if (amountOut > 0n && minAmountOut === 0n) {\n return 1n;\n }\n\n return minAmountOut;\n}\n\nexport function quoteFromMarkrQuoteResponseData(\n data: QuoteResponseData,\n quoterProps: QuoterProps,\n partnerFeeBps: number,\n): Quote {\n const partnerFee: bigint = (data.amountOut * BigInt(partnerFeeBps)) / 10_000n;\n const amountOutAfterFees: bigint = data.amountOut - partnerFee;\n\n const fees: QuoteFees = [\n ...mapMarkrQuoteResponseDataFeesToQuoteFees(data.fees),\n // Add the partner fee as a QuoteFee component for Markr quotes.\n {\n type: 'partner',\n name: 'Core Fee',\n amount: partnerFee,\n chainId: quoterProps.targetChain.chainId,\n token: assetToFeeToken(quoterProps.targetAsset),\n },\n ];\n\n return {\n aggregator: {\n id: data.aggregator.id,\n logoUrl: data.aggregator.logo_url,\n name: data.aggregator.name,\n },\n amountIn: data.amountIn,\n amountOut: amountOutAfterFees,\n assetIn: quoterProps.sourceAsset,\n assetOut: quoterProps.targetAsset,\n expiresAt: data.expiredAt, // Markr returns `expiredAt` as Unix time in seconds; use as-is.\n fees,\n fromAddress: quoterProps.fromAddress,\n /**\n * This gasEstimate is rough or may be missing.\n * Consumers should use TransferManager.estimateGas for a more accurate estimate.\n */\n gasEstimate: data.gasEstimate,\n id: data.uuid,\n partnerFeeBps,\n serviceType: ServiceType.MARKR,\n slippageBps: quoterProps.slippageBps ?? data.recommendedSlippage,\n sourceChain: quoterProps.sourceChain,\n targetChain: quoterProps.targetChain,\n toAddress: quoterProps.toAddress,\n } satisfies Quote;\n}\n\nexport async function getPartnerFeeBps(apiOptions: ApiOptions): Promise<number> {\n try {\n const partnerInfo = await markrGetPartnerInfo(apiOptions);\n return partnerInfo.fee;\n } catch (error) {\n throw new SdkError(ErrorReason.UNKNOWN, ErrorCode.INITIALIZATION_FAILED, {\n cause: error,\n details: 'Failed to fetch partner info from Markr API.',\n });\n }\n}\n\nexport function mapMarkrQuoteResponseDataFeesToQuoteFees(markrFees: QuoteResponseData['fees']): QuoteFees {\n if (!markrFees) {\n return [];\n }\n\n const fees: QuoteFee[] = [];\n\n for (const fee of markrFees) {\n const chainId = typeof fee.token.chainId === 'number' ? eip155ChainIdToCaip2(fee.token.chainId) : fee.token.chainId;\n\n let token: QuoteFeeToken | undefined;\n\n if (isTokenAddressNative(fee.token.address)) {\n token = { type: TokenType.NATIVE };\n } else if (isEvmAddress(fee.token.address)) {\n token = { type: TokenType.ERC20, address: fee.token.address };\n } else if (isSolAddress(fee.token.address)) {\n token = { type: TokenType.SPL, address: fee.token.address };\n }\n\n if (!token) {\n // Skip fee if we can't determine token type.\n continue;\n }\n\n fees.push({\n type: fee.type,\n name: fee.name,\n amount: fee.amount,\n chainId,\n token,\n });\n }\n\n return fees;\n}\n\nfunction assetToFeeToken(asset: Asset): QuoteFeeToken {\n if (asset.type === TokenType.NATIVE) {\n return { type: TokenType.NATIVE };\n }\n\n if (asset.type === TokenType.SPL) {\n return { type: TokenType.SPL, address: asset.address };\n }\n\n return { type: TokenType.ERC20, address: asset.address };\n}\n\nexport type MarkrRouterAbi =\n | (typeof import('./_abis/swap-wrapper-abi'))['MARKR_SWAP_WRAPPER_ABI']\n | (typeof import('./_abis/cross-chain-swap-wrapper-abi'))['MARKR_CROSS_CHAIN_SWAP_WRAPPER_ABI'];\n\nexport async function getMarkrSwapWrapperAbi(crossChain: boolean): Promise<MarkrRouterAbi> {\n if (crossChain) {\n return (await import('./_abis/cross-chain-swap-wrapper-abi')).MARKR_CROSS_CHAIN_SWAP_WRAPPER_ABI;\n }\n\n return (await import('./_abis/swap-wrapper-abi')).MARKR_SWAP_WRAPPER_ABI;\n}\n\nexport function extractHexDataFromError(error: unknown): Hex | undefined {\n if (error instanceof BaseError) {\n const directData = (error as { data?: unknown }).data;\n if (isHex(directData)) {\n return directData;\n }\n\n let walkedData: Hex | undefined;\n error.walk((walkedError) => {\n const nestedData = (walkedError as { data?: unknown }).data;\n if (!walkedData && isHex(nestedData)) {\n walkedData = nestedData;\n }\n return false;\n });\n\n if (walkedData) {\n return walkedData;\n }\n\n const causeData = (error as { cause?: { data?: unknown } }).cause?.data;\n if (isHex(causeData)) {\n return causeData;\n }\n }\n\n if (!error || typeof error !== 'object') {\n return undefined;\n }\n\n const genericError = error as {\n data?: unknown;\n error?: { data?: unknown };\n cause?: { data?: unknown };\n response?: { data?: unknown };\n body?: { error?: { data?: unknown } };\n };\n\n if (isHex(genericError.data)) {\n return genericError.data;\n }\n\n if (isHex(genericError.error?.data)) {\n return genericError.error.data;\n }\n\n if (isHex(genericError.cause?.data)) {\n return genericError.cause.data;\n }\n\n if (isHex(genericError.response?.data)) {\n return genericError.response.data;\n }\n\n if (isHex(genericError.body?.error?.data)) {\n return genericError.body.error.data;\n }\n\n return undefined;\n}\n\nexport function decodeMarkrRevertError(abi: MarkrRouterAbi, error: unknown): string | null {\n const revertData = extractHexDataFromError(error);\n\n if (!revertData) {\n return null;\n }\n\n try {\n const decoded = decodeErrorResult({ abi, data: revertData });\n const decodedArgs = decoded.args.length > 0 ? `(${decoded.args.map(String).join(', ')})` : '()';\n\n return `${decoded.errorName}${decodedArgs}`;\n } catch {\n const selector = revertData.slice(0, 10).toLowerCase();\n\n for (const abiItem of abi) {\n if (abiItem.type !== 'error') {\n continue;\n }\n\n const signature = `${abiItem.name}(${abiItem.inputs.map((input) => input.type).join(',')})`;\n if (toFunctionSelector(signature).toLowerCase() === selector) {\n return `${abiItem.name}()`;\n }\n }\n }\n\n return null;\n}\n"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- import{ERC_ZERO_ADDRESS as e,SOL_MINT_ADDRESS as t,ServiceType as n,TokenType as r}from"../../constants.js";import{ErrorCode as i,ErrorReason as a,SdkError as o}from"../../errors.js";import{eip155ChainIdToCaip2 as s}from"../../utils/caip.js";import{isEvmAddress as c}from"../../utils/evm-address.js";import{isSolanaNamespace as l}from"../../_utils/chain.js";import{markrGetInfoChains as u,markrGetPartnerInfo as d,markrGetTokenList as f}from"./_api.js";import{calculateMinimumAmountOut as p}from"../../_utils/math.js";import{isSolAddress as m}from"../../utils/sol-address.js";import{BaseError as h,decodeErrorResult as g,isHex as _,toFunctionSelector as v}from"viem";async function y(e,t=!1){let n=new Map;try{let r=(await u(e)).filter(e=>e.chainType===`evm`||e.chainType===`svm`);for(let e of r){let r=typeof e.chainId==`number`?s(e.chainId):e.chainId,i=e.enabled_services.includes(`cross-chain-quote`)&&e.enabled_services.includes(`cross-chain-swap`),a=e.enabled_services.includes(`quote`)&&e.enabled_services.includes(`swap`),o=new Set;for(let t of e.lanes){let e=typeof t==`number`?s(t):t;e!==r&&o.add(e)}let c=t?!1:i,l=c?o:new Set;!a&&l.size===0||n.set(r,{chainId:e.chainId,crossChainSwapEnabled:c,crossChainTargetChainIds:l,swapEnabled:a,tokenList:e.enabled_services.includes(`token-list`)})}}catch(e){throw new o(a.UNKNOWN,i.INITIALIZATION_FAILED,{cause:e,details:`Failed to fetch supported chains from Markr API.`})}return n}async function b(e,t){let n=new Map;for(let[r,i]of t.entries())if(typeof i.chainId==`number`&&i.tokenList&&(i.crossChainSwapEnabled||i.swapEnabled))try{let t=f(e,i.chainId);n.set(r,t)}catch{}return n}function x(n){return n===e||n===t}function S(n,i){return n.type===r.NATIVE?l(i)?t:e:n.address}function C({amountOut:e,assetOut:t,slippageBps:n}){let r=p({amountOut:e,assetOut:t,slippageBps:n});return e>0n&&r===0n?1n:r}function w(e,t,r){let i=e.amountOut*BigInt(r)/10000n,a=e.amountOut-i,o=[...E(e.fees),{type:`partner`,name:`Core Fee`,amount:i,chainId:t.targetChain.chainId,token:D(t.targetAsset)}];return{aggregator:{id:e.aggregator.id,logoUrl:e.aggregator.logo_url,name:e.aggregator.name},amountIn:e.amountIn,amountOut:a,assetIn:t.sourceAsset,assetOut:t.targetAsset,expiresAt:e.expiredAt,fees:o,fromAddress:t.fromAddress,gasEstimate:e.gasEstimate,id:e.uuid,partnerFeeBps:r,serviceType:n.MARKR,slippageBps:t.slippageBps??e.recommendedSlippage,sourceChain:t.sourceChain,targetChain:t.targetChain,toAddress:t.toAddress}}async function T(e){try{return(await d(e)).fee}catch(e){throw new o(a.UNKNOWN,i.INITIALIZATION_FAILED,{cause:e,details:`Failed to fetch partner info from Markr API.`})}}function E(e){if(!e)return[];let t=[];for(let n of e){let e=typeof n.token.chainId==`number`?s(n.token.chainId):n.token.chainId,i;x(n.token.address)?i={type:r.NATIVE}:c(n.token.address)?i={type:r.ERC20,address:n.token.address}:m(n.token.address)&&(i={type:r.SPL,address:n.token.address}),i&&t.push({type:n.type,name:n.name,amount:n.amount,chainId:e,token:i})}return t}function D(e){return e.type===r.NATIVE?{type:r.NATIVE}:e.type===r.SPL?{type:r.SPL,address:e.address}:{type:r.ERC20,address:e.address}}async function O(e){return e?(await import(`./_abis/cross-chain-swap-wrapper-abi.js`)).MARKR_CROSS_CHAIN_SWAP_WRAPPER_ABI:(await import(`./_abis/swap-wrapper-abi.js`)).MARKR_SWAP_WRAPPER_ABI}function k(e){if(e instanceof h){let t=e.data;if(_(t))return t;let n;if(e.walk(e=>{let t=e.data;return!n&&_(t)&&(n=t),!1}),n)return n;let r=e.cause?.data;if(_(r))return r}if(!e||typeof e!=`object`)return;let t=e;if(_(t.data))return t.data;if(_(t.error?.data))return t.error.data;if(_(t.cause?.data))return t.cause.data;if(_(t.response?.data))return t.response.data;if(_(t.body?.error?.data))return t.body.error.data}function A(e,t){let n=k(t);if(!n)return null;try{let t=g({abi:e,data:n}),r=t.args.length>0?`(${t.args.map(String).join(`, `)})`:`()`;return`${t.errorName}${r}`}catch{let t=n.slice(0,10).toLowerCase();for(let n of e)if(n.type===`error`&&v(`${n.name}(${n.inputs.map(e=>e.type).join(`,`)})`).toLowerCase()===t)return`${n.name}()`}return null}export{S as assetToAddressString,C as calculateMarkrMinimumAmountOut,A as decodeMarkrRevertError,O as getMarkrSwapWrapperAbi,T as getPartnerFeeBps,y as getSupportedChains,b as getSupportedTokens,x as isTokenAddressNative,w as quoteFromMarkrQuoteResponseData};
1
+ import{ERC_ZERO_ADDRESS as e,SOL_MINT_ADDRESS as t,ServiceType as n,TokenType as r}from"../../constants.js";import{ErrorCode as i,ErrorReason as a,SdkError as o}from"../../errors.js";import{eip155ChainIdToCaip2 as s}from"../../utils/caip.js";import{isEvmAddress as c}from"../../utils/evm-address.js";import{isSolanaNamespace as l}from"../../_utils/chain.js";import{calculateMinimumAmountOut as u}from"../../_utils/math.js";import{markrGetInfoChains as d,markrGetPartnerInfo as f,markrGetTokenList as p}from"./_api.js";import{isSolAddress as m}from"../../utils/sol-address.js";import{BaseError as h,decodeErrorResult as g,isHex as _,toFunctionSelector as v}from"viem";function y(e,t,n){let r=e.get(t),i=e.get(n);return!r||!i?!1:t===n?r.swapEnabled:r.crossChainSwapEnabled&&r.crossChainTargetChainIds.has(n)}async function b(e,t=!1){let n=new Map;try{let r=(await d(e)).filter(e=>e.chainType===`evm`||e.chainType===`svm`);for(let e of r){let r=typeof e.chainId==`number`?s(e.chainId):e.chainId,i=e.enabled_services.includes(`cross-chain-quote`)&&e.enabled_services.includes(`cross-chain-swap`),a=e.enabled_services.includes(`quote`)&&e.enabled_services.includes(`swap`),o=new Set;for(let t of e.lanes){let e=typeof t==`number`?s(t):t;e!==r&&o.add(e)}let c=t?!1:i,l=c?o:new Set;!a&&l.size===0||n.set(r,{chainId:e.chainId,crossChainSwapEnabled:c,crossChainTargetChainIds:l,swapEnabled:a,tokenList:e.enabled_services.includes(`token-list`)})}}catch(e){throw new o(a.UNKNOWN,i.INITIALIZATION_FAILED,{cause:e,details:`Failed to fetch supported chains from Markr API.`})}return n}async function x(e,t){let n=new Map;for(let[r,i]of t.entries())if(typeof i.chainId==`number`&&i.tokenList&&(i.crossChainSwapEnabled||i.swapEnabled))try{let t=p(e,i.chainId);n.set(r,t)}catch{}return n}function S(n){return n===e||n===t}function C(n,i){return n.type===r.NATIVE?l(i)?t:e:n.address}function w({amountOut:e,assetOut:t,slippageBps:n}){let r=u({amountOut:e,assetOut:t,slippageBps:n});return e>0n&&r===0n?1n:r}function T(e,t,r){let i=e.amountOut*BigInt(r)/10000n,a=e.amountOut-i,o=[...D(e.fees),{type:`partner`,name:`Core Fee`,amount:i,chainId:t.targetChain.chainId,token:O(t.targetAsset)}];return{aggregator:{id:e.aggregator.id,logoUrl:e.aggregator.logo_url,name:e.aggregator.name},amountIn:e.amountIn,amountOut:a,assetIn:t.sourceAsset,assetOut:t.targetAsset,expiresAt:e.expiredAt,fees:o,fromAddress:t.fromAddress,gasEstimate:e.gasEstimate,id:e.uuid,partnerFeeBps:r,serviceType:n.MARKR,slippageBps:t.slippageBps??e.recommendedSlippage,sourceChain:t.sourceChain,targetChain:t.targetChain,toAddress:t.toAddress}}async function E(e){try{return(await f(e)).fee}catch(e){throw new o(a.UNKNOWN,i.INITIALIZATION_FAILED,{cause:e,details:`Failed to fetch partner info from Markr API.`})}}function D(e){if(!e)return[];let t=[];for(let n of e){let e=typeof n.token.chainId==`number`?s(n.token.chainId):n.token.chainId,i;S(n.token.address)?i={type:r.NATIVE}:c(n.token.address)?i={type:r.ERC20,address:n.token.address}:m(n.token.address)&&(i={type:r.SPL,address:n.token.address}),i&&t.push({type:n.type,name:n.name,amount:n.amount,chainId:e,token:i})}return t}function O(e){return e.type===r.NATIVE?{type:r.NATIVE}:e.type===r.SPL?{type:r.SPL,address:e.address}:{type:r.ERC20,address:e.address}}async function k(e){return e?(await import(`./_abis/cross-chain-swap-wrapper-abi.js`)).MARKR_CROSS_CHAIN_SWAP_WRAPPER_ABI:(await import(`./_abis/swap-wrapper-abi.js`)).MARKR_SWAP_WRAPPER_ABI}function A(e){if(e instanceof h){let t=e.data;if(_(t))return t;let n;if(e.walk(e=>{let t=e.data;return!n&&_(t)&&(n=t),!1}),n)return n;let r=e.cause?.data;if(_(r))return r}if(!e||typeof e!=`object`)return;let t=e;if(_(t.data))return t.data;if(_(t.error?.data))return t.error.data;if(_(t.cause?.data))return t.cause.data;if(_(t.response?.data))return t.response.data;if(_(t.body?.error?.data))return t.body.error.data}function j(e,t){let n=A(t);if(!n)return null;try{let t=g({abi:e,data:n}),r=t.args.length>0?`(${t.args.map(String).join(`, `)})`:`()`;return`${t.errorName}${r}`}catch{let t=n.slice(0,10).toLowerCase();for(let n of e)if(n.type===`error`&&v(`${n.name}(${n.inputs.map(e=>e.type).join(`,`)})`).toLowerCase()===t)return`${n.name}()`}return null}export{C as assetToAddressString,w as calculateMarkrMinimumAmountOut,j as decodeMarkrRevertError,k as getMarkrSwapWrapperAbi,E as getPartnerFeeBps,b as getSupportedChains,x as getSupportedTokens,y as isRouteSupported,S as isTokenAddressNative,T as quoteFromMarkrQuoteResponseData};
2
2
  //# sourceMappingURL=_utils.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"_utils.js","names":[],"sources":["../../../src/transfer-service/markr/_utils.ts"],"sourcesContent":["import { ErrorCode, ErrorReason, SdkError } from '../../errors';\nimport { BaseError, decodeErrorResult, type Hex, isHex, toFunctionSelector } from 'viem';\nimport {\n type QuoteResponseData,\n type SupportedChainsResponseItemEvm,\n type SupportedChainsResponseItemSvm,\n type TokenListResponse,\n} from './_schema';\nimport { ERC_ZERO_ADDRESS, SOL_MINT_ADDRESS, ServiceType, TokenType } from '../../constants';\nimport { isSolanaNamespace } from '../../_utils/chain';\nimport { calculateMinimumAmountOut } from '../../_utils/math';\nimport { eip155ChainIdToCaip2 } from '../../utils/caip';\nimport type { Asset } from '../../types/asset';\nimport type { Caip2ChainId } from '../../types/caip';\nimport type { Quote, QuoteFee, QuoteFees, QuoteFeeToken, QuoterProps } from '../../types/quote';\nimport { markrGetInfoChains, markrGetPartnerInfo, markrGetTokenList, type ApiOptions } from './_api';\nimport { isEvmAddress } from '../../utils/evm-address';\nimport { isSolAddress } from '../../utils/sol-address';\n\nexport type SupportedChainsMap = Map<\n Caip2ChainId,\n {\n /** `number` for EVM, `Caip2ChainId` for SVM */\n chainId: number | Caip2ChainId;\n crossChainSwapEnabled: boolean;\n crossChainTargetChainIds: ReadonlySet<Caip2ChainId>;\n swapEnabled: boolean;\n tokenList: boolean;\n }\n>;\n\nexport async function getSupportedChains(\n apiOptions: ApiOptions,\n disableCrossChainSwaps = false,\n): Promise<SupportedChainsMap> {\n const supportedChains: SupportedChainsMap = new Map();\n\n try {\n const chains = await markrGetInfoChains(apiOptions);\n const filteredSupportedChains = chains.filter(\n (chain): chain is SupportedChainsResponseItemEvm | SupportedChainsResponseItemSvm => {\n // Only include chains types that we support in the SDK (EVM and Solana for now).\n return chain.chainType === 'evm' || chain.chainType === 'svm';\n },\n );\n\n for (const chain of filteredSupportedChains) {\n const key: Caip2ChainId = typeof chain.chainId === 'number' ? eip155ChainIdToCaip2(chain.chainId) : chain.chainId;\n\n const isCrossChainSwapEnabled =\n chain.enabled_services.includes('cross-chain-quote') && chain.enabled_services.includes('cross-chain-swap');\n const isSwapEnabled = chain.enabled_services.includes('quote') && chain.enabled_services.includes('swap');\n const normalizedLaneChainIds = new Set<Caip2ChainId>();\n\n for (const lane of chain.lanes) {\n const laneChainId = typeof lane === 'number' ? eip155ChainIdToCaip2(lane) : lane;\n\n if (laneChainId !== key) {\n normalizedLaneChainIds.add(laneChainId);\n }\n }\n\n const crossChainSwapEnabled = disableCrossChainSwaps ? false : isCrossChainSwapEnabled;\n const crossChainTargetChainIds = crossChainSwapEnabled ? normalizedLaneChainIds : new Set<Caip2ChainId>();\n\n if (!isSwapEnabled && crossChainTargetChainIds.size === 0) {\n continue;\n }\n\n supportedChains.set(key, {\n chainId: chain.chainId,\n crossChainSwapEnabled,\n crossChainTargetChainIds,\n swapEnabled: isSwapEnabled,\n tokenList: chain.enabled_services.includes('token-list'),\n });\n }\n } catch (error) {\n throw new SdkError(ErrorReason.UNKNOWN, ErrorCode.INITIALIZATION_FAILED, {\n cause: error,\n details: 'Failed to fetch supported chains from Markr API.',\n });\n }\n\n return supportedChains;\n}\n\nexport async function getSupportedTokens(\n apiOptions: ApiOptions,\n supportedChains: SupportedChainsMap,\n): Promise<Map<Caip2ChainId, Promise<TokenListResponse>>> {\n // Parallel fetch token lists for all supported chains.\n const supportedTokens: Map<Caip2ChainId, Promise<TokenListResponse>> = new Map();\n\n for (const [caip2ChainId, chainInfo] of supportedChains.entries()) {\n // Only fetch token list for EVM chains that support swaps.\n if (\n typeof chainInfo.chainId === 'number' &&\n chainInfo.tokenList &&\n (chainInfo.crossChainSwapEnabled || chainInfo.swapEnabled)\n ) {\n try {\n const tokenListPromise = markrGetTokenList(apiOptions, chainInfo.chainId);\n supportedTokens.set(caip2ChainId, tokenListPromise);\n } catch {\n // Ignore errors for individual token list fetches.\n // TODO: Logger?\n }\n }\n }\n\n return supportedTokens;\n}\n\n/**\n * Determine if the provided token address represents the native token for its chain.\n *\n * Markr represents EVM native tokens as the zero address and Solana native SOL\n * as the wrapped SOL mint address.\n */\nexport function isTokenAddressNative(address: string): boolean {\n return address === ERC_ZERO_ADDRESS || address === SOL_MINT_ADDRESS;\n}\n\n/**\n * Convert an `Asset` to the address string expected by the Markr API.\n *\n * For NATIVE assets the representation depends on the chain:\n * - EVM chains: `0x0000...0000` (ERC zero address)\n * - Solana chains: `So11111111111111111111111111111111111111112` (wrapped SOL mint)\n *\n * @param asset The asset to convert.\n * @param chainId CAIP-2 chain ID used to disambiguate NATIVE assets across chain types.\n */\nexport function assetToAddressString(asset: Asset, chainId: Caip2ChainId): string {\n if (asset.type === TokenType.NATIVE) {\n if (isSolanaNamespace(chainId)) {\n return SOL_MINT_ADDRESS;\n }\n\n return ERC_ZERO_ADDRESS;\n }\n\n return asset.address;\n}\n\n/**\n * Markr rejects `minAmountOut=0` for non-zero quotes.\n *\n * For very small quotes, integer truncation after slippage can produce `0`.\n * Clamp to `1` in that edge case to satisfy Markr API validation while\n * preserving normal slippage behavior for larger quotes.\n */\nexport function calculateMarkrMinimumAmountOut({\n amountOut,\n assetOut,\n slippageBps,\n}: Pick<Quote, 'amountOut' | 'assetOut' | 'slippageBps'>): bigint {\n const minAmountOut = calculateMinimumAmountOut({ amountOut, assetOut, slippageBps });\n\n if (amountOut > 0n && minAmountOut === 0n) {\n return 1n;\n }\n\n return minAmountOut;\n}\n\nexport function quoteFromMarkrQuoteResponseData(\n data: QuoteResponseData,\n quoterProps: QuoterProps,\n partnerFeeBps: number,\n): Quote {\n const partnerFee: bigint = (data.amountOut * BigInt(partnerFeeBps)) / 10_000n;\n const amountOutAfterFees: bigint = data.amountOut - partnerFee;\n\n const fees: QuoteFees = [\n ...mapMarkrQuoteResponseDataFeesToQuoteFees(data.fees),\n // Add the partner fee as a QuoteFee component for Markr quotes.\n {\n type: 'partner',\n name: 'Core Fee',\n amount: partnerFee,\n chainId: quoterProps.targetChain.chainId,\n token: assetToFeeToken(quoterProps.targetAsset),\n },\n ];\n\n return {\n aggregator: {\n id: data.aggregator.id,\n logoUrl: data.aggregator.logo_url,\n name: data.aggregator.name,\n },\n amountIn: data.amountIn,\n amountOut: amountOutAfterFees,\n assetIn: quoterProps.sourceAsset,\n assetOut: quoterProps.targetAsset,\n expiresAt: data.expiredAt, // Markr returns `expiredAt` as Unix time in seconds; use as-is.\n fees,\n fromAddress: quoterProps.fromAddress,\n /**\n * This gasEstimate is rough or may be missing.\n * Consumers should use TransferManager.estimateGas for a more accurate estimate.\n */\n gasEstimate: data.gasEstimate,\n id: data.uuid,\n partnerFeeBps,\n serviceType: ServiceType.MARKR,\n slippageBps: quoterProps.slippageBps ?? data.recommendedSlippage,\n sourceChain: quoterProps.sourceChain,\n targetChain: quoterProps.targetChain,\n toAddress: quoterProps.toAddress,\n } satisfies Quote;\n}\n\nexport async function getPartnerFeeBps(apiOptions: ApiOptions): Promise<number> {\n try {\n const partnerInfo = await markrGetPartnerInfo(apiOptions);\n return partnerInfo.fee;\n } catch (error) {\n throw new SdkError(ErrorReason.UNKNOWN, ErrorCode.INITIALIZATION_FAILED, {\n cause: error,\n details: 'Failed to fetch partner info from Markr API.',\n });\n }\n}\n\nexport function mapMarkrQuoteResponseDataFeesToQuoteFees(markrFees: QuoteResponseData['fees']): QuoteFees {\n if (!markrFees) {\n return [];\n }\n\n const fees: QuoteFee[] = [];\n\n for (const fee of markrFees) {\n const chainId = typeof fee.token.chainId === 'number' ? eip155ChainIdToCaip2(fee.token.chainId) : fee.token.chainId;\n\n let token: QuoteFeeToken | undefined;\n\n if (isTokenAddressNative(fee.token.address)) {\n token = { type: TokenType.NATIVE };\n } else if (isEvmAddress(fee.token.address)) {\n token = { type: TokenType.ERC20, address: fee.token.address };\n } else if (isSolAddress(fee.token.address)) {\n token = { type: TokenType.SPL, address: fee.token.address };\n }\n\n if (!token) {\n // Skip fee if we can't determine token type.\n continue;\n }\n\n fees.push({\n type: fee.type,\n name: fee.name,\n amount: fee.amount,\n chainId,\n token,\n });\n }\n\n return fees;\n}\n\nfunction assetToFeeToken(asset: Asset): QuoteFeeToken {\n if (asset.type === TokenType.NATIVE) {\n return { type: TokenType.NATIVE };\n }\n\n if (asset.type === TokenType.SPL) {\n return { type: TokenType.SPL, address: asset.address };\n }\n\n return { type: TokenType.ERC20, address: asset.address };\n}\n\nexport type MarkrRouterAbi =\n | (typeof import('./_abis/swap-wrapper-abi'))['MARKR_SWAP_WRAPPER_ABI']\n | (typeof import('./_abis/cross-chain-swap-wrapper-abi'))['MARKR_CROSS_CHAIN_SWAP_WRAPPER_ABI'];\n\nexport async function getMarkrSwapWrapperAbi(crossChain: boolean): Promise<MarkrRouterAbi> {\n if (crossChain) {\n return (await import('./_abis/cross-chain-swap-wrapper-abi')).MARKR_CROSS_CHAIN_SWAP_WRAPPER_ABI;\n }\n\n return (await import('./_abis/swap-wrapper-abi')).MARKR_SWAP_WRAPPER_ABI;\n}\n\nexport function extractHexDataFromError(error: unknown): Hex | undefined {\n if (error instanceof BaseError) {\n const directData = (error as { data?: unknown }).data;\n if (isHex(directData)) {\n return directData;\n }\n\n let walkedData: Hex | undefined;\n error.walk((walkedError) => {\n const nestedData = (walkedError as { data?: unknown }).data;\n if (!walkedData && isHex(nestedData)) {\n walkedData = nestedData;\n }\n return false;\n });\n\n if (walkedData) {\n return walkedData;\n }\n\n const causeData = (error as { cause?: { data?: unknown } }).cause?.data;\n if (isHex(causeData)) {\n return causeData;\n }\n }\n\n if (!error || typeof error !== 'object') {\n return undefined;\n }\n\n const genericError = error as {\n data?: unknown;\n error?: { data?: unknown };\n cause?: { data?: unknown };\n response?: { data?: unknown };\n body?: { error?: { data?: unknown } };\n };\n\n if (isHex(genericError.data)) {\n return genericError.data;\n }\n\n if (isHex(genericError.error?.data)) {\n return genericError.error.data;\n }\n\n if (isHex(genericError.cause?.data)) {\n return genericError.cause.data;\n }\n\n if (isHex(genericError.response?.data)) {\n return genericError.response.data;\n }\n\n if (isHex(genericError.body?.error?.data)) {\n return genericError.body.error.data;\n }\n\n return undefined;\n}\n\nexport function decodeMarkrRevertError(abi: MarkrRouterAbi, error: unknown): string | null {\n const revertData = extractHexDataFromError(error);\n\n if (!revertData) {\n return null;\n }\n\n try {\n const decoded = decodeErrorResult({ abi, data: revertData });\n const decodedArgs = decoded.args.length > 0 ? `(${decoded.args.map(String).join(', ')})` : '()';\n\n return `${decoded.errorName}${decodedArgs}`;\n } catch {\n const selector = revertData.slice(0, 10).toLowerCase();\n\n for (const abiItem of abi) {\n if (abiItem.type !== 'error') {\n continue;\n }\n\n const signature = `${abiItem.name}(${abiItem.inputs.map((input) => input.type).join(',')})`;\n if (toFunctionSelector(signature).toLowerCase() === selector) {\n return `${abiItem.name}()`;\n }\n }\n }\n\n return null;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"_utils.js","names":[],"sources":["../../../src/transfer-service/markr/_utils.ts"],"sourcesContent":["import { ErrorCode, ErrorReason, SdkError } from '../../errors';\nimport { BaseError, decodeErrorResult, type Hex, isHex, toFunctionSelector } from 'viem';\nimport {\n type QuoteResponseData,\n type SupportedChainsResponseItemEvm,\n type SupportedChainsResponseItemSvm,\n type TokenListResponse,\n} from './_schema';\nimport { ERC_ZERO_ADDRESS, SOL_MINT_ADDRESS, ServiceType, TokenType } from '../../constants';\nimport { isSolanaNamespace } from '../../_utils/chain';\nimport { calculateMinimumAmountOut } from '../../_utils/math';\nimport { eip155ChainIdToCaip2 } from '../../utils/caip';\nimport type { Asset } from '../../types/asset';\nimport type { Caip2ChainId } from '../../types/caip';\nimport type { Quote, QuoteFee, QuoteFees, QuoteFeeToken, QuoterProps } from '../../types/quote';\nimport { markrGetInfoChains, markrGetPartnerInfo, markrGetTokenList, type ApiOptions } from './_api';\nimport { isEvmAddress } from '../../utils/evm-address';\nimport { isSolAddress } from '../../utils/sol-address';\n\nexport type SupportedChainsMap = Map<\n Caip2ChainId,\n {\n /** `number` for EVM, `Caip2ChainId` for SVM */\n chainId: number | Caip2ChainId;\n crossChainSwapEnabled: boolean;\n crossChainTargetChainIds: ReadonlySet<Caip2ChainId>;\n swapEnabled: boolean;\n tokenList: boolean;\n }\n>;\n\n/**\n * Checks whether the given source → target chain route is supported by Markr.\n */\nexport function isRouteSupported(\n supportedChains: SupportedChainsMap,\n sourceChainId: Caip2ChainId,\n targetChainId: Caip2ChainId,\n): boolean {\n const sourceChain = supportedChains.get(sourceChainId);\n const targetChain = supportedChains.get(targetChainId);\n\n if (!sourceChain || !targetChain) return false;\n\n if (sourceChainId === targetChainId) {\n return sourceChain.swapEnabled;\n }\n\n return sourceChain.crossChainSwapEnabled && sourceChain.crossChainTargetChainIds.has(targetChainId);\n}\n\nexport async function getSupportedChains(\n apiOptions: ApiOptions,\n disableCrossChainSwaps = false,\n): Promise<SupportedChainsMap> {\n const supportedChains: SupportedChainsMap = new Map();\n\n try {\n const chains = await markrGetInfoChains(apiOptions);\n const filteredSupportedChains = chains.filter(\n (chain): chain is SupportedChainsResponseItemEvm | SupportedChainsResponseItemSvm => {\n // Only include chains types that we support in the SDK (EVM and Solana for now).\n return chain.chainType === 'evm' || chain.chainType === 'svm';\n },\n );\n\n for (const chain of filteredSupportedChains) {\n const key: Caip2ChainId = typeof chain.chainId === 'number' ? eip155ChainIdToCaip2(chain.chainId) : chain.chainId;\n\n const isCrossChainSwapEnabled =\n chain.enabled_services.includes('cross-chain-quote') && chain.enabled_services.includes('cross-chain-swap');\n const isSwapEnabled = chain.enabled_services.includes('quote') && chain.enabled_services.includes('swap');\n const normalizedLaneChainIds = new Set<Caip2ChainId>();\n\n for (const lane of chain.lanes) {\n const laneChainId = typeof lane === 'number' ? eip155ChainIdToCaip2(lane) : lane;\n\n if (laneChainId !== key) {\n normalizedLaneChainIds.add(laneChainId);\n }\n }\n\n const crossChainSwapEnabled = disableCrossChainSwaps ? false : isCrossChainSwapEnabled;\n const crossChainTargetChainIds = crossChainSwapEnabled ? normalizedLaneChainIds : new Set<Caip2ChainId>();\n\n if (!isSwapEnabled && crossChainTargetChainIds.size === 0) {\n continue;\n }\n\n supportedChains.set(key, {\n chainId: chain.chainId,\n crossChainSwapEnabled,\n crossChainTargetChainIds,\n swapEnabled: isSwapEnabled,\n tokenList: chain.enabled_services.includes('token-list'),\n });\n }\n } catch (error) {\n throw new SdkError(ErrorReason.UNKNOWN, ErrorCode.INITIALIZATION_FAILED, {\n cause: error,\n details: 'Failed to fetch supported chains from Markr API.',\n });\n }\n\n return supportedChains;\n}\n\nexport async function getSupportedTokens(\n apiOptions: ApiOptions,\n supportedChains: SupportedChainsMap,\n): Promise<Map<Caip2ChainId, Promise<TokenListResponse>>> {\n // Parallel fetch token lists for all supported chains.\n const supportedTokens: Map<Caip2ChainId, Promise<TokenListResponse>> = new Map();\n\n for (const [caip2ChainId, chainInfo] of supportedChains.entries()) {\n // Only fetch token list for EVM chains that support swaps.\n if (\n typeof chainInfo.chainId === 'number' &&\n chainInfo.tokenList &&\n (chainInfo.crossChainSwapEnabled || chainInfo.swapEnabled)\n ) {\n try {\n const tokenListPromise = markrGetTokenList(apiOptions, chainInfo.chainId);\n supportedTokens.set(caip2ChainId, tokenListPromise);\n } catch {\n // Ignore errors for individual token list fetches.\n // TODO: Logger?\n }\n }\n }\n\n return supportedTokens;\n}\n\n/**\n * Determine if the provided token address represents the native token for its chain.\n *\n * Markr represents EVM native tokens as the zero address and Solana native SOL\n * as the wrapped SOL mint address.\n */\nexport function isTokenAddressNative(address: string): boolean {\n return address === ERC_ZERO_ADDRESS || address === SOL_MINT_ADDRESS;\n}\n\n/**\n * Convert an `Asset` to the address string expected by the Markr API.\n *\n * For NATIVE assets the representation depends on the chain:\n * - EVM chains: `0x0000...0000` (ERC zero address)\n * - Solana chains: `So11111111111111111111111111111111111111112` (wrapped SOL mint)\n *\n * @param asset The asset to convert.\n * @param chainId CAIP-2 chain ID used to disambiguate NATIVE assets across chain types.\n */\nexport function assetToAddressString(asset: Asset, chainId: Caip2ChainId): string {\n if (asset.type === TokenType.NATIVE) {\n if (isSolanaNamespace(chainId)) {\n return SOL_MINT_ADDRESS;\n }\n\n return ERC_ZERO_ADDRESS;\n }\n\n return asset.address;\n}\n\n/**\n * Markr rejects `minAmountOut=0` for non-zero quotes.\n *\n * For very small quotes, integer truncation after slippage can produce `0`.\n * Clamp to `1` in that edge case to satisfy Markr API validation while\n * preserving normal slippage behavior for larger quotes.\n */\nexport function calculateMarkrMinimumAmountOut({\n amountOut,\n assetOut,\n slippageBps,\n}: Pick<Quote, 'amountOut' | 'assetOut' | 'slippageBps'>): bigint {\n const minAmountOut = calculateMinimumAmountOut({ amountOut, assetOut, slippageBps });\n\n if (amountOut > 0n && minAmountOut === 0n) {\n return 1n;\n }\n\n return minAmountOut;\n}\n\nexport function quoteFromMarkrQuoteResponseData(\n data: QuoteResponseData,\n quoterProps: QuoterProps,\n partnerFeeBps: number,\n): Quote {\n const partnerFee: bigint = (data.amountOut * BigInt(partnerFeeBps)) / 10_000n;\n const amountOutAfterFees: bigint = data.amountOut - partnerFee;\n\n const fees: QuoteFees = [\n ...mapMarkrQuoteResponseDataFeesToQuoteFees(data.fees),\n // Add the partner fee as a QuoteFee component for Markr quotes.\n {\n type: 'partner',\n name: 'Core Fee',\n amount: partnerFee,\n chainId: quoterProps.targetChain.chainId,\n token: assetToFeeToken(quoterProps.targetAsset),\n },\n ];\n\n return {\n aggregator: {\n id: data.aggregator.id,\n logoUrl: data.aggregator.logo_url,\n name: data.aggregator.name,\n },\n amountIn: data.amountIn,\n amountOut: amountOutAfterFees,\n assetIn: quoterProps.sourceAsset,\n assetOut: quoterProps.targetAsset,\n expiresAt: data.expiredAt, // Markr returns `expiredAt` as Unix time in seconds; use as-is.\n fees,\n fromAddress: quoterProps.fromAddress,\n /**\n * This gasEstimate is rough or may be missing.\n * Consumers should use TransferManager.estimateGas for a more accurate estimate.\n */\n gasEstimate: data.gasEstimate,\n id: data.uuid,\n partnerFeeBps,\n serviceType: ServiceType.MARKR,\n slippageBps: quoterProps.slippageBps ?? data.recommendedSlippage,\n sourceChain: quoterProps.sourceChain,\n targetChain: quoterProps.targetChain,\n toAddress: quoterProps.toAddress,\n } satisfies Quote;\n}\n\nexport async function getPartnerFeeBps(apiOptions: ApiOptions): Promise<number> {\n try {\n const partnerInfo = await markrGetPartnerInfo(apiOptions);\n return partnerInfo.fee;\n } catch (error) {\n throw new SdkError(ErrorReason.UNKNOWN, ErrorCode.INITIALIZATION_FAILED, {\n cause: error,\n details: 'Failed to fetch partner info from Markr API.',\n });\n }\n}\n\nexport function mapMarkrQuoteResponseDataFeesToQuoteFees(markrFees: QuoteResponseData['fees']): QuoteFees {\n if (!markrFees) {\n return [];\n }\n\n const fees: QuoteFee[] = [];\n\n for (const fee of markrFees) {\n const chainId = typeof fee.token.chainId === 'number' ? eip155ChainIdToCaip2(fee.token.chainId) : fee.token.chainId;\n\n let token: QuoteFeeToken | undefined;\n\n if (isTokenAddressNative(fee.token.address)) {\n token = { type: TokenType.NATIVE };\n } else if (isEvmAddress(fee.token.address)) {\n token = { type: TokenType.ERC20, address: fee.token.address };\n } else if (isSolAddress(fee.token.address)) {\n token = { type: TokenType.SPL, address: fee.token.address };\n }\n\n if (!token) {\n // Skip fee if we can't determine token type.\n continue;\n }\n\n fees.push({\n type: fee.type,\n name: fee.name,\n amount: fee.amount,\n chainId,\n token,\n });\n }\n\n return fees;\n}\n\nfunction assetToFeeToken(asset: Asset): QuoteFeeToken {\n if (asset.type === TokenType.NATIVE) {\n return { type: TokenType.NATIVE };\n }\n\n if (asset.type === TokenType.SPL) {\n return { type: TokenType.SPL, address: asset.address };\n }\n\n return { type: TokenType.ERC20, address: asset.address };\n}\n\nexport type MarkrRouterAbi =\n | (typeof import('./_abis/swap-wrapper-abi'))['MARKR_SWAP_WRAPPER_ABI']\n | (typeof import('./_abis/cross-chain-swap-wrapper-abi'))['MARKR_CROSS_CHAIN_SWAP_WRAPPER_ABI'];\n\nexport async function getMarkrSwapWrapperAbi(crossChain: boolean): Promise<MarkrRouterAbi> {\n if (crossChain) {\n return (await import('./_abis/cross-chain-swap-wrapper-abi')).MARKR_CROSS_CHAIN_SWAP_WRAPPER_ABI;\n }\n\n return (await import('./_abis/swap-wrapper-abi')).MARKR_SWAP_WRAPPER_ABI;\n}\n\nexport function extractHexDataFromError(error: unknown): Hex | undefined {\n if (error instanceof BaseError) {\n const directData = (error as { data?: unknown }).data;\n if (isHex(directData)) {\n return directData;\n }\n\n let walkedData: Hex | undefined;\n error.walk((walkedError) => {\n const nestedData = (walkedError as { data?: unknown }).data;\n if (!walkedData && isHex(nestedData)) {\n walkedData = nestedData;\n }\n return false;\n });\n\n if (walkedData) {\n return walkedData;\n }\n\n const causeData = (error as { cause?: { data?: unknown } }).cause?.data;\n if (isHex(causeData)) {\n return causeData;\n }\n }\n\n if (!error || typeof error !== 'object') {\n return undefined;\n }\n\n const genericError = error as {\n data?: unknown;\n error?: { data?: unknown };\n cause?: { data?: unknown };\n response?: { data?: unknown };\n body?: { error?: { data?: unknown } };\n };\n\n if (isHex(genericError.data)) {\n return genericError.data;\n }\n\n if (isHex(genericError.error?.data)) {\n return genericError.error.data;\n }\n\n if (isHex(genericError.cause?.data)) {\n return genericError.cause.data;\n }\n\n if (isHex(genericError.response?.data)) {\n return genericError.response.data;\n }\n\n if (isHex(genericError.body?.error?.data)) {\n return genericError.body.error.data;\n }\n\n return undefined;\n}\n\nexport function decodeMarkrRevertError(abi: MarkrRouterAbi, error: unknown): string | null {\n const revertData = extractHexDataFromError(error);\n\n if (!revertData) {\n return null;\n }\n\n try {\n const decoded = decodeErrorResult({ abi, data: revertData });\n const decodedArgs = decoded.args.length > 0 ? `(${decoded.args.map(String).join(', ')})` : '()';\n\n return `${decoded.errorName}${decodedArgs}`;\n } catch {\n const selector = revertData.slice(0, 10).toLowerCase();\n\n for (const abiItem of abi) {\n if (abiItem.type !== 'error') {\n continue;\n }\n\n const signature = `${abiItem.name}(${abiItem.inputs.map((input) => input.type).join(',')})`;\n if (toFunctionSelector(signature).toLowerCase() === selector) {\n return `${abiItem.name}()`;\n }\n }\n }\n\n return null;\n}\n"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- exports.DEFAULT_MARKR_API_URL=`https://proxy-api.avax.network/proxy/markr`,exports.SOLANA_POLLING_INTERVAL_MS=2500,exports.SOLANA_REQUIRED_CONFIRMATIONS=32,exports.SOLANA_TX_TIMEOUT_MS=12e4;
1
+ const e={fast:2e3,medium:5e3,slow:3e4,verySlow:18e4},t={fast:6e4,medium:20*6e4,slow:120*6e4},n={apechain:50*6e4,arbitrum:17*6e4,astar:35e3,avalanche:1e3,base:18*6e4,berachain:7e3,bitlayer:6e4,blast:20*6e4,bnbchain:5e3,bob:120*6e4,bsquared:20*6e4,celo:1e3,core:6e4,corn:720*6e4,cronos:1e3,cronoszkevm:1860*6e4,ethereum:15*6e4,fraxtal:30*6e4,gnosis:3*6e4,hashkey:60*6e4,ink:120*6e4,kroma:25*6e4,linea:20*6e4,mantle:28*6e4,metis:120*6e4,mindnetwork:60*6e4,mode:37*6e4,monad:48e3,opmainnet:20*6e4,polygon:17*6e4,polygonzkevm:120*6e4,ronin:1e4,scroll:60*6e4,sei:1e3,shibarium:6e4,solana:1e3,sonic:7e3,soneium:27*6e4,treasure:420*6e4,unichain:24*6e4,wemix:1e3,worldchain:40*6e4,xlayer:60*6e4,zircuit:21*6e4,zksync:20*6e4},r={"eip155:1":`ethereum`,"eip155:10":`opmainnet`,"eip155:25":`cronos`,"eip155:56":`bnbchain`,"eip155:100":`gnosis`,"eip155:137":`polygon`,"eip155:324":`zksync`,"eip155:1101":`polygonzkevm`,"eip155:1116":`core`,"eip155:1329":`sei`,"eip155:196":`xlayer`,"eip155:252":`fraxtal`,"eip155:480":`worldchain`,"eip155:59144":`linea`,"eip155:8453":`base`,"eip155:1088":`metis`,"eip155:2020":`ronin`,"eip155:42220":`celo`,"eip155:43114":`avalanche`,"eip155:48900":`zircuit`,"eip155:5000":`mantle`,"eip155:534352":`scroll`,"eip155:42161":`arbitrum`,"eip155:81457":`blast`,"solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp":`solana`},i=[{aliases:[`apechain`],chainKey:`apechain`},{aliases:[`arbitrum`],chainKey:`arbitrum`},{aliases:[`astar`],chainKey:`astar`},{aliases:[`avalanche`],chainKey:`avalanche`},{aliases:[`base`],chainKey:`base`},{aliases:[`berachain`],chainKey:`berachain`},{aliases:[`bitlayer`],chainKey:`bitlayer`},{aliases:[`blast`],chainKey:`blast`},{aliases:[`bnbchain`,`bnbsmartchain`,`binancesmartchain`,`binancechain`],chainKey:`bnbchain`},{aliases:[`bob`],chainKey:`bob`},{aliases:[`b2`,`bsquared`],chainKey:`bsquared`},{aliases:[`celo`],chainKey:`celo`},{aliases:[`core`],chainKey:`core`},{aliases:[`corn`],chainKey:`corn`},{aliases:[`cronoszkevm`],chainKey:`cronoszkevm`},{aliases:[`cronos`],chainKey:`cronos`},{aliases:[`ethereum`],chainKey:`ethereum`},{aliases:[`fraxtal`],chainKey:`fraxtal`},{aliases:[`gnosis`],chainKey:`gnosis`},{aliases:[`hashkey`],chainKey:`hashkey`},{aliases:[`ink`],chainKey:`ink`},{aliases:[`kroma`],chainKey:`kroma`},{aliases:[`linea`],chainKey:`linea`},{aliases:[`mantle`],chainKey:`mantle`},{aliases:[`metis`],chainKey:`metis`},{aliases:[`mindnetwork`],chainKey:`mindnetwork`},{aliases:[`mode`],chainKey:`mode`},{aliases:[`monad`],chainKey:`monad`},{aliases:[`opmainnet`,`optimism`],chainKey:`opmainnet`},{aliases:[`polygonzkevm`],chainKey:`polygonzkevm`},{aliases:[`polygon`],chainKey:`polygon`},{aliases:[`ronin`],chainKey:`ronin`},{aliases:[`scroll`],chainKey:`scroll`},{aliases:[`sei`],chainKey:`sei`},{aliases:[`solana`],chainKey:`solana`},{aliases:[`soneium`],chainKey:`soneium`},{aliases:[`sonic`],chainKey:`sonic`},{aliases:[`shibarium`],chainKey:`shibarium`},{aliases:[`treasure`],chainKey:`treasure`},{aliases:[`unichain`],chainKey:`unichain`},{aliases:[`wemix`],chainKey:`wemix`},{aliases:[`worldchain`],chainKey:`worldchain`},{aliases:[`xlayer`],chainKey:`xlayer`},{aliases:[`zircuit`],chainKey:`zircuit`},{aliases:[`zksync`],chainKey:`zksync`}],a={...Object.fromEntries(Object.entries(r).map(([e,t])=>[e,n[t]]))},o=[...i.map(({aliases:e,chainKey:t})=>({aliases:e,finalityMs:n[t]}))];exports.CROSS_CHAIN_POLLING_INTERVAL_MS=e,exports.DEFAULT_MARKR_API_URL=`https://proxy-api.avax.network/proxy/markr`,exports.FINALITY_MS_BY_CHAIN_ID=a,exports.FINALITY_MS_BY_CHAIN_NAME_ALIAS=o,exports.FINALITY_TIER_MAX_FINALITY_MS=t,exports.SOLANA_POLLING_INTERVAL_MS=2500,exports.SOLANA_REQUIRED_CONFIRMATIONS=32,exports.SOLANA_TX_TIMEOUT_MS=12e4;
2
2
  //# sourceMappingURL=constants.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"constants.cjs","names":[],"sources":["../../../src/transfer-service/markr/constants.ts"],"sourcesContent":["export const DEFAULT_MARKR_API_URL = 'https://proxy-api.avax.network/proxy/markr' as const;\n\n// Solana slot time is ~400ms. Polling every 2.5s (~6 slots) balances\n// responsiveness against RPC rate-limits — fast enough to detect finalization\n// promptly, without hammering the endpoint.\nexport const SOLANA_POLLING_INTERVAL_MS = 2_500;\n\n// A Solana blockhash is valid for 150 slots (~60s at 400ms/slot). Validators\n// may hold a transaction for up to ~90s before dropping it. We set a 120s\n// timeout to provide a comfortable buffer above worst-case blockhash expiry,\n// ensuring we don't falsely time out a transaction that is still eligible for\n// inclusion in a block.\nexport const SOLANA_TX_TIMEOUT_MS = 120_000;\n\n// Solana finalizes a block once ≥31 confirmed blocks are built on top of it.\n// `getSignatureStatuses` returns the running `confirmations` count (0 → N),\n// then `null` once the status flips to `finalized`. We use 32 as the\n// required-confirmation target so the progress bar fills smoothly from 0 → 31\n// during polling and snaps to 32 (= done) only when finalization is confirmed.\nexport const SOLANA_REQUIRED_CONFIRMATIONS = 32;\n"],"mappings":""}
1
+ {"version":3,"file":"constants.cjs","names":[],"sources":["../../../src/transfer-service/markr/constants.ts"],"sourcesContent":["import type { Caip2ChainId } from '../../types/caip';\n\nexport const DEFAULT_MARKR_API_URL = 'https://proxy-api.avax.network/proxy/markr' as const;\n\n/**\n * Cross-chain polling tiers used by Markr transfer tracking.\n *\n * Tier boundaries are selected from known destination/source finality windows\n * so we poll fast-finality chains more aggressively and avoid excessive RPC\n * traffic on slow-finality chains.\n *\n * Finality reference:\n * https://docs.chain.link/ccip/ccip-execution-latency#finality-by-blockchain\n */\nexport const CROSS_CHAIN_POLLING_INTERVAL_MS = {\n fast: 2_000, // 2 seconds\n medium: 5_000, // 5 seconds\n slow: 30_000, // 30 seconds\n verySlow: 180_000, // 3 minutes\n} as const;\n\n/**\n * Upper bounds (in ms) used to map known finality time to a polling tier.\n *\n * Values greater than `slow` are classified as `verySlow`.\n */\nexport const FINALITY_TIER_MAX_FINALITY_MS: Readonly<Record<'fast' | 'medium' | 'slow', number>> = {\n fast: 60_000,\n medium: 20 * 60_000,\n slow: 2 * 60 * 60_000,\n};\n\nconst FINALITY_MS_BY_CHAIN_KEY = {\n apechain: 50 * 60_000,\n arbitrum: 17 * 60_000,\n astar: 35_000,\n avalanche: 1_000,\n base: 18 * 60_000,\n berachain: 7_000,\n bitlayer: 60_000,\n blast: 20 * 60_000,\n bnbchain: 5_000,\n bob: 2 * 60 * 60_000,\n bsquared: 20 * 60_000,\n celo: 1_000,\n core: 60_000,\n corn: 12 * 60 * 60_000,\n cronos: 1_000,\n cronoszkevm: 31 * 60 * 60_000,\n ethereum: 15 * 60_000,\n fraxtal: 30 * 60_000,\n gnosis: 3 * 60_000,\n hashkey: 60 * 60_000,\n ink: 2 * 60 * 60_000,\n kroma: 25 * 60_000,\n linea: 20 * 60_000,\n mantle: 28 * 60_000,\n metis: 2 * 60 * 60_000,\n mindnetwork: 60 * 60_000,\n mode: 37 * 60_000,\n monad: 48_000,\n opmainnet: 20 * 60_000,\n polygon: 17 * 60_000,\n polygonzkevm: 2 * 60 * 60_000,\n ronin: 10_000,\n scroll: 60 * 60_000,\n sei: 1_000,\n shibarium: 60_000,\n solana: 1_000,\n sonic: 7_000,\n soneium: 27 * 60_000,\n treasure: 7 * 60 * 60_000,\n unichain: 24 * 60_000,\n wemix: 1_000,\n worldchain: 40 * 60_000,\n xlayer: 60 * 60_000,\n zircuit: 21 * 60_000,\n zksync: 20 * 60_000,\n} as const;\n\ntype FinalityChainKey = keyof typeof FINALITY_MS_BY_CHAIN_KEY;\n\nconst FINALITY_CHAIN_KEY_BY_CHAIN_ID = {\n 'eip155:1': 'ethereum',\n 'eip155:10': 'opmainnet',\n 'eip155:25': 'cronos',\n 'eip155:56': 'bnbchain',\n 'eip155:100': 'gnosis',\n 'eip155:137': 'polygon',\n 'eip155:324': 'zksync',\n 'eip155:1101': 'polygonzkevm',\n 'eip155:1116': 'core',\n 'eip155:1329': 'sei',\n 'eip155:196': 'xlayer',\n 'eip155:252': 'fraxtal',\n 'eip155:480': 'worldchain',\n 'eip155:59144': 'linea',\n 'eip155:8453': 'base',\n 'eip155:1088': 'metis',\n 'eip155:2020': 'ronin',\n 'eip155:42220': 'celo',\n 'eip155:43114': 'avalanche',\n 'eip155:48900': 'zircuit',\n 'eip155:5000': 'mantle',\n 'eip155:534352': 'scroll',\n 'eip155:42161': 'arbitrum',\n 'eip155:81457': 'blast',\n 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp': 'solana',\n} as const satisfies Partial<Record<Caip2ChainId, FinalityChainKey>>;\n\nconst FINALITY_CHAIN_NAME_ALIASES = [\n { aliases: ['apechain'], chainKey: 'apechain' },\n { aliases: ['arbitrum'], chainKey: 'arbitrum' },\n { aliases: ['astar'], chainKey: 'astar' },\n { aliases: ['avalanche'], chainKey: 'avalanche' },\n { aliases: ['base'], chainKey: 'base' },\n { aliases: ['berachain'], chainKey: 'berachain' },\n { aliases: ['bitlayer'], chainKey: 'bitlayer' },\n { aliases: ['blast'], chainKey: 'blast' },\n { aliases: ['bnbchain', 'bnbsmartchain', 'binancesmartchain', 'binancechain'], chainKey: 'bnbchain' },\n { aliases: ['bob'], chainKey: 'bob' },\n { aliases: ['b2', 'bsquared'], chainKey: 'bsquared' },\n { aliases: ['celo'], chainKey: 'celo' },\n { aliases: ['core'], chainKey: 'core' },\n { aliases: ['corn'], chainKey: 'corn' },\n { aliases: ['cronoszkevm'], chainKey: 'cronoszkevm' },\n { aliases: ['cronos'], chainKey: 'cronos' },\n { aliases: ['ethereum'], chainKey: 'ethereum' },\n { aliases: ['fraxtal'], chainKey: 'fraxtal' },\n { aliases: ['gnosis'], chainKey: 'gnosis' },\n { aliases: ['hashkey'], chainKey: 'hashkey' },\n { aliases: ['ink'], chainKey: 'ink' },\n { aliases: ['kroma'], chainKey: 'kroma' },\n { aliases: ['linea'], chainKey: 'linea' },\n { aliases: ['mantle'], chainKey: 'mantle' },\n { aliases: ['metis'], chainKey: 'metis' },\n { aliases: ['mindnetwork'], chainKey: 'mindnetwork' },\n { aliases: ['mode'], chainKey: 'mode' },\n { aliases: ['monad'], chainKey: 'monad' },\n { aliases: ['opmainnet', 'optimism'], chainKey: 'opmainnet' },\n { aliases: ['polygonzkevm'], chainKey: 'polygonzkevm' },\n { aliases: ['polygon'], chainKey: 'polygon' },\n { aliases: ['ronin'], chainKey: 'ronin' },\n { aliases: ['scroll'], chainKey: 'scroll' },\n { aliases: ['sei'], chainKey: 'sei' },\n { aliases: ['solana'], chainKey: 'solana' },\n { aliases: ['soneium'], chainKey: 'soneium' },\n { aliases: ['sonic'], chainKey: 'sonic' },\n { aliases: ['shibarium'], chainKey: 'shibarium' },\n { aliases: ['treasure'], chainKey: 'treasure' },\n { aliases: ['unichain'], chainKey: 'unichain' },\n { aliases: ['wemix'], chainKey: 'wemix' },\n { aliases: ['worldchain'], chainKey: 'worldchain' },\n { aliases: ['xlayer'], chainKey: 'xlayer' },\n { aliases: ['zircuit'], chainKey: 'zircuit' },\n { aliases: ['zksync'], chainKey: 'zksync' },\n] as const satisfies ReadonlyArray<{ aliases: readonly string[]; chainKey: FinalityChainKey }>;\n\n/**\n * Known CAIP-2 chain IDs and their approximate CCIP finality times in\n * milliseconds.\n *\n * Finality reference:\n * https://docs.chain.link/ccip/ccip-execution-latency#finality-by-blockchain\n */\nexport const FINALITY_MS_BY_CHAIN_ID: Partial<Record<Caip2ChainId, number>> = {\n ...Object.fromEntries(\n Object.entries(FINALITY_CHAIN_KEY_BY_CHAIN_ID).map(([chainId, chainKey]) => [\n chainId,\n FINALITY_MS_BY_CHAIN_KEY[chainKey],\n ]),\n ),\n};\n\n/**\n * Chain-name aliases and their approximate CCIP finality times in\n * milliseconds.\n *\n * These aliases are used as a fallback when a chain ID is not present in\n * `FINALITY_MS_BY_CHAIN_ID`.\n *\n * Finality reference:\n * https://docs.chain.link/ccip/ccip-execution-latency#finality-by-blockchain\n */\nexport const FINALITY_MS_BY_CHAIN_NAME_ALIAS: ReadonlyArray<{ aliases: readonly string[]; finalityMs: number }> = [\n ...FINALITY_CHAIN_NAME_ALIASES.map(({ aliases, chainKey }) => ({\n aliases,\n finalityMs: FINALITY_MS_BY_CHAIN_KEY[chainKey],\n })),\n];\n\n// Solana slot time is ~400ms. Polling every 2.5s (~6 slots) balances\n// responsiveness against RPC rate-limits — fast enough to detect finalization\n// promptly, without hammering the endpoint.\nexport const SOLANA_POLLING_INTERVAL_MS = 2_500;\n\n// A Solana blockhash is valid for 150 slots (~60s at 400ms/slot). Validators\n// may hold a transaction for up to ~90s before dropping it. We set a 120s\n// timeout to provide a comfortable buffer above worst-case blockhash expiry,\n// ensuring we don't falsely time out a transaction that is still eligible for\n// inclusion in a block.\nexport const SOLANA_TX_TIMEOUT_MS = 120_000;\n\n// Solana finalizes a block once ≥31 confirmed blocks are built on top of it.\n// `getSignatureStatuses` returns the running `confirmations` count (0 → N),\n// then `null` once the status flips to `finalized`. We use 32 as the\n// required-confirmation target so the progress bar fills smoothly from 0 → 31\n// during polling and snaps to 32 (= done) only when finalization is confirmed.\nexport const SOLANA_REQUIRED_CONFIRMATIONS = 32;\n"],"mappings":"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"}