UNPKG

@atomiqlabs/sdk-lib

Version:

Basic SDK functionality library for atomiq

145 lines (117 loc) 4.96 kB
import {ToBTCWrapper} from "./ToBTCWrapper"; import {isIToBTCSwapInit, IToBTCSwap, IToBTCSwapInit} from "../IToBTCSwap"; import {SwapType} from "../../SwapType"; import {ChainType, SwapData} from "@atomiqlabs/base"; import {Buffer} from "buffer"; import {IntermediaryError} from "../../../errors/IntermediaryError"; import {BtcToken, TokenAmount, Token, BitcoinTokens, toTokenAmount} from "../../Tokens"; import {getLogger} from "../../../utils/Utils"; export type ToBTCSwapInit<T extends SwapData> = IToBTCSwapInit<T> & { address: string; amount: bigint; confirmationTarget: number; satsPerVByte: number; requiredConfirmations: number; nonce: bigint; }; export function isToBTCSwapInit<T extends SwapData>(obj: any): obj is ToBTCSwapInit<T> { return typeof (obj.address) === "string" && typeof(obj.amount) === "bigint" && typeof (obj.confirmationTarget) === "number" && typeof (obj.satsPerVByte) === "number" && isIToBTCSwapInit<T>(obj); } export class ToBTCSwap<T extends ChainType = ChainType> extends IToBTCSwap<T> { protected readonly outputToken: BtcToken<false> = BitcoinTokens.BTC; protected readonly TYPE = SwapType.TO_BTC; protected readonly wrapper: ToBTCWrapper<T>; private readonly address: string; private readonly amount: bigint; private readonly confirmationTarget: number; private readonly satsPerVByte: number; private readonly requiredConfirmations: number; private readonly nonce: bigint; private txId?: string; constructor(wrapper: ToBTCWrapper<T>, serializedObject: any); constructor(wrapper: ToBTCWrapper<T>, init: ToBTCSwapInit<T["Data"]>); constructor( wrapper: ToBTCWrapper<T>, initOrObject: ToBTCSwapInit<T["Data"]> | any ) { if(isToBTCSwapInit(initOrObject)) initOrObject.url += "/tobtc"; super(wrapper, initOrObject); if(!isToBTCSwapInit(initOrObject)) { this.address = initOrObject.address; this.amount = BigInt(initOrObject.amount); this.confirmationTarget = initOrObject.confirmationTarget; this.satsPerVByte = initOrObject.satsPerVByte; this.txId = initOrObject.txId; this.requiredConfirmations = initOrObject.requiredConfirmations ?? this.data.getConfirmationsHint(); this.nonce = (initOrObject.nonce==null ? null : BigInt(initOrObject.nonce)) ?? this.data.getNonceHint(); } this.logger = getLogger("ToBTC("+this.getIdentifierHashString()+"): "); this.tryCalculateSwapFee(); } async _setPaymentResult(result: { secret?: string; txId?: string }, check: boolean = false): Promise<boolean> { if(result==null) return false; if(result.txId==null) throw new IntermediaryError("No btc txId returned!"); if(check) { const btcTx = await this.wrapper.btcRpc.getTransaction(result.txId); if(btcTx==null) return false; const foundVout = btcTx.outs.find(vout => this.data.getClaimHash()===this.wrapper.contract.getHashForOnchain( Buffer.from(vout.scriptPubKey.hex, "hex"), BigInt(vout.value), this.requiredConfirmations, this.nonce ).toString("hex")); if(foundVout==null) throw new IntermediaryError("Invalid btc txId returned"); } this.txId = result.txId; return true; } ////////////////////////////// //// Amounts & fees getOutput(): TokenAmount<T["ChainId"], BtcToken<false>> { return toTokenAmount(this.amount, this.outputToken, this.wrapper.prices); } ////////////////////////////// //// Getters & utils getOutputTxId(): string | null { return this.txId; } /** * Returns fee rate of the bitcoin transaction in sats/vB */ getBitcoinFeeRate(): number { return this.satsPerVByte; } /** * Returns the bitcoin address where the BTC will be sent to */ getBitcoinAddress(): string { return this.address; } /** * Returns the transaction ID of the transaction sending the BTC */ getBitcoinTxId(): string | null { return this.txId; } getRecipient(): string { return this.address; } ////////////////////////////// //// Storage serialize(): any { return { ...super.serialize(), address: this.address, amount: 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 }; } }