@avalabs/fusion-sdk 0.14.3 → 0.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -2
- package/dist/constants.cjs.map +1 -1
- package/dist/constants.js.map +1 -1
- package/dist/errors.cjs +1 -1
- package/dist/errors.cjs.map +1 -1
- package/dist/errors.d.cts +62 -1
- package/dist/errors.d.ts +62 -1
- package/dist/errors.js +1 -1
- package/dist/errors.js.map +1 -1
- package/dist/mod.cjs +1 -1
- package/dist/mod.d.cts +2 -2
- package/dist/mod.d.ts +2 -2
- package/dist/mod.js +1 -1
- package/dist/quoter/constants.cjs +1 -1
- package/dist/quoter/constants.js +1 -1
- package/dist/quoter/constants.js.map +1 -1
- package/dist/quoter/quoter.cjs +1 -1
- package/dist/quoter/quoter.cjs.map +1 -1
- package/dist/quoter/quoter.d.ts +0 -3
- package/dist/quoter/quoter.js +1 -1
- package/dist/quoter/quoter.js.map +1 -1
- package/dist/transfer-service/_evm-errors.cjs +2 -0
- package/dist/transfer-service/_evm-errors.cjs.map +1 -0
- package/dist/transfer-service/_evm-errors.js +2 -0
- package/dist/transfer-service/_evm-errors.js.map +1 -0
- package/dist/transfer-service/avalanche-evm/_handlers/estimate-native-fee.cjs +1 -1
- package/dist/transfer-service/avalanche-evm/_handlers/estimate-native-fee.cjs.map +1 -1
- package/dist/transfer-service/avalanche-evm/_handlers/estimate-native-fee.js +1 -1
- package/dist/transfer-service/avalanche-evm/_handlers/estimate-native-fee.js.map +1 -1
- package/dist/transfer-service/lombard/_utils/fee.js +1 -1
- package/dist/transfer-service/lombard/_utils/fee.js.map +1 -1
- package/dist/transfer-service/lombard/btc-to-btcb/_handlers/estimate-native-fee.cjs +1 -1
- package/dist/transfer-service/lombard/btc-to-btcb/_handlers/estimate-native-fee.cjs.map +1 -1
- package/dist/transfer-service/lombard/btc-to-btcb/_handlers/estimate-native-fee.js +1 -1
- package/dist/transfer-service/lombard/btc-to-btcb/_handlers/estimate-native-fee.js.map +1 -1
- package/dist/transfer-service/lombard/btc-to-btcb/_handlers/track-transfer.cjs +1 -1
- package/dist/transfer-service/lombard/btc-to-btcb/_handlers/track-transfer.cjs.map +1 -1
- package/dist/transfer-service/lombard/btc-to-btcb/_handlers/track-transfer.js +1 -1
- package/dist/transfer-service/lombard/btc-to-btcb/_handlers/track-transfer.js.map +1 -1
- package/dist/transfer-service/lombard/btc-to-btcb/_handlers/transfer-asset.cjs +1 -1
- package/dist/transfer-service/lombard/btc-to-btcb/_handlers/transfer-asset.cjs.map +1 -1
- package/dist/transfer-service/lombard/btc-to-btcb/_handlers/transfer-asset.js +1 -1
- package/dist/transfer-service/lombard/btc-to-btcb/_handlers/transfer-asset.js.map +1 -1
- package/dist/transfer-service/lombard/btcb-to-btc/_handlers/estimate-native-fee.cjs +1 -1
- package/dist/transfer-service/lombard/btcb-to-btc/_handlers/estimate-native-fee.cjs.map +1 -1
- package/dist/transfer-service/lombard/btcb-to-btc/_handlers/estimate-native-fee.js +1 -1
- package/dist/transfer-service/lombard/btcb-to-btc/_handlers/estimate-native-fee.js.map +1 -1
- package/dist/transfer-service/lombard/btcb-to-btc/_handlers/transfer-asset.cjs +1 -1
- package/dist/transfer-service/lombard/btcb-to-btc/_handlers/transfer-asset.cjs.map +1 -1
- package/dist/transfer-service/lombard/btcb-to-btc/_handlers/transfer-asset.js +1 -1
- package/dist/transfer-service/lombard/btcb-to-btc/_handlers/transfer-asset.js.map +1 -1
- package/dist/transfer-service/lombard/constants.cjs +1 -1
- package/dist/transfer-service/lombard/constants.js +1 -1
- package/dist/transfer-service/lombard/constants.js.map +1 -1
- package/dist/transfer-service/markr/_handlers/estimate-native-fee.cjs +1 -1
- package/dist/transfer-service/markr/_handlers/estimate-native-fee.cjs.map +1 -1
- package/dist/transfer-service/markr/_handlers/estimate-native-fee.js +1 -1
- package/dist/transfer-service/markr/_handlers/estimate-native-fee.js.map +1 -1
- package/dist/transfer-service/markr/_handlers/track-transfer.cjs +1 -1
- package/dist/transfer-service/markr/_handlers/track-transfer.cjs.map +1 -1
- package/dist/transfer-service/markr/_handlers/track-transfer.js +1 -1
- package/dist/transfer-service/markr/_handlers/track-transfer.js.map +1 -1
- package/dist/transfer-service/markr/_handlers/transfer-asset.cjs +1 -1
- package/dist/transfer-service/markr/_handlers/transfer-asset.cjs.map +1 -1
- package/dist/transfer-service/markr/_handlers/transfer-asset.js +1 -1
- package/dist/transfer-service/markr/_handlers/transfer-asset.js.map +1 -1
- package/dist/transfer-service/markr/_utils.cjs +1 -1
- package/dist/transfer-service/markr/_utils.cjs.map +1 -1
- package/dist/transfer-service/markr/_utils.js +1 -1
- package/dist/transfer-service/markr/_utils.js.map +1 -1
- package/dist/transfer-service/markr/constants.cjs +1 -1
- package/dist/transfer-service/markr/constants.js +1 -1
- package/dist/transfer-service/markr/constants.js.map +1 -1
- package/dist/transfer-service/markr/markr-service.cjs +1 -1
- package/dist/transfer-service/markr/markr-service.cjs.map +1 -1
- package/dist/transfer-service/markr/markr-service.js +1 -1
- package/dist/transfer-service/markr/markr-service.js.map +1 -1
- package/dist/transfer-service/wrap-unwrap/_handlers/estimate-native-fee.cjs +1 -1
- package/dist/transfer-service/wrap-unwrap/_handlers/estimate-native-fee.cjs.map +1 -1
- package/dist/transfer-service/wrap-unwrap/_handlers/estimate-native-fee.js +1 -1
- package/dist/transfer-service/wrap-unwrap/_handlers/estimate-native-fee.js.map +1 -1
- package/dist/transfer-service/wrap-unwrap/_utils.cjs +1 -1
- package/dist/transfer-service/wrap-unwrap/_utils.cjs.map +1 -1
- package/dist/transfer-service/wrap-unwrap/_utils.js +1 -1
- package/dist/transfer-service/wrap-unwrap/_utils.js.map +1 -1
- package/dist/types/service.d.cts +11 -49
- package/dist/types/service.d.ts +11 -49
- package/dist/utils/solana.cjs +2 -0
- package/dist/utils/solana.cjs.map +1 -0
- package/dist/utils/solana.js +2 -0
- package/dist/utils/solana.js.map +1 -0
- package/package.json +4 -4
- package/dist/transfer-service/markr/_solana-utils.cjs +0 -2
- package/dist/transfer-service/markr/_solana-utils.cjs.map +0 -1
- package/dist/transfer-service/markr/_solana-utils.js +0 -2
- package/dist/transfer-service/markr/_solana-utils.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"track-transfer.cjs","names":["getEvmClientForChain","waitForTimeoutOrAbort","awaitOrAbort","getMetadataUpdates","isDepositFailed","ErrorCode","EVM_CONFIRMATION_COUNT"],"sources":["../../../../../src/transfer-service/lombard/btc-to-btcb/_handlers/track-transfer.ts"],"sourcesContent":["import { getDepositsByAddress } from '@lombard.finance/sdk';\nimport { ErrorCode } from '../../../../errors';\nimport type { BitcoinFunctions } from '../../../../types/bitcoin';\nimport type { TransferService } from '../../../../types/service';\nimport type {\n CompletedTransfer,\n FailedTransfer,\n SourceCompletedTransfer,\n SourcePendingTransfer,\n TargetPendingTransfer,\n Transfer,\n} from '../../../../types/transfer';\nimport { awaitOrAbort, getEvmClientForChain, waitForTimeoutOrAbort } from '../../../_utils';\nimport type { BtcToBtcbConfig } from '../../types';\nimport { isHash } from 'viem';\nimport { getMetadataUpdates, isDepositFailed } from '../../_utils/metadata';\nimport { EVM_CONFIRMATION_COUNT } from '../../constants';\n\n// Polling interval for BTC deposits (30 seconds - faster than BTC block time since we also poll Lombard API)\nconst DEPOSIT_POLLING_INTERVAL_MS = 1000 * 30;\n\nexport interface TrackTransferFactoryOptions {\n bitcoinFunctions: BitcoinFunctions;\n config: BtcToBtcbConfig;\n}\n\nexport function trackTransferFactory({\n bitcoinFunctions,\n config,\n}: TrackTransferFactoryOptions): TransferService['trackTransfer'] {\n return ({ transfer, updateListener }) => {\n const ac = new AbortController();\n const cancel = () => {\n ac.abort();\n };\n\n if (transfer.status === 'completed' || transfer.status === 'failed') {\n return {\n cancel,\n result: Promise.resolve(transfer),\n };\n }\n\n const executeTracking = async (): Promise<Transfer> => {\n let currentTransfer: Transfer = structuredClone(transfer);\n\n const targetClient = getEvmClientForChain({ chain: transfer.targetChain });\n\n while (!ac.signal.aborted) {\n const statusBeforeTracking = currentTransfer.status;\n\n switch (currentTransfer.status) {\n case 'source-pending': {\n currentTransfer = await _trackSourceTx({\n bitcoinFunctions,\n currentTransfer,\n signal: ac.signal,\n });\n\n if (!ac.signal.aborted) {\n updateListener(currentTransfer);\n }\n\n break;\n }\n case 'source-completed':\n case 'target-pending': {\n currentTransfer = await _trackTargetTx({\n config,\n currentTransfer,\n signal: ac.signal,\n targetClient,\n });\n\n if (!ac.signal.aborted) {\n updateListener(currentTransfer);\n }\n\n break;\n }\n default: {\n return currentTransfer;\n }\n }\n\n const hasStatusChanged = currentTransfer.status !== statusBeforeTracking;\n\n if (!hasStatusChanged) {\n await waitForTimeoutOrAbort({ timeoutMs: DEPOSIT_POLLING_INTERVAL_MS, signal: ac.signal });\n }\n }\n\n return currentTransfer;\n };\n\n return {\n cancel,\n result: executeTracking(),\n };\n };\n}\n\nexport interface TrackBaseParams {\n currentTransfer: Transfer;\n signal: AbortSignal;\n}\n\nexport interface TrackSourceTxParams extends TrackBaseParams {\n bitcoinFunctions: BitcoinFunctions;\n currentTransfer: SourcePendingTransfer;\n}\n\nexport interface TrackTargetTxParams extends TrackBaseParams {\n config: BtcToBtcbConfig;\n currentTransfer: SourceCompletedTransfer | TargetPendingTransfer;\n targetClient: ReturnType<typeof getEvmClientForChain>;\n}\n\nexport async function _trackSourceTx({\n bitcoinFunctions,\n currentTransfer,\n signal,\n}: TrackSourceTxParams): Promise<SourcePendingTransfer | SourceCompletedTransfer | FailedTransfer> {\n try {\n const transactionResult = await awaitOrAbort(\n bitcoinFunctions.getTransaction(currentTransfer.source.txHash),\n signal,\n );\n\n if (transactionResult.status === 'aborted') {\n return currentTransfer;\n }\n\n const { confirmations: confirmationCount } = transactionResult.value;\n\n if (confirmationCount < currentTransfer.source.requiredConfirmationCount) {\n return {\n ...currentTransfer,\n source: {\n ...currentTransfer.source,\n confirmationCount,\n },\n } satisfies SourcePendingTransfer;\n }\n\n return {\n ...currentTransfer,\n source: {\n ...currentTransfer.source,\n confirmationCount,\n },\n status: 'source-completed',\n } satisfies SourceCompletedTransfer;\n } catch {\n return currentTransfer;\n }\n}\n\nexport async function _trackTargetTx({\n config,\n currentTransfer,\n signal,\n targetClient,\n}: TrackTargetTxParams): Promise<SourceCompletedTransfer | TargetPendingTransfer | FailedTransfer | CompletedTransfer> {\n switch (currentTransfer.status) {\n case 'source-completed': {\n try {\n const depositsResult = await awaitOrAbort(\n getDepositsByAddress({ address: currentTransfer.toAddress, env: config.env }),\n signal,\n );\n\n if (depositsResult.status === 'aborted') {\n return currentTransfer;\n }\n\n const transferDeposit = depositsResult.value.find(\n (d) => d.txHash.toLowerCase() === currentTransfer.source.txHash.toLowerCase(),\n );\n\n if (!transferDeposit) {\n // Source Completed but no deposit found yet on target\n return currentTransfer;\n }\n\n const { needsNotarizationUpdate, needsSessionStateUpdate } = getMetadataUpdates(\n currentTransfer.metadata,\n transferDeposit.notarizationStatus,\n transferDeposit.sessionState,\n );\n\n // Update metadata if needed\n if (needsNotarizationUpdate || needsSessionStateUpdate) {\n return {\n ...currentTransfer,\n metadata: {\n ...currentTransfer.metadata,\n ...(needsNotarizationUpdate && { notarizationStatus: transferDeposit.notarizationStatus }),\n ...(needsSessionStateUpdate && { sessionState: transferDeposit.sessionState }),\n },\n } satisfies SourceCompletedTransfer;\n }\n\n if (isDepositFailed(transferDeposit)) {\n return {\n ...currentTransfer,\n errorCode: ErrorCode.NOTARIZATION_FAILED,\n errorReason: 'Deposit notarization failed',\n failedAtMs: Date.now(),\n status: 'failed',\n } satisfies FailedTransfer;\n }\n\n if (!transferDeposit.claimTxHash) {\n return currentTransfer;\n }\n\n return {\n ...currentTransfer,\n status: 'target-pending',\n target: {\n confirmationCount: 0,\n requiredConfirmationCount: EVM_CONFIRMATION_COUNT,\n startedAtMs: Date.now(),\n txHash: transferDeposit.claimTxHash,\n },\n } satisfies TargetPendingTransfer;\n } catch {\n return currentTransfer;\n }\n }\n default: {\n // target-pending\n\n if (!currentTransfer.target?.txHash) {\n // Transfer missing target info, should not reach here\n return {\n ...currentTransfer,\n errorCode: ErrorCode.UNKNOWN,\n errorReason: 'Missing target transaction hash',\n failedAtMs: Date.now(),\n status: 'failed',\n } satisfies FailedTransfer;\n }\n\n const { confirmationCount, requiredConfirmationCount, txHash } = currentTransfer.target;\n\n if (!isHash(txHash)) {\n // Invalid tx hash\n return {\n ...currentTransfer,\n errorCode: ErrorCode.UNKNOWN,\n errorReason: 'Invalid target transaction hash',\n failedAtMs: Date.now(),\n status: 'failed',\n } satisfies FailedTransfer;\n }\n\n try {\n const transactionResult = await awaitOrAbort(\n targetClient.waitForTransactionReceipt({\n confirmations: Math.min(confirmationCount + 1, requiredConfirmationCount),\n hash: txHash,\n }),\n signal,\n );\n\n if (transactionResult.status === 'aborted') {\n return currentTransfer;\n }\n\n const transactionReceipt = transactionResult.value;\n\n if (transactionReceipt.status === 'reverted') {\n return {\n ...currentTransfer,\n errorCode: ErrorCode.TRANSACTION_REVERTED,\n errorReason: 'Target transaction was reverted',\n failedAtMs: Date.now(),\n status: 'failed',\n } satisfies FailedTransfer;\n }\n\n const newConfirmationCount: number = await targetClient\n .getTransactionConfirmations({\n transactionReceipt,\n })\n .then((count) => Number(count))\n .catch(() => confirmationCount + 1);\n\n // If still not enough confirmations, update the count\n if (newConfirmationCount < requiredConfirmationCount) {\n return {\n ...currentTransfer,\n target: {\n ...currentTransfer.target,\n confirmationCount: newConfirmationCount,\n },\n } satisfies TargetPendingTransfer;\n }\n\n return {\n ...currentTransfer,\n completedAtMs: Date.now(),\n status: 'completed',\n target: {\n ...currentTransfer.target,\n confirmationCount: newConfirmationCount,\n },\n } satisfies CompletedTransfer;\n } catch {\n return currentTransfer;\n }\n }\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"track-transfer.cjs","names":["getEvmClientForChain","waitForTimeoutOrAbort","awaitOrAbort","getMetadataUpdates","isDepositFailed","ErrorCode"],"sources":["../../../../../src/transfer-service/lombard/btc-to-btcb/_handlers/track-transfer.ts"],"sourcesContent":["import { getDepositsByAddress } from '@lombard.finance/sdk';\nimport { ErrorCode } from '../../../../errors';\nimport type { BitcoinFunctions } from '../../../../types/bitcoin';\nimport type { TransferService } from '../../../../types/service';\nimport type {\n CompletedTransfer,\n FailedTransfer,\n SourceCompletedTransfer,\n SourcePendingTransfer,\n TargetPendingTransfer,\n Transfer,\n} from '../../../../types/transfer';\nimport { awaitOrAbort, getEvmClientForChain, waitForTimeoutOrAbort } from '../../../_utils';\nimport type { BtcToBtcbConfig } from '../../types';\nimport { isHash } from 'viem';\nimport { getMetadataUpdates, isDepositFailed } from '../../_utils/metadata';\nimport { EVM_CONFIRMATION_COUNT } from '../../constants';\n\n// Polling interval for BTC deposits (30 seconds - faster than BTC block time since we also poll Lombard API)\nconst DEPOSIT_POLLING_INTERVAL_MS = 1000 * 30;\n\nexport interface TrackTransferFactoryOptions {\n bitcoinFunctions: BitcoinFunctions;\n config: BtcToBtcbConfig;\n}\n\nexport function trackTransferFactory({\n bitcoinFunctions,\n config,\n}: TrackTransferFactoryOptions): TransferService['trackTransfer'] {\n return ({ transfer, updateListener }) => {\n const ac = new AbortController();\n const cancel = () => {\n ac.abort();\n };\n\n if (transfer.status === 'completed' || transfer.status === 'failed') {\n return {\n cancel,\n result: Promise.resolve(transfer),\n };\n }\n\n const executeTracking = async (): Promise<Transfer> => {\n let currentTransfer: Transfer = structuredClone(transfer);\n\n const targetClient = getEvmClientForChain({ chain: transfer.targetChain });\n\n while (!ac.signal.aborted) {\n const statusBeforeTracking = currentTransfer.status;\n\n switch (currentTransfer.status) {\n case 'source-pending': {\n currentTransfer = await _trackSourceTx({\n bitcoinFunctions,\n currentTransfer,\n signal: ac.signal,\n });\n\n if (!ac.signal.aborted) {\n updateListener(currentTransfer);\n }\n\n break;\n }\n case 'source-completed':\n case 'target-pending': {\n currentTransfer = await _trackTargetTx({\n config,\n currentTransfer,\n signal: ac.signal,\n targetClient,\n });\n\n if (!ac.signal.aborted) {\n updateListener(currentTransfer);\n }\n\n break;\n }\n default: {\n return currentTransfer;\n }\n }\n\n const hasStatusChanged = currentTransfer.status !== statusBeforeTracking;\n\n if (!hasStatusChanged) {\n await waitForTimeoutOrAbort({ timeoutMs: DEPOSIT_POLLING_INTERVAL_MS, signal: ac.signal });\n }\n }\n\n return currentTransfer;\n };\n\n return {\n cancel,\n result: executeTracking(),\n };\n };\n}\n\nexport interface TrackBaseParams {\n currentTransfer: Transfer;\n signal: AbortSignal;\n}\n\nexport interface TrackSourceTxParams extends TrackBaseParams {\n bitcoinFunctions: BitcoinFunctions;\n currentTransfer: SourcePendingTransfer;\n}\n\nexport interface TrackTargetTxParams extends TrackBaseParams {\n config: BtcToBtcbConfig;\n currentTransfer: SourceCompletedTransfer | TargetPendingTransfer;\n targetClient: ReturnType<typeof getEvmClientForChain>;\n}\n\nexport async function _trackSourceTx({\n bitcoinFunctions,\n currentTransfer,\n signal,\n}: TrackSourceTxParams): Promise<SourcePendingTransfer | SourceCompletedTransfer | FailedTransfer> {\n try {\n const transactionResult = await awaitOrAbort(\n bitcoinFunctions.getTransaction(currentTransfer.source.txHash),\n signal,\n );\n\n if (transactionResult.status === 'aborted') {\n return currentTransfer;\n }\n\n const { confirmations: confirmationCount } = transactionResult.value;\n\n if (confirmationCount < currentTransfer.source.requiredConfirmationCount) {\n return {\n ...currentTransfer,\n source: {\n ...currentTransfer.source,\n confirmationCount,\n },\n } satisfies SourcePendingTransfer;\n }\n\n return {\n ...currentTransfer,\n source: {\n ...currentTransfer.source,\n confirmationCount,\n },\n status: 'source-completed',\n } satisfies SourceCompletedTransfer;\n } catch {\n return currentTransfer;\n }\n}\n\nexport async function _trackTargetTx({\n config,\n currentTransfer,\n signal,\n targetClient,\n}: TrackTargetTxParams): Promise<SourceCompletedTransfer | TargetPendingTransfer | FailedTransfer | CompletedTransfer> {\n switch (currentTransfer.status) {\n case 'source-completed': {\n try {\n const depositsResult = await awaitOrAbort(\n getDepositsByAddress({ address: currentTransfer.toAddress, env: config.env }),\n signal,\n );\n\n if (depositsResult.status === 'aborted') {\n return currentTransfer;\n }\n\n const transferDeposit = depositsResult.value.find(\n (d) => d.txHash.toLowerCase() === currentTransfer.source.txHash.toLowerCase(),\n );\n\n if (!transferDeposit) {\n // Source Completed but no deposit found yet on target\n return currentTransfer;\n }\n\n const { needsNotarizationUpdate, needsSessionStateUpdate } = getMetadataUpdates(\n currentTransfer.metadata,\n transferDeposit.notarizationStatus,\n transferDeposit.sessionState,\n );\n\n // Update metadata if needed\n if (needsNotarizationUpdate || needsSessionStateUpdate) {\n return {\n ...currentTransfer,\n metadata: {\n ...currentTransfer.metadata,\n ...(needsNotarizationUpdate && { notarizationStatus: transferDeposit.notarizationStatus }),\n ...(needsSessionStateUpdate && { sessionState: transferDeposit.sessionState }),\n },\n } satisfies SourceCompletedTransfer;\n }\n\n if (isDepositFailed(transferDeposit)) {\n return {\n ...currentTransfer,\n errorCode: ErrorCode.NOTARIZATION_FAILED,\n errorReason: 'Deposit notarization failed',\n failedAtMs: Date.now(),\n status: 'failed',\n } satisfies FailedTransfer;\n }\n\n if (!transferDeposit.claimTxHash) {\n return currentTransfer;\n }\n\n return {\n ...currentTransfer,\n status: 'target-pending',\n target: {\n confirmationCount: 0,\n requiredConfirmationCount: EVM_CONFIRMATION_COUNT,\n startedAtMs: Date.now(),\n txHash: transferDeposit.claimTxHash,\n },\n } satisfies TargetPendingTransfer;\n } catch {\n return currentTransfer;\n }\n }\n default: {\n // target-pending\n\n if (!currentTransfer.target?.txHash) {\n // Transfer missing target info, should not reach here\n return {\n ...currentTransfer,\n errorCode: ErrorCode.UNKNOWN,\n errorReason: 'Missing target transaction hash',\n failedAtMs: Date.now(),\n status: 'failed',\n } satisfies FailedTransfer;\n }\n\n const { confirmationCount, requiredConfirmationCount, txHash } = currentTransfer.target;\n\n if (!isHash(txHash)) {\n // Invalid tx hash\n return {\n ...currentTransfer,\n errorCode: ErrorCode.UNKNOWN,\n errorReason: 'Invalid target transaction hash',\n failedAtMs: Date.now(),\n status: 'failed',\n } satisfies FailedTransfer;\n }\n\n try {\n const transactionResult = await awaitOrAbort(\n targetClient.waitForTransactionReceipt({\n confirmations: Math.min(confirmationCount + 1, requiredConfirmationCount),\n hash: txHash,\n }),\n signal,\n );\n\n if (transactionResult.status === 'aborted') {\n return currentTransfer;\n }\n\n const transactionReceipt = transactionResult.value;\n\n if (transactionReceipt.status === 'reverted') {\n return {\n ...currentTransfer,\n errorCode: ErrorCode.TRANSACTION_REVERTED,\n errorReason: 'Target transaction was reverted',\n failedAtMs: Date.now(),\n status: 'failed',\n } satisfies FailedTransfer;\n }\n\n const newConfirmationCount: number = await targetClient\n .getTransactionConfirmations({\n transactionReceipt,\n })\n .then((count) => Number(count))\n .catch(() => confirmationCount + 1);\n\n // If still not enough confirmations, update the count\n if (newConfirmationCount < requiredConfirmationCount) {\n return {\n ...currentTransfer,\n target: {\n ...currentTransfer.target,\n confirmationCount: newConfirmationCount,\n },\n } satisfies TargetPendingTransfer;\n }\n\n return {\n ...currentTransfer,\n completedAtMs: Date.now(),\n status: 'completed',\n target: {\n ...currentTransfer.target,\n confirmationCount: newConfirmationCount,\n },\n } satisfies CompletedTransfer;\n } catch {\n return currentTransfer;\n }\n }\n }\n}\n"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{ErrorCode as e}from"../../../../errors.js";import{awaitOrAbort as t,getEvmClientForChain as n,waitForTimeoutOrAbort as r}from"../../../_utils.js";import{
|
|
1
|
+
import{ErrorCode as e}from"../../../../errors.js";import{awaitOrAbort as t,getEvmClientForChain as n,waitForTimeoutOrAbort as r}from"../../../_utils.js";import{getMetadataUpdates as i,isDepositFailed as a}from"../../_utils/metadata.js";import{isHash as o}from"viem";import{getDepositsByAddress as s}from"@lombard.finance/sdk";function c({bitcoinFunctions:e,config:t}){return({transfer:i,updateListener:a})=>{let o=new AbortController,s=()=>{o.abort()};return i.status===`completed`||i.status===`failed`?{cancel:s,result:Promise.resolve(i)}:{cancel:s,result:(async()=>{let s=structuredClone(i),c=n({chain:i.targetChain});for(;!o.signal.aborted;){let n=s.status;switch(s.status){case`source-pending`:s=await l({bitcoinFunctions:e,currentTransfer:s,signal:o.signal}),o.signal.aborted||a(s);break;case`source-completed`:case`target-pending`:s=await u({config:t,currentTransfer:s,signal:o.signal,targetClient:c}),o.signal.aborted||a(s);break;default:return s}s.status===n&&await r({timeoutMs:3e4,signal:o.signal})}return s})()}}}async function l({bitcoinFunctions:e,currentTransfer:n,signal:r}){try{let i=await t(e.getTransaction(n.source.txHash),r);if(i.status===`aborted`)return n;let{confirmations:a}=i.value;return a<n.source.requiredConfirmationCount?{...n,source:{...n.source,confirmationCount:a}}:{...n,source:{...n.source,confirmationCount:a},status:`source-completed`}}catch{return n}}async function u({config:n,currentTransfer:r,signal:c,targetClient:l}){switch(r.status){case`source-completed`:try{let o=await t(s({address:r.toAddress,env:n.env}),c);if(o.status===`aborted`)return r;let l=o.value.find(e=>e.txHash.toLowerCase()===r.source.txHash.toLowerCase());if(!l)return r;let{needsNotarizationUpdate:u,needsSessionStateUpdate:d}=i(r.metadata,l.notarizationStatus,l.sessionState);return u||d?{...r,metadata:{...r.metadata,...u&&{notarizationStatus:l.notarizationStatus},...d&&{sessionState:l.sessionState}}}:a(l)?{...r,errorCode:e.NOTARIZATION_FAILED,errorReason:`Deposit notarization failed`,failedAtMs:Date.now(),status:`failed`}:l.claimTxHash?{...r,status:`target-pending`,target:{confirmationCount:0,requiredConfirmationCount:1,startedAtMs:Date.now(),txHash:l.claimTxHash}}:r}catch{return r}default:{if(!r.target?.txHash)return{...r,errorCode:e.UNKNOWN,errorReason:`Missing target transaction hash`,failedAtMs:Date.now(),status:`failed`};let{confirmationCount:n,requiredConfirmationCount:i,txHash:a}=r.target;if(!o(a))return{...r,errorCode:e.UNKNOWN,errorReason:`Invalid target transaction hash`,failedAtMs:Date.now(),status:`failed`};try{let o=await t(l.waitForTransactionReceipt({confirmations:Math.min(n+1,i),hash:a}),c);if(o.status===`aborted`)return r;let s=o.value;if(s.status===`reverted`)return{...r,errorCode:e.TRANSACTION_REVERTED,errorReason:`Target transaction was reverted`,failedAtMs:Date.now(),status:`failed`};let u=await l.getTransactionConfirmations({transactionReceipt:s}).then(e=>Number(e)).catch(()=>n+1);return u<i?{...r,target:{...r.target,confirmationCount:u}}:{...r,completedAtMs:Date.now(),status:`completed`,target:{...r.target,confirmationCount:u}}}catch{return r}}}}export{c as trackTransferFactory};
|
|
2
2
|
//# sourceMappingURL=track-transfer.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"track-transfer.js","names":[],"sources":["../../../../../src/transfer-service/lombard/btc-to-btcb/_handlers/track-transfer.ts"],"sourcesContent":["import { getDepositsByAddress } from '@lombard.finance/sdk';\nimport { ErrorCode } from '../../../../errors';\nimport type { BitcoinFunctions } from '../../../../types/bitcoin';\nimport type { TransferService } from '../../../../types/service';\nimport type {\n CompletedTransfer,\n FailedTransfer,\n SourceCompletedTransfer,\n SourcePendingTransfer,\n TargetPendingTransfer,\n Transfer,\n} from '../../../../types/transfer';\nimport { awaitOrAbort, getEvmClientForChain, waitForTimeoutOrAbort } from '../../../_utils';\nimport type { BtcToBtcbConfig } from '../../types';\nimport { isHash } from 'viem';\nimport { getMetadataUpdates, isDepositFailed } from '../../_utils/metadata';\nimport { EVM_CONFIRMATION_COUNT } from '../../constants';\n\n// Polling interval for BTC deposits (30 seconds - faster than BTC block time since we also poll Lombard API)\nconst DEPOSIT_POLLING_INTERVAL_MS = 1000 * 30;\n\nexport interface TrackTransferFactoryOptions {\n bitcoinFunctions: BitcoinFunctions;\n config: BtcToBtcbConfig;\n}\n\nexport function trackTransferFactory({\n bitcoinFunctions,\n config,\n}: TrackTransferFactoryOptions): TransferService['trackTransfer'] {\n return ({ transfer, updateListener }) => {\n const ac = new AbortController();\n const cancel = () => {\n ac.abort();\n };\n\n if (transfer.status === 'completed' || transfer.status === 'failed') {\n return {\n cancel,\n result: Promise.resolve(transfer),\n };\n }\n\n const executeTracking = async (): Promise<Transfer> => {\n let currentTransfer: Transfer = structuredClone(transfer);\n\n const targetClient = getEvmClientForChain({ chain: transfer.targetChain });\n\n while (!ac.signal.aborted) {\n const statusBeforeTracking = currentTransfer.status;\n\n switch (currentTransfer.status) {\n case 'source-pending': {\n currentTransfer = await _trackSourceTx({\n bitcoinFunctions,\n currentTransfer,\n signal: ac.signal,\n });\n\n if (!ac.signal.aborted) {\n updateListener(currentTransfer);\n }\n\n break;\n }\n case 'source-completed':\n case 'target-pending': {\n currentTransfer = await _trackTargetTx({\n config,\n currentTransfer,\n signal: ac.signal,\n targetClient,\n });\n\n if (!ac.signal.aborted) {\n updateListener(currentTransfer);\n }\n\n break;\n }\n default: {\n return currentTransfer;\n }\n }\n\n const hasStatusChanged = currentTransfer.status !== statusBeforeTracking;\n\n if (!hasStatusChanged) {\n await waitForTimeoutOrAbort({ timeoutMs: DEPOSIT_POLLING_INTERVAL_MS, signal: ac.signal });\n }\n }\n\n return currentTransfer;\n };\n\n return {\n cancel,\n result: executeTracking(),\n };\n };\n}\n\nexport interface TrackBaseParams {\n currentTransfer: Transfer;\n signal: AbortSignal;\n}\n\nexport interface TrackSourceTxParams extends TrackBaseParams {\n bitcoinFunctions: BitcoinFunctions;\n currentTransfer: SourcePendingTransfer;\n}\n\nexport interface TrackTargetTxParams extends TrackBaseParams {\n config: BtcToBtcbConfig;\n currentTransfer: SourceCompletedTransfer | TargetPendingTransfer;\n targetClient: ReturnType<typeof getEvmClientForChain>;\n}\n\nexport async function _trackSourceTx({\n bitcoinFunctions,\n currentTransfer,\n signal,\n}: TrackSourceTxParams): Promise<SourcePendingTransfer | SourceCompletedTransfer | FailedTransfer> {\n try {\n const transactionResult = await awaitOrAbort(\n bitcoinFunctions.getTransaction(currentTransfer.source.txHash),\n signal,\n );\n\n if (transactionResult.status === 'aborted') {\n return currentTransfer;\n }\n\n const { confirmations: confirmationCount } = transactionResult.value;\n\n if (confirmationCount < currentTransfer.source.requiredConfirmationCount) {\n return {\n ...currentTransfer,\n source: {\n ...currentTransfer.source,\n confirmationCount,\n },\n } satisfies SourcePendingTransfer;\n }\n\n return {\n ...currentTransfer,\n source: {\n ...currentTransfer.source,\n confirmationCount,\n },\n status: 'source-completed',\n } satisfies SourceCompletedTransfer;\n } catch {\n return currentTransfer;\n }\n}\n\nexport async function _trackTargetTx({\n config,\n currentTransfer,\n signal,\n targetClient,\n}: TrackTargetTxParams): Promise<SourceCompletedTransfer | TargetPendingTransfer | FailedTransfer | CompletedTransfer> {\n switch (currentTransfer.status) {\n case 'source-completed': {\n try {\n const depositsResult = await awaitOrAbort(\n getDepositsByAddress({ address: currentTransfer.toAddress, env: config.env }),\n signal,\n );\n\n if (depositsResult.status === 'aborted') {\n return currentTransfer;\n }\n\n const transferDeposit = depositsResult.value.find(\n (d) => d.txHash.toLowerCase() === currentTransfer.source.txHash.toLowerCase(),\n );\n\n if (!transferDeposit) {\n // Source Completed but no deposit found yet on target\n return currentTransfer;\n }\n\n const { needsNotarizationUpdate, needsSessionStateUpdate } = getMetadataUpdates(\n currentTransfer.metadata,\n transferDeposit.notarizationStatus,\n transferDeposit.sessionState,\n );\n\n // Update metadata if needed\n if (needsNotarizationUpdate || needsSessionStateUpdate) {\n return {\n ...currentTransfer,\n metadata: {\n ...currentTransfer.metadata,\n ...(needsNotarizationUpdate && { notarizationStatus: transferDeposit.notarizationStatus }),\n ...(needsSessionStateUpdate && { sessionState: transferDeposit.sessionState }),\n },\n } satisfies SourceCompletedTransfer;\n }\n\n if (isDepositFailed(transferDeposit)) {\n return {\n ...currentTransfer,\n errorCode: ErrorCode.NOTARIZATION_FAILED,\n errorReason: 'Deposit notarization failed',\n failedAtMs: Date.now(),\n status: 'failed',\n } satisfies FailedTransfer;\n }\n\n if (!transferDeposit.claimTxHash) {\n return currentTransfer;\n }\n\n return {\n ...currentTransfer,\n status: 'target-pending',\n target: {\n confirmationCount: 0,\n requiredConfirmationCount: EVM_CONFIRMATION_COUNT,\n startedAtMs: Date.now(),\n txHash: transferDeposit.claimTxHash,\n },\n } satisfies TargetPendingTransfer;\n } catch {\n return currentTransfer;\n }\n }\n default: {\n // target-pending\n\n if (!currentTransfer.target?.txHash) {\n // Transfer missing target info, should not reach here\n return {\n ...currentTransfer,\n errorCode: ErrorCode.UNKNOWN,\n errorReason: 'Missing target transaction hash',\n failedAtMs: Date.now(),\n status: 'failed',\n } satisfies FailedTransfer;\n }\n\n const { confirmationCount, requiredConfirmationCount, txHash } = currentTransfer.target;\n\n if (!isHash(txHash)) {\n // Invalid tx hash\n return {\n ...currentTransfer,\n errorCode: ErrorCode.UNKNOWN,\n errorReason: 'Invalid target transaction hash',\n failedAtMs: Date.now(),\n status: 'failed',\n } satisfies FailedTransfer;\n }\n\n try {\n const transactionResult = await awaitOrAbort(\n targetClient.waitForTransactionReceipt({\n confirmations: Math.min(confirmationCount + 1, requiredConfirmationCount),\n hash: txHash,\n }),\n signal,\n );\n\n if (transactionResult.status === 'aborted') {\n return currentTransfer;\n }\n\n const transactionReceipt = transactionResult.value;\n\n if (transactionReceipt.status === 'reverted') {\n return {\n ...currentTransfer,\n errorCode: ErrorCode.TRANSACTION_REVERTED,\n errorReason: 'Target transaction was reverted',\n failedAtMs: Date.now(),\n status: 'failed',\n } satisfies FailedTransfer;\n }\n\n const newConfirmationCount: number = await targetClient\n .getTransactionConfirmations({\n transactionReceipt,\n })\n .then((count) => Number(count))\n .catch(() => confirmationCount + 1);\n\n // If still not enough confirmations, update the count\n if (newConfirmationCount < requiredConfirmationCount) {\n return {\n ...currentTransfer,\n target: {\n ...currentTransfer.target,\n confirmationCount: newConfirmationCount,\n },\n } satisfies TargetPendingTransfer;\n }\n\n return {\n ...currentTransfer,\n completedAtMs: Date.now(),\n status: 'completed',\n target: {\n ...currentTransfer.target,\n confirmationCount: newConfirmationCount,\n },\n } satisfies CompletedTransfer;\n } catch {\n return currentTransfer;\n }\n }\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"track-transfer.js","names":[],"sources":["../../../../../src/transfer-service/lombard/btc-to-btcb/_handlers/track-transfer.ts"],"sourcesContent":["import { getDepositsByAddress } from '@lombard.finance/sdk';\nimport { ErrorCode } from '../../../../errors';\nimport type { BitcoinFunctions } from '../../../../types/bitcoin';\nimport type { TransferService } from '../../../../types/service';\nimport type {\n CompletedTransfer,\n FailedTransfer,\n SourceCompletedTransfer,\n SourcePendingTransfer,\n TargetPendingTransfer,\n Transfer,\n} from '../../../../types/transfer';\nimport { awaitOrAbort, getEvmClientForChain, waitForTimeoutOrAbort } from '../../../_utils';\nimport type { BtcToBtcbConfig } from '../../types';\nimport { isHash } from 'viem';\nimport { getMetadataUpdates, isDepositFailed } from '../../_utils/metadata';\nimport { EVM_CONFIRMATION_COUNT } from '../../constants';\n\n// Polling interval for BTC deposits (30 seconds - faster than BTC block time since we also poll Lombard API)\nconst DEPOSIT_POLLING_INTERVAL_MS = 1000 * 30;\n\nexport interface TrackTransferFactoryOptions {\n bitcoinFunctions: BitcoinFunctions;\n config: BtcToBtcbConfig;\n}\n\nexport function trackTransferFactory({\n bitcoinFunctions,\n config,\n}: TrackTransferFactoryOptions): TransferService['trackTransfer'] {\n return ({ transfer, updateListener }) => {\n const ac = new AbortController();\n const cancel = () => {\n ac.abort();\n };\n\n if (transfer.status === 'completed' || transfer.status === 'failed') {\n return {\n cancel,\n result: Promise.resolve(transfer),\n };\n }\n\n const executeTracking = async (): Promise<Transfer> => {\n let currentTransfer: Transfer = structuredClone(transfer);\n\n const targetClient = getEvmClientForChain({ chain: transfer.targetChain });\n\n while (!ac.signal.aborted) {\n const statusBeforeTracking = currentTransfer.status;\n\n switch (currentTransfer.status) {\n case 'source-pending': {\n currentTransfer = await _trackSourceTx({\n bitcoinFunctions,\n currentTransfer,\n signal: ac.signal,\n });\n\n if (!ac.signal.aborted) {\n updateListener(currentTransfer);\n }\n\n break;\n }\n case 'source-completed':\n case 'target-pending': {\n currentTransfer = await _trackTargetTx({\n config,\n currentTransfer,\n signal: ac.signal,\n targetClient,\n });\n\n if (!ac.signal.aborted) {\n updateListener(currentTransfer);\n }\n\n break;\n }\n default: {\n return currentTransfer;\n }\n }\n\n const hasStatusChanged = currentTransfer.status !== statusBeforeTracking;\n\n if (!hasStatusChanged) {\n await waitForTimeoutOrAbort({ timeoutMs: DEPOSIT_POLLING_INTERVAL_MS, signal: ac.signal });\n }\n }\n\n return currentTransfer;\n };\n\n return {\n cancel,\n result: executeTracking(),\n };\n };\n}\n\nexport interface TrackBaseParams {\n currentTransfer: Transfer;\n signal: AbortSignal;\n}\n\nexport interface TrackSourceTxParams extends TrackBaseParams {\n bitcoinFunctions: BitcoinFunctions;\n currentTransfer: SourcePendingTransfer;\n}\n\nexport interface TrackTargetTxParams extends TrackBaseParams {\n config: BtcToBtcbConfig;\n currentTransfer: SourceCompletedTransfer | TargetPendingTransfer;\n targetClient: ReturnType<typeof getEvmClientForChain>;\n}\n\nexport async function _trackSourceTx({\n bitcoinFunctions,\n currentTransfer,\n signal,\n}: TrackSourceTxParams): Promise<SourcePendingTransfer | SourceCompletedTransfer | FailedTransfer> {\n try {\n const transactionResult = await awaitOrAbort(\n bitcoinFunctions.getTransaction(currentTransfer.source.txHash),\n signal,\n );\n\n if (transactionResult.status === 'aborted') {\n return currentTransfer;\n }\n\n const { confirmations: confirmationCount } = transactionResult.value;\n\n if (confirmationCount < currentTransfer.source.requiredConfirmationCount) {\n return {\n ...currentTransfer,\n source: {\n ...currentTransfer.source,\n confirmationCount,\n },\n } satisfies SourcePendingTransfer;\n }\n\n return {\n ...currentTransfer,\n source: {\n ...currentTransfer.source,\n confirmationCount,\n },\n status: 'source-completed',\n } satisfies SourceCompletedTransfer;\n } catch {\n return currentTransfer;\n }\n}\n\nexport async function _trackTargetTx({\n config,\n currentTransfer,\n signal,\n targetClient,\n}: TrackTargetTxParams): Promise<SourceCompletedTransfer | TargetPendingTransfer | FailedTransfer | CompletedTransfer> {\n switch (currentTransfer.status) {\n case 'source-completed': {\n try {\n const depositsResult = await awaitOrAbort(\n getDepositsByAddress({ address: currentTransfer.toAddress, env: config.env }),\n signal,\n );\n\n if (depositsResult.status === 'aborted') {\n return currentTransfer;\n }\n\n const transferDeposit = depositsResult.value.find(\n (d) => d.txHash.toLowerCase() === currentTransfer.source.txHash.toLowerCase(),\n );\n\n if (!transferDeposit) {\n // Source Completed but no deposit found yet on target\n return currentTransfer;\n }\n\n const { needsNotarizationUpdate, needsSessionStateUpdate } = getMetadataUpdates(\n currentTransfer.metadata,\n transferDeposit.notarizationStatus,\n transferDeposit.sessionState,\n );\n\n // Update metadata if needed\n if (needsNotarizationUpdate || needsSessionStateUpdate) {\n return {\n ...currentTransfer,\n metadata: {\n ...currentTransfer.metadata,\n ...(needsNotarizationUpdate && { notarizationStatus: transferDeposit.notarizationStatus }),\n ...(needsSessionStateUpdate && { sessionState: transferDeposit.sessionState }),\n },\n } satisfies SourceCompletedTransfer;\n }\n\n if (isDepositFailed(transferDeposit)) {\n return {\n ...currentTransfer,\n errorCode: ErrorCode.NOTARIZATION_FAILED,\n errorReason: 'Deposit notarization failed',\n failedAtMs: Date.now(),\n status: 'failed',\n } satisfies FailedTransfer;\n }\n\n if (!transferDeposit.claimTxHash) {\n return currentTransfer;\n }\n\n return {\n ...currentTransfer,\n status: 'target-pending',\n target: {\n confirmationCount: 0,\n requiredConfirmationCount: EVM_CONFIRMATION_COUNT,\n startedAtMs: Date.now(),\n txHash: transferDeposit.claimTxHash,\n },\n } satisfies TargetPendingTransfer;\n } catch {\n return currentTransfer;\n }\n }\n default: {\n // target-pending\n\n if (!currentTransfer.target?.txHash) {\n // Transfer missing target info, should not reach here\n return {\n ...currentTransfer,\n errorCode: ErrorCode.UNKNOWN,\n errorReason: 'Missing target transaction hash',\n failedAtMs: Date.now(),\n status: 'failed',\n } satisfies FailedTransfer;\n }\n\n const { confirmationCount, requiredConfirmationCount, txHash } = currentTransfer.target;\n\n if (!isHash(txHash)) {\n // Invalid tx hash\n return {\n ...currentTransfer,\n errorCode: ErrorCode.UNKNOWN,\n errorReason: 'Invalid target transaction hash',\n failedAtMs: Date.now(),\n status: 'failed',\n } satisfies FailedTransfer;\n }\n\n try {\n const transactionResult = await awaitOrAbort(\n targetClient.waitForTransactionReceipt({\n confirmations: Math.min(confirmationCount + 1, requiredConfirmationCount),\n hash: txHash,\n }),\n signal,\n );\n\n if (transactionResult.status === 'aborted') {\n return currentTransfer;\n }\n\n const transactionReceipt = transactionResult.value;\n\n if (transactionReceipt.status === 'reverted') {\n return {\n ...currentTransfer,\n errorCode: ErrorCode.TRANSACTION_REVERTED,\n errorReason: 'Target transaction was reverted',\n failedAtMs: Date.now(),\n status: 'failed',\n } satisfies FailedTransfer;\n }\n\n const newConfirmationCount: number = await targetClient\n .getTransactionConfirmations({\n transactionReceipt,\n })\n .then((count) => Number(count))\n .catch(() => confirmationCount + 1);\n\n // If still not enough confirmations, update the count\n if (newConfirmationCount < requiredConfirmationCount) {\n return {\n ...currentTransfer,\n target: {\n ...currentTransfer.target,\n confirmationCount: newConfirmationCount,\n },\n } satisfies TargetPendingTransfer;\n }\n\n return {\n ...currentTransfer,\n completedAtMs: Date.now(),\n status: 'completed',\n target: {\n ...currentTransfer.target,\n confirmationCount: newConfirmationCount,\n },\n } satisfies CompletedTransfer;\n } catch {\n return currentTransfer;\n }\n }\n }\n}\n"],"mappings":"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"}
|
|
@@ -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.cjs`),i=require(`../../../../utils/bitcoin-address.cjs`),a=require(`../../constants.cjs`),o=require(`../../_utils/utxo.cjs`);let s=require(`viem`),c=require(`@lombard.finance/sdk`);function l({bitcoinFunctions:l,btcSigner:u,config:d,evmSigner:f}){return async({quote:p,onStepChange:m})=>{if(!i.isBech32AddressInNetwork(p.fromAddress,d.environment===e.Environment.PROD))throw new t.InvalidParamsError(t.ErrorReason.INCORRECT_ADDRESS_PROVIDED,`Invalid fromAddress was provided. Make sure it is a BTC address from correct environment.`);if(!(0,s.isAddress)(p.toAddress))throw new t.InvalidParamsError(t.ErrorReason.INCORRECT_ADDRESS_PROVIDED,`Invalid toAddress was provided. Must be a valid EVM address.`);let h=p.toAddress,g=n.caip2ToEip155ChainId(p.targetChain.chainId),_;try{_=await(0,c.getDepositBtcAddress)({address:h,chainId:g,partnerId:a.LOMBARD_PARTNER_ID,env:d.env,token:d.targetToken})}catch{}let v=_?1:2,y={currentSignature:1,currentSignatureReason:_?e.TransferSignatureReason.TokensTransfer:e.TransferSignatureReason.AddressOwnership,quote:p,requiredSignatures:v};if(!_){let n=r.getEvmClientForChain({chain:p.targetChain}),i=(0,c.getAddressConfirmationMessage)(g),o=await f.signMessage({message:i,address:h,chainId:g},e=>n.sendRawTransaction({serializedTransaction:e}),y);if(y.currentSignature=2,y.currentSignatureReason=e.TransferSignatureReason.TokensTransfer,_=await(0,c.generateDepositBtcAddress)({address:h,chainId:g,env:d.env,partnerId:a.LOMBARD_PARTNER_ID,signature:o,token:d.targetToken}),_===c.SANCTIONED_ADDRESS)throw new t.InvalidParamsError(t.ErrorReason.ADDRESS_IS_BLOCKED,_)}if(!i.isBech32AddressInNetwork(_,d.environment===e.Environment.PROD))throw new t.InvalidParamsError(t.ErrorReason.INCORRECT_ADDRESS_PROVIDED,`Generated deposit address is invalid`);let{low:b,high:x}=await l.getFeeRates(),S=d.environment===e.Environment.PROD?x:b,{utxos:C}=await l.getUtxoBalance(p.fromAddress,!1),{inputs:w,outputs:T}=await o.selectUtxos(_,p.fromAddress,p.amountIn,S,C,l);if(!w||!T)throw new t.InvalidParamsError(t.ErrorReason.INVALID_PARAMS,`Unable to create transaction. UTXO selection failed.`);let E=Date.now();m?.(y);let D;try{D=await r.getEvmClientForChain({chain:p.targetChain}).getBlockNumber()}catch{return{amountIn:p.amountIn,amountOut:p.amountOut,environment:d.environment,errorCode:t.ErrorCode.UNKNOWN,errorReason:`Unable to fetch target chain block number`,failedAtMs:Date.now(),fees:p.fees,fromAddress:p.fromAddress,id:p.id,partnerFeeBps:p.partnerFeeBps,sourceAsset:p.assetIn,sourceChain:p.sourceChain,targetAsset:p.assetOut,targetChain:p.targetChain,toAddress:p.toAddress,status:`failed`,type:e.ServiceType.LOMBARD_BTC_TO_BTCB}}let O=await u.sign({inputs:w,outputs:T},l.issueRawTx,y);return{amountIn:p.amountIn,amountOut:p.amountOut,environment:d.environment,fees:p.fees,fromAddress:p.fromAddress,id:p.id,partnerFeeBps:p.partnerFeeBps,source:{confirmationCount:0,requiredConfirmationCount:
|
|
1
|
+
require(`../../../../_virtual/_rolldown/runtime.cjs`);const e=require(`../../../../constants.cjs`),t=require(`../../../../errors.cjs`),n=require(`../../../../utils/caip.cjs`),r=require(`../../../_utils.cjs`),i=require(`../../../../utils/bitcoin-address.cjs`),a=require(`../../constants.cjs`),o=require(`../../_utils/utxo.cjs`);let s=require(`viem`),c=require(`@lombard.finance/sdk`);function l({bitcoinFunctions:l,btcSigner:u,config:d,evmSigner:f}){return async({quote:p,onStepChange:m})=>{if(!i.isBech32AddressInNetwork(p.fromAddress,d.environment===e.Environment.PROD))throw new t.InvalidParamsError(t.ErrorReason.INCORRECT_ADDRESS_PROVIDED,`Invalid fromAddress was provided. Make sure it is a BTC address from correct environment.`);if(!(0,s.isAddress)(p.toAddress))throw new t.InvalidParamsError(t.ErrorReason.INCORRECT_ADDRESS_PROVIDED,`Invalid toAddress was provided. Must be a valid EVM address.`);let h=p.toAddress,g=n.caip2ToEip155ChainId(p.targetChain.chainId),_;try{_=await(0,c.getDepositBtcAddress)({address:h,chainId:g,partnerId:a.LOMBARD_PARTNER_ID,env:d.env,token:d.targetToken})}catch{}let v=_?1:2,y={currentSignature:1,currentSignatureReason:_?e.TransferSignatureReason.TokensTransfer:e.TransferSignatureReason.AddressOwnership,quote:p,requiredSignatures:v};if(!_){let n=r.getEvmClientForChain({chain:p.targetChain}),i=(0,c.getAddressConfirmationMessage)(g),o=await f.signMessage({message:i,address:h,chainId:g},e=>n.sendRawTransaction({serializedTransaction:e}),y);if(y.currentSignature=2,y.currentSignatureReason=e.TransferSignatureReason.TokensTransfer,_=await(0,c.generateDepositBtcAddress)({address:h,chainId:g,env:d.env,partnerId:a.LOMBARD_PARTNER_ID,signature:o,token:d.targetToken}),_===c.SANCTIONED_ADDRESS)throw new t.InvalidParamsError(t.ErrorReason.ADDRESS_IS_BLOCKED,_)}if(!i.isBech32AddressInNetwork(_,d.environment===e.Environment.PROD))throw new t.InvalidParamsError(t.ErrorReason.INCORRECT_ADDRESS_PROVIDED,`Generated deposit address is invalid`);let{low:b,high:x}=await l.getFeeRates(),S=d.environment===e.Environment.PROD?x:b,{utxos:C}=await l.getUtxoBalance(p.fromAddress,!1),{inputs:w,outputs:T}=await o.selectUtxos(_,p.fromAddress,p.amountIn,S,C,l);if(!w||!T)throw new t.InvalidParamsError(t.ErrorReason.INVALID_PARAMS,`Unable to create transaction. UTXO selection failed.`);let E=Date.now();m?.(y);let D;try{D=await r.getEvmClientForChain({chain:p.targetChain}).getBlockNumber()}catch{return{amountIn:p.amountIn,amountOut:p.amountOut,environment:d.environment,errorCode:t.ErrorCode.UNKNOWN,errorReason:`Unable to fetch target chain block number`,failedAtMs:Date.now(),fees:p.fees,fromAddress:p.fromAddress,id:p.id,partnerFeeBps:p.partnerFeeBps,sourceAsset:p.assetIn,sourceChain:p.sourceChain,targetAsset:p.assetOut,targetChain:p.targetChain,toAddress:p.toAddress,status:`failed`,type:e.ServiceType.LOMBARD_BTC_TO_BTCB}}let O=await u.sign({inputs:w,outputs:T},l.issueRawTx,y);return{amountIn:p.amountIn,amountOut:p.amountOut,environment:d.environment,fees:p.fees,fromAddress:p.fromAddress,id:p.id,partnerFeeBps:p.partnerFeeBps,source:{confirmationCount:0,requiredConfirmationCount:6,startedAtMs:E,txHash:O,targetStartBlockNumber:D},sourceAsset:p.assetIn,sourceChain:p.sourceChain,status:`source-pending`,targetAsset:p.assetOut,targetChain:p.targetChain,toAddress:p.toAddress,type:e.ServiceType.LOMBARD_BTC_TO_BTCB}}}exports.transferAssetFactory=l;
|
|
2
2
|
//# sourceMappingURL=transfer-asset.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transfer-asset.cjs","names":["isBech32AddressInNetwork","Environment","InvalidParamsError","ErrorReason","caip2ToEip155ChainId","LOMBARD_PARTNER_ID","TransferSignatureReason","getEvmClientForChain","SANCTIONED_ADDRESS","selectUtxos","ErrorCode","ServiceType"
|
|
1
|
+
{"version":3,"file":"transfer-asset.cjs","names":["isBech32AddressInNetwork","Environment","InvalidParamsError","ErrorReason","caip2ToEip155ChainId","LOMBARD_PARTNER_ID","TransferSignatureReason","getEvmClientForChain","SANCTIONED_ADDRESS","selectUtxos","ErrorCode","ServiceType"],"sources":["../../../../../src/transfer-service/lombard/btc-to-btcb/_handlers/transfer-asset.ts"],"sourcesContent":["import { isAddress, type Mutable } from 'viem';\nimport { Environment, ServiceType, TransferSignatureReason } from '../../../../constants';\nimport { ErrorCode, ErrorReason, InvalidParamsError } from '../../../../errors';\nimport { caip2ToEip155ChainId } from '../../../../utils/caip';\nimport type { BitcoinFunctions } from '../../../../types/bitcoin';\nimport type { TransferService } from '../../../../types/service';\nimport type { BtcSigner, EvmSignerWithMessage } from '../../../../types/signer';\nimport type { FailedTransfer, SourcePendingTransfer, TransferStepDetails } from '../../../../types/transfer';\nimport { isBech32AddressInNetwork } from '../../../../utils/bitcoin-address';\nimport type { BtcToBtcbConfig } from '../../types';\nimport {\n generateDepositBtcAddress,\n getDepositBtcAddress,\n SANCTIONED_ADDRESS,\n getAddressConfirmationMessage,\n type ChainId,\n} from '@lombard.finance/sdk';\nimport { BTC_CONFIRMATION_COUNT, LOMBARD_PARTNER_ID } from '../../constants';\nimport { getEvmClientForChain } from '../../../_utils';\nimport { selectUtxos } from '../../_utils/utxo';\n\nexport interface TransferAssetFactoryOptions {\n bitcoinFunctions: BitcoinFunctions;\n btcSigner: BtcSigner;\n config: BtcToBtcbConfig;\n evmSigner: EvmSignerWithMessage;\n}\n\nexport function transferAssetFactory({\n bitcoinFunctions,\n btcSigner,\n config,\n evmSigner,\n}: TransferAssetFactoryOptions): TransferService['transferAsset'] {\n return async ({ quote, onStepChange }) => {\n if (!isBech32AddressInNetwork(quote.fromAddress, config.environment === Environment.PROD)) {\n throw new InvalidParamsError(\n ErrorReason.INCORRECT_ADDRESS_PROVIDED,\n 'Invalid fromAddress was provided. Make sure it is a BTC address from correct environment.',\n );\n }\n\n if (!isAddress(quote.toAddress)) {\n throw new InvalidParamsError(\n ErrorReason.INCORRECT_ADDRESS_PROVIDED,\n 'Invalid toAddress was provided. Must be a valid EVM address.',\n );\n }\n\n const targetAddress = quote.toAddress;\n const targetChainId: number = caip2ToEip155ChainId(quote.targetChain.chainId);\n\n let btcDepositAddress: string | undefined;\n\n try {\n btcDepositAddress = await getDepositBtcAddress({\n address: targetAddress,\n chainId: targetChainId as ChainId,\n partnerId: LOMBARD_PARTNER_ID,\n env: config.env,\n token: config.targetToken,\n });\n } catch {\n // Deposit address not found. Generate a new one.\n }\n\n const requiredSignatures: number = btcDepositAddress ? 1 : 2;\n const transferStep: Mutable<TransferStepDetails> = {\n currentSignature: 1,\n currentSignatureReason: btcDepositAddress\n ? TransferSignatureReason.TokensTransfer\n : TransferSignatureReason.AddressOwnership,\n quote,\n requiredSignatures,\n };\n\n // Generate a new deposit address if not existing\n if (!btcDepositAddress) {\n const client = getEvmClientForChain({ chain: quote.targetChain });\n\n // This message MUST match whatever Lombard is using to verify the provided signature.\n const message = getAddressConfirmationMessage(targetChainId);\n const signature = await evmSigner.signMessage(\n { message, address: targetAddress, chainId: targetChainId },\n (signedTxHash) => client.sendRawTransaction({ serializedTransaction: signedTxHash }),\n transferStep,\n );\n\n // Update step for the next signature (tokens transfer)\n transferStep.currentSignature = 2;\n transferStep.currentSignatureReason = TransferSignatureReason.TokensTransfer;\n\n btcDepositAddress = await generateDepositBtcAddress({\n address: targetAddress,\n chainId: targetChainId as ChainId,\n env: config.env,\n partnerId: LOMBARD_PARTNER_ID,\n signature,\n token: config.targetToken,\n });\n\n if (btcDepositAddress === SANCTIONED_ADDRESS) {\n throw new InvalidParamsError(ErrorReason.ADDRESS_IS_BLOCKED, btcDepositAddress);\n }\n }\n\n if (!isBech32AddressInNetwork(btcDepositAddress, config.environment === Environment.PROD)) {\n throw new InvalidParamsError(ErrorReason.INCORRECT_ADDRESS_PROVIDED, 'Generated deposit address is invalid');\n }\n\n const { low, high } = await bitcoinFunctions.getFeeRates();\n const feeRate = config.environment === Environment.PROD ? high : low;\n const { utxos } = await bitcoinFunctions.getUtxoBalance(quote.fromAddress, false);\n\n const { inputs, outputs } = await selectUtxos(\n btcDepositAddress,\n quote.fromAddress,\n quote.amountIn,\n feeRate,\n utxos,\n bitcoinFunctions,\n );\n\n if (!inputs || !outputs) {\n throw new InvalidParamsError(ErrorReason.INVALID_PARAMS, 'Unable to create transaction. UTXO selection failed.');\n }\n\n const startedAtMs = Date.now();\n\n onStepChange?.(transferStep);\n\n let targetStartBlockNumber: bigint;\n\n try {\n const targetClient = getEvmClientForChain({ chain: quote.targetChain });\n targetStartBlockNumber = await targetClient.getBlockNumber();\n } catch {\n // Unable to get the target block number. Can't track from this point.\n\n return {\n amountIn: quote.amountIn,\n amountOut: quote.amountOut,\n environment: config.environment,\n errorCode: ErrorCode.UNKNOWN,\n errorReason: 'Unable to fetch target chain block number',\n failedAtMs: Date.now(),\n fees: quote.fees,\n fromAddress: quote.fromAddress,\n id: quote.id,\n partnerFeeBps: quote.partnerFeeBps,\n sourceAsset: quote.assetIn,\n sourceChain: quote.sourceChain,\n targetAsset: quote.assetOut,\n targetChain: quote.targetChain,\n toAddress: quote.toAddress,\n status: 'failed',\n type: ServiceType.LOMBARD_BTC_TO_BTCB,\n } satisfies FailedTransfer;\n }\n\n const txHash = await btcSigner.sign({ inputs, outputs }, bitcoinFunctions.issueRawTx, transferStep);\n\n return {\n amountIn: quote.amountIn,\n amountOut: quote.amountOut,\n environment: config.environment,\n fees: quote.fees,\n fromAddress: quote.fromAddress,\n id: quote.id,\n partnerFeeBps: quote.partnerFeeBps,\n source: {\n confirmationCount: 0,\n requiredConfirmationCount: BTC_CONFIRMATION_COUNT,\n startedAtMs,\n txHash,\n targetStartBlockNumber,\n },\n sourceAsset: quote.assetIn,\n sourceChain: quote.sourceChain,\n status: 'source-pending',\n targetAsset: quote.assetOut,\n targetChain: quote.targetChain,\n toAddress: quote.toAddress,\n type: ServiceType.LOMBARD_BTC_TO_BTCB,\n } satisfies SourcePendingTransfer;\n };\n}\n"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{Environment as e,ServiceType as t,TransferSignatureReason as n}from"../../../../constants.js";import{ErrorCode as r,ErrorReason as i,InvalidParamsError as a}from"../../../../errors.js";import{caip2ToEip155ChainId as o}from"../../../../utils/caip.js";import{getEvmClientForChain as s}from"../../../_utils.js";import{isBech32AddressInNetwork as c}from"../../../../utils/bitcoin-address.js";import{
|
|
1
|
+
import{Environment as e,ServiceType as t,TransferSignatureReason as n}from"../../../../constants.js";import{ErrorCode as r,ErrorReason as i,InvalidParamsError as a}from"../../../../errors.js";import{caip2ToEip155ChainId as o}from"../../../../utils/caip.js";import{getEvmClientForChain as s}from"../../../_utils.js";import{isBech32AddressInNetwork as c}from"../../../../utils/bitcoin-address.js";import{LOMBARD_PARTNER_ID as l}from"../../constants.js";import{selectUtxos as u}from"../../_utils/utxo.js";import{isAddress as d}from"viem";import{SANCTIONED_ADDRESS as f,generateDepositBtcAddress as p,getAddressConfirmationMessage as m,getDepositBtcAddress as h}from"@lombard.finance/sdk";function g({bitcoinFunctions:g,btcSigner:_,config:v,evmSigner:y}){return async({quote:b,onStepChange:x})=>{if(!c(b.fromAddress,v.environment===e.PROD))throw new a(i.INCORRECT_ADDRESS_PROVIDED,`Invalid fromAddress was provided. Make sure it is a BTC address from correct environment.`);if(!d(b.toAddress))throw new a(i.INCORRECT_ADDRESS_PROVIDED,`Invalid toAddress was provided. Must be a valid EVM address.`);let S=b.toAddress,C=o(b.targetChain.chainId),w;try{w=await h({address:S,chainId:C,partnerId:l,env:v.env,token:v.targetToken})}catch{}let T=w?1:2,E={currentSignature:1,currentSignatureReason:w?n.TokensTransfer:n.AddressOwnership,quote:b,requiredSignatures:T};if(!w){let e=s({chain:b.targetChain}),t=m(C),r=await y.signMessage({message:t,address:S,chainId:C},t=>e.sendRawTransaction({serializedTransaction:t}),E);if(E.currentSignature=2,E.currentSignatureReason=n.TokensTransfer,w=await p({address:S,chainId:C,env:v.env,partnerId:l,signature:r,token:v.targetToken}),w===f)throw new a(i.ADDRESS_IS_BLOCKED,w)}if(!c(w,v.environment===e.PROD))throw new a(i.INCORRECT_ADDRESS_PROVIDED,`Generated deposit address is invalid`);let{low:D,high:O}=await g.getFeeRates(),k=v.environment===e.PROD?O:D,{utxos:A}=await g.getUtxoBalance(b.fromAddress,!1),{inputs:j,outputs:M}=await u(w,b.fromAddress,b.amountIn,k,A,g);if(!j||!M)throw new a(i.INVALID_PARAMS,`Unable to create transaction. UTXO selection failed.`);let N=Date.now();x?.(E);let P;try{P=await s({chain:b.targetChain}).getBlockNumber()}catch{return{amountIn:b.amountIn,amountOut:b.amountOut,environment:v.environment,errorCode:r.UNKNOWN,errorReason:`Unable to fetch target chain block number`,failedAtMs:Date.now(),fees:b.fees,fromAddress:b.fromAddress,id:b.id,partnerFeeBps:b.partnerFeeBps,sourceAsset:b.assetIn,sourceChain:b.sourceChain,targetAsset:b.assetOut,targetChain:b.targetChain,toAddress:b.toAddress,status:`failed`,type:t.LOMBARD_BTC_TO_BTCB}}let F=await _.sign({inputs:j,outputs:M},g.issueRawTx,E);return{amountIn:b.amountIn,amountOut:b.amountOut,environment:v.environment,fees:b.fees,fromAddress:b.fromAddress,id:b.id,partnerFeeBps:b.partnerFeeBps,source:{confirmationCount:0,requiredConfirmationCount:6,startedAtMs:N,txHash:F,targetStartBlockNumber:P},sourceAsset:b.assetIn,sourceChain:b.sourceChain,status:`source-pending`,targetAsset:b.assetOut,targetChain:b.targetChain,toAddress:b.toAddress,type:t.LOMBARD_BTC_TO_BTCB}}}export{g as transferAssetFactory};
|
|
2
2
|
//# sourceMappingURL=transfer-asset.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transfer-asset.js","names":[],"sources":["../../../../../src/transfer-service/lombard/btc-to-btcb/_handlers/transfer-asset.ts"],"sourcesContent":["import { isAddress, type Mutable } from 'viem';\nimport { Environment, ServiceType, TransferSignatureReason } from '../../../../constants';\nimport { ErrorCode, ErrorReason, InvalidParamsError } from '../../../../errors';\nimport { caip2ToEip155ChainId } from '../../../../utils/caip';\nimport type { BitcoinFunctions } from '../../../../types/bitcoin';\nimport type { TransferService } from '../../../../types/service';\nimport type { BtcSigner, EvmSignerWithMessage } from '../../../../types/signer';\nimport type { FailedTransfer, SourcePendingTransfer, TransferStepDetails } from '../../../../types/transfer';\nimport { isBech32AddressInNetwork } from '../../../../utils/bitcoin-address';\nimport type { BtcToBtcbConfig } from '../../types';\nimport {\n generateDepositBtcAddress,\n getDepositBtcAddress,\n SANCTIONED_ADDRESS,\n getAddressConfirmationMessage,\n type ChainId,\n} from '@lombard.finance/sdk';\nimport { BTC_CONFIRMATION_COUNT, LOMBARD_PARTNER_ID } from '../../constants';\nimport { getEvmClientForChain } from '../../../_utils';\nimport { selectUtxos } from '../../_utils/utxo';\n\nexport interface TransferAssetFactoryOptions {\n bitcoinFunctions: BitcoinFunctions;\n btcSigner: BtcSigner;\n config: BtcToBtcbConfig;\n evmSigner: EvmSignerWithMessage;\n}\n\nexport function transferAssetFactory({\n bitcoinFunctions,\n btcSigner,\n config,\n evmSigner,\n}: TransferAssetFactoryOptions): TransferService['transferAsset'] {\n return async ({ quote, onStepChange }) => {\n if (!isBech32AddressInNetwork(quote.fromAddress, config.environment === Environment.PROD)) {\n throw new InvalidParamsError(\n ErrorReason.INCORRECT_ADDRESS_PROVIDED,\n 'Invalid fromAddress was provided. Make sure it is a BTC address from correct environment.',\n );\n }\n\n if (!isAddress(quote.toAddress)) {\n throw new InvalidParamsError(\n ErrorReason.INCORRECT_ADDRESS_PROVIDED,\n 'Invalid toAddress was provided. Must be a valid EVM address.',\n );\n }\n\n const targetAddress = quote.toAddress;\n const targetChainId: number = caip2ToEip155ChainId(quote.targetChain.chainId);\n\n let btcDepositAddress: string | undefined;\n\n try {\n btcDepositAddress = await getDepositBtcAddress({\n address: targetAddress,\n chainId: targetChainId as ChainId,\n partnerId: LOMBARD_PARTNER_ID,\n env: config.env,\n token: config.targetToken,\n });\n } catch {\n // Deposit address not found. Generate a new one.\n }\n\n const requiredSignatures: number = btcDepositAddress ? 1 : 2;\n const transferStep: Mutable<TransferStepDetails> = {\n currentSignature: 1,\n currentSignatureReason: btcDepositAddress\n ? TransferSignatureReason.TokensTransfer\n : TransferSignatureReason.AddressOwnership,\n quote,\n requiredSignatures,\n };\n\n // Generate a new deposit address if not existing\n if (!btcDepositAddress) {\n const client = getEvmClientForChain({ chain: quote.targetChain });\n\n // This message MUST match whatever Lombard is using to verify the provided signature.\n const message = getAddressConfirmationMessage(targetChainId);\n const signature = await evmSigner.signMessage(\n { message, address: targetAddress, chainId: targetChainId },\n (signedTxHash) => client.sendRawTransaction({ serializedTransaction: signedTxHash }),\n transferStep,\n );\n\n // Update step for the next signature (tokens transfer)\n transferStep.currentSignature = 2;\n transferStep.currentSignatureReason = TransferSignatureReason.TokensTransfer;\n\n btcDepositAddress = await generateDepositBtcAddress({\n address: targetAddress,\n chainId: targetChainId as ChainId,\n env: config.env,\n partnerId: LOMBARD_PARTNER_ID,\n signature,\n token: config.targetToken,\n });\n\n if (btcDepositAddress === SANCTIONED_ADDRESS) {\n throw new InvalidParamsError(ErrorReason.ADDRESS_IS_BLOCKED, btcDepositAddress);\n }\n }\n\n if (!isBech32AddressInNetwork(btcDepositAddress, config.environment === Environment.PROD)) {\n throw new InvalidParamsError(ErrorReason.INCORRECT_ADDRESS_PROVIDED, 'Generated deposit address is invalid');\n }\n\n const { low, high } = await bitcoinFunctions.getFeeRates();\n const feeRate = config.environment === Environment.PROD ? high : low;\n const { utxos } = await bitcoinFunctions.getUtxoBalance(quote.fromAddress, false);\n\n const { inputs, outputs } = await selectUtxos(\n btcDepositAddress,\n quote.fromAddress,\n quote.amountIn,\n feeRate,\n utxos,\n bitcoinFunctions,\n );\n\n if (!inputs || !outputs) {\n throw new InvalidParamsError(ErrorReason.INVALID_PARAMS, 'Unable to create transaction. UTXO selection failed.');\n }\n\n const startedAtMs = Date.now();\n\n onStepChange?.(transferStep);\n\n let targetStartBlockNumber: bigint;\n\n try {\n const targetClient = getEvmClientForChain({ chain: quote.targetChain });\n targetStartBlockNumber = await targetClient.getBlockNumber();\n } catch {\n // Unable to get the target block number. Can't track from this point.\n\n return {\n amountIn: quote.amountIn,\n amountOut: quote.amountOut,\n environment: config.environment,\n errorCode: ErrorCode.UNKNOWN,\n errorReason: 'Unable to fetch target chain block number',\n failedAtMs: Date.now(),\n fees: quote.fees,\n fromAddress: quote.fromAddress,\n id: quote.id,\n partnerFeeBps: quote.partnerFeeBps,\n sourceAsset: quote.assetIn,\n sourceChain: quote.sourceChain,\n targetAsset: quote.assetOut,\n targetChain: quote.targetChain,\n toAddress: quote.toAddress,\n status: 'failed',\n type: ServiceType.LOMBARD_BTC_TO_BTCB,\n } satisfies FailedTransfer;\n }\n\n const txHash = await btcSigner.sign({ inputs, outputs }, bitcoinFunctions.issueRawTx, transferStep);\n\n return {\n amountIn: quote.amountIn,\n amountOut: quote.amountOut,\n environment: config.environment,\n fees: quote.fees,\n fromAddress: quote.fromAddress,\n id: quote.id,\n partnerFeeBps: quote.partnerFeeBps,\n source: {\n confirmationCount: 0,\n requiredConfirmationCount: BTC_CONFIRMATION_COUNT,\n startedAtMs,\n txHash,\n targetStartBlockNumber,\n },\n sourceAsset: quote.assetIn,\n sourceChain: quote.sourceChain,\n status: 'source-pending',\n targetAsset: quote.assetOut,\n targetChain: quote.targetChain,\n toAddress: quote.toAddress,\n type: ServiceType.LOMBARD_BTC_TO_BTCB,\n } satisfies SourcePendingTransfer;\n };\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"transfer-asset.js","names":[],"sources":["../../../../../src/transfer-service/lombard/btc-to-btcb/_handlers/transfer-asset.ts"],"sourcesContent":["import { isAddress, type Mutable } from 'viem';\nimport { Environment, ServiceType, TransferSignatureReason } from '../../../../constants';\nimport { ErrorCode, ErrorReason, InvalidParamsError } from '../../../../errors';\nimport { caip2ToEip155ChainId } from '../../../../utils/caip';\nimport type { BitcoinFunctions } from '../../../../types/bitcoin';\nimport type { TransferService } from '../../../../types/service';\nimport type { BtcSigner, EvmSignerWithMessage } from '../../../../types/signer';\nimport type { FailedTransfer, SourcePendingTransfer, TransferStepDetails } from '../../../../types/transfer';\nimport { isBech32AddressInNetwork } from '../../../../utils/bitcoin-address';\nimport type { BtcToBtcbConfig } from '../../types';\nimport {\n generateDepositBtcAddress,\n getDepositBtcAddress,\n SANCTIONED_ADDRESS,\n getAddressConfirmationMessage,\n type ChainId,\n} from '@lombard.finance/sdk';\nimport { BTC_CONFIRMATION_COUNT, LOMBARD_PARTNER_ID } from '../../constants';\nimport { getEvmClientForChain } from '../../../_utils';\nimport { selectUtxos } from '../../_utils/utxo';\n\nexport interface TransferAssetFactoryOptions {\n bitcoinFunctions: BitcoinFunctions;\n btcSigner: BtcSigner;\n config: BtcToBtcbConfig;\n evmSigner: EvmSignerWithMessage;\n}\n\nexport function transferAssetFactory({\n bitcoinFunctions,\n btcSigner,\n config,\n evmSigner,\n}: TransferAssetFactoryOptions): TransferService['transferAsset'] {\n return async ({ quote, onStepChange }) => {\n if (!isBech32AddressInNetwork(quote.fromAddress, config.environment === Environment.PROD)) {\n throw new InvalidParamsError(\n ErrorReason.INCORRECT_ADDRESS_PROVIDED,\n 'Invalid fromAddress was provided. Make sure it is a BTC address from correct environment.',\n );\n }\n\n if (!isAddress(quote.toAddress)) {\n throw new InvalidParamsError(\n ErrorReason.INCORRECT_ADDRESS_PROVIDED,\n 'Invalid toAddress was provided. Must be a valid EVM address.',\n );\n }\n\n const targetAddress = quote.toAddress;\n const targetChainId: number = caip2ToEip155ChainId(quote.targetChain.chainId);\n\n let btcDepositAddress: string | undefined;\n\n try {\n btcDepositAddress = await getDepositBtcAddress({\n address: targetAddress,\n chainId: targetChainId as ChainId,\n partnerId: LOMBARD_PARTNER_ID,\n env: config.env,\n token: config.targetToken,\n });\n } catch {\n // Deposit address not found. Generate a new one.\n }\n\n const requiredSignatures: number = btcDepositAddress ? 1 : 2;\n const transferStep: Mutable<TransferStepDetails> = {\n currentSignature: 1,\n currentSignatureReason: btcDepositAddress\n ? TransferSignatureReason.TokensTransfer\n : TransferSignatureReason.AddressOwnership,\n quote,\n requiredSignatures,\n };\n\n // Generate a new deposit address if not existing\n if (!btcDepositAddress) {\n const client = getEvmClientForChain({ chain: quote.targetChain });\n\n // This message MUST match whatever Lombard is using to verify the provided signature.\n const message = getAddressConfirmationMessage(targetChainId);\n const signature = await evmSigner.signMessage(\n { message, address: targetAddress, chainId: targetChainId },\n (signedTxHash) => client.sendRawTransaction({ serializedTransaction: signedTxHash }),\n transferStep,\n );\n\n // Update step for the next signature (tokens transfer)\n transferStep.currentSignature = 2;\n transferStep.currentSignatureReason = TransferSignatureReason.TokensTransfer;\n\n btcDepositAddress = await generateDepositBtcAddress({\n address: targetAddress,\n chainId: targetChainId as ChainId,\n env: config.env,\n partnerId: LOMBARD_PARTNER_ID,\n signature,\n token: config.targetToken,\n });\n\n if (btcDepositAddress === SANCTIONED_ADDRESS) {\n throw new InvalidParamsError(ErrorReason.ADDRESS_IS_BLOCKED, btcDepositAddress);\n }\n }\n\n if (!isBech32AddressInNetwork(btcDepositAddress, config.environment === Environment.PROD)) {\n throw new InvalidParamsError(ErrorReason.INCORRECT_ADDRESS_PROVIDED, 'Generated deposit address is invalid');\n }\n\n const { low, high } = await bitcoinFunctions.getFeeRates();\n const feeRate = config.environment === Environment.PROD ? high : low;\n const { utxos } = await bitcoinFunctions.getUtxoBalance(quote.fromAddress, false);\n\n const { inputs, outputs } = await selectUtxos(\n btcDepositAddress,\n quote.fromAddress,\n quote.amountIn,\n feeRate,\n utxos,\n bitcoinFunctions,\n );\n\n if (!inputs || !outputs) {\n throw new InvalidParamsError(ErrorReason.INVALID_PARAMS, 'Unable to create transaction. UTXO selection failed.');\n }\n\n const startedAtMs = Date.now();\n\n onStepChange?.(transferStep);\n\n let targetStartBlockNumber: bigint;\n\n try {\n const targetClient = getEvmClientForChain({ chain: quote.targetChain });\n targetStartBlockNumber = await targetClient.getBlockNumber();\n } catch {\n // Unable to get the target block number. Can't track from this point.\n\n return {\n amountIn: quote.amountIn,\n amountOut: quote.amountOut,\n environment: config.environment,\n errorCode: ErrorCode.UNKNOWN,\n errorReason: 'Unable to fetch target chain block number',\n failedAtMs: Date.now(),\n fees: quote.fees,\n fromAddress: quote.fromAddress,\n id: quote.id,\n partnerFeeBps: quote.partnerFeeBps,\n sourceAsset: quote.assetIn,\n sourceChain: quote.sourceChain,\n targetAsset: quote.assetOut,\n targetChain: quote.targetChain,\n toAddress: quote.toAddress,\n status: 'failed',\n type: ServiceType.LOMBARD_BTC_TO_BTCB,\n } satisfies FailedTransfer;\n }\n\n const txHash = await btcSigner.sign({ inputs, outputs }, bitcoinFunctions.issueRawTx, transferStep);\n\n return {\n amountIn: quote.amountIn,\n amountOut: quote.amountOut,\n environment: config.environment,\n fees: quote.fees,\n fromAddress: quote.fromAddress,\n id: quote.id,\n partnerFeeBps: quote.partnerFeeBps,\n source: {\n confirmationCount: 0,\n requiredConfirmationCount: BTC_CONFIRMATION_COUNT,\n startedAtMs,\n txHash,\n targetStartBlockNumber,\n },\n sourceAsset: quote.assetIn,\n sourceChain: quote.sourceChain,\n status: 'source-pending',\n targetAsset: quote.assetOut,\n targetChain: quote.targetChain,\n toAddress: quote.toAddress,\n type: ServiceType.LOMBARD_BTC_TO_BTCB,\n } satisfies SourcePendingTransfer;\n };\n}\n"],"mappings":"6qBA4BA,SAAgB,EAAqB,CACnC,mBACA,YACA,SACA,aACgE,CAChE,OAAO,MAAO,CAAE,QAAO,kBAAmB,CACxC,GAAI,CAAC,EAAyB,EAAM,YAAa,EAAO,cAAgB,EAAY,KAAK,CACvF,MAAM,IAAI,EACR,EAAY,2BACZ,4FACD,CAGH,GAAI,CAAC,EAAU,EAAM,UAAU,CAC7B,MAAM,IAAI,EACR,EAAY,2BACZ,+DACD,CAGH,IAAM,EAAgB,EAAM,UACtB,EAAwB,EAAqB,EAAM,YAAY,QAAQ,CAEzE,EAEJ,GAAI,CACF,EAAoB,MAAM,EAAqB,CAC7C,QAAS,EACT,QAAS,EACT,UAAW,EACX,IAAK,EAAO,IACZ,MAAO,EAAO,YACf,CAAC,MACI,EAIR,IAAM,EAA6B,EAAoB,EAAI,EACrD,EAA6C,CACjD,iBAAkB,EAClB,uBAAwB,EACpB,EAAwB,eACxB,EAAwB,iBAC5B,QACA,qBACD,CAGD,GAAI,CAAC,EAAmB,CACtB,IAAM,EAAS,EAAqB,CAAE,MAAO,EAAM,YAAa,CAAC,CAG3D,EAAU,EAA8B,EAAc,CACtD,EAAY,MAAM,EAAU,YAChC,CAAE,UAAS,QAAS,EAAe,QAAS,EAAe,CAC1D,GAAiB,EAAO,mBAAmB,CAAE,sBAAuB,EAAc,CAAC,CACpF,EACD,CAeD,GAZA,EAAa,iBAAmB,EAChC,EAAa,uBAAyB,EAAwB,eAE9D,EAAoB,MAAM,EAA0B,CAClD,QAAS,EACT,QAAS,EACT,IAAK,EAAO,IACZ,UAAW,EACX,YACA,MAAO,EAAO,YACf,CAAC,CAEE,IAAsB,EACxB,MAAM,IAAI,EAAmB,EAAY,mBAAoB,EAAkB,CAInF,GAAI,CAAC,EAAyB,EAAmB,EAAO,cAAgB,EAAY,KAAK,CACvF,MAAM,IAAI,EAAmB,EAAY,2BAA4B,uCAAuC,CAG9G,GAAM,CAAE,MAAK,QAAS,MAAM,EAAiB,aAAa,CACpD,EAAU,EAAO,cAAgB,EAAY,KAAO,EAAO,EAC3D,CAAE,SAAU,MAAM,EAAiB,eAAe,EAAM,YAAa,GAAM,CAE3E,CAAE,SAAQ,WAAY,MAAM,EAChC,EACA,EAAM,YACN,EAAM,SACN,EACA,EACA,EACD,CAED,GAAI,CAAC,GAAU,CAAC,EACd,MAAM,IAAI,EAAmB,EAAY,eAAgB,uDAAuD,CAGlH,IAAM,EAAc,KAAK,KAAK,CAE9B,IAAe,EAAa,CAE5B,IAAI,EAEJ,GAAI,CAEF,EAAyB,MADJ,EAAqB,CAAE,MAAO,EAAM,YAAa,CAAC,CAC3B,gBAAgB,MACtD,CAGN,MAAO,CACL,SAAU,EAAM,SAChB,UAAW,EAAM,UACjB,YAAa,EAAO,YACpB,UAAW,EAAU,QACrB,YAAa,4CACb,WAAY,KAAK,KAAK,CACtB,KAAM,EAAM,KACZ,YAAa,EAAM,YACnB,GAAI,EAAM,GACV,cAAe,EAAM,cACrB,YAAa,EAAM,QACnB,YAAa,EAAM,YACnB,YAAa,EAAM,SACnB,YAAa,EAAM,YACnB,UAAW,EAAM,UACjB,OAAQ,SACR,KAAM,EAAY,oBACnB,CAGH,IAAM,EAAS,MAAM,EAAU,KAAK,CAAE,SAAQ,UAAS,CAAE,EAAiB,WAAY,EAAa,CAEnG,MAAO,CACL,SAAU,EAAM,SAChB,UAAW,EAAM,UACjB,YAAa,EAAO,YACpB,KAAM,EAAM,KACZ,YAAa,EAAM,YACnB,GAAI,EAAM,GACV,cAAe,EAAM,cACrB,OAAQ,CACN,kBAAmB,EACnB,0BAAA,EACA,cACA,SACA,yBACD,CACD,YAAa,EAAM,QACnB,YAAa,EAAM,YACnB,OAAQ,iBACR,YAAa,EAAM,SACnB,YAAa,EAAM,YACnB,UAAW,EAAM,UACjB,KAAM,EAAY,oBACnB"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
require(`../../../../_virtual/_rolldown/runtime.cjs`);const e=require(`../../../../errors.cjs`),t=require(`../../../_utils.cjs`),n=require(`../../../_evm-gas.cjs`);let r=require(`viem`);const i=60000n,a=300000n,o=({config:o})=>async({amountIn:s,fromAddress:c,sourceChain:l},u)=>{if(!(0,r.isAddress)(c))throw new e.InvalidParamsError(e.ErrorReason.INVALID_PARAMS,`Invalid fromAddress: ${c}`);let d=t.getEvmClientForChain({chain:l}),f=await d.readContract({address:o.sourceAsset.address,abi:r.erc20Abi,functionName:`allowance`,args:[c,o.adapterAddress]})<s,p=
|
|
1
|
+
require(`../../../../_virtual/_rolldown/runtime.cjs`);const e=require(`../../../../errors.cjs`),t=require(`../../../_utils.cjs`),n=require(`../../../_evm-gas.cjs`);let r=require(`viem`);const i=60000n,a=300000n,o=({config:o})=>async({amountIn:s,fromAddress:c,sourceChain:l},u)=>{if(!(0,r.isAddress)(c))throw new e.InvalidParamsError(e.ErrorReason.INVALID_PARAMS,`Invalid fromAddress: ${c}`);let d=t.getEvmClientForChain({chain:l}),f=await d.readContract({address:o.sourceAsset.address,abi:r.erc20Abi,functionName:`allowance`,args:[c,o.adapterAddress]})<s,p=f?i+a:a,m=await n.estimateEvmFeesPerGas(d,l,u?.overrides?.feeRateTier),h=u?.overrides?.maxFeePerGas??m.maxFeePerGas,g=u?.overrides?.maxPriorityFeePerGas??m.maxPriorityFeePerGas,_=p*h,v=t.applyFeeUnitsBpsMargin(_,u?.feeUnitsMarginBps);return{asset:l.networkToken,totalFee:v,totalFeeWithoutMargin:_,meta:{approvalFee:f?i*h:void 0,maxFeePerGas:h,maxPriorityFeePerGas:g}}};exports.estimateNativeFeeFactory=o;
|
|
2
2
|
//# sourceMappingURL=estimate-native-fee.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"estimate-native-fee.cjs","names":["InvalidParamsError","ErrorReason","getEvmClientForChain","erc20Abi","
|
|
1
|
+
{"version":3,"file":"estimate-native-fee.cjs","names":["InvalidParamsError","ErrorReason","getEvmClientForChain","erc20Abi","estimateEvmFeesPerGas","applyFeeUnitsBpsMargin"],"sources":["../../../../../src/transfer-service/lombard/btcb-to-btc/_handlers/estimate-native-fee.ts"],"sourcesContent":["import { erc20Abi, isAddress } from 'viem';\nimport type { BtcbToBtcConfig } from '../../types';\nimport { ErrorReason, InvalidParamsError } from '../../../../errors';\nimport type { TransferService } from '../../../../types/service';\nimport { applyFeeUnitsBpsMargin, getEvmClientForChain } from '../../../_utils';\nimport { estimateEvmFeesPerGas } from '../../../_evm-gas';\n\n// Hardcoded gas estimates for BTCb redemption on Avalanche.\n// These are approximations used for UI display only - DO NOT use as gasLimit.\n// Based on typical ERC20 approval and AssetRouter.redeemForBtc call costs.\nexport const AVAX_APPROVAL_GAS_ESTIMATE = 60_000n; // Standard ERC20 approval (~55k + buffer)\nexport const AVAX_REDEEM_GAS_ESTIMATE = 300_000n; // AssetRouter.redeemForBtc (~250k + buffer)\n\nexport interface EstimateNativeFeeFactoryOptions {\n config: BtcbToBtcConfig;\n}\n\n/**\n * Estimates gas for BTCb-to-BTC redemption on Avalanche.\n *\n * The redemption consists of up to two transactions:\n * 1. Token spend approval to the adapter contract (if needed)\n * 2. Redeem call via the AssetRouter contract\n *\n * Since the redeem needs the approval to be complete, we can't call estimateGas()\n * on the actual contract. Instead, we use hardcoded estimates.\n */\nexport const estimateNativeFeeFactory = ({\n config,\n}: EstimateNativeFeeFactoryOptions): TransferService['estimateNativeFee'] => {\n return async ({ amountIn, fromAddress, sourceChain }, options) => {\n if (!isAddress(fromAddress)) {\n throw new InvalidParamsError(ErrorReason.INVALID_PARAMS, `Invalid fromAddress: ${fromAddress}`);\n }\n\n const client = getEvmClientForChain({ chain: sourceChain });\n\n // Check if approval is already granted to the adapter\n const allowance = await client.readContract({\n address: config.sourceAsset.address,\n abi: erc20Abi,\n functionName: 'allowance',\n args: [fromAddress, config.adapterAddress],\n });\n\n const needsApproval = allowance < amountIn;\n\n const totalGas = needsApproval ? AVAX_APPROVAL_GAS_ESTIMATE + AVAX_REDEEM_GAS_ESTIMATE : AVAX_REDEEM_GAS_ESTIMATE;\n\n const fees = await estimateEvmFeesPerGas(client, sourceChain, options?.overrides?.feeRateTier);\n\n const maxFeePerGas = options?.overrides?.maxFeePerGas ?? fees.maxFeePerGas;\n const maxPriorityFeePerGas = options?.overrides?.maxPriorityFeePerGas ?? fees.maxPriorityFeePerGas;\n\n const totalFeeWithoutMargin = totalGas * maxFeePerGas;\n const totalFee = applyFeeUnitsBpsMargin(totalFeeWithoutMargin, options?.feeUnitsMarginBps);\n\n return {\n asset: sourceChain.networkToken,\n totalFee,\n totalFeeWithoutMargin,\n meta: {\n approvalFee: needsApproval ? AVAX_APPROVAL_GAS_ESTIMATE * maxFeePerGas : undefined,\n maxFeePerGas,\n maxPriorityFeePerGas,\n },\n };\n };\n};\n"],"mappings":"0LAUA,MAAa,EAA6B,OAC7B,EAA2B,QAgB3B,GAA4B,CACvC,YAEO,MAAO,CAAE,WAAU,cAAa,eAAe,IAAY,CAChE,GAAI,EAAA,EAAA,EAAA,WAAW,EAAY,CACzB,MAAM,IAAIA,EAAAA,mBAAmBC,EAAAA,YAAY,eAAgB,wBAAwB,IAAc,CAGjG,IAAM,EAASC,EAAAA,qBAAqB,CAAE,MAAO,EAAa,CAAC,CAUrD,EAPY,MAAM,EAAO,aAAa,CAC1C,QAAS,EAAO,YAAY,QAC5B,IAAKC,EAAAA,SACL,aAAc,YACd,KAAM,CAAC,EAAa,EAAO,eAAe,CAC3C,CAAC,CAEgC,EAE5B,EAAW,EAAgB,EAA6B,EAA2B,EAEnF,EAAO,MAAMC,EAAAA,sBAAsB,EAAQ,EAAa,GAAS,WAAW,YAAY,CAExF,EAAe,GAAS,WAAW,cAAgB,EAAK,aACxD,EAAuB,GAAS,WAAW,sBAAwB,EAAK,qBAExE,EAAwB,EAAW,EACnC,EAAWC,EAAAA,uBAAuB,EAAuB,GAAS,kBAAkB,CAE1F,MAAO,CACL,MAAO,EAAY,aACnB,WACA,wBACA,KAAM,CACJ,YAAa,EAAgB,EAA6B,EAAe,IAAA,GACzE,eACA,uBACD,CACF"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{ErrorReason as e,InvalidParamsError as t}from"../../../../errors.js";import{applyFeeUnitsBpsMargin as n,getEvmClientForChain as r}from"../../../_utils.js";import{estimateEvmFeesPerGas as i}from"../../../_evm-gas.js";import{erc20Abi as a,isAddress as o}from"viem";const s=60000n,c=300000n,l=({config:l})=>async({amountIn:u,fromAddress:d,sourceChain:f},p)=>{if(!o(d))throw new t(e.INVALID_PARAMS,`Invalid fromAddress: ${d}`);let m=r({chain:f}),h=await m.readContract({address:l.sourceAsset.address,abi:a,functionName:`allowance`,args:[d,l.adapterAddress]})<u,g=
|
|
1
|
+
import{ErrorReason as e,InvalidParamsError as t}from"../../../../errors.js";import{applyFeeUnitsBpsMargin as n,getEvmClientForChain as r}from"../../../_utils.js";import{estimateEvmFeesPerGas as i}from"../../../_evm-gas.js";import{erc20Abi as a,isAddress as o}from"viem";const s=60000n,c=300000n,l=({config:l})=>async({amountIn:u,fromAddress:d,sourceChain:f},p)=>{if(!o(d))throw new t(e.INVALID_PARAMS,`Invalid fromAddress: ${d}`);let m=r({chain:f}),h=await m.readContract({address:l.sourceAsset.address,abi:a,functionName:`allowance`,args:[d,l.adapterAddress]})<u,g=h?s+c:c,_=await i(m,f,p?.overrides?.feeRateTier),v=p?.overrides?.maxFeePerGas??_.maxFeePerGas,y=p?.overrides?.maxPriorityFeePerGas??_.maxPriorityFeePerGas,b=g*v,x=n(b,p?.feeUnitsMarginBps);return{asset:f.networkToken,totalFee:x,totalFeeWithoutMargin:b,meta:{approvalFee:h?s*v:void 0,maxFeePerGas:v,maxPriorityFeePerGas:y}}};export{l as estimateNativeFeeFactory};
|
|
2
2
|
//# sourceMappingURL=estimate-native-fee.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"estimate-native-fee.js","names":[],"sources":["../../../../../src/transfer-service/lombard/btcb-to-btc/_handlers/estimate-native-fee.ts"],"sourcesContent":["import { erc20Abi, isAddress } from 'viem';\nimport type { BtcbToBtcConfig } from '../../types';\nimport { ErrorReason, InvalidParamsError } from '../../../../errors';\nimport type { TransferService } from '../../../../types/service';\nimport { applyFeeUnitsBpsMargin, getEvmClientForChain } from '../../../_utils';\nimport { estimateEvmFeesPerGas } from '../../../_evm-gas';\n\n// Hardcoded gas estimates for BTCb redemption on Avalanche.\n// These are approximations used for UI display only - DO NOT use as gasLimit.\n// Based on typical ERC20 approval and AssetRouter.redeemForBtc call costs.\nexport const AVAX_APPROVAL_GAS_ESTIMATE = 60_000n; // Standard ERC20 approval (~55k + buffer)\nexport const AVAX_REDEEM_GAS_ESTIMATE = 300_000n; // AssetRouter.redeemForBtc (~250k + buffer)\n\nexport interface EstimateNativeFeeFactoryOptions {\n config: BtcbToBtcConfig;\n}\n\n/**\n * Estimates gas for BTCb-to-BTC redemption on Avalanche.\n *\n * The redemption consists of up to two transactions:\n * 1. Token spend approval to the adapter contract (if needed)\n * 2. Redeem call via the AssetRouter contract\n *\n * Since the redeem needs the approval to be complete, we can't call estimateGas()\n * on the actual contract. Instead, we use hardcoded estimates.\n */\nexport const estimateNativeFeeFactory = ({\n config,\n}: EstimateNativeFeeFactoryOptions): TransferService['estimateNativeFee'] => {\n return async ({ amountIn, fromAddress, sourceChain }, options) => {\n if (!isAddress(fromAddress)) {\n throw new InvalidParamsError(ErrorReason.INVALID_PARAMS, `Invalid fromAddress: ${fromAddress}`);\n }\n\n const client = getEvmClientForChain({ chain: sourceChain });\n\n // Check if approval is already granted to the adapter\n const allowance = await client.readContract({\n address: config.sourceAsset.address,\n abi: erc20Abi,\n functionName: 'allowance',\n args: [fromAddress, config.adapterAddress],\n });\n\n const needsApproval = allowance < amountIn;\n\n const totalGas = needsApproval ? AVAX_APPROVAL_GAS_ESTIMATE + AVAX_REDEEM_GAS_ESTIMATE : AVAX_REDEEM_GAS_ESTIMATE;\n\n const
|
|
1
|
+
{"version":3,"file":"estimate-native-fee.js","names":[],"sources":["../../../../../src/transfer-service/lombard/btcb-to-btc/_handlers/estimate-native-fee.ts"],"sourcesContent":["import { erc20Abi, isAddress } from 'viem';\nimport type { BtcbToBtcConfig } from '../../types';\nimport { ErrorReason, InvalidParamsError } from '../../../../errors';\nimport type { TransferService } from '../../../../types/service';\nimport { applyFeeUnitsBpsMargin, getEvmClientForChain } from '../../../_utils';\nimport { estimateEvmFeesPerGas } from '../../../_evm-gas';\n\n// Hardcoded gas estimates for BTCb redemption on Avalanche.\n// These are approximations used for UI display only - DO NOT use as gasLimit.\n// Based on typical ERC20 approval and AssetRouter.redeemForBtc call costs.\nexport const AVAX_APPROVAL_GAS_ESTIMATE = 60_000n; // Standard ERC20 approval (~55k + buffer)\nexport const AVAX_REDEEM_GAS_ESTIMATE = 300_000n; // AssetRouter.redeemForBtc (~250k + buffer)\n\nexport interface EstimateNativeFeeFactoryOptions {\n config: BtcbToBtcConfig;\n}\n\n/**\n * Estimates gas for BTCb-to-BTC redemption on Avalanche.\n *\n * The redemption consists of up to two transactions:\n * 1. Token spend approval to the adapter contract (if needed)\n * 2. Redeem call via the AssetRouter contract\n *\n * Since the redeem needs the approval to be complete, we can't call estimateGas()\n * on the actual contract. Instead, we use hardcoded estimates.\n */\nexport const estimateNativeFeeFactory = ({\n config,\n}: EstimateNativeFeeFactoryOptions): TransferService['estimateNativeFee'] => {\n return async ({ amountIn, fromAddress, sourceChain }, options) => {\n if (!isAddress(fromAddress)) {\n throw new InvalidParamsError(ErrorReason.INVALID_PARAMS, `Invalid fromAddress: ${fromAddress}`);\n }\n\n const client = getEvmClientForChain({ chain: sourceChain });\n\n // Check if approval is already granted to the adapter\n const allowance = await client.readContract({\n address: config.sourceAsset.address,\n abi: erc20Abi,\n functionName: 'allowance',\n args: [fromAddress, config.adapterAddress],\n });\n\n const needsApproval = allowance < amountIn;\n\n const totalGas = needsApproval ? AVAX_APPROVAL_GAS_ESTIMATE + AVAX_REDEEM_GAS_ESTIMATE : AVAX_REDEEM_GAS_ESTIMATE;\n\n const fees = await estimateEvmFeesPerGas(client, sourceChain, options?.overrides?.feeRateTier);\n\n const maxFeePerGas = options?.overrides?.maxFeePerGas ?? fees.maxFeePerGas;\n const maxPriorityFeePerGas = options?.overrides?.maxPriorityFeePerGas ?? fees.maxPriorityFeePerGas;\n\n const totalFeeWithoutMargin = totalGas * maxFeePerGas;\n const totalFee = applyFeeUnitsBpsMargin(totalFeeWithoutMargin, options?.feeUnitsMarginBps);\n\n return {\n asset: sourceChain.networkToken,\n totalFee,\n totalFeeWithoutMargin,\n meta: {\n approvalFee: needsApproval ? AVAX_APPROVAL_GAS_ESTIMATE * maxFeePerGas : undefined,\n maxFeePerGas,\n maxPriorityFeePerGas,\n },\n };\n };\n};\n"],"mappings":"8QAUA,MAAa,EAA6B,OAC7B,EAA2B,QAgB3B,GAA4B,CACvC,YAEO,MAAO,CAAE,WAAU,cAAa,eAAe,IAAY,CAChE,GAAI,CAAC,EAAU,EAAY,CACzB,MAAM,IAAI,EAAmB,EAAY,eAAgB,wBAAwB,IAAc,CAGjG,IAAM,EAAS,EAAqB,CAAE,MAAO,EAAa,CAAC,CAUrD,EAPY,MAAM,EAAO,aAAa,CAC1C,QAAS,EAAO,YAAY,QAC5B,IAAK,EACL,aAAc,YACd,KAAM,CAAC,EAAa,EAAO,eAAe,CAC3C,CAAC,CAEgC,EAE5B,EAAW,EAAgB,EAA6B,EAA2B,EAEnF,EAAO,MAAM,EAAsB,EAAQ,EAAa,GAAS,WAAW,YAAY,CAExF,EAAe,GAAS,WAAW,cAAgB,EAAK,aACxD,EAAuB,GAAS,WAAW,sBAAwB,EAAK,qBAExE,EAAwB,EAAW,EACnC,EAAW,EAAuB,EAAuB,GAAS,kBAAkB,CAE1F,MAAO,CACL,MAAO,EAAY,aACnB,WACA,wBACA,KAAM,CACJ,YAAa,EAAgB,EAA6B,EAAe,IAAA,GACzE,eACA,uBACD,CACF"}
|
|
@@ -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/bitcoin-address.cjs`)
|
|
1
|
+
require(`../../../../_virtual/_rolldown/runtime.cjs`);const e=require(`../../../../constants.cjs`),t=require(`../../../../errors.cjs`),n=require(`../../../../utils/caip.cjs`),r=require(`../../../../utils/bitcoin-address.cjs`);let i=require(`viem`),a=require(`@lombard.finance/sdk`);function o({bitcoinFunctions:o,config:s,evmSigner:c}){return async({quote:l})=>{if(!(0,i.isAddress)(l.fromAddress))throw new t.InvalidParamsError(t.ErrorReason.INCORRECT_ADDRESS_PROVIDED,`Invalid fromAddress was provided. Must be a valid EVM address.`);if(!r.isBech32AddressInNetwork(l.toAddress,s.environment===e.Environment.PROD))throw new t.InvalidParamsError(t.ErrorReason.INCORRECT_ADDRESS_PROVIDED,`Invalid toAddress was provided. Make sure it is a BTC address from correct environment.`);let u=Date.now(),d;try{d=BigInt(await o.getChainHeight())}catch{return{amountIn:l.amountIn,amountOut:l.amountOut,environment:s.environment,errorCode:t.ErrorCode.UNKNOWN,errorReason:`Unable to fetch target chain height`,failedAtMs:Date.now(),fees:l.fees,fromAddress:l.fromAddress,id:l.id,partnerFeeBps:l.partnerFeeBps,sourceAsset:l.assetIn,sourceChain:l.sourceChain,status:`failed`,targetAsset:l.assetOut,targetChain:l.targetChain,toAddress:l.toAddress,type:e.ServiceType.LOMBARD_BTCB_TO_BTC}}let f=await(0,a.redeemToken)({account:l.fromAddress,btcAddress:l.toAddress,amount:(0,a.fromBaseDenomination)(l.amountIn.toString(),s.sourceAsset.decimals),chainId:s.sourceChainId,signer:{sign:async(t,r)=>c.sign({...t,chainId:t.chainId??n.caip2ToEip155HexChainId(s.sourceChain)},r,{currentSignature:1,currentSignatureReason:e.TransferSignatureReason.TokensTransfer,quote:l,requiredSignatures:1})},tokenIn:a.Token.BTCb,tokenOut:void 0,env:s.env});return{amountIn:l.amountIn,amountOut:l.amountOut,environment:s.environment,fees:l.fees,fromAddress:l.fromAddress,id:l.id,partnerFeeBps:l.partnerFeeBps,source:{confirmationCount:0,requiredConfirmationCount:1,startedAtMs:u,targetStartBlockNumber:d,txHash:f},sourceAsset:l.assetIn,sourceChain:l.sourceChain,status:`source-pending`,targetAsset:l.assetOut,targetChain:l.targetChain,toAddress:l.toAddress,type:e.ServiceType.LOMBARD_BTCB_TO_BTC}}}exports.transferAssetFactory=o;
|
|
2
2
|
//# sourceMappingURL=transfer-asset.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transfer-asset.cjs","names":["InvalidParamsError","ErrorReason","isBech32AddressInNetwork","Environment","ErrorCode","ServiceType","caip2ToEip155HexChainId","TransferSignatureReason","Token"
|
|
1
|
+
{"version":3,"file":"transfer-asset.cjs","names":["InvalidParamsError","ErrorReason","isBech32AddressInNetwork","Environment","ErrorCode","ServiceType","caip2ToEip155HexChainId","TransferSignatureReason","Token"],"sources":["../../../../../src/transfer-service/lombard/btcb-to-btc/_handlers/transfer-asset.ts"],"sourcesContent":["import { isAddress } from 'viem';\nimport { Environment, ServiceType, TransferSignatureReason } from '../../../../constants';\nimport { ErrorCode, ErrorReason, InvalidParamsError } from '../../../../errors';\nimport { caip2ToEip155HexChainId } from '../../../../utils/caip';\nimport type { BitcoinFunctions } from '../../../../types/bitcoin';\nimport type { TransferService } from '../../../../types/service';\nimport type { EvmSignerWithMessage } from '../../../../types/signer';\nimport type { FailedTransfer, SourcePendingTransfer } from '../../../../types/transfer';\nimport type { BtcbToBtcConfig } from '../../types';\nimport { isBech32AddressInNetwork } from '../../../../utils/bitcoin-address';\nimport { fromBaseDenomination, redeemToken, Token } from '@lombard.finance/sdk';\nimport { EVM_CONFIRMATION_COUNT } from '../../constants';\n\nexport interface TransferAssetFactoryOptions {\n bitcoinFunctions: BitcoinFunctions;\n config: BtcbToBtcConfig;\n evmSigner: EvmSignerWithMessage;\n}\n\nexport function transferAssetFactory({\n bitcoinFunctions,\n config,\n evmSigner,\n}: TransferAssetFactoryOptions): TransferService['transferAsset'] {\n return async ({ quote }) => {\n if (!isAddress(quote.fromAddress)) {\n throw new InvalidParamsError(\n ErrorReason.INCORRECT_ADDRESS_PROVIDED,\n 'Invalid fromAddress was provided. Must be a valid EVM address.',\n );\n }\n\n if (!isBech32AddressInNetwork(quote.toAddress, config.environment === Environment.PROD)) {\n throw new InvalidParamsError(\n ErrorReason.INCORRECT_ADDRESS_PROVIDED,\n 'Invalid toAddress was provided. Make sure it is a BTC address from correct environment.',\n );\n }\n\n const startedAtMs = Date.now();\n\n let targetStartBlockNumber: bigint;\n\n try {\n targetStartBlockNumber = BigInt(await bitcoinFunctions.getChainHeight());\n } catch {\n // Unable to get chain height. Not able to track from this point.\n\n return {\n amountIn: quote.amountIn,\n amountOut: quote.amountOut,\n environment: config.environment,\n errorCode: ErrorCode.UNKNOWN,\n errorReason: 'Unable to fetch target chain height',\n failedAtMs: Date.now(),\n fees: quote.fees,\n fromAddress: quote.fromAddress,\n id: quote.id,\n partnerFeeBps: quote.partnerFeeBps,\n sourceAsset: quote.assetIn,\n sourceChain: quote.sourceChain,\n status: 'failed',\n targetAsset: quote.assetOut,\n targetChain: quote.targetChain,\n toAddress: quote.toAddress,\n type: ServiceType.LOMBARD_BTCB_TO_BTC,\n } satisfies FailedTransfer;\n }\n\n const txHash = await redeemToken({\n account: quote.fromAddress,\n btcAddress: quote.toAddress,\n amount: fromBaseDenomination(quote.amountIn.toString(), config.sourceAsset.decimals),\n chainId: config.sourceChainId,\n signer: {\n sign: async (tx, dispatch) => {\n return evmSigner.sign(\n {\n ...tx,\n chainId: tx.chainId ?? caip2ToEip155HexChainId(config.sourceChain),\n },\n dispatch,\n {\n currentSignature: 1,\n currentSignatureReason: TransferSignatureReason.TokensTransfer,\n quote,\n requiredSignatures: 1,\n },\n );\n },\n },\n tokenIn: Token.BTCb,\n tokenOut: undefined,\n env: config.env,\n });\n\n return {\n amountIn: quote.amountIn,\n amountOut: quote.amountOut,\n environment: config.environment,\n fees: quote.fees,\n fromAddress: quote.fromAddress,\n id: quote.id,\n partnerFeeBps: quote.partnerFeeBps,\n source: {\n confirmationCount: 0,\n requiredConfirmationCount: EVM_CONFIRMATION_COUNT,\n startedAtMs,\n targetStartBlockNumber,\n txHash,\n },\n sourceAsset: quote.assetIn,\n sourceChain: quote.sourceChain,\n status: 'source-pending',\n targetAsset: quote.assetOut,\n targetChain: quote.targetChain,\n toAddress: quote.toAddress,\n type: ServiceType.LOMBARD_BTCB_TO_BTC,\n } satisfies SourcePendingTransfer;\n };\n}\n"],"mappings":"0RAmBA,SAAgB,EAAqB,CACnC,mBACA,SACA,aACgE,CAChE,OAAO,MAAO,CAAE,WAAY,CAC1B,GAAI,EAAA,EAAA,EAAA,WAAW,EAAM,YAAY,CAC/B,MAAM,IAAIA,EAAAA,mBACRC,EAAAA,YAAY,2BACZ,iEACD,CAGH,GAAI,CAACC,EAAAA,yBAAyB,EAAM,UAAW,EAAO,cAAgBC,EAAAA,YAAY,KAAK,CACrF,MAAM,IAAIH,EAAAA,mBACRC,EAAAA,YAAY,2BACZ,0FACD,CAGH,IAAM,EAAc,KAAK,KAAK,CAE1B,EAEJ,GAAI,CACF,EAAyB,OAAO,MAAM,EAAiB,gBAAgB,CAAC,MAClE,CAGN,MAAO,CACL,SAAU,EAAM,SAChB,UAAW,EAAM,UACjB,YAAa,EAAO,YACpB,UAAWG,EAAAA,UAAU,QACrB,YAAa,sCACb,WAAY,KAAK,KAAK,CACtB,KAAM,EAAM,KACZ,YAAa,EAAM,YACnB,GAAI,EAAM,GACV,cAAe,EAAM,cACrB,YAAa,EAAM,QACnB,YAAa,EAAM,YACnB,OAAQ,SACR,YAAa,EAAM,SACnB,YAAa,EAAM,YACnB,UAAW,EAAM,UACjB,KAAMC,EAAAA,YAAY,oBACnB,CAGH,IAAM,EAAS,MAAA,EAAA,EAAA,aAAkB,CAC/B,QAAS,EAAM,YACf,WAAY,EAAM,UAClB,QAAA,EAAA,EAAA,sBAA6B,EAAM,SAAS,UAAU,CAAE,EAAO,YAAY,SAAS,CACpF,QAAS,EAAO,cAChB,OAAQ,CACN,KAAM,MAAO,EAAI,IACR,EAAU,KACf,CACE,GAAG,EACH,QAAS,EAAG,SAAWC,EAAAA,wBAAwB,EAAO,YAAY,CACnE,CACD,EACA,CACE,iBAAkB,EAClB,uBAAwBC,EAAAA,wBAAwB,eAChD,QACA,mBAAoB,EACrB,CACF,CAEJ,CACD,QAASC,EAAAA,MAAM,KACf,SAAU,IAAA,GACV,IAAK,EAAO,IACb,CAAC,CAEF,MAAO,CACL,SAAU,EAAM,SAChB,UAAW,EAAM,UACjB,YAAa,EAAO,YACpB,KAAM,EAAM,KACZ,YAAa,EAAM,YACnB,GAAI,EAAM,GACV,cAAe,EAAM,cACrB,OAAQ,CACN,kBAAmB,EACnB,0BAAA,EACA,cACA,yBACA,SACD,CACD,YAAa,EAAM,QACnB,YAAa,EAAM,YACnB,OAAQ,iBACR,YAAa,EAAM,SACnB,YAAa,EAAM,YACnB,UAAW,EAAM,UACjB,KAAMH,EAAAA,YAAY,oBACnB"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{Environment as e,ServiceType as t,TransferSignatureReason as n}from"../../../../constants.js";import{ErrorCode as r,ErrorReason as i,InvalidParamsError as a}from"../../../../errors.js";import{caip2ToEip155HexChainId as o}from"../../../../utils/caip.js";import{isBech32AddressInNetwork as s}from"../../../../utils/bitcoin-address.js";import{
|
|
1
|
+
import{Environment as e,ServiceType as t,TransferSignatureReason as n}from"../../../../constants.js";import{ErrorCode as r,ErrorReason as i,InvalidParamsError as a}from"../../../../errors.js";import{caip2ToEip155HexChainId as o}from"../../../../utils/caip.js";import{isBech32AddressInNetwork as s}from"../../../../utils/bitcoin-address.js";import{isAddress as c}from"viem";import{Token as l,fromBaseDenomination as u,redeemToken as d}from"@lombard.finance/sdk";function f({bitcoinFunctions:f,config:p,evmSigner:m}){return async({quote:h})=>{if(!c(h.fromAddress))throw new a(i.INCORRECT_ADDRESS_PROVIDED,`Invalid fromAddress was provided. Must be a valid EVM address.`);if(!s(h.toAddress,p.environment===e.PROD))throw new a(i.INCORRECT_ADDRESS_PROVIDED,`Invalid toAddress was provided. Make sure it is a BTC address from correct environment.`);let g=Date.now(),_;try{_=BigInt(await f.getChainHeight())}catch{return{amountIn:h.amountIn,amountOut:h.amountOut,environment:p.environment,errorCode:r.UNKNOWN,errorReason:`Unable to fetch target chain height`,failedAtMs:Date.now(),fees:h.fees,fromAddress:h.fromAddress,id:h.id,partnerFeeBps:h.partnerFeeBps,sourceAsset:h.assetIn,sourceChain:h.sourceChain,status:`failed`,targetAsset:h.assetOut,targetChain:h.targetChain,toAddress:h.toAddress,type:t.LOMBARD_BTCB_TO_BTC}}let v=await d({account:h.fromAddress,btcAddress:h.toAddress,amount:u(h.amountIn.toString(),p.sourceAsset.decimals),chainId:p.sourceChainId,signer:{sign:async(e,t)=>m.sign({...e,chainId:e.chainId??o(p.sourceChain)},t,{currentSignature:1,currentSignatureReason:n.TokensTransfer,quote:h,requiredSignatures:1})},tokenIn:l.BTCb,tokenOut:void 0,env:p.env});return{amountIn:h.amountIn,amountOut:h.amountOut,environment:p.environment,fees:h.fees,fromAddress:h.fromAddress,id:h.id,partnerFeeBps:h.partnerFeeBps,source:{confirmationCount:0,requiredConfirmationCount:1,startedAtMs:g,targetStartBlockNumber:_,txHash:v},sourceAsset:h.assetIn,sourceChain:h.sourceChain,status:`source-pending`,targetAsset:h.assetOut,targetChain:h.targetChain,toAddress:h.toAddress,type:t.LOMBARD_BTCB_TO_BTC}}}export{f as transferAssetFactory};
|
|
2
2
|
//# sourceMappingURL=transfer-asset.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transfer-asset.js","names":[],"sources":["../../../../../src/transfer-service/lombard/btcb-to-btc/_handlers/transfer-asset.ts"],"sourcesContent":["import { isAddress } from 'viem';\nimport { Environment, ServiceType, TransferSignatureReason } from '../../../../constants';\nimport { ErrorCode, ErrorReason, InvalidParamsError } from '../../../../errors';\nimport { caip2ToEip155HexChainId } from '../../../../utils/caip';\nimport type { BitcoinFunctions } from '../../../../types/bitcoin';\nimport type { TransferService } from '../../../../types/service';\nimport type { EvmSignerWithMessage } from '../../../../types/signer';\nimport type { FailedTransfer, SourcePendingTransfer } from '../../../../types/transfer';\nimport type { BtcbToBtcConfig } from '../../types';\nimport { isBech32AddressInNetwork } from '../../../../utils/bitcoin-address';\nimport { fromBaseDenomination, redeemToken, Token } from '@lombard.finance/sdk';\nimport { EVM_CONFIRMATION_COUNT } from '../../constants';\n\nexport interface TransferAssetFactoryOptions {\n bitcoinFunctions: BitcoinFunctions;\n config: BtcbToBtcConfig;\n evmSigner: EvmSignerWithMessage;\n}\n\nexport function transferAssetFactory({\n bitcoinFunctions,\n config,\n evmSigner,\n}: TransferAssetFactoryOptions): TransferService['transferAsset'] {\n return async ({ quote }) => {\n if (!isAddress(quote.fromAddress)) {\n throw new InvalidParamsError(\n ErrorReason.INCORRECT_ADDRESS_PROVIDED,\n 'Invalid fromAddress was provided. Must be a valid EVM address.',\n );\n }\n\n if (!isBech32AddressInNetwork(quote.toAddress, config.environment === Environment.PROD)) {\n throw new InvalidParamsError(\n ErrorReason.INCORRECT_ADDRESS_PROVIDED,\n 'Invalid toAddress was provided. Make sure it is a BTC address from correct environment.',\n );\n }\n\n const startedAtMs = Date.now();\n\n let targetStartBlockNumber: bigint;\n\n try {\n targetStartBlockNumber = BigInt(await bitcoinFunctions.getChainHeight());\n } catch {\n // Unable to get chain height. Not able to track from this point.\n\n return {\n amountIn: quote.amountIn,\n amountOut: quote.amountOut,\n environment: config.environment,\n errorCode: ErrorCode.UNKNOWN,\n errorReason: 'Unable to fetch target chain height',\n failedAtMs: Date.now(),\n fees: quote.fees,\n fromAddress: quote.fromAddress,\n id: quote.id,\n partnerFeeBps: quote.partnerFeeBps,\n sourceAsset: quote.assetIn,\n sourceChain: quote.sourceChain,\n status: 'failed',\n targetAsset: quote.assetOut,\n targetChain: quote.targetChain,\n toAddress: quote.toAddress,\n type: ServiceType.LOMBARD_BTCB_TO_BTC,\n } satisfies FailedTransfer;\n }\n\n const txHash = await redeemToken({\n account: quote.fromAddress,\n btcAddress: quote.toAddress,\n amount: fromBaseDenomination(quote.amountIn.toString(), config.sourceAsset.decimals),\n chainId: config.sourceChainId,\n signer: {\n sign: async (tx, dispatch) => {\n return evmSigner.sign(\n {\n ...tx,\n chainId: tx.chainId ?? caip2ToEip155HexChainId(config.sourceChain),\n },\n dispatch,\n {\n currentSignature: 1,\n currentSignatureReason: TransferSignatureReason.TokensTransfer,\n quote,\n requiredSignatures: 1,\n },\n );\n },\n },\n tokenIn: Token.BTCb,\n tokenOut: undefined,\n env: config.env,\n });\n\n return {\n amountIn: quote.amountIn,\n amountOut: quote.amountOut,\n environment: config.environment,\n fees: quote.fees,\n fromAddress: quote.fromAddress,\n id: quote.id,\n partnerFeeBps: quote.partnerFeeBps,\n source: {\n confirmationCount: 0,\n requiredConfirmationCount: EVM_CONFIRMATION_COUNT,\n startedAtMs,\n targetStartBlockNumber,\n txHash,\n },\n sourceAsset: quote.assetIn,\n sourceChain: quote.sourceChain,\n status: 'source-pending',\n targetAsset: quote.assetOut,\n targetChain: quote.targetChain,\n toAddress: quote.toAddress,\n type: ServiceType.LOMBARD_BTCB_TO_BTC,\n } satisfies SourcePendingTransfer;\n };\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"transfer-asset.js","names":[],"sources":["../../../../../src/transfer-service/lombard/btcb-to-btc/_handlers/transfer-asset.ts"],"sourcesContent":["import { isAddress } from 'viem';\nimport { Environment, ServiceType, TransferSignatureReason } from '../../../../constants';\nimport { ErrorCode, ErrorReason, InvalidParamsError } from '../../../../errors';\nimport { caip2ToEip155HexChainId } from '../../../../utils/caip';\nimport type { BitcoinFunctions } from '../../../../types/bitcoin';\nimport type { TransferService } from '../../../../types/service';\nimport type { EvmSignerWithMessage } from '../../../../types/signer';\nimport type { FailedTransfer, SourcePendingTransfer } from '../../../../types/transfer';\nimport type { BtcbToBtcConfig } from '../../types';\nimport { isBech32AddressInNetwork } from '../../../../utils/bitcoin-address';\nimport { fromBaseDenomination, redeemToken, Token } from '@lombard.finance/sdk';\nimport { EVM_CONFIRMATION_COUNT } from '../../constants';\n\nexport interface TransferAssetFactoryOptions {\n bitcoinFunctions: BitcoinFunctions;\n config: BtcbToBtcConfig;\n evmSigner: EvmSignerWithMessage;\n}\n\nexport function transferAssetFactory({\n bitcoinFunctions,\n config,\n evmSigner,\n}: TransferAssetFactoryOptions): TransferService['transferAsset'] {\n return async ({ quote }) => {\n if (!isAddress(quote.fromAddress)) {\n throw new InvalidParamsError(\n ErrorReason.INCORRECT_ADDRESS_PROVIDED,\n 'Invalid fromAddress was provided. Must be a valid EVM address.',\n );\n }\n\n if (!isBech32AddressInNetwork(quote.toAddress, config.environment === Environment.PROD)) {\n throw new InvalidParamsError(\n ErrorReason.INCORRECT_ADDRESS_PROVIDED,\n 'Invalid toAddress was provided. Make sure it is a BTC address from correct environment.',\n );\n }\n\n const startedAtMs = Date.now();\n\n let targetStartBlockNumber: bigint;\n\n try {\n targetStartBlockNumber = BigInt(await bitcoinFunctions.getChainHeight());\n } catch {\n // Unable to get chain height. Not able to track from this point.\n\n return {\n amountIn: quote.amountIn,\n amountOut: quote.amountOut,\n environment: config.environment,\n errorCode: ErrorCode.UNKNOWN,\n errorReason: 'Unable to fetch target chain height',\n failedAtMs: Date.now(),\n fees: quote.fees,\n fromAddress: quote.fromAddress,\n id: quote.id,\n partnerFeeBps: quote.partnerFeeBps,\n sourceAsset: quote.assetIn,\n sourceChain: quote.sourceChain,\n status: 'failed',\n targetAsset: quote.assetOut,\n targetChain: quote.targetChain,\n toAddress: quote.toAddress,\n type: ServiceType.LOMBARD_BTCB_TO_BTC,\n } satisfies FailedTransfer;\n }\n\n const txHash = await redeemToken({\n account: quote.fromAddress,\n btcAddress: quote.toAddress,\n amount: fromBaseDenomination(quote.amountIn.toString(), config.sourceAsset.decimals),\n chainId: config.sourceChainId,\n signer: {\n sign: async (tx, dispatch) => {\n return evmSigner.sign(\n {\n ...tx,\n chainId: tx.chainId ?? caip2ToEip155HexChainId(config.sourceChain),\n },\n dispatch,\n {\n currentSignature: 1,\n currentSignatureReason: TransferSignatureReason.TokensTransfer,\n quote,\n requiredSignatures: 1,\n },\n );\n },\n },\n tokenIn: Token.BTCb,\n tokenOut: undefined,\n env: config.env,\n });\n\n return {\n amountIn: quote.amountIn,\n amountOut: quote.amountOut,\n environment: config.environment,\n fees: quote.fees,\n fromAddress: quote.fromAddress,\n id: quote.id,\n partnerFeeBps: quote.partnerFeeBps,\n source: {\n confirmationCount: 0,\n requiredConfirmationCount: EVM_CONFIRMATION_COUNT,\n startedAtMs,\n targetStartBlockNumber,\n txHash,\n },\n sourceAsset: quote.assetIn,\n sourceChain: quote.sourceChain,\n status: 'source-pending',\n targetAsset: quote.assetOut,\n targetChain: quote.targetChain,\n toAddress: quote.toAddress,\n type: ServiceType.LOMBARD_BTCB_TO_BTC,\n } satisfies SourcePendingTransfer;\n };\n}\n"],"mappings":"6cAmBA,SAAgB,EAAqB,CACnC,mBACA,SACA,aACgE,CAChE,OAAO,MAAO,CAAE,WAAY,CAC1B,GAAI,CAAC,EAAU,EAAM,YAAY,CAC/B,MAAM,IAAI,EACR,EAAY,2BACZ,iEACD,CAGH,GAAI,CAAC,EAAyB,EAAM,UAAW,EAAO,cAAgB,EAAY,KAAK,CACrF,MAAM,IAAI,EACR,EAAY,2BACZ,0FACD,CAGH,IAAM,EAAc,KAAK,KAAK,CAE1B,EAEJ,GAAI,CACF,EAAyB,OAAO,MAAM,EAAiB,gBAAgB,CAAC,MAClE,CAGN,MAAO,CACL,SAAU,EAAM,SAChB,UAAW,EAAM,UACjB,YAAa,EAAO,YACpB,UAAW,EAAU,QACrB,YAAa,sCACb,WAAY,KAAK,KAAK,CACtB,KAAM,EAAM,KACZ,YAAa,EAAM,YACnB,GAAI,EAAM,GACV,cAAe,EAAM,cACrB,YAAa,EAAM,QACnB,YAAa,EAAM,YACnB,OAAQ,SACR,YAAa,EAAM,SACnB,YAAa,EAAM,YACnB,UAAW,EAAM,UACjB,KAAM,EAAY,oBACnB,CAGH,IAAM,EAAS,MAAM,EAAY,CAC/B,QAAS,EAAM,YACf,WAAY,EAAM,UAClB,OAAQ,EAAqB,EAAM,SAAS,UAAU,CAAE,EAAO,YAAY,SAAS,CACpF,QAAS,EAAO,cAChB,OAAQ,CACN,KAAM,MAAO,EAAI,IACR,EAAU,KACf,CACE,GAAG,EACH,QAAS,EAAG,SAAW,EAAwB,EAAO,YAAY,CACnE,CACD,EACA,CACE,iBAAkB,EAClB,uBAAwB,EAAwB,eAChD,QACA,mBAAoB,EACrB,CACF,CAEJ,CACD,QAAS,EAAM,KACf,SAAU,IAAA,GACV,IAAK,EAAO,IACb,CAAC,CAEF,MAAO,CACL,SAAU,EAAM,SAChB,UAAW,EAAM,UACjB,YAAa,EAAO,YACpB,KAAM,EAAM,KACZ,YAAa,EAAM,YACnB,GAAI,EAAM,GACV,cAAe,EAAM,cACrB,OAAQ,CACN,kBAAmB,EACnB,0BAAA,EACA,cACA,yBACA,SACD,CACD,YAAa,EAAM,QACnB,YAAa,EAAM,YACnB,OAAQ,iBACR,YAAa,EAAM,SACnB,YAAa,EAAM,YACnB,UAAW,EAAM,UACjB,KAAM,EAAY,oBACnB"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
require(`../../_virtual/_rolldown/runtime.cjs`);const e=require(`../../constants.cjs`);let t=require(`@lombard.finance/sdk`);const n={[e.Environment.DEV]:t.Env.dev,[e.Environment.TEST]:t.Env.ibc,[e.Environment.PROD]:t.Env.prod},r={type:e.TokenType.NATIVE,name:`Bitcoin`,symbol:`BTC`,decimals:8,logoUri:`https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/bitcoin/info/logo.png`},i={[t.Env.dev]:{43113:`0x7fbdc44bfebde80c970ba622b678dab36cee31f6`},[t.Env.ibc]:{43113:`0x71ba2b8dc58e7ca1b6d81a60729e31aefa37ae02`},[t.Env.stage]:{43113:`0x7fbdc44bfebde80c970ba622b678dab36cee31f6`},[t.Env.testnet]:{43113:`0xb14f240714bd23bda103a7189d512a90326e4d01`},[t.Env.prod]:{43114:`0x152b9d0fdc40c096757f570a51e494bd4b943e50`}},a={[t.Env.dev]:{43113:`0x0a65c37d07c32e5ea8ea40495b7f249cde26935e`},[t.Env.ibc]:{43113:`0x1391f9ac408cf13214ddb71d359002658eaf9ebb`},[t.Env.stage]:{43113:`0x0a65c37d07c32e5ea8ea40495b7f249cde26935e`},[t.Env.testnet]:{43113:`0x41bcd71e7c92b1c8dde53037f9b2c4aa2058b1cb`},[t.Env.prod]:{43114:`0x85d1d52e11290f174444d21c2a167bedbe36e4d2`}};exports.BTCB_ADAPTER_ADDRESSES=a,exports.BTCB_ADDRESSES=i,exports.BTCB_LOGO_URI=`https://images.ctfassets.net/gcj8jwzm6086/aeab859f-78aa-4a05-8f77-b7e3492beb39/12c3dad31c4e71389d11661e4504c34b/43114-0x152b9d0FdC40C096757F570A51E494bd4b943E50.png`,exports.
|
|
1
|
+
require(`../../_virtual/_rolldown/runtime.cjs`);const e=require(`../../constants.cjs`);let t=require(`@lombard.finance/sdk`);const n={[e.Environment.DEV]:t.Env.dev,[e.Environment.TEST]:t.Env.ibc,[e.Environment.PROD]:t.Env.prod},r={type:e.TokenType.NATIVE,name:`Bitcoin`,symbol:`BTC`,decimals:8,logoUri:`https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/bitcoin/info/logo.png`},i={[t.Env.dev]:{43113:`0x7fbdc44bfebde80c970ba622b678dab36cee31f6`},[t.Env.ibc]:{43113:`0x71ba2b8dc58e7ca1b6d81a60729e31aefa37ae02`},[t.Env.stage]:{43113:`0x7fbdc44bfebde80c970ba622b678dab36cee31f6`},[t.Env.testnet]:{43113:`0xb14f240714bd23bda103a7189d512a90326e4d01`},[t.Env.prod]:{43114:`0x152b9d0fdc40c096757f570a51e494bd4b943e50`}},a={[t.Env.dev]:{43113:`0x0a65c37d07c32e5ea8ea40495b7f249cde26935e`},[t.Env.ibc]:{43113:`0x1391f9ac408cf13214ddb71d359002658eaf9ebb`},[t.Env.stage]:{43113:`0x0a65c37d07c32e5ea8ea40495b7f249cde26935e`},[t.Env.testnet]:{43113:`0x41bcd71e7c92b1c8dde53037f9b2c4aa2058b1cb`},[t.Env.prod]:{43114:`0x85d1d52e11290f174444d21c2a167bedbe36e4d2`}};exports.BTCB_ADAPTER_ADDRESSES=a,exports.BTCB_ADDRESSES=i,exports.BTCB_LOGO_URI=`https://images.ctfassets.net/gcj8jwzm6086/aeab859f-78aa-4a05-8f77-b7e3492beb39/12c3dad31c4e71389d11661e4504c34b/43114-0x152b9d0FdC40C096757F570A51E494bd4b943E50.png`,exports.BTC_NATIVE_ASSET=r,exports.ENV_MAP=n,exports.LOMBARD_PARTNER_ID=`core`,exports.MIN_DEPOSIT_BTC_AMOUNT_SATOSHI=20000n;
|
|
2
2
|
//# sourceMappingURL=constants.cjs.map
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{Environment as e,TokenType as t}from"../../constants.js";import{Env as n}from"@lombard.finance/sdk";const r=`core`,i=
|
|
1
|
+
import{Environment as e,TokenType as t}from"../../constants.js";import{Env as n}from"@lombard.finance/sdk";const r=`core`,i={[e.DEV]:n.dev,[e.TEST]:n.ibc,[e.PROD]:n.prod},a=20000n,o=`https://images.ctfassets.net/gcj8jwzm6086/aeab859f-78aa-4a05-8f77-b7e3492beb39/12c3dad31c4e71389d11661e4504c34b/43114-0x152b9d0FdC40C096757F570A51E494bd4b943E50.png`,s={type:t.NATIVE,name:`Bitcoin`,symbol:`BTC`,decimals:8,logoUri:`https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/bitcoin/info/logo.png`},c={[n.dev]:{43113:`0x7fbdc44bfebde80c970ba622b678dab36cee31f6`},[n.ibc]:{43113:`0x71ba2b8dc58e7ca1b6d81a60729e31aefa37ae02`},[n.stage]:{43113:`0x7fbdc44bfebde80c970ba622b678dab36cee31f6`},[n.testnet]:{43113:`0xb14f240714bd23bda103a7189d512a90326e4d01`},[n.prod]:{43114:`0x152b9d0fdc40c096757f570a51e494bd4b943e50`}},l={[n.dev]:{43113:`0x0a65c37d07c32e5ea8ea40495b7f249cde26935e`},[n.ibc]:{43113:`0x1391f9ac408cf13214ddb71d359002658eaf9ebb`},[n.stage]:{43113:`0x0a65c37d07c32e5ea8ea40495b7f249cde26935e`},[n.testnet]:{43113:`0x41bcd71e7c92b1c8dde53037f9b2c4aa2058b1cb`},[n.prod]:{43114:`0x85d1d52e11290f174444d21c2a167bedbe36e4d2`}};export{l as BTCB_ADAPTER_ADDRESSES,c as BTCB_ADDRESSES,o as BTCB_LOGO_URI,s as BTC_NATIVE_ASSET,i as ENV_MAP,r as LOMBARD_PARTNER_ID,a as MIN_DEPOSIT_BTC_AMOUNT_SATOSHI};
|
|
2
2
|
//# sourceMappingURL=constants.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constants.js","names":[],"sources":["../../../src/transfer-service/lombard/constants.ts"],"sourcesContent":["import { type ChainId, Env } from '@lombard.finance/sdk';\nimport type { Address as EvmAddress } from 'viem';\nimport { Environment, TokenType } from '../../constants';\nimport type { NativeAsset } from '../../types/asset';\n\n/** The Lombard partner ID */\nexport const LOMBARD_PARTNER_ID = 'core';\n\n/**\n * The number of confirmations needed on BTC network for\n * the deposit to be picked up by claimer.\n */\nexport const BTC_CONFIRMATION_COUNT = 6;\n\n/** The number of confirmations on EVM network */\nexport const EVM_CONFIRMATION_COUNT = 1;\n\n/** The mapping of SDK environments to Lombard's SDK env. */\nexport const ENV_MAP: Record<Environment, Env> = {\n [Environment.DEV]: Env.dev,\n [Environment.TEST]: Env.ibc,\n [Environment.PROD]: Env.prod,\n};\n\n/** The minimum BTC amount eligible for depositing (in Satoshis). */\nexport const MIN_DEPOSIT_BTC_AMOUNT_SATOSHI = 20000n;\n\n/** Estimated bridging time in hours for BTCb to BTC direction */\nexport const ESTIMATED_BRIDGING_TIME_BTCB_TO_BTC_HOURS = 6;\n\nexport const BTC_LOGO_URI =\n 'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/bitcoin/info/logo.png';\nexport const BTCB_LOGO_URI =\n 'https://images.ctfassets.net/gcj8jwzm6086/aeab859f-78aa-4a05-8f77-b7e3492beb39/12c3dad31c4e71389d11661e4504c34b/43114-0x152b9d0FdC40C096757F570A51E494bd4b943E50.png';\n\nexport const BTC_NATIVE_ASSET: NativeAsset = {\n type: TokenType.NATIVE,\n name: 'Bitcoin',\n symbol: 'BTC',\n decimals: 8,\n logoUri: BTC_LOGO_URI,\n};\n\n/**\n * BTCb token contract addresses by environment and chain ID.\n * These are the ERC20 token contracts for BTCb.\n * Organized as: Env -> ChainId -> Address\n */\nexport const BTCB_ADDRESSES: Record<Env, Partial<Record<ChainId, EvmAddress>>> = {\n [Env.dev]: {\n 43113: '0x7fbdc44bfebde80c970ba622b678dab36cee31f6',\n },\n [Env.ibc]: {\n 43113: '0x71ba2b8dc58e7ca1b6d81a60729e31aefa37ae02',\n },\n [Env.stage]: {\n 43113: '0x7fbdc44bfebde80c970ba622b678dab36cee31f6',\n },\n [Env.testnet]: {\n 43113: '0xb14f240714bd23bda103a7189d512a90326e4d01',\n },\n [Env.prod]: {\n 43114: '0x152b9d0fdc40c096757f570a51e494bd4b943e50',\n },\n};\n\n/**\n * BTCb adapter contract addresses by environment and chain ID.\n * On Avalanche, BTCb uses a dual-contract architecture:\n * - Token contract: ERC20 for balances, permits, approvals\n * - Adapter contract: For bridge operations (burn/mint), needs approval for redemptions\n * Organized as: Env -> ChainId -> Address\n */\nexport const BTCB_ADAPTER_ADDRESSES: Record<Env, Partial<Record<ChainId, EvmAddress>>> = {\n [Env.dev]: {\n 43113: '0x0a65c37d07c32e5ea8ea40495b7f249cde26935e',\n },\n [Env.ibc]: {\n 43113: '0x1391f9ac408cf13214ddb71d359002658eaf9ebb',\n },\n [Env.stage]: {\n 43113: '0x0a65c37d07c32e5ea8ea40495b7f249cde26935e',\n },\n [Env.testnet]: {\n 43113: '0x41bcd71e7c92b1c8dde53037f9b2c4aa2058b1cb',\n },\n [Env.prod]: {\n 43114: '0x85d1d52e11290f174444d21c2a167bedbe36e4d2',\n },\n};\n"],"mappings":"2GAMA,MAAa,EAAqB,
|
|
1
|
+
{"version":3,"file":"constants.js","names":[],"sources":["../../../src/transfer-service/lombard/constants.ts"],"sourcesContent":["import { type ChainId, Env } from '@lombard.finance/sdk';\nimport type { Address as EvmAddress } from 'viem';\nimport { Environment, TokenType } from '../../constants';\nimport type { NativeAsset } from '../../types/asset';\n\n/** The Lombard partner ID */\nexport const LOMBARD_PARTNER_ID = 'core';\n\n/**\n * The number of confirmations needed on BTC network for\n * the deposit to be picked up by claimer.\n */\nexport const BTC_CONFIRMATION_COUNT = 6;\n\n/** The number of confirmations on EVM network */\nexport const EVM_CONFIRMATION_COUNT = 1;\n\n/** The mapping of SDK environments to Lombard's SDK env. */\nexport const ENV_MAP: Record<Environment, Env> = {\n [Environment.DEV]: Env.dev,\n [Environment.TEST]: Env.ibc,\n [Environment.PROD]: Env.prod,\n};\n\n/** The minimum BTC amount eligible for depositing (in Satoshis). */\nexport const MIN_DEPOSIT_BTC_AMOUNT_SATOSHI = 20000n;\n\n/** Estimated bridging time in hours for BTCb to BTC direction */\nexport const ESTIMATED_BRIDGING_TIME_BTCB_TO_BTC_HOURS = 6;\n\nexport const BTC_LOGO_URI =\n 'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/bitcoin/info/logo.png';\nexport const BTCB_LOGO_URI =\n 'https://images.ctfassets.net/gcj8jwzm6086/aeab859f-78aa-4a05-8f77-b7e3492beb39/12c3dad31c4e71389d11661e4504c34b/43114-0x152b9d0FdC40C096757F570A51E494bd4b943E50.png';\n\nexport const BTC_NATIVE_ASSET: NativeAsset = {\n type: TokenType.NATIVE,\n name: 'Bitcoin',\n symbol: 'BTC',\n decimals: 8,\n logoUri: BTC_LOGO_URI,\n};\n\n/**\n * BTCb token contract addresses by environment and chain ID.\n * These are the ERC20 token contracts for BTCb.\n * Organized as: Env -> ChainId -> Address\n */\nexport const BTCB_ADDRESSES: Record<Env, Partial<Record<ChainId, EvmAddress>>> = {\n [Env.dev]: {\n 43113: '0x7fbdc44bfebde80c970ba622b678dab36cee31f6',\n },\n [Env.ibc]: {\n 43113: '0x71ba2b8dc58e7ca1b6d81a60729e31aefa37ae02',\n },\n [Env.stage]: {\n 43113: '0x7fbdc44bfebde80c970ba622b678dab36cee31f6',\n },\n [Env.testnet]: {\n 43113: '0xb14f240714bd23bda103a7189d512a90326e4d01',\n },\n [Env.prod]: {\n 43114: '0x152b9d0fdc40c096757f570a51e494bd4b943e50',\n },\n};\n\n/**\n * BTCb adapter contract addresses by environment and chain ID.\n * On Avalanche, BTCb uses a dual-contract architecture:\n * - Token contract: ERC20 for balances, permits, approvals\n * - Adapter contract: For bridge operations (burn/mint), needs approval for redemptions\n * Organized as: Env -> ChainId -> Address\n */\nexport const BTCB_ADAPTER_ADDRESSES: Record<Env, Partial<Record<ChainId, EvmAddress>>> = {\n [Env.dev]: {\n 43113: '0x0a65c37d07c32e5ea8ea40495b7f249cde26935e',\n },\n [Env.ibc]: {\n 43113: '0x1391f9ac408cf13214ddb71d359002658eaf9ebb',\n },\n [Env.stage]: {\n 43113: '0x0a65c37d07c32e5ea8ea40495b7f249cde26935e',\n },\n [Env.testnet]: {\n 43113: '0x41bcd71e7c92b1c8dde53037f9b2c4aa2058b1cb',\n },\n [Env.prod]: {\n 43114: '0x85d1d52e11290f174444d21c2a167bedbe36e4d2',\n },\n};\n"],"mappings":"2GAMA,MAAa,EAAqB,OAYrB,EAAoC,EAC9C,EAAY,KAAM,EAAI,KACtB,EAAY,MAAO,EAAI,KACvB,EAAY,MAAO,EAAI,KACzB,CAGY,EAAiC,OAOjC,EACX,uKAEW,EAAgC,CAC3C,KAAM,EAAU,OAChB,KAAM,UACN,OAAQ,MACR,SAAU,EACV,QAAS,gGACV,CAOY,EAAoE,EAC9E,EAAI,KAAM,CACT,MAAO,6CACR,EACA,EAAI,KAAM,CACT,MAAO,6CACR,EACA,EAAI,OAAQ,CACX,MAAO,6CACR,EACA,EAAI,SAAU,CACb,MAAO,6CACR,EACA,EAAI,MAAO,CACV,MAAO,6CACR,CACF,CASY,EAA4E,EACtF,EAAI,KAAM,CACT,MAAO,6CACR,EACA,EAAI,KAAM,CACT,MAAO,6CACR,EACA,EAAI,OAAQ,CACX,MAAO,6CACR,EACA,EAAI,SAAU,CACb,MAAO,6CACR,EACA,EAAI,MAAO,CACV,MAAO,6CACR,CACF"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
require(`../../../_virtual/_rolldown/runtime.cjs`);const e=require(`../../../errors.cjs`),t=require(`../../../utils/caip.cjs`),n=require(`../../../_utils/chain.cjs`),r=require(`../../_utils.cjs`),i=require(`../../_evm-gas.cjs`),a=require(`../_api.cjs`),
|
|
1
|
+
require(`../../../_virtual/_rolldown/runtime.cjs`);const e=require(`../../../errors.cjs`),t=require(`../../../utils/caip.cjs`),n=require(`../../../_utils/chain.cjs`),r=require(`../../_utils.cjs`),i=require(`../../_evm-gas.cjs`),a=require(`../../_evm-errors.cjs`),o=require(`../_api.cjs`),s=require(`../_utils.cjs`),c=require(`../_type-guards.cjs`),l=require(`../../../utils/solana.cjs`);let u=require(`viem`),d=require(`@solana/kit`);function f(t){return async(r,i)=>{if(n.isEvmNamespace(r.sourceChain.chainId))return await p(r,i,t);if(n.isSolanaNamespace(r.sourceChain.chainId))return await m(r,i,t);throw new e.InvalidParamsError(e.ErrorReason.INVALID_PARAMS,`Unsupported source chain namespace for estimateNativeFee: ${r.sourceChain.chainId}`)}}async function p(n,l,{apiOptions:d,appId:f}){if(!(0,u.isAddress)(n.fromAddress))throw new e.InvalidParamsError(e.ErrorReason.INVALID_PARAMS,`Invalid fromAddress: ${n.fromAddress}`);let p=r.getEvmClientForChain({chain:n.sourceChain}),m=s.assetToAddressString(n.assetIn,n.sourceChain.chainId);if(!(0,u.isAddress)(m))throw new e.SdkError(e.ErrorReason.INVALID_PARAMS,e.ErrorCode.INVALID_PARAMS,{details:`assetIn address is not a valid EVM address. Can not call estimateGas.`});let g=s.isTokenAddressNative(m),_=n.sourceChain.chainId.toLowerCase()!==n.targetChain.chainId.toLowerCase(),v=n.amountIn+s.getAdditiveSourceAssetFeeAmount(n),y=0n;if(!g){let r,{address:i}=await o.markrGetSpenderAddress(d,{chainId:t.caip2ToEip155ChainId(n.sourceChain.chainId),crossChainSwap:_,quoteId:n.id});try{r=await p.readContract({address:m,abi:u.erc20Abi,functionName:`allowance`,args:[n.fromAddress,i]})}catch(t){throw new e.SdkError(`Error during allowance check`,e.ErrorCode.VIEM_ERROR,{cause:t,details:`Failed to read ERC20 allowance for Markr spender.`})}r<v&&(y=await a.estimateGasWithRevert(p,{account:n.fromAddress,to:m,data:(0,u.encodeFunctionData)({abi:u.erc20Abi,functionName:`approve`,args:[i,v]})},u.erc20Abi,`Failed to estimate gas for ERC20 approval transaction.`))}let b=y>0n,x=s.calculateMarkrMinimumAmountOut({amountOut:n.amountOut,assetOut:n.assetOut,slippageBps:n.slippageBps}),S=await o.markrSwap(d,{amountIn:n.amountIn.toString(),appId:f,minAmountOut:x.toString(),tokenIn:m,tokenOut:s.assetToAddressString(n.assetOut,n.targetChain.chainId),uuid:n.id});if(!c.isEvmSwapResponse(S))throw new e.SdkError(e.ErrorReason.CHAIN_NOT_SUPPORTED,e.ErrorCode.INVALID_PARAMS,{details:`Received non-EVM swap response from Markr. Expected EVM transaction data for gas estimation, but got response with chainType ${S.chainType}.`});let C=0n;C=b?n.gasEstimate?n.gasEstimate:n.fees.filter(e=>e.type===`gas`&&e.chainId===n.sourceChain.chainId).reduce((e,t)=>e+t.amount,0n)||700000n:await h({crossChain:_,fromAddress:n.fromAddress,sourceClient:p,swap:S});let w=await i.estimateEvmFeesPerGas(p,n.sourceChain,l?.overrides?.feeRateTier),T=l?.overrides?.maxFeePerGas??w.maxFeePerGas,E=l?.overrides?.maxPriorityFeePerGas??w.maxPriorityFeePerGas,D=(C+y)*T;return{asset:n.sourceChain.networkToken,totalFee:r.applyFeeUnitsBpsMargin(D,l?.feeUnitsMarginBps),totalFeeWithoutMargin:D,meta:{approvalFee:b?y*T:void 0,maxFeePerGas:T,maxPriorityFeePerGas:E}}}async function m(t,n,{apiOptions:i,appId:a}){let u=s.assetToAddressString(t.assetIn,t.sourceChain.chainId);if(!(0,d.isAddress)(u))throw new e.SdkError(e.ErrorReason.INVALID_PARAMS,e.ErrorCode.INVALID_PARAMS,{details:`assetIn address is not a valid Solana address. Can not call estimateGas.`});let f=s.getAdditiveSourceNativeAssetFeeAmount(t),p=t.amountIn+f,m=s.calculateMarkrMinimumAmountOut({amountOut:t.amountOut,assetOut:t.assetOut,slippageBps:t.slippageBps}),h=await o.markrSwap(i,{amountIn:t.amountIn.toString(),appId:a,minAmountOut:m.toString(),tokenIn:u,tokenOut:s.assetToAddressString(t.assetOut,t.targetChain.chainId),userPublicKey:t.fromAddress,uuid:t.id});if(!c.isSolanaSwapResponse(h))throw new e.SdkError(e.ErrorReason.CHAIN_NOT_SUPPORTED,e.ErrorCode.INVALID_PARAMS,{details:`Received non-Solana swap response from Markr. Expected Solana transaction data for fee estimation.`});let{baseFeeLamports:g,priorityFeeLamports:_,...v}=await l.estimateSolanaFee(r.getSolanaRpcForChain({chain:t.sourceChain}),h.swapTransaction),y=v.feePayerBalanceDiffLamports-p;return{asset:t.sourceChain.networkToken,totalFee:r.applyFeeUnitsBpsMargin(y,n?.feeUnitsMarginBps),totalFeeWithoutMargin:y,meta:{...v,baseFee:g,priorityFee:_}}}async function h({crossChain:e,feeUnitsMarginBps:t,fromAddress:n,sourceClient:i,swap:o}){let c=await s.getMarkrSwapWrapperAbi(e);return r.applyFeeUnitsBpsMargin(await a.estimateGasWithRevert(i,{account:n,to:o.to,data:o.data,value:o.value},c,`Failed to estimate gas for Markr swap transaction.`),t)}exports._estimateGasFromSwapResponse=h,exports.estimateNativeFeeFactory=f;
|
|
2
2
|
//# sourceMappingURL=estimate-native-fee.cjs.map
|