@atomiqlabs/sdk 8.7.7 → 8.9.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/api/index.d.ts +1 -0
- package/api/index.js +3 -0
- package/dist/ApiList.d.ts +37 -0
- package/dist/ApiList.js +30 -0
- package/dist/api/ApiEndpoints.d.ts +393 -0
- package/dist/api/ApiEndpoints.js +2 -0
- package/dist/api/ApiParser.d.ts +10 -0
- package/dist/api/ApiParser.js +134 -0
- package/dist/api/ApiTypes.d.ts +157 -0
- package/dist/api/ApiTypes.js +75 -0
- package/dist/api/SerializedAction.d.ts +40 -0
- package/dist/api/SerializedAction.js +59 -0
- package/dist/api/SwapperApi.d.ts +50 -0
- package/dist/api/SwapperApi.js +431 -0
- package/dist/api/index.d.ts +5 -0
- package/dist/api/index.js +24 -0
- package/dist/bitcoin/coinselect2/accumulative.d.ts +1 -0
- package/dist/bitcoin/coinselect2/accumulative.js +1 -1
- package/dist/bitcoin/coinselect2/blackjack.d.ts +1 -0
- package/dist/bitcoin/coinselect2/blackjack.js +1 -1
- package/dist/bitcoin/coinselect2/index.d.ts +3 -2
- package/dist/bitcoin/coinselect2/index.js +2 -2
- package/dist/bitcoin/coinselect2/utils.d.ts +7 -2
- package/dist/bitcoin/coinselect2/utils.js +45 -10
- package/dist/bitcoin/wallet/BitcoinWallet.d.ts +8 -25
- package/dist/bitcoin/wallet/BitcoinWallet.js +31 -18
- package/dist/bitcoin/wallet/IBitcoinWallet.d.ts +40 -2
- package/dist/bitcoin/wallet/SingleAddressBitcoinWallet.d.ts +7 -2
- package/dist/bitcoin/wallet/SingleAddressBitcoinWallet.js +10 -4
- package/dist/events/UnifiedSwapEventListener.d.ts +4 -3
- package/dist/events/UnifiedSwapEventListener.js +8 -2
- package/dist/http/HttpUtils.d.ts +4 -2
- package/dist/http/HttpUtils.js +10 -4
- package/dist/http/paramcoders/client/StreamingFetchPromise.d.ts +2 -1
- package/dist/http/paramcoders/client/StreamingFetchPromise.js +3 -2
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/intermediaries/IntermediaryDiscovery.d.ts +7 -2
- package/dist/intermediaries/IntermediaryDiscovery.js +4 -4
- package/dist/intermediaries/apis/IntermediaryAPI.d.ts +182 -15
- package/dist/intermediaries/apis/IntermediaryAPI.js +192 -31
- package/dist/intermediaries/auth/SignedKeyBasedAuth.d.ts +14 -0
- package/dist/intermediaries/auth/SignedKeyBasedAuth.js +68 -0
- package/dist/storage/IUnifiedStorage.d.ts +45 -3
- package/dist/storage/UnifiedSwapStorage.d.ts +8 -2
- package/dist/storage/UnifiedSwapStorage.js +46 -8
- package/dist/swapper/Swapper.d.ts +77 -4
- package/dist/swapper/Swapper.js +117 -25
- package/dist/swapper/SwapperUtils.d.ts +18 -2
- package/dist/swapper/SwapperUtils.js +39 -1
- package/dist/swaps/ISwap.d.ts +70 -9
- package/dist/swaps/ISwap.js +28 -6
- package/dist/swaps/ISwapWrapper.d.ts +11 -1
- package/dist/swaps/ISwapWrapper.js +23 -3
- package/dist/swaps/escrow_swaps/IEscrowSwap.d.ts +1 -1
- package/dist/swaps/escrow_swaps/IEscrowSwap.js +4 -2
- package/dist/swaps/escrow_swaps/IEscrowSwapWrapper.d.ts +2 -1
- package/dist/swaps/escrow_swaps/IEscrowSwapWrapper.js +2 -2
- package/dist/swaps/escrow_swaps/frombtc/IFromBTCLNWrapper.d.ts +3 -1
- package/dist/swaps/escrow_swaps/frombtc/IFromBTCLNWrapper.js +3 -2
- package/dist/swaps/escrow_swaps/frombtc/ln/FromBTCLNSwap.d.ts +47 -31
- package/dist/swaps/escrow_swaps/frombtc/ln/FromBTCLNSwap.js +201 -67
- package/dist/swaps/escrow_swaps/frombtc/ln/FromBTCLNWrapper.d.ts +3 -1
- package/dist/swaps/escrow_swaps/frombtc/ln/FromBTCLNWrapper.js +6 -6
- package/dist/swaps/escrow_swaps/frombtc/ln_auto/FromBTCLNAutoSwap.d.ts +82 -15
- package/dist/swaps/escrow_swaps/frombtc/ln_auto/FromBTCLNAutoSwap.js +304 -98
- package/dist/swaps/escrow_swaps/frombtc/ln_auto/FromBTCLNAutoWrapper.d.ts +3 -1
- package/dist/swaps/escrow_swaps/frombtc/ln_auto/FromBTCLNAutoWrapper.js +6 -6
- package/dist/swaps/escrow_swaps/frombtc/onchain/FromBTCSwap.d.ts +75 -42
- package/dist/swaps/escrow_swaps/frombtc/onchain/FromBTCSwap.js +424 -87
- package/dist/swaps/escrow_swaps/frombtc/onchain/FromBTCWrapper.d.ts +3 -1
- package/dist/swaps/escrow_swaps/frombtc/onchain/FromBTCWrapper.js +7 -7
- package/dist/swaps/escrow_swaps/tobtc/IToBTCSwap.d.ts +54 -11
- package/dist/swaps/escrow_swaps/tobtc/IToBTCSwap.js +214 -41
- package/dist/swaps/escrow_swaps/tobtc/ln/ToBTCLNWrapper.d.ts +2 -1
- package/dist/swaps/escrow_swaps/tobtc/ln/ToBTCLNWrapper.js +7 -8
- package/dist/swaps/escrow_swaps/tobtc/onchain/ToBTCWrapper.d.ts +3 -1
- package/dist/swaps/escrow_swaps/tobtc/onchain/ToBTCWrapper.js +5 -5
- package/dist/swaps/spv_swaps/SpvFromBTCSwap.d.ts +85 -22
- package/dist/swaps/spv_swaps/SpvFromBTCSwap.js +299 -56
- package/dist/swaps/spv_swaps/SpvFromBTCWrapper.d.ts +41 -7
- package/dist/swaps/spv_swaps/SpvFromBTCWrapper.js +183 -58
- package/dist/swaps/trusted/ln/LnForGasSwap.d.ts +53 -12
- package/dist/swaps/trusted/ln/LnForGasSwap.js +163 -49
- package/dist/swaps/trusted/ln/LnForGasWrapper.js +1 -2
- package/dist/swaps/trusted/onchain/OnchainForGasSwap.d.ts +14 -13
- package/dist/swaps/trusted/onchain/OnchainForGasSwap.js +30 -47
- package/dist/swaps/trusted/onchain/OnchainForGasWrapper.d.ts +3 -1
- package/dist/swaps/trusted/onchain/OnchainForGasWrapper.js +4 -4
- package/dist/types/SwapExecutionAction.d.ts +141 -34
- package/dist/types/SwapExecutionAction.js +104 -0
- package/dist/types/SwapExecutionStep.d.ts +144 -0
- package/dist/types/SwapExecutionStep.js +87 -0
- package/dist/types/TokenAmount.d.ts +6 -0
- package/dist/types/TokenAmount.js +26 -1
- package/dist/utils/BitcoinUtils.d.ts +4 -0
- package/dist/utils/BitcoinUtils.js +73 -1
- package/dist/utils/BitcoinWalletUtils.d.ts +2 -2
- package/dist/utils/Utils.d.ts +3 -1
- package/dist/utils/Utils.js +7 -1
- package/package.json +7 -4
- package/src/api/ApiEndpoints.ts +427 -0
- package/src/api/ApiParser.ts +138 -0
- package/src/api/ApiTypes.ts +229 -0
- package/src/api/SerializedAction.ts +97 -0
- package/src/api/SwapperApi.ts +545 -0
- package/src/api/index.ts +5 -0
- package/src/bitcoin/coinselect2/accumulative.ts +2 -1
- package/src/bitcoin/coinselect2/blackjack.ts +2 -1
- package/src/bitcoin/coinselect2/index.ts +5 -4
- package/src/bitcoin/coinselect2/utils.ts +55 -14
- package/src/bitcoin/wallet/BitcoinWallet.ts +69 -57
- package/src/bitcoin/wallet/IBitcoinWallet.ts +44 -3
- package/src/bitcoin/wallet/SingleAddressBitcoinWallet.ts +12 -4
- package/src/events/UnifiedSwapEventListener.ts +11 -3
- package/src/http/HttpUtils.ts +10 -4
- package/src/http/paramcoders/client/StreamingFetchPromise.ts +4 -2
- package/src/index.ts +1 -0
- package/src/intermediaries/IntermediaryDiscovery.ts +9 -2
- package/src/intermediaries/apis/IntermediaryAPI.ts +335 -35
- package/src/intermediaries/auth/SignedKeyBasedAuth.ts +69 -0
- package/src/storage/IUnifiedStorage.ts +45 -4
- package/src/storage/UnifiedSwapStorage.ts +42 -8
- package/src/swapper/Swapper.ts +165 -24
- package/src/swapper/SwapperUtils.ts +42 -2
- package/src/swaps/ISwap.ts +88 -16
- package/src/swaps/ISwapWrapper.ts +28 -3
- package/src/swaps/escrow_swaps/IEscrowSwap.ts +5 -3
- package/src/swaps/escrow_swaps/IEscrowSwapWrapper.ts +3 -1
- package/src/swaps/escrow_swaps/frombtc/IFromBTCLNWrapper.ts +4 -1
- package/src/swaps/escrow_swaps/frombtc/ln/FromBTCLNSwap.ts +264 -67
- package/src/swaps/escrow_swaps/frombtc/ln/FromBTCLNWrapper.ts +6 -4
- package/src/swaps/escrow_swaps/frombtc/ln_auto/FromBTCLNAutoSwap.ts +390 -89
- package/src/swaps/escrow_swaps/frombtc/ln_auto/FromBTCLNAutoWrapper.ts +6 -4
- package/src/swaps/escrow_swaps/frombtc/onchain/FromBTCSwap.ts +548 -94
- package/src/swaps/escrow_swaps/frombtc/onchain/FromBTCWrapper.ts +7 -5
- package/src/swaps/escrow_swaps/tobtc/IToBTCSwap.ts +276 -45
- package/src/swaps/escrow_swaps/tobtc/ln/ToBTCLNWrapper.ts +7 -6
- package/src/swaps/escrow_swaps/tobtc/onchain/ToBTCWrapper.ts +5 -3
- package/src/swaps/spv_swaps/SpvFromBTCSwap.ts +413 -64
- package/src/swaps/spv_swaps/SpvFromBTCWrapper.ts +239 -61
- package/src/swaps/trusted/ln/LnForGasSwap.ts +211 -47
- package/src/swaps/trusted/ln/LnForGasWrapper.ts +1 -2
- package/src/swaps/trusted/onchain/OnchainForGasSwap.ts +32 -51
- package/src/swaps/trusted/onchain/OnchainForGasWrapper.ts +5 -3
- package/src/types/SwapExecutionAction.ts +266 -43
- package/src/types/SwapExecutionStep.ts +224 -0
- package/src/types/TokenAmount.ts +36 -2
- package/src/utils/BitcoinUtils.ts +73 -0
- package/src/utils/BitcoinWalletUtils.ts +2 -2
- package/src/utils/Utils.ts +10 -1
- package/src/intermediaries/apis/TrustedIntermediaryAPI.ts +0 -258
|
@@ -0,0 +1,431 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.SwapperApi = void 0;
|
|
4
|
+
const ApiTypes_1 = require("./ApiTypes");
|
|
5
|
+
const SerializedAction_1 = require("./SerializedAction");
|
|
6
|
+
const FeeType_1 = require("../enums/FeeType");
|
|
7
|
+
const SwapSide_1 = require("../enums/SwapSide");
|
|
8
|
+
const SwapType_1 = require("../enums/SwapType");
|
|
9
|
+
const FromBTCLNSwap_1 = require("../swaps/escrow_swaps/frombtc/ln/FromBTCLNSwap");
|
|
10
|
+
const FromBTCLNAutoSwap_1 = require("../swaps/escrow_swaps/frombtc/ln_auto/FromBTCLNAutoSwap");
|
|
11
|
+
const IEscrowSwap_1 = require("../swaps/escrow_swaps/IEscrowSwap");
|
|
12
|
+
const ToBTCLNSwap_1 = require("../swaps/escrow_swaps/tobtc/ln/ToBTCLNSwap");
|
|
13
|
+
function requiresSecretRevealForApi(swap, state) {
|
|
14
|
+
if (swap instanceof FromBTCLNSwap_1.FromBTCLNSwap) {
|
|
15
|
+
if (swap.hasSecretPreimage())
|
|
16
|
+
return false;
|
|
17
|
+
return state === FromBTCLNSwap_1.FromBTCLNSwapState.PR_PAID || state === FromBTCLNSwap_1.FromBTCLNSwapState.CLAIM_COMMITED;
|
|
18
|
+
}
|
|
19
|
+
if (swap instanceof FromBTCLNAutoSwap_1.FromBTCLNAutoSwap) {
|
|
20
|
+
if (swap.hasSecretPreimage())
|
|
21
|
+
return false;
|
|
22
|
+
return state === FromBTCLNAutoSwap_1.FromBTCLNAutoSwapState.CLAIM_COMMITED;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
function createSwapOutputBase(swap, steps, stateInfo) {
|
|
26
|
+
const input = swap.getInput();
|
|
27
|
+
const output = swap.getOutput();
|
|
28
|
+
const feeBreakdown = swap.getFeeBreakdown();
|
|
29
|
+
// Build fees from breakdown
|
|
30
|
+
const swapFeeEntry = feeBreakdown.find(f => f.type === FeeType_1.FeeType.SWAP);
|
|
31
|
+
const networkFeeEntry = feeBreakdown.find(f => f.type === FeeType_1.FeeType.NETWORK_OUTPUT);
|
|
32
|
+
return {
|
|
33
|
+
swapId: swap.getId(),
|
|
34
|
+
swapType: SwapType_1.SwapType[swap.getType()],
|
|
35
|
+
state: {
|
|
36
|
+
number: stateInfo.state,
|
|
37
|
+
name: stateInfo.name,
|
|
38
|
+
description: stateInfo.description
|
|
39
|
+
},
|
|
40
|
+
quote: {
|
|
41
|
+
inputAmount: (0, ApiTypes_1.toApiAmount)(input),
|
|
42
|
+
outputAmount: (0, ApiTypes_1.toApiAmount)(output),
|
|
43
|
+
fees: {
|
|
44
|
+
swap: swapFeeEntry
|
|
45
|
+
? (0, ApiTypes_1.toApiAmount)(swapFeeEntry.fee.amountInSrcToken)
|
|
46
|
+
: { amount: "0", rawAmount: "0", decimals: 0, symbol: "", chain: "" },
|
|
47
|
+
...(networkFeeEntry ? {
|
|
48
|
+
networkOutput: (0, ApiTypes_1.toApiAmount)(networkFeeEntry.fee.amountInSrcToken)
|
|
49
|
+
} : {})
|
|
50
|
+
},
|
|
51
|
+
expiry: swap.getQuoteExpiry(),
|
|
52
|
+
outputAddress: swap.getOutputAddress()
|
|
53
|
+
},
|
|
54
|
+
createdAt: swap.createdAt,
|
|
55
|
+
steps,
|
|
56
|
+
...(swap instanceof ToBTCLNSwap_1.ToBTCLNSwap && swap.isLNURL() ? {
|
|
57
|
+
lnurl: {
|
|
58
|
+
pay: swap.getLNURL(),
|
|
59
|
+
successAction: swap.getSuccessAction() ?? undefined
|
|
60
|
+
}
|
|
61
|
+
} : (swap instanceof FromBTCLNSwap_1.FromBTCLNSwap || swap instanceof FromBTCLNAutoSwap_1.FromBTCLNAutoSwap) && swap.isLNURL() ? {
|
|
62
|
+
lnurl: {
|
|
63
|
+
withdraw: swap.getLNURL(),
|
|
64
|
+
}
|
|
65
|
+
} : {})
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
function createListSwapOutput(swap, steps, stateInfo) {
|
|
69
|
+
return {
|
|
70
|
+
...createSwapOutputBase(swap, steps, stateInfo),
|
|
71
|
+
isFinished: swap.isFinished(),
|
|
72
|
+
isSuccess: swap.isSuccessful(),
|
|
73
|
+
isFailed: swap.isFailed(),
|
|
74
|
+
isExpired: swap.isQuoteExpired()
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
function parseSwapSide(side) {
|
|
78
|
+
return side === "INPUT" ? SwapSide_1.SwapSide.INPUT : SwapSide_1.SwapSide.OUTPUT;
|
|
79
|
+
}
|
|
80
|
+
class SwapperApi {
|
|
81
|
+
constructor(swapper, config) {
|
|
82
|
+
this.swapper = swapper;
|
|
83
|
+
this.config = config;
|
|
84
|
+
this.config ??= {};
|
|
85
|
+
this.config.syncOnGetStatus ??= true;
|
|
86
|
+
this.endpoints = {
|
|
87
|
+
createSwap: (0, ApiTypes_1.createApiEndpoint)("POST", "Create a new cross-chain atomic swap. Returns a swap object with swapId, swapType, state, createdAt, quote (with inputAmount and outputAmount as ApiAmount objects each having amount/rawAmount/decimals/symbol/chain, a fees breakdown {swap, networkOutput?} of ApiAmount values, expiry, and outputAddress), a steps array, and optional lnurl. After creation, poll getSwapStatus periodically to get the next required action.", this.createSwap.bind(this), {
|
|
88
|
+
srcToken: { type: "string", required: true, description: "Source token ticker (e.g. 'BITCOIN-BTC', 'LIGHTNING-BTC', 'STARKNET-STRK', 'SOLANA-SOL')" },
|
|
89
|
+
dstToken: { type: "string", required: true, description: "Destination token ticker" },
|
|
90
|
+
amount: { type: "bigint", required: true, description: "Amount in base units as an integer" },
|
|
91
|
+
amountType: { type: "string", required: true, description: "EXACT_IN or EXACT_OUT", allowedValues: ["EXACT_IN", "EXACT_OUT"] },
|
|
92
|
+
srcAddress: { type: "string", required: false, description: "Source address (only required for Smart chain -> BTC/Lightning swaps)" },
|
|
93
|
+
dstAddress: { type: "string", required: true, description: "Destination address" },
|
|
94
|
+
gasAmount: { type: "bigint", required: false, description: "Gas token amount to receive on destination chain, in base units" },
|
|
95
|
+
paymentHash: { type: "string", required: false, description: "Custom payment hash for Lightning swaps" },
|
|
96
|
+
lightningInvoiceDescription: { type: "string", required: false, description: "Description for Lightning invoice" },
|
|
97
|
+
lightningInvoiceDescriptionHash: { type: "string", required: false, description: "Description hash for Lightning invoice (hex)" },
|
|
98
|
+
lightningPaymentHTLCTimeout: { type: "number", required: false, description: "Custom expiry time in seconds" }
|
|
99
|
+
}),
|
|
100
|
+
listSwaps: (0, ApiTypes_1.createApiEndpoint)("GET", "List all swaps for a given signer address. Returns an array of swap objects, each with swapId, swapType, state, quote, steps, and terminal state flags (isFinished, isSuccess, isFailed, isExpired). Optionally filter by smart chain.", this.listSwaps.bind(this), {
|
|
101
|
+
signer: { type: "string", required: true, description: "Smart chain signer address to filter swaps for" },
|
|
102
|
+
chainId: { type: "string", required: false, description: "Optional smart chain identifier to filter swaps" }
|
|
103
|
+
}),
|
|
104
|
+
listPendingSwaps: (0, ApiTypes_1.createApiEndpoint)("GET", "List swaps that require user action for a given signer address. Returns an array of swap objects with the same structure as listSwaps.", this.listPendingSwaps.bind(this), {
|
|
105
|
+
signer: { type: "string", required: true, description: "Smart chain signer address to filter pending swaps for" },
|
|
106
|
+
chainId: { type: "string", required: false, description: "Optional smart chain identifier to filter pending swaps" }
|
|
107
|
+
}),
|
|
108
|
+
getSupportedTokens: (0, ApiTypes_1.createApiEndpoint)("GET", "List all tokens available as swap input or output. Returns an array of ApiToken objects, each with id (e.g. BITCOIN-BTC, LIGHTNING-BTC, STARKNET-STRK), chainId, ticker, name, decimals, and address.", this.getSupportedTokens.bind(this), {
|
|
109
|
+
side: {
|
|
110
|
+
type: "string",
|
|
111
|
+
required: true,
|
|
112
|
+
description: "Whether to list valid source tokens (INPUT) or destination tokens (OUTPUT)",
|
|
113
|
+
allowedValues: ["INPUT", "OUTPUT"]
|
|
114
|
+
}
|
|
115
|
+
}),
|
|
116
|
+
getSwapCounterTokens: (0, ApiTypes_1.createApiEndpoint)("GET", "Get tokens that can be swapped against a given token. Returns an array of ApiToken objects (id, chainId, ticker, name, decimals, address). Use to discover valid trading pairs.", this.getSwapCounterTokens.bind(this), {
|
|
117
|
+
token: {
|
|
118
|
+
type: "string",
|
|
119
|
+
required: true,
|
|
120
|
+
description: "Token identifier accepted by the API, e.g. BITCOIN-BTC, LIGHTNING-BTC, STARKNET-STRK, or a token address"
|
|
121
|
+
},
|
|
122
|
+
side: {
|
|
123
|
+
type: "string",
|
|
124
|
+
required: true,
|
|
125
|
+
description: "Treat the provided token as a source token (INPUT) or destination token (OUTPUT)",
|
|
126
|
+
allowedValues: ["INPUT", "OUTPUT"]
|
|
127
|
+
}
|
|
128
|
+
}),
|
|
129
|
+
getSwapLimits: (0, ApiTypes_1.createApiEndpoint)("GET", "Get minimum and maximum swap amounts for a source/destination token pair. Returns {input: {min, max?}, output: {min, max?}} where each value is an ApiAmount object with amount (decimal string), rawAmount (base units string), decimals, symbol, and chain.", this.getSwapLimits.bind(this), {
|
|
130
|
+
srcToken: { type: "string", required: true, description: "Source token identifier accepted by the API, e.g. BITCOIN-BTC, LIGHTNING-BTC, STARKNET-STRK" },
|
|
131
|
+
dstToken: { type: "string", required: true, description: "Destination token identifier accepted by the API, e.g. BITCOIN-BTC, LIGHTNING-BTC, STARKNET-STRK" }
|
|
132
|
+
}),
|
|
133
|
+
parseAddress: (0, ApiTypes_1.createApiEndpoint)("GET", "Parse and validate an address, Lightning invoice, LNURL, or Bitcoin URI. Returns {address, type} and optionally lnurl (ApiLNURL with pay/withdraw details), min/max/amount (as ApiAmount objects).", this.parseAddress.bind(this), {
|
|
134
|
+
address: { type: "string", required: true, description: "Address, invoice, LNURL, or URI string to parse" }
|
|
135
|
+
}),
|
|
136
|
+
getSpendableBalance: (0, ApiTypes_1.createApiEndpoint)("GET", "Get the spendable balance for a wallet address and token, accounting for chain fees. Returns {balance: ApiAmount, feeRate?} where ApiAmount has amount (decimal string), rawAmount (base units string), decimals, symbol, and chain.", this.getSpendableBalance.bind(this), {
|
|
137
|
+
wallet: { type: "string", required: true, description: "Wallet address to query" },
|
|
138
|
+
token: { type: "string", required: true, description: "Token identifier accepted by the API, e.g. BITCOIN-BTC, STARKNET-STRK, or a token address" },
|
|
139
|
+
targetChain: { type: "string", required: false, description: "Destination smart chain for Bitcoin SPV-vault fee estimation" },
|
|
140
|
+
gasDrop: { type: "boolean", required: false, description: "Whether to include gas-drop footprint when estimating Bitcoin SPV-vault spendable balance" },
|
|
141
|
+
feeRate: { type: "string", required: false, description: "Manual fee rate override" },
|
|
142
|
+
minBitcoinFeeRate: { type: "number", required: false, description: "Minimum Bitcoin fee rate to enforce" },
|
|
143
|
+
feeMultiplier: { type: "number", required: false, description: "Multiplier applied to smart-chain native token commit fee estimate" }
|
|
144
|
+
}),
|
|
145
|
+
getSwapStatus: (0, ApiTypes_1.createApiEndpoint)("GET", "Get the current status and next required action for a swap. Returns swap state, terminal flags (isFinished, isSuccess, isFailed, isExpired), and currentAction (an action object, or null when no action is currently required). For Lightning-to-smart-chain swaps it may also return requiresSecretReveal: true — when set, pass the secret parameter in subsequent getSwapStatus calls so the HTLC can be claimed. Handle each action type: SignPSBT — ask user to sign the Bitcoin PSBT with their wallet, then submit via submitTransaction. SignSmartChainTransaction — ask user to sign with their Solana/Starknet/EVM wallet, then submit via submitTransaction. SendToAddress — show the address and amount to the user, they pay externally, keep polling. Wait — poll again after pollTimeSeconds. Poll repeatedly until isFinished is true.", this.getSwapStatus.bind(this), {
|
|
146
|
+
swapId: { type: "string", required: true, description: "The swap identifier" },
|
|
147
|
+
secret: { type: "string", required: false, description: "Revealed swap secret pre-image (in hexadecimal format) for lightning network swaps" },
|
|
148
|
+
bitcoinAddress: { type: "string", required: false, description: "Bitcoin wallet address to obtain funded PSBT" },
|
|
149
|
+
bitcoinPublicKey: { type: "string", required: false, description: "Bitcoin wallet public key (in hexadecimal format) to obtain funded PSBT" },
|
|
150
|
+
bitcoinFeeRate: { type: "number", required: false, description: "Fee rate to use when creating a funded PSBT" },
|
|
151
|
+
signer: { type: "string", required: false, description: "Alternative different smart chain signer to use for refunds and manual settlement" }
|
|
152
|
+
}),
|
|
153
|
+
submitTransaction: (0, ApiTypes_1.createApiEndpoint)("POST", "Submit signed transaction(s) for a swap. Call this after the user has signed the transaction returned by getSwapStatus. Returns {txHashes: string[]} with the submitted transaction hashes. After submission, continue polling getSwapStatus.", this.submitTransaction.bind(this), {
|
|
154
|
+
swapId: { type: "string", required: true, description: "The swap identifier" },
|
|
155
|
+
signedTxs: {
|
|
156
|
+
type: "array",
|
|
157
|
+
required: true,
|
|
158
|
+
description: "Array of signed transaction data",
|
|
159
|
+
items: { type: "string", required: true, description: "Single string-serialized & signed transaction" }
|
|
160
|
+
}
|
|
161
|
+
}),
|
|
162
|
+
settleWithLnurl: (0, ApiTypes_1.createApiEndpoint)("POST", "Settle a Lightning Network swap using an LNURL-withdraw link. Returns {paymentHash: string} on success.", this.settleWithLnurl.bind(this), {
|
|
163
|
+
swapId: { type: "string", required: true, description: "The swap identifier" },
|
|
164
|
+
lnurlWithdraw: { type: "string", required: false, description: "LNURL-withdraw link to use to settle the Lightning network swap, if the swap was already created with the LNURL-withdraw link, this is optional" }
|
|
165
|
+
})
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
txSerializer(chainId, tx) {
|
|
169
|
+
const chain = this.swapper._chains[chainId];
|
|
170
|
+
if (chain == null)
|
|
171
|
+
throw new Error("Unknown chain: " + chainId);
|
|
172
|
+
return chain.chainInterface.serializeTx(tx);
|
|
173
|
+
}
|
|
174
|
+
async init() {
|
|
175
|
+
await this.swapper.init();
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Should be ran periodically, this synchronizes the swap's state with the on-chain data and also purges
|
|
179
|
+
* expired swaps from the persistent storage
|
|
180
|
+
*/
|
|
181
|
+
async sync() {
|
|
182
|
+
await this.swapper._syncSwaps();
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* Optionally good to run this periodically, such that any LPs that are dropped off because they are unresponsive
|
|
186
|
+
* can be found again.
|
|
187
|
+
*/
|
|
188
|
+
async reloadLps() {
|
|
189
|
+
await this.swapper.intermediaryDiscovery.reloadIntermediaries();
|
|
190
|
+
}
|
|
191
|
+
async createSwap(input) {
|
|
192
|
+
const exactIn = input.amountType === "EXACT_IN";
|
|
193
|
+
// Build options from input
|
|
194
|
+
const options = {};
|
|
195
|
+
if (input.gasAmount != null)
|
|
196
|
+
options.gasAmount = input.gasAmount;
|
|
197
|
+
if (input.paymentHash != null)
|
|
198
|
+
options.paymentHash = Buffer.from(input.paymentHash, "hex");
|
|
199
|
+
if (input.lightningInvoiceDescription != null)
|
|
200
|
+
options.description = input.lightningInvoiceDescription;
|
|
201
|
+
if (input.lightningInvoiceDescriptionHash != null)
|
|
202
|
+
options.descriptionHash = Buffer.from(input.lightningInvoiceDescriptionHash, "hex");
|
|
203
|
+
if (input.lightningPaymentHTLCTimeout != null)
|
|
204
|
+
options.expirySeconds = input.lightningPaymentHTLCTimeout;
|
|
205
|
+
// swapper.swap() handles routing based on token types
|
|
206
|
+
const swap = await this.swapper.swap(input.srcToken, input.dstToken, input.amount, exactIn, input.srcAddress, input.dstAddress, Object.keys(options).length > 0 ? options : undefined);
|
|
207
|
+
const { steps, stateInfo } = await swap.getExecutionStatus({ skipBuildingAction: true });
|
|
208
|
+
return createSwapOutputBase(swap, steps, stateInfo);
|
|
209
|
+
}
|
|
210
|
+
validateSwapListInput(input) {
|
|
211
|
+
if (input.chainId != null && !this.swapper.getSmartChains().includes(input.chainId)) {
|
|
212
|
+
throw new Error("Unknown chainId: " + input.chainId);
|
|
213
|
+
}
|
|
214
|
+
if (!this.swapper.Utils.isValidSmartChainAddress(input.signer, input.chainId)) {
|
|
215
|
+
throw new Error(input.chainId != null
|
|
216
|
+
? `Invalid ${input.chainId} signer address: ` + input.signer
|
|
217
|
+
: `Invalid smart chain signer address: ` + input.signer);
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
async createListedSwapOutputs(swaps) {
|
|
221
|
+
return Promise.all(swaps
|
|
222
|
+
.filter(swap => swap.getType() !== SwapType_1.SwapType.TRUSTED_FROM_BTC)
|
|
223
|
+
.map(async (swap) => {
|
|
224
|
+
const { steps, stateInfo } = await swap.getExecutionStatus({ skipBuildingAction: true });
|
|
225
|
+
return createListSwapOutput(swap, steps, stateInfo);
|
|
226
|
+
}));
|
|
227
|
+
}
|
|
228
|
+
async listSwaps(input) {
|
|
229
|
+
this.validateSwapListInput(input);
|
|
230
|
+
const swaps = await this.swapper.getAllSwaps(input.chainId, input.signer);
|
|
231
|
+
return this.createListedSwapOutputs(swaps);
|
|
232
|
+
}
|
|
233
|
+
async listPendingSwaps(input) {
|
|
234
|
+
this.validateSwapListInput(input);
|
|
235
|
+
const swaps = await this.swapper.getPendingSwaps(input.chainId, input.signer);
|
|
236
|
+
return this.createListedSwapOutputs(swaps);
|
|
237
|
+
}
|
|
238
|
+
async getSupportedTokens(input) {
|
|
239
|
+
return this.swapper.getSupportedTokens(parseSwapSide(input.side)).map(ApiTypes_1.toApiToken);
|
|
240
|
+
}
|
|
241
|
+
async getSwapCounterTokens(input) {
|
|
242
|
+
const token = this.swapper.getToken(input.token);
|
|
243
|
+
return this.swapper.getSwapCounterTokens(token, parseSwapSide(input.side)).map(ApiTypes_1.toApiToken);
|
|
244
|
+
}
|
|
245
|
+
async getSwapLimits(input) {
|
|
246
|
+
const srcToken = this.swapper.getToken(input.srcToken);
|
|
247
|
+
const dstToken = this.swapper.getToken(input.dstToken);
|
|
248
|
+
let limits = this.swapper.getSwapLimits(srcToken, dstToken);
|
|
249
|
+
if (dstToken.chainId !== "LIGHTNING") {
|
|
250
|
+
if (limits.input.min.rawAmount === 1n || limits.output.min.rawAmount === 1n) {
|
|
251
|
+
// Execute a dummy swap to get the proper limits
|
|
252
|
+
try {
|
|
253
|
+
await this.swapper.swap(srcToken, dstToken, 1n, limits.input.min.rawAmount === 1n, srcToken.chainId === "LIGHTNING" ? undefined : this.swapper.Utils.randomAddress(srcToken.chainId), this.swapper.Utils.randomAddress(dstToken.chainId));
|
|
254
|
+
}
|
|
255
|
+
catch (e) { }
|
|
256
|
+
limits = this.swapper.getSwapLimits(srcToken, dstToken);
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
return {
|
|
260
|
+
input: {
|
|
261
|
+
min: (0, ApiTypes_1.toApiAmount)(limits.input.min),
|
|
262
|
+
...(limits.input.max != null ? { max: (0, ApiTypes_1.toApiAmount)(limits.input.max) } : {})
|
|
263
|
+
},
|
|
264
|
+
output: {
|
|
265
|
+
min: (0, ApiTypes_1.toApiAmount)(limits.output.min),
|
|
266
|
+
...(limits.output.max != null ? { max: (0, ApiTypes_1.toApiAmount)(limits.output.max) } : {})
|
|
267
|
+
}
|
|
268
|
+
};
|
|
269
|
+
}
|
|
270
|
+
async parseAddress(input) {
|
|
271
|
+
const result = await this.swapper.Utils.parseAddress(input.address);
|
|
272
|
+
if (result == null)
|
|
273
|
+
throw new Error("Invalid address");
|
|
274
|
+
return {
|
|
275
|
+
address: result.address,
|
|
276
|
+
type: result.type,
|
|
277
|
+
...(result.lnurl != null ? { lnurl: (0, ApiTypes_1.toApiLNURL)(result.lnurl, this.swapper) } : {}),
|
|
278
|
+
...(result.min != null ? { min: (0, ApiTypes_1.toApiAmount)(result.min) } : {}),
|
|
279
|
+
...(result.max != null ? { max: (0, ApiTypes_1.toApiAmount)(result.max) } : {}),
|
|
280
|
+
...(result.amount != null ? { amount: (0, ApiTypes_1.toApiAmount)(result.amount) } : {})
|
|
281
|
+
};
|
|
282
|
+
}
|
|
283
|
+
async getSpendableBalance(input) {
|
|
284
|
+
const token = this.swapper.getToken(input.token);
|
|
285
|
+
if (token.chainId === "LIGHTNING")
|
|
286
|
+
throw new Error("Lightning wallet spendable balance is not supported by this endpoint.");
|
|
287
|
+
if (input.feeRate != null && input.feeMultiplier != null)
|
|
288
|
+
throw new Error("`feeMultiplier` cannot be specified alongside the `feeRate` parameter.");
|
|
289
|
+
if (token.chainId === "BITCOIN") {
|
|
290
|
+
if (input.targetChain != null && !this.swapper.getSmartChains().includes(input.targetChain)) {
|
|
291
|
+
throw new Error("Unknown targetChain: " + input.targetChain);
|
|
292
|
+
}
|
|
293
|
+
if (!this.swapper.Utils.isValidBitcoinAddress(input.wallet))
|
|
294
|
+
throw new Error(`Invalid BITCOIN wallet address: ` + input.wallet);
|
|
295
|
+
let btcFeeRate;
|
|
296
|
+
if (input.feeRate != null) {
|
|
297
|
+
btcFeeRate = parseFloat(input.feeRate);
|
|
298
|
+
if (isNaN(btcFeeRate) || btcFeeRate <= 0)
|
|
299
|
+
throw new Error("Bitcoin `feeRate` must be a valid positive number!");
|
|
300
|
+
}
|
|
301
|
+
else
|
|
302
|
+
btcFeeRate = await this.swapper._bitcoinRpc.getFeeRate();
|
|
303
|
+
if (input.feeMultiplier != null)
|
|
304
|
+
btcFeeRate *= input.feeMultiplier;
|
|
305
|
+
const { balance, feeRate } = await this.swapper.Utils.getBitcoinSpendableBalance(input.wallet, input.targetChain, {
|
|
306
|
+
gasDrop: input.gasDrop,
|
|
307
|
+
feeRate: btcFeeRate,
|
|
308
|
+
minFeeRate: input.minBitcoinFeeRate
|
|
309
|
+
});
|
|
310
|
+
return {
|
|
311
|
+
balance: (0, ApiTypes_1.toApiAmount)(balance),
|
|
312
|
+
feeRate
|
|
313
|
+
};
|
|
314
|
+
}
|
|
315
|
+
if (input.gasDrop === true)
|
|
316
|
+
throw new Error("`gasDrop` is only supported for Bitcoin balances.");
|
|
317
|
+
if (input.minBitcoinFeeRate != null)
|
|
318
|
+
throw new Error("`minBitcoinFeeRate` is only supported for Bitcoin balances.");
|
|
319
|
+
if (!this.swapper.Utils.isValidSmartChainAddress(input.wallet, token.chainId))
|
|
320
|
+
throw new Error(`Invalid ${token.chainId} wallet address: ` + input.wallet);
|
|
321
|
+
const balance = await this.swapper.Utils.getSpendableBalance(input.wallet, token, {
|
|
322
|
+
feeMultiplier: input.feeMultiplier,
|
|
323
|
+
feeRate: input.feeRate
|
|
324
|
+
});
|
|
325
|
+
return {
|
|
326
|
+
balance: (0, ApiTypes_1.toApiAmount)(balance)
|
|
327
|
+
};
|
|
328
|
+
}
|
|
329
|
+
async getSwapStatus(input) {
|
|
330
|
+
const swap = await this.swapper.getSwapById(input.swapId);
|
|
331
|
+
if (swap == null) {
|
|
332
|
+
throw new Error("Swap not found: " + input.swapId);
|
|
333
|
+
}
|
|
334
|
+
if (input.signer != null && !this.swapper.Utils.isValidSmartChainAddress(input.signer, swap.chainIdentifier)) {
|
|
335
|
+
throw new Error(`Invalid ${swap.chainIdentifier} signer address: ` + input.signer);
|
|
336
|
+
}
|
|
337
|
+
if (input.secret != null) {
|
|
338
|
+
try {
|
|
339
|
+
Buffer.from(input.secret, "hex");
|
|
340
|
+
}
|
|
341
|
+
catch (e) {
|
|
342
|
+
throw new Error(`Invalid secret passed, has to be a hexadecimal string!`);
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
let bitcoinWallet;
|
|
346
|
+
if (input.bitcoinAddress != null && input.bitcoinPublicKey != null) {
|
|
347
|
+
bitcoinWallet = {
|
|
348
|
+
publicKey: input.bitcoinPublicKey,
|
|
349
|
+
address: input.bitcoinAddress
|
|
350
|
+
};
|
|
351
|
+
}
|
|
352
|
+
else if (input.bitcoinAddress != null || input.bitcoinPublicKey != null) {
|
|
353
|
+
throw new Error("When specifying bitcoin wallet you have to pass both `bitcoinAddress` and `bitcoinPublicKey` params!");
|
|
354
|
+
}
|
|
355
|
+
if (input.bitcoinFeeRate != null) {
|
|
356
|
+
if (isNaN(input.bitcoinFeeRate))
|
|
357
|
+
throw new Error("Bitcoin fee rate passed cannot be NaN!");
|
|
358
|
+
if (input.bitcoinFeeRate <= 0)
|
|
359
|
+
throw new Error("Bitcoin fee rate passed cannot be negative or 0!");
|
|
360
|
+
}
|
|
361
|
+
if (this.config?.syncOnGetStatus)
|
|
362
|
+
await swap._sync(true);
|
|
363
|
+
const { steps, stateInfo, currentAction } = await swap.getExecutionStatus({
|
|
364
|
+
secret: input.secret,
|
|
365
|
+
bitcoinWallet,
|
|
366
|
+
bitcoinFeeRate: input.bitcoinFeeRate,
|
|
367
|
+
manualSettlementSmartChainSigner: input.signer,
|
|
368
|
+
refundSmartChainSigner: input.signer
|
|
369
|
+
});
|
|
370
|
+
return {
|
|
371
|
+
...createListSwapOutput(swap, steps, stateInfo),
|
|
372
|
+
currentAction: currentAction ? await (0, SerializedAction_1.serializeAction)(currentAction, this.txSerializer.bind(this)) : null,
|
|
373
|
+
requiresSecretReveal: requiresSecretRevealForApi(swap, stateInfo.state),
|
|
374
|
+
escrow: swap instanceof IEscrowSwap_1.IEscrowSwap && swap._data != null ? {
|
|
375
|
+
data: swap._data.getEscrowStruct(),
|
|
376
|
+
initTxId: swap._commitTxId
|
|
377
|
+
} : undefined
|
|
378
|
+
};
|
|
379
|
+
}
|
|
380
|
+
async submitTransaction(input, abortSignal) {
|
|
381
|
+
const swap = await this.swapper.getSwapById(input.swapId);
|
|
382
|
+
if (swap == null) {
|
|
383
|
+
throw new Error("Swap not found: " + input.swapId);
|
|
384
|
+
}
|
|
385
|
+
return {
|
|
386
|
+
txHashes: await swap._submitExecutionTransactions(input.signedTxs, abortSignal, undefined, this.config?.idempotentTxSubmission)
|
|
387
|
+
};
|
|
388
|
+
}
|
|
389
|
+
async settleWithLnurl(input, abortSignal) {
|
|
390
|
+
const swap = await this.swapper.getSwapById(input.swapId);
|
|
391
|
+
if (swap == null)
|
|
392
|
+
throw new Error("Swap not found: " + input.swapId);
|
|
393
|
+
if (swap instanceof FromBTCLNAutoSwap_1.FromBTCLNAutoSwap) {
|
|
394
|
+
if (swap._state !== FromBTCLNAutoSwap_1.FromBTCLNAutoSwapState.PR_CREATED)
|
|
395
|
+
throw new Error("Invalid swap state, must be in PR_CREATED state!");
|
|
396
|
+
}
|
|
397
|
+
else if (swap instanceof FromBTCLNSwap_1.FromBTCLNSwap) {
|
|
398
|
+
if (swap._state !== FromBTCLNSwap_1.FromBTCLNSwapState.PR_CREATED)
|
|
399
|
+
throw new Error("Invalid swap state, must be in PR_CREATED state!");
|
|
400
|
+
}
|
|
401
|
+
else {
|
|
402
|
+
throw new Error("Endpoint only supports swaps from Lightning");
|
|
403
|
+
}
|
|
404
|
+
if (!swap.isLNURL()) {
|
|
405
|
+
if (input.lnurlWithdraw == null)
|
|
406
|
+
throw new Error("The swap is not configured to use LNURL, please pass the `lnurlWithdraw` parameter!");
|
|
407
|
+
if (!this.swapper.Utils.isValidLNURL(input.lnurlWithdraw))
|
|
408
|
+
throw new Error("Invalid LNURL-withdraw link provided: " + input.lnurlWithdraw);
|
|
409
|
+
await swap.settleWithLNURLWithdraw(input.lnurlWithdraw);
|
|
410
|
+
}
|
|
411
|
+
else {
|
|
412
|
+
if (input.lnurlWithdraw != null)
|
|
413
|
+
throw new Error("The swap is already configured with an LNURL link, don't pass the `lnurlWithdraw` parameter!");
|
|
414
|
+
}
|
|
415
|
+
let success;
|
|
416
|
+
if (swap instanceof FromBTCLNAutoSwap_1.FromBTCLNAutoSwap) {
|
|
417
|
+
// For non-legacy swap, we don't need to wait till the swap advances all the way to committed state
|
|
418
|
+
success = await swap._waitForLpPaymentReceived(2, abortSignal);
|
|
419
|
+
}
|
|
420
|
+
else {
|
|
421
|
+
// For legacy swap waitForPayment waits just for the swap to transition into PR_PAID
|
|
422
|
+
success = await swap.waitForPayment(undefined, 2, abortSignal);
|
|
423
|
+
}
|
|
424
|
+
if (!success)
|
|
425
|
+
throw new Error("Failed to settle the swap with the LNURL-withdraw link!");
|
|
426
|
+
return {
|
|
427
|
+
paymentHash: swap.getInputTxId()
|
|
428
|
+
};
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
exports.SwapperApi = SwapperApi;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { ApiAmount, ApiEndpoint, ApiLNURL, ApiLNURLPay, ApiLNURLWithdraw, ApiToken, InputSchema, InputSchemaField, toApiLNURL, toApiToken } from "./ApiTypes";
|
|
2
|
+
export { SerializedAction } from "./SerializedAction";
|
|
3
|
+
export * from "./SwapperApi";
|
|
4
|
+
export * from "./ApiEndpoints";
|
|
5
|
+
export { parseApiInput } from "./ApiParser";
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
exports.parseApiInput = exports.toApiToken = exports.toApiLNURL = void 0;
|
|
18
|
+
var ApiTypes_1 = require("./ApiTypes");
|
|
19
|
+
Object.defineProperty(exports, "toApiLNURL", { enumerable: true, get: function () { return ApiTypes_1.toApiLNURL; } });
|
|
20
|
+
Object.defineProperty(exports, "toApiToken", { enumerable: true, get: function () { return ApiTypes_1.toApiToken; } });
|
|
21
|
+
__exportStar(require("./SwapperApi"), exports);
|
|
22
|
+
__exportStar(require("./ApiEndpoints"), exports);
|
|
23
|
+
var ApiParser_1 = require("./ApiParser");
|
|
24
|
+
Object.defineProperty(exports, "parseApiInput", { enumerable: true, get: function () { return ApiParser_1.parseApiInput; } });
|
|
@@ -2,5 +2,6 @@ import { CoinselectAddressTypes, CoinselectTxInput, CoinselectTxOutput } from ".
|
|
|
2
2
|
export declare function accumulative(utxos: CoinselectTxInput[], outputs: CoinselectTxOutput[], feeRate: number, type: CoinselectAddressTypes, requiredInputs?: CoinselectTxInput[]): {
|
|
3
3
|
inputs?: CoinselectTxInput[];
|
|
4
4
|
outputs?: CoinselectTxOutput[];
|
|
5
|
+
effectiveFeeRate?: number;
|
|
5
6
|
fee: number;
|
|
6
7
|
};
|
|
@@ -7,7 +7,7 @@ const logger = (0, Logger_1.getLogger)("CoinSelect: ");
|
|
|
7
7
|
// add inputs until we reach or surpass the target value (or deplete)
|
|
8
8
|
// worst-case: O(n)
|
|
9
9
|
function accumulative(utxos, outputs, feeRate, type, requiredInputs) {
|
|
10
|
-
if (!isFinite(utils_1.utils.
|
|
10
|
+
if (!isFinite(utils_1.utils.numberOrNaN(feeRate)))
|
|
11
11
|
throw new Error("Invalid feeRate passed!");
|
|
12
12
|
const inputs = requiredInputs == null ? [] : [...requiredInputs];
|
|
13
13
|
let bytesAccum = utils_1.utils.transactionBytes(inputs, outputs, type);
|
|
@@ -2,5 +2,6 @@ import { CoinselectAddressTypes, CoinselectTxInput, CoinselectTxOutput } from ".
|
|
|
2
2
|
export declare function blackjack(utxos: CoinselectTxInput[], outputs: CoinselectTxOutput[], feeRate: number, type: CoinselectAddressTypes, requiredInputs?: CoinselectTxInput[]): {
|
|
3
3
|
inputs?: CoinselectTxInput[];
|
|
4
4
|
outputs?: CoinselectTxOutput[];
|
|
5
|
+
effectiveFeeRate?: number;
|
|
5
6
|
fee: number;
|
|
6
7
|
};
|
|
@@ -5,7 +5,7 @@ const utils_1 = require("./utils");
|
|
|
5
5
|
// add inputs until we reach or surpass the target value (or deplete)
|
|
6
6
|
// worst-case: O(n)
|
|
7
7
|
function blackjack(utxos, outputs, feeRate, type, requiredInputs) {
|
|
8
|
-
if (!isFinite(utils_1.utils.
|
|
8
|
+
if (!isFinite(utils_1.utils.numberOrNaN(feeRate)))
|
|
9
9
|
throw new Error("Invalid feeRate passed!");
|
|
10
10
|
const inputs = requiredInputs == null ? [] : [...requiredInputs];
|
|
11
11
|
let bytesAccum = utils_1.utils.transactionBytes(inputs, outputs, type);
|
|
@@ -5,12 +5,13 @@ export { CoinselectAddressTypes, CoinselectTxInput, CoinselectTxOutput, DUST_THR
|
|
|
5
5
|
export declare function coinSelect(utxos: CoinselectTxInput[], outputs: CoinselectTxOutput[], feeRate: number, type: CoinselectAddressTypes, requiredInputs?: CoinselectTxInput[]): {
|
|
6
6
|
inputs?: CoinselectTxInput[];
|
|
7
7
|
outputs?: CoinselectTxOutput[];
|
|
8
|
+
effectiveFeeRate?: number;
|
|
8
9
|
fee: number;
|
|
9
10
|
};
|
|
10
|
-
export declare function maxSendable(utxos: CoinselectTxInput[], output: {
|
|
11
|
+
export declare function maxSendable(utxos: Omit<CoinselectTxInput, "txId" | "address" | "vout" | "outputScript">[], output: {
|
|
11
12
|
script: Buffer;
|
|
12
13
|
type: CoinselectAddressTypes;
|
|
13
|
-
}, feeRate: number, requiredInputs?: CoinselectTxInput[], additionalOutputs?: {
|
|
14
|
+
}, feeRate: number, requiredInputs?: Omit<CoinselectTxInput, "txId" | "address" | "vout" | "outputScript">[], additionalOutputs?: {
|
|
14
15
|
script: Buffer;
|
|
15
16
|
value: number;
|
|
16
17
|
}[]): {
|
|
@@ -28,7 +28,7 @@ function coinSelect(utxos, outputs, feeRate, type, requiredInputs) {
|
|
|
28
28
|
}
|
|
29
29
|
exports.coinSelect = coinSelect;
|
|
30
30
|
function maxSendable(utxos, output, feeRate, requiredInputs, additionalOutputs) {
|
|
31
|
-
if (!isFinite(utils_1.utils.
|
|
31
|
+
if (!isFinite(utils_1.utils.numberOrNaN(feeRate)))
|
|
32
32
|
throw new Error("Invalid feeRate passed!");
|
|
33
33
|
const outputs = additionalOutputs ?? [];
|
|
34
34
|
const inputs = requiredInputs ?? [];
|
|
@@ -42,7 +42,7 @@ function maxSendable(utxos, output, feeRate, requiredInputs, additionalOutputs)
|
|
|
42
42
|
const utxoFee = feeRate * utxoBytes;
|
|
43
43
|
let cpfpFee = 0;
|
|
44
44
|
if (utxo.cpfp != null && utxo.cpfp.txEffectiveFeeRate < feeRate)
|
|
45
|
-
cpfpFee = utxo.cpfp.txVsize * (feeRate - utxo.cpfp.txEffectiveFeeRate);
|
|
45
|
+
cpfpFee = Math.ceil(utxo.cpfp.txVsize * (feeRate - utxo.cpfp.txEffectiveFeeRate));
|
|
46
46
|
const utxoValue = utils_1.utils.uintOrNaN(utxo.value);
|
|
47
47
|
// skip detrimental input
|
|
48
48
|
if (utxoFee + cpfpFee > utxo.value) {
|
|
@@ -52,6 +52,7 @@ declare function transactionBytes(inputs: {
|
|
|
52
52
|
script?: Buffer;
|
|
53
53
|
type?: CoinselectAddressTypes;
|
|
54
54
|
}[], changeType?: CoinselectAddressTypes): number;
|
|
55
|
+
declare function numberOrNaN(v: number): number;
|
|
55
56
|
declare function uintOrNaN(v: number): number;
|
|
56
57
|
declare function sumForgiving(range: {
|
|
57
58
|
value: number;
|
|
@@ -59,11 +60,13 @@ declare function sumForgiving(range: {
|
|
|
59
60
|
declare function sumOrNaN(range: {
|
|
60
61
|
value: number;
|
|
61
62
|
}[]): number;
|
|
62
|
-
declare function finalize(inputs:
|
|
63
|
-
inputs?:
|
|
63
|
+
declare function finalize<T extends Omit<CoinselectTxInput, "txId" | "address" | "vout" | "outputScript">>(inputs: T[], outputs: CoinselectTxOutput[], feeRate: number, changeType: CoinselectAddressTypes | null, cpfpAddFee?: number): {
|
|
64
|
+
inputs?: T[];
|
|
64
65
|
outputs?: CoinselectTxOutput[];
|
|
66
|
+
effectiveFeeRate?: number;
|
|
65
67
|
fee: number;
|
|
66
68
|
};
|
|
69
|
+
declare function isDetrimentalInput(feeRate: number, utxo: Omit<CoinselectTxInput, "txId" | "address" | "vout" | "outputScript">): boolean;
|
|
67
70
|
export declare const utils: {
|
|
68
71
|
dustThreshold: typeof dustThreshold;
|
|
69
72
|
finalize: typeof finalize;
|
|
@@ -73,5 +76,7 @@ export declare const utils: {
|
|
|
73
76
|
sumForgiving: typeof sumForgiving;
|
|
74
77
|
transactionBytes: typeof transactionBytes;
|
|
75
78
|
uintOrNaN: typeof uintOrNaN;
|
|
79
|
+
numberOrNaN: typeof numberOrNaN;
|
|
80
|
+
isDetrimentalInput: typeof isDetrimentalInput;
|
|
76
81
|
};
|
|
77
82
|
export {};
|