UNPKG

@atomiqlabs/sdk-lib

Version:

Basic SDK functionality library for atomiq

238 lines (237 loc) 10.3 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.ISwap = exports.ppmToPercentage = exports.isISwapInit = void 0; const SwapType_1 = require("./enums/SwapType"); const events_1 = require("events"); const ISwapPrice_1 = require("../prices/abstract/ISwapPrice"); const Utils_1 = require("../utils/Utils"); const SwapDirection_1 = require("./enums/SwapDirection"); function isISwapInit(obj) { return typeof obj === 'object' && obj != null && (0, ISwapPrice_1.isPriceInfoType)(obj.pricingInfo) && (obj.url == null || typeof obj.url === 'string') && typeof obj.expiry === 'number' && typeof (obj.swapFee) === "bigint" && (obj.swapFeeBtc == null || typeof (obj.swapFeeBtc) === "bigint") && (typeof obj.exactIn === 'boolean'); } exports.isISwapInit = isISwapInit; function ppmToPercentage(ppm) { if (ppm == null) return null; const percentage = Number(ppm) / 10000; return { ppm, decimal: Number(ppm) / 1000000, percentage: percentage, toString: (decimals) => (decimals != null ? percentage.toFixed(decimals) : percentage) + "%" }; } exports.ppmToPercentage = ppmToPercentage; class ISwap { constructor(wrapper, swapInitOrObj) { this.currentVersion = 1; this.initiated = false; /** * Event emitter emitting "swapState" event when swap's state changes */ this.events = new events_1.EventEmitter(); this.chainIdentifier = wrapper.chainIdentifier; this.wrapper = wrapper; if (isISwapInit(swapInitOrObj)) { Object.assign(this, swapInitOrObj); this.version = this.currentVersion; this.createdAt = Date.now(); this.randomNonce = (0, Utils_1.randomBytes)(16).toString("hex"); } else { this.expiry = swapInitOrObj.expiry; this.url = swapInitOrObj.url; this.state = swapInitOrObj.state; this.pricingInfo = { isValid: swapInitOrObj._isValid, differencePPM: swapInitOrObj._differencePPM == null ? null : BigInt(swapInitOrObj._differencePPM), satsBaseFee: swapInitOrObj._satsBaseFee == null ? null : BigInt(swapInitOrObj._satsBaseFee), feePPM: swapInitOrObj._feePPM == null ? null : BigInt(swapInitOrObj._feePPM), realPriceUSatPerToken: swapInitOrObj._realPriceUSatPerToken == null ? null : BigInt(swapInitOrObj._realPriceUSatPerToken), swapPriceUSatPerToken: swapInitOrObj._swapPriceUSatPerToken == null ? null : BigInt(swapInitOrObj._swapPriceUSatPerToken), }; this.swapFee = swapInitOrObj.swapFee == null ? null : BigInt(swapInitOrObj.swapFee); this.swapFeeBtc = swapInitOrObj.swapFeeBtc == null ? null : BigInt(swapInitOrObj.swapFeeBtc); this.version = swapInitOrObj.version; this.initiated = swapInitOrObj.initiated; this.exactIn = swapInitOrObj.exactIn; this.createdAt = swapInitOrObj.createdAt ?? swapInitOrObj.expiry; this.randomNonce = swapInitOrObj.randomNonce; } if (this.version !== this.currentVersion) { this.upgradeVersion(); } if (this.initiated == null) this.initiated = true; } /** * Waits till the swap reaches a specific state * * @param targetState The state to wait for * @param type Whether to wait for the state exactly or also to a state with a higher number * @param abortSignal * @protected */ waitTillState(targetState, type = "eq", abortSignal) { return new Promise((resolve, reject) => { let listener; listener = (swap) => { if (type === "eq" ? swap.state === targetState : type === "gte" ? swap.state >= targetState : swap.state != targetState) { resolve(); this.events.removeListener("swapState", listener); } }; this.events.on("swapState", listener); if (abortSignal != null) abortSignal.addEventListener("abort", () => { this.events.removeListener("swapState", listener); reject(abortSignal.reason); }); }); } ////////////////////////////// //// Pricing tryRecomputeSwapPrice() { if (this.pricingInfo.swapPriceUSatPerToken == null) { if (this.getDirection() === SwapDirection_1.SwapDirection.TO_BTC) { const input = this.getInput(); this.pricingInfo = this.wrapper.prices.recomputePriceInfoSend(this.chainIdentifier, this.getOutput().rawAmount, this.pricingInfo.satsBaseFee, this.pricingInfo.feePPM, input.rawAmount, input.token.address); } else { const output = this.getOutput(); this.pricingInfo = this.wrapper.prices.recomputePriceInfoReceive(this.chainIdentifier, this.getInput().rawAmount, this.pricingInfo.satsBaseFee, this.pricingInfo.feePPM, output.rawAmount, output.token.address); } } } /** * Re-fetches & revalidates the price data */ async refreshPriceData() { if (this.pricingInfo == null) return null; if (this.getDirection() === SwapDirection_1.SwapDirection.TO_BTC) { const input = this.getInput(); this.pricingInfo = await this.wrapper.prices.isValidAmountSend(this.chainIdentifier, this.getOutput().rawAmount, this.pricingInfo.satsBaseFee, this.pricingInfo.feePPM, input.rawAmount, input.token.address); } else { const output = this.getOutput(); this.pricingInfo = await this.wrapper.prices.isValidAmountReceive(this.chainIdentifier, this.getInput().rawAmount, this.pricingInfo.satsBaseFee, this.pricingInfo.feePPM, output.rawAmount, output.token.address); } } /** * Checks if the pricing for the swap is valid, according to max allowed price difference set in the ISwapPrice */ hasValidPrice() { return this.pricingInfo == null ? null : this.pricingInfo.isValid; } /** * Returns pricing info about the swap */ getPriceInfo() { const swapPrice = this.getDirection() === SwapDirection_1.SwapDirection.TO_BTC ? 100000000000000 / Number(this.pricingInfo.swapPriceUSatPerToken) : Number(this.pricingInfo.swapPriceUSatPerToken) / 100000000000000; const marketPrice = this.getDirection() === SwapDirection_1.SwapDirection.TO_BTC ? 100000000000000 / Number(this.pricingInfo.realPriceUSatPerToken) : Number(this.pricingInfo.realPriceUSatPerToken) / 100000000000000; return { marketPrice, swapPrice, difference: ppmToPercentage(this.pricingInfo.differencePPM) }; } /** * @param signer Signer to check with this swap's initiator * @throws {Error} When signer's address doesn't match with the swap's initiator one */ checkSigner(signer) { if ((typeof (signer) === "string" ? signer : signer.getAddress()) !== this._getInitiator()) throw new Error("Invalid signer provided!"); } isInitiated() { return this.initiated; } _setInitiated() { this.initiated = true; } /** * Returns quote expiry in UNIX millis */ getQuoteExpiry() { return this.expiry; } /** * Returns the type of the swap */ getType() { return this.TYPE; } /** * Returns the direction of the swap */ getDirection() { return this.TYPE === SwapType_1.SwapType.TO_BTC || this.TYPE === SwapType_1.SwapType.TO_BTCLN ? SwapDirection_1.SwapDirection.TO_BTC : SwapDirection_1.SwapDirection.FROM_BTC; } /** * Returns the current state of the swap */ getState() { return this.state; } ////////////////////////////// //// Storage serialize() { if (this.pricingInfo == null) return {}; return { id: this.getId(), type: this.getType(), escrowHash: this._getEscrowHash(), initiator: this._getInitiator(), _isValid: this.pricingInfo.isValid, _differencePPM: this.pricingInfo.differencePPM == null ? null : this.pricingInfo.differencePPM.toString(10), _satsBaseFee: this.pricingInfo.satsBaseFee == null ? null : this.pricingInfo.satsBaseFee.toString(10), _feePPM: this.pricingInfo.feePPM == null ? null : this.pricingInfo.feePPM.toString(10), _realPriceUSatPerToken: this.pricingInfo.realPriceUSatPerToken == null ? null : this.pricingInfo.realPriceUSatPerToken.toString(10), _swapPriceUSatPerToken: this.pricingInfo.swapPriceUSatPerToken == null ? null : this.pricingInfo.swapPriceUSatPerToken.toString(10), state: this.state, url: this.url, swapFee: this.swapFee == null ? null : this.swapFee.toString(10), swapFeeBtc: this.swapFeeBtc == null ? null : this.swapFeeBtc.toString(10), expiry: this.expiry, version: this.version, initiated: this.initiated, exactIn: this.exactIn, createdAt: this.createdAt, randomNonce: this.randomNonce }; } _save() { if (this.isQuoteExpired()) { return this.wrapper.removeSwapData(this); } else { return this.wrapper.saveSwapData(this); } } async _saveAndEmit(state) { if (state != null) this.state = state; await this._save(); this._emitEvent(); } ////////////////////////////// //// Events _emitEvent() { this.wrapper.events.emit("swapState", this); this.events.emit("swapState", this); } } exports.ISwap = ISwap;