@atomiqlabs/sdk
Version:
atomiq labs SDK for cross-chain swaps between smart chains and bitcoin
156 lines (155 loc) • 6.62 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.ToBTCSwap = exports.isToBTCSwapInit = void 0;
const IToBTCSwap_1 = require("../IToBTCSwap");
const SwapType_1 = require("../../../../enums/SwapType");
const buffer_1 = require("buffer");
const IntermediaryError_1 = require("../../../../errors/IntermediaryError");
const Utils_1 = require("../../../../utils/Utils");
const TokenAmount_1 = require("../../../../types/TokenAmount");
const Token_1 = require("../../../../types/Token");
const Logger_1 = require("../../../../utils/Logger");
const BitcoinUtils_1 = require("../../../../utils/BitcoinUtils");
function isToBTCSwapInit(obj) {
return (obj.address == null || typeof (obj.address) === "string") &&
(obj.amount == null || typeof (obj.amount) === "bigint") &&
typeof (obj.confirmationTarget) === "number" &&
typeof (obj.satsPerVByte) === "number" &&
(obj.requiredConfirmations == null || typeof (obj.requiredConfirmations) === "number") &&
(obj.nonce == null || typeof (obj.nonce) === "bigint") &&
(0, IToBTCSwap_1.isIToBTCSwapInit)(obj);
}
exports.isToBTCSwapInit = isToBTCSwapInit;
/**
* Escrow based (PrTLC) swap for Smart chains -> Bitcoin
*
* @category Swaps/Smart chain → Bitcoin
*/
class ToBTCSwap extends IToBTCSwap_1.IToBTCSwap {
constructor(wrapper, initOrObject) {
if (isToBTCSwapInit(initOrObject) && initOrObject.url != null)
initOrObject.url += "/tobtc";
super(wrapper, initOrObject);
this.TYPE = SwapType_1.SwapType.TO_BTC;
/**
* @internal
*/
this.outputToken = Token_1.BitcoinTokens.BTC;
if (isToBTCSwapInit(initOrObject)) {
this.address = initOrObject.address;
this.amount = initOrObject.amount;
this.confirmationTarget = initOrObject.confirmationTarget;
this.satsPerVByte = initOrObject.satsPerVByte;
this.requiredConfirmations = initOrObject.requiredConfirmations;
this.nonce = initOrObject.nonce;
}
else {
this.address = initOrObject.address;
this.amount = (0, Utils_1.toBigInt)(initOrObject.amount);
this.confirmationTarget = initOrObject.confirmationTarget;
this.satsPerVByte = initOrObject.satsPerVByte;
this.txId = initOrObject.txId;
this.requiredConfirmations = initOrObject.requiredConfirmations ?? this._data.getConfirmationsHint();
this.nonce = (0, Utils_1.toBigInt)(initOrObject.nonce) ?? this._data.getNonceHint();
}
this.logger = (0, Logger_1.getLogger)("ToBTC(" + this.getIdentifierHashString() + "): ");
this.tryRecomputeSwapPrice();
}
/**
* @inheritDoc
* @internal
*/
async _setPaymentResult(result, check = false) {
if (result == null)
return false;
if (result.txId == null)
throw new IntermediaryError_1.IntermediaryError("No btc txId returned!");
if (check || this.address == null || this.amount == null || this.nonce == null || this.requiredConfirmations == null) {
const btcTx = await this.wrapper._btcRpc.getTransaction(result.txId);
if (btcTx == null)
return false;
//Extract nonce from tx
const nonce = this.nonce ?? (BigInt(btcTx.ins[0].sequence) & 0x00ffffffn) | (BigInt(btcTx.locktime - 500000000) << 24n);
let requiredConfirmations = this.requiredConfirmations;
const foundVout = btcTx.outs.find(vout => {
if (requiredConfirmations != null) {
return this._data.getClaimHash() === this._contract.getHashForOnchain(buffer_1.Buffer.from(vout.scriptPubKey.hex, "hex"), BigInt(vout.value), requiredConfirmations, nonce).toString("hex");
}
else {
for (let i = 1; i <= 20; i++) {
if (this._data.getClaimHash() === this._contract.getHashForOnchain(buffer_1.Buffer.from(vout.scriptPubKey.hex, "hex"), BigInt(vout.value), i, nonce).toString("hex")) {
requiredConfirmations = i;
return true;
}
}
}
});
if (requiredConfirmations == null)
this.logger.warn(`_setPaymentResult(): Tried to recover data from bitcoin transaction ${result.txId} data, but wasn't able to!`);
if (foundVout != null) {
this.nonce = nonce;
this.address = (0, BitcoinUtils_1.fromOutputScript)(this.wrapper._options.bitcoinNetwork, foundVout.scriptPubKey.hex);
this.amount = BigInt(foundVout.value);
this.requiredConfirmations = requiredConfirmations;
}
else {
if (check)
throw new IntermediaryError_1.IntermediaryError("Invalid btc txId returned");
}
}
this.txId = result.txId;
return true;
}
//////////////////////////////
//// Amounts & fees
/**
* @inheritDoc
*/
getOutputToken() {
return Token_1.BitcoinTokens.BTC;
}
/**
* @inheritDoc
*/
getOutput() {
return (0, TokenAmount_1.toTokenAmount)(this.amount ?? null, this.outputToken, this.wrapper._prices, this.pricingInfo);
}
//////////////////////////////
//// Getters & utils
/**
* @inheritDoc
*/
getOutputAddress() {
return this.address ?? null;
}
/**
* @inheritDoc
*/
getOutputTxId() {
return this.txId ?? null;
}
/**
* Returns fee rate of the output bitcoin transaction in sats/vB as reported by the intermediary (LP)
*/
getBitcoinFeeRate() {
return this.satsPerVByte;
}
//////////////////////////////
//// Storage
/**
* @inheritDoc
*/
serialize() {
return {
...super.serialize(),
address: this.address,
amount: this.amount == null ? null : this.amount.toString(10),
confirmationTarget: this.confirmationTarget,
satsPerVByte: this.satsPerVByte,
nonce: this.nonce == null ? null : this.nonce.toString(10),
requiredConfirmations: this.requiredConfirmations,
txId: this.txId
};
}
}
exports.ToBTCSwap = ToBTCSwap;