@atomiqlabs/sdk
Version:
atomiq labs SDK for cross-chain swaps between smart chains and bitcoin
575 lines (574 loc) • 31.3 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ToBTCLNWrapper = void 0;
const bolt11_1 = require("@atomiqlabs/bolt11");
const ToBTCLNSwap_1 = require("./ToBTCLNSwap");
const IToBTCWrapper_1 = require("../IToBTCWrapper");
const UserError_1 = require("../../../../errors/UserError");
const base_1 = require("@atomiqlabs/base");
const Intermediary_1 = require("../../../../intermediaries/Intermediary");
const IntermediaryError_1 = require("../../../../errors/IntermediaryError");
const SwapType_1 = require("../../../../enums/SwapType");
const Utils_1 = require("../../../../utils/Utils");
const RequestError_1 = require("../../../../errors/RequestError");
const LNURL_1 = require("../../../../lnurl/LNURL");
const IToBTCSwap_1 = require("../IToBTCSwap");
const sha2_1 = require("@noble/hashes/sha2");
const RetryUtils_1 = require("../../../../utils/RetryUtils");
/**
* Escrow based (HTLC) swap for Smart chains -> Bitcoin lightning
*
* @category Swaps/Smart chain → Lightning
*/
class ToBTCLNWrapper extends IToBTCWrapper_1.IToBTCWrapper {
constructor(chainIdentifier, unifiedStorage, unifiedChainEvents, chain, prices, tokens, versionedContracts, lpApi, options, events) {
super(chainIdentifier, unifiedStorage, unifiedChainEvents, chain, prices, tokens, lpApi, {
...options,
paymentTimeoutSeconds: options?.paymentTimeoutSeconds ?? 5 * 24 * 60 * 60,
maxPaymentTimeoutSeconds: options?.maxPaymentTimeoutSeconds ?? 10 * 24 * 60 * 60,
lightningBaseFee: options?.lightningBaseFee ?? 10,
lightningFeePPM: options?.lightningFeePPM ?? 2000
}, versionedContracts, events);
this.TYPE = SwapType_1.SwapType.TO_BTCLN;
/**
* @internal
*/
this._swapDeserializer = ToBTCLNSwap_1.ToBTCLNSwap;
}
toRequiredSwapOptions(amountData, options, pricePreFetchPromise, abortSignal) {
const expirySeconds = options?.expirySeconds ?? this._options.paymentTimeoutSeconds;
const maxRoutingBaseFee = options?.maxRoutingBaseFee ?? BigInt(this._options.lightningBaseFee);
const maxRoutingPPM = options?.maxRoutingFeePercentage != null
? BigInt(Math.floor(options.maxRoutingFeePercentage * 10000))
: options?.maxRoutingPPM ?? BigInt(this._options.lightningFeePPM);
let maxFee;
if (options?.maxFee != null) {
maxFee = options.maxFee;
}
else if (amountData.exactIn) {
if (pricePreFetchPromise != null) {
maxFee = pricePreFetchPromise
.then(val => this._prices.getFromBtcSwapAmount(this.chainIdentifier, maxRoutingBaseFee, amountData.token, abortSignal, val))
.then(_maxBaseFee => this.calculateFeeForAmount(amountData.amount, _maxBaseFee, maxRoutingPPM));
}
else {
maxFee = this._prices.getFromBtcSwapAmount(this.chainIdentifier, maxRoutingBaseFee, amountData.token, abortSignal)
.then(_maxBaseFee => this.calculateFeeForAmount(amountData.amount, _maxBaseFee, maxRoutingPPM));
}
}
else {
maxFee = this.calculateFeeForAmount(amountData.amount, maxRoutingBaseFee, maxRoutingPPM);
}
return {
expiryTimestamp: options?.expiryTimestamp ?? BigInt(Math.floor(Date.now() / 1000) + expirySeconds),
maxFee
};
}
/**
* Verifies whether a given payment hash was already paid by checking the local
* storage of known swaps
*
* @param paymentHash Payment hash to check
*
* @private
*/
async checkPaymentHashWasPaid(paymentHash) {
const swaps = await this.unifiedStorage.query([[{ key: "type", value: this.TYPE }, { key: "paymentHash", value: paymentHash }]], (obj) => new this._swapDeserializer(this, obj));
for (let value of swaps) {
if (value._state === IToBTCSwap_1.ToBTCSwapState.CLAIMED || value._state === IToBTCSwap_1.ToBTCSwapState.SOFT_CLAIMED)
throw new UserError_1.UserError("Lightning invoice was already paid!");
}
}
/**
* Calculates maximum lightning network routing fee based on amount
*
* @param amount BTC amount of the swap in satoshis
* @param overrideBaseFee Override wrapper's default base fee
* @param overrideFeePPM Override wrapper's default PPM
*
* @returns Maximum lightning routing fee in sats
*
* @private
*/
calculateFeeForAmount(amount, overrideBaseFee, overrideFeePPM) {
return BigInt(overrideBaseFee ?? this._options.lightningBaseFee)
+ (amount * BigInt(overrideFeePPM ?? this._options.lightningFeePPM) / 1000000n);
}
/**
* Verifies returned LP data
*
* @param signer
* @param resp Response as returned by the LP
* @param parsedPr Parsed bolt11 lightning invoice
* @param token Smart chain token to be used in the swap
* @param lp
* @param calculatedOptions Swap options computed from the swap create options
* @param data Parsed swap data returned by the LP
* @param requiredTotal Required total to be paid on the input (for exactIn swaps)
*
* @throws {IntermediaryError} In case the response is not valid
*
* @private
*/
async verifyReturnedData(signer, resp, parsedPr, token, lp, calculatedOptions, data, requiredTotal) {
if (resp.routingFeeSats > await calculatedOptions.maxFee)
throw new IntermediaryError_1.IntermediaryError("Invalid max fee sats returned");
if (requiredTotal != null && resp.total !== requiredTotal)
throw new IntermediaryError_1.IntermediaryError("Invalid data returned - total amount");
if (parsedPr.tagsObject.payment_hash == null)
throw new Error("Swap invoice doesn't contain payment hash field!");
const claimHash = this._contract(lp.getContractVersion(this.chainIdentifier)).getHashForHtlc(Buffer.from(parsedPr.tagsObject.payment_hash, "hex"));
if (data.getAmount() !== resp.total ||
!Buffer.from(data.getClaimHash(), "hex").equals(claimHash) ||
data.getExpiry() !== calculatedOptions.expiryTimestamp ||
data.getType() !== base_1.ChainSwapType.HTLC ||
!data.isPayIn() ||
!data.isToken(token) ||
!data.isClaimer(lp.getAddress(this.chainIdentifier)) ||
!data.isOfferer(signer) ||
data.getTotalDeposit() !== 0n) {
throw new IntermediaryError_1.IntermediaryError("Invalid data returned");
}
}
/**
* Returns the expiry seconds to use to calculate expiration timeout for HTLC, considers the `expirySeconds` and
* `maxExpirySeconds` params.
*
* @param parsedPr
* @param options
* @private
*/
getExpirySeconds(parsedPr, options) {
let expirySeconds = options?.expirySeconds;
let longExpiry = false;
if (parsedPr.tagsObject.min_final_cltv_expiry != null &&
parsedPr.tagsObject.min_final_cltv_expiry > 144) {
expirySeconds ??= this._options.paymentTimeoutSeconds;
let maxExpirySeconds = options?.maxExpirySeconds;
if (maxExpirySeconds != null) {
if (maxExpirySeconds < expirySeconds)
throw new Error(`maxExpirySeconds must be strictly larger than the regular expiration seconds: ${expirySeconds}`);
}
maxExpirySeconds ??= this._options.maxPaymentTimeoutSeconds;
if (maxExpirySeconds > expirySeconds) {
expirySeconds = Math.min(maxExpirySeconds, ((parsedPr.tagsObject.min_final_cltv_expiry - 144) * 600 * 2) + expirySeconds);
longExpiry = true;
}
}
return { expirySeconds, longExpiry };
}
/**
* Returns the quote/swap from a given intermediary
*
* @param signer Smartchain signer initiating the swap
* @param amountData
* @param lp Intermediary
* @param pr bolt11 lightning network invoice
* @param parsedPr Parsed bolt11 lightning network invoice
* @param calculatedOptions Swap options computed from the swap create options
* @param preFetches
* @param abort Abort signal or controller, if AbortController is passed it is used as-is, when AbortSignal is passed
* it is extended with extendAbortController and then used
* @param additionalParams Additional params that should be sent to the LP
*
* @private
*/
async getIntermediaryQuote(signer, amountData, lp, pr, parsedPr, calculatedOptions, preFetches, abort, additionalParams) {
if (lp.services[SwapType_1.SwapType.TO_BTCLN] == null)
throw new Error("LP service for processing to btcln swaps not found!");
const version = lp.getContractVersion(this.chainIdentifier);
const abortController = abort instanceof AbortController ? abort : (0, Utils_1.extendAbortController)(abort);
const reputationPromise = this.preFetchIntermediaryReputation(amountData, lp, abortController, version);
try {
const { signDataPromise, resp } = await (0, RetryUtils_1.tryWithRetries)(async (retryCount) => {
const { signDataPrefetch, response } = this._lpApi.initToBTCLN(this.chainIdentifier, lp.url, {
offerer: signer,
pr,
maxFee: await calculatedOptions.maxFee,
expiryTimestamp: calculatedOptions.expiryTimestamp,
token: amountData.token,
feeRate: (0, Utils_1.throwIfUndefined)(preFetches.feeRatePromise[version], "Network fee rate pre-fetch failed!"),
additionalParams
}, this._options.postRequestTimeout, abortController.signal, retryCount > 0 ? false : undefined);
let signDataPromise = preFetches.signDataPrefetchPromise?.[version];
if (signDataPromise == null) {
signDataPromise = this.preFetchSignData(signDataPrefetch, version);
}
else
signDataPrefetch.catch(() => { });
return {
signDataPromise,
resp: await response
};
}, undefined, e => e instanceof RequestError_1.RequestError, abortController.signal);
if (parsedPr.millisatoshis == null)
throw new Error("Swap invoice doesn't have msat amount field!");
const amountOut = (BigInt(parsedPr.millisatoshis) + 999n) / 1000n;
const totalFee = resp.swapFee + resp.maxFee;
const data = new (this._swapDataDeserializer(version))(resp.data);
data.setOfferer(signer);
await this.verifyReturnedData(signer, resp, parsedPr, amountData.token, lp, calculatedOptions, data);
const swapFeeBtc = resp.swapFee * amountOut / (data.getAmount() - totalFee);
const [pricingInfo, signatureExpiry, reputation] = await Promise.all([
this.verifyReturnedPrice(lp.services[SwapType_1.SwapType.TO_BTCLN], true, amountOut, data.getAmount(), amountData.token, { networkFee: resp.maxFee, swapFeeBtc }, preFetches.pricePreFetchPromise, preFetches.usdPricePrefetchPromise, abortController.signal),
this.verifyReturnedSignature(signer, data, resp, preFetches.feeRatePromise[version], signDataPromise, version, abortController.signal),
reputationPromise
]);
abortController.signal.throwIfAborted();
if (reputation != null)
lp.reputation[amountData.token.toString()] = reputation;
const quote = new ToBTCLNSwap_1.ToBTCLNSwap(this, {
pricingInfo,
url: lp.url,
expiry: signatureExpiry,
swapFee: resp.swapFee,
swapFeeBtc,
feeRate: (await preFetches.feeRatePromise[version]),
signatureData: resp,
data,
networkFee: resp.maxFee,
networkFeeBtc: resp.routingFeeSats,
confidence: resp.confidence,
pr,
exactIn: false,
contractVersion: version,
longExpiry: calculatedOptions.longExpiry
});
return quote;
}
catch (e) {
abortController.abort(e);
throw e;
}
}
/**
* Returns a newly created Smart chain -> Lightning swap using the HTLC based escrow swap protocol,
* the amount is parsed from the provided lightning network payment request (bolt11 invoice)
*
* @param signer Source chain signer address initiating the swap
* @param recipient BOLT11 payment request (bitcoin lightning invoice) you wish to pay
* @param amountData Token to swap
* @param lps An array of intermediaries (LPs) to get the quotes from
* @param options Optional additional quote options
* @param additionalParams Optional additional parameters sent to the LP when creating the swap
* @param abortSignal Abort signal
* @param preFetches Optional existing pre-fetch promises for the swap (only used internally for LNURL swaps)
*/
async create(signer, recipient, amountData, lps, options, additionalParams, abortSignal, preFetches) {
const parsedPr = (0, bolt11_1.decode)(recipient);
if (parsedPr.millisatoshis == null)
throw new UserError_1.UserError("Must be an invoice with amount");
const amountOut = (BigInt(parsedPr.millisatoshis) + 999n) / 1000n;
const lpVersions = Intermediary_1.Intermediary.getContractVersionsForLps(this.chainIdentifier, lps);
const { expirySeconds, longExpiry } = this.getExpirySeconds(parsedPr, options);
const _options = {
...this.toRequiredSwapOptions({ ...amountData, amount: amountOut }, { ...options, expirySeconds }),
longExpiry
};
if (parsedPr.tagsObject.payment_hash == null)
throw new Error("Provided lightning invoice doesn't contain payment hash field!");
await this.checkPaymentHashWasPaid(parsedPr.tagsObject.payment_hash);
const _hash = (0, Utils_1.mapArrayToObject)(lpVersions, (contractVersion) => {
return this._contract(contractVersion).getHashForHtlc(Buffer.from(parsedPr.tagsObject.payment_hash, "hex")).toString("hex");
});
const _abortController = (0, Utils_1.extendAbortController)(abortSignal);
const _preFetches = preFetches ?? {
pricePreFetchPromise: this.preFetchPrice(amountData, _abortController.signal),
feeRatePromise: this.preFetchFeeRate(signer, amountData, _hash, _abortController, lpVersions),
usdPricePrefetchPromise: this.preFetchUsdPrice(_abortController.signal),
signDataPrefetchPromise: (0, Utils_1.mapArrayToObject)(lpVersions, (contractVersion) => {
return this._contract(contractVersion).preFetchBlockDataForSignatures == null ?
this.preFetchSignData(Promise.resolve(true), contractVersion) :
undefined;
})
};
return lps.map(lp => {
return {
intermediary: lp,
quote: this.getIntermediaryQuote(signer, amountData, lp, recipient, parsedPr, _options, _preFetches, _abortController.signal, additionalParams)
};
});
}
/**
* Parses and fetches lnurl pay params from the specified lnurl
*
* @param lnurl LNURL to be parsed and fetched
* @param abortSignal Abort signal
* @throws {UserError} if the LNURL is invalid or if it's not a LNURL-pay
*
* @private
*/
async getLNURLPay(lnurl, abortSignal) {
if (typeof (lnurl) !== "string")
return lnurl;
const res = await LNURL_1.LNURL.getLNURL(lnurl, true, this._options.getRequestTimeout, abortSignal);
if (res == null)
throw new UserError_1.UserError("Invalid LNURL");
if (res.tag !== "payRequest")
throw new UserError_1.UserError("Not a LNURL-pay");
return res;
}
/**
* Returns the quote/swap from the given LP
*
* @param signer Source chain signer address initiating the swap
* @param amountData Token to swap
* @param invoiceCreateService Service for creating fixed amount invoices
* @param lp Intermediary (LPs) to get the quote from
* @param dummyPr Dummy minimum value bolt11 lightning invoice returned from the LNURL-pay, used to estimate
* network fees for an actual invoice
* @param calculatedOptions Swap options computed from the swap create options
* @param preFetches Optional existing pre-fetch promises for the swap (only used internally for LNURL swaps)
* @param abortSignal Abort signal
* @param additionalParams Additional params to be sent to the intermediary
*
* @private
*/
async getIntermediaryQuoteExactIn(signer, amountData, invoiceCreateService, lp, dummyPr, calculatedOptions, preFetches, abortSignal, additionalParams) {
if (lp.services[SwapType_1.SwapType.TO_BTCLN] == null)
throw new Error("LP service for processing to btcln swaps not found!");
const version = lp.getContractVersion(this.chainIdentifier);
const abortController = (0, Utils_1.extendAbortController)(abortSignal);
const reputationPromise = this.preFetchIntermediaryReputation(amountData, lp, abortController, version);
try {
const { signDataPromise, prepareResp } = await (0, RetryUtils_1.tryWithRetries)(async (retryCount) => {
const { signDataPrefetch, response } = this._lpApi.prepareToBTCLNExactIn(this.chainIdentifier, lp.url, {
token: amountData.token,
offerer: signer,
pr: dummyPr,
amount: amountData.amount,
maxFee: await calculatedOptions.maxFee,
expiryTimestamp: calculatedOptions.expiryTimestamp,
additionalParams
}, this._options.postRequestTimeout, abortController.signal, retryCount > 0 ? false : undefined);
return {
signDataPromise: this.preFetchSignData(signDataPrefetch, version),
prepareResp: await response
};
}, undefined, e => e instanceof RequestError_1.RequestError, abortController.signal);
if (prepareResp.amount <= 0n)
throw new IntermediaryError_1.IntermediaryError("Invalid amount returned (zero or negative)");
if (invoiceCreateService.minMsats != null) {
if (prepareResp.amount < invoiceCreateService.minMsats / 1000n)
throw new UserError_1.UserError("Amount less than minimum");
}
if (invoiceCreateService.maxMSats != null) {
if (prepareResp.amount > invoiceCreateService.maxMSats / 1000n)
throw new UserError_1.UserError("Amount more than maximum");
}
const invoice = await invoiceCreateService.getInvoice(Number(prepareResp.amount), abortController.signal);
const parsedInvoice = (0, bolt11_1.decode)(invoice);
const resp = await (0, RetryUtils_1.tryWithRetries)((retryCount) => this._lpApi.initToBTCLNExactIn(lp.url, {
pr: invoice,
reqId: prepareResp.reqId,
feeRate: (0, Utils_1.throwIfUndefined)(preFetches.feeRatePromise[version], "Network fee rate pre-fetch failed!"),
additionalParams
}, this._options.postRequestTimeout, abortController.signal, retryCount > 0 ? false : undefined), undefined, RequestError_1.RequestError, abortController.signal);
if (parsedInvoice.millisatoshis == null)
throw new Error("Swap invoice doesn't have msat amount field!");
const amountOut = (BigInt(parsedInvoice.millisatoshis) + 999n) / 1000n;
const totalFee = resp.swapFee + resp.maxFee;
const data = new (this._swapDataDeserializer(version))(resp.data);
data.setOfferer(signer);
await this.verifyReturnedData(signer, resp, parsedInvoice, amountData.token, lp, calculatedOptions, data, amountData.amount);
const swapFeeBtc = resp.swapFee * amountOut / (data.getAmount() - totalFee);
const [pricingInfo, signatureExpiry, reputation] = await Promise.all([
this.verifyReturnedPrice(lp.services[SwapType_1.SwapType.TO_BTCLN], true, prepareResp.amount, data.getAmount(), amountData.token, { networkFee: resp.maxFee, swapFeeBtc }, preFetches.pricePreFetchPromise, preFetches.usdPricePrefetchPromise, abortSignal),
this.verifyReturnedSignature(signer, data, resp, preFetches.feeRatePromise[version], signDataPromise, version, abortController.signal),
reputationPromise
]);
abortController.signal.throwIfAborted();
if (reputation != null)
lp.reputation[amountData.token.toString()] = reputation;
const quote = new ToBTCLNSwap_1.ToBTCLNSwap(this, {
pricingInfo,
url: lp.url,
expiry: signatureExpiry,
swapFee: resp.swapFee,
swapFeeBtc,
feeRate: (await preFetches.feeRatePromise[version]),
signatureData: resp,
data,
networkFee: resp.maxFee,
networkFeeBtc: resp.routingFeeSats,
confidence: resp.confidence,
pr: invoice,
exactIn: true,
contractVersion: version,
longExpiry: calculatedOptions?.longExpiry
});
return quote;
}
catch (e) {
abortController.abort(e);
throw e;
}
}
/**
* Returns a newly created Smart chain -> Lightning swap using the HTLC based escrow swap protocol via
* invoice creation service. This allows exactIn swaps by requesting the desired fixed amount lightning
* network invoice from the service.
*
* @param signer Source chain signer address initiating the swap
* @param invoiceCreateServicePromise Service to request destination lightning network invoices from
* @param amountData Amount, token and exact input/output data for to swap
* @param lps An array of intermediaries (LPs) to get the quotes from
* @param options Optional additional quote options
* @param additionalParams Optional additional parameters sent to the LP when creating the swap
* @param abortSignal Abort signal
*/
async createViaInvoiceCreateService(signer, invoiceCreateServicePromise, amountData, lps, options, additionalParams, abortSignal) {
if (!this.isInitialized)
throw new Error("Not initialized, call init() first!");
const lpVersions = Intermediary_1.Intermediary.getContractVersionsForLps(this.chainIdentifier, lps);
const _abortController = (0, Utils_1.extendAbortController)(abortSignal);
const pricePreFetchPromise = this.preFetchPrice(amountData, _abortController.signal);
const usdPricePrefetchPromise = this.preFetchUsdPrice(_abortController.signal);
const feeRatePromise = this.preFetchFeeRate(signer, amountData, undefined, _abortController, lpVersions);
const signDataPrefetchPromise = (0, Utils_1.mapArrayToObject)(lpVersions, (contractVersion) => {
return this._contract(contractVersion).preFetchBlockDataForSignatures == null ?
this.preFetchSignData(Promise.resolve(true), contractVersion) :
undefined;
});
try {
const invoiceCreateService = await invoiceCreateServicePromise;
if (amountData.exactIn) {
const dummyInvoice = await invoiceCreateService.getInvoice(invoiceCreateService.minMsats == null ? 1 : Number(invoiceCreateService.minMsats / 1000n), _abortController.signal);
const parsedDummyInvoice = (0, bolt11_1.decode)(dummyInvoice);
const { expirySeconds, longExpiry } = this.getExpirySeconds(parsedDummyInvoice, options);
const _options = {
...this.toRequiredSwapOptions(amountData, { ...options, expirySeconds }, pricePreFetchPromise, _abortController.signal),
longExpiry
};
return lps.map(lp => {
return {
quote: this.getIntermediaryQuoteExactIn(signer, amountData, invoiceCreateService, lp, dummyInvoice, _options, {
pricePreFetchPromise,
usdPricePrefetchPromise,
feeRatePromise
}, _abortController.signal, additionalParams),
intermediary: lp
};
});
}
else {
if (invoiceCreateService.minMsats != null) {
if (amountData.amount < invoiceCreateService.minMsats / 1000n)
throw new UserError_1.UserError("Amount less than minimum");
}
if (invoiceCreateService.maxMSats != null) {
if (amountData.amount > invoiceCreateService.maxMSats / 1000n)
throw new UserError_1.UserError("Amount more than maximum");
}
const invoice = await invoiceCreateService.getInvoice(Number(amountData.amount), _abortController.signal);
return (await this.create(signer, invoice, { ...amountData, exactIn: false }, lps, options, additionalParams, _abortController.signal, {
feeRatePromise,
pricePreFetchPromise,
usdPricePrefetchPromise,
signDataPrefetchPromise
}));
}
}
catch (e) {
_abortController.abort(e);
throw e;
}
}
/**
* Returns a newly created Smart chain -> Lightning swap using the HTLC based escrow swap protocol. Pays to
* an LNURL-pay link. This allows exactIn swaps by requesting the desired fixed amount lightning
* network invoice from the LNURL service.
*
* @param signer Source chain signer address initiating the swap
* @param lnurl LNURL-pay link of the recipient
* @param amountData Amount, token and exact input/output data for to swap
* @param lps An array of intermediaries (LPs) to get the quotes from
* @param options Optional additional quote options
* @param additionalParams Optional additional parameters sent to the LP when creating the swap
* @param abortSignal Abort signal
*/
async createViaLNURL(signer, lnurl, amountData, lps, options, additionalParams, abortSignal) {
let successActions = {};
const _abortController = (0, Utils_1.extendAbortController)(abortSignal);
const invoiceCreateService = (async () => {
let payRequest = await this.getLNURLPay(lnurl, _abortController.signal);
if (options?.comment != null &&
(payRequest.commentAllowed == null || options.comment.length > payRequest.commentAllowed))
throw new UserError_1.UserError("Comment not allowed or too long");
return {
getInvoice: async (amountSats, abortSignal) => {
const { invoice, successAction } = await LNURL_1.LNURL.useLNURLPay(payRequest, BigInt(amountSats), options?.comment, this._options.getRequestTimeout, abortSignal);
if (successAction != null)
successActions[invoice] = successAction;
return invoice;
},
minMsats: BigInt(payRequest.minSendable),
maxMsats: BigInt(payRequest.maxSendable),
url: payRequest.url
};
})();
const quotes = await this.createViaInvoiceCreateService(signer, invoiceCreateService, amountData, lps, options, additionalParams, _abortController.signal);
_abortController.signal.throwIfAborted();
const resolved = await invoiceCreateService;
_abortController.signal.throwIfAborted();
return quotes.map(value => ({
quote: value.quote.then(quote => {
let _successAction;
const quoteAddress = quote.getOutputAddress();
if (quoteAddress != null) {
const successAction = successActions[quoteAddress];
if (successAction != null)
_successAction = successAction;
}
quote._setLNURLData(resolved.url, _successAction);
return quote;
}),
intermediary: value.intermediary
}));
}
/**
* @inheritDoc
*/
async recoverFromSwapDataAndState(init, state, contractVersion, lp) {
const data = init.data;
let paymentHash = data.getHTLCHashHint();
let secret;
if (state.type === base_1.SwapCommitStateType.PAID) {
secret = await state.getClaimResult();
paymentHash = Buffer.from((0, sha2_1.sha256)(Buffer.from(secret, "hex"))).toString("hex");
}
const swapInit = {
pricingInfo: {
isValid: true,
satsBaseFee: 0n,
swapPriceUSatPerToken: 100000000000000n,
realPriceUSatPerToken: 100000000000000n,
differencePPM: 0n,
feePPM: 0n,
},
url: lp?.url,
expiry: 0,
swapFee: 0n,
swapFeeBtc: 0n,
feeRate: "",
signatureData: undefined,
data,
networkFee: 0n,
networkFeeBtc: 0n,
confidence: 0,
pr: paymentHash ?? undefined,
exactIn: false,
contractVersion
};
const swap = new ToBTCLNSwap_1.ToBTCLNSwap(this, swapInit);
swap._commitTxId = await init.getInitTxId();
const blockData = await init.getTxBlock();
swap.createdAt = blockData.blockTime * 1000;
swap._setInitiated();
swap._state = IToBTCSwap_1.ToBTCSwapState.COMMITED;
await swap._sync(false, false, state);
await swap._save();
return swap;
}
}
exports.ToBTCLNWrapper = ToBTCLNWrapper;