@atomiqlabs/sdk
Version:
atomiq labs SDK for cross-chain swaps between smart chains and bitcoin
108 lines (100 loc) • 4.08 kB
text/typescript
import {ISwapWrapperOptions} from "../../ISwapWrapper";
import {Intermediary} from "../../../intermediaries/Intermediary";
import {IntermediaryError} from "../../../errors/IntermediaryError";
import {mapArrayToObject, randomBytes} from "../../../utils/Utils";
import {BigIntBufferUtils, ChainType} from "@atomiqlabs/base";
import {IEscrowSwapDefinition, IEscrowSwapWrapper} from "../IEscrowSwapWrapper";
import {IEscrowSwap} from "../IEscrowSwap";
import {AmountData} from "../../../types/AmountData";
export type IFromBTCDefinition<T extends ChainType, W extends IFromBTCWrapper<T, any>, S extends IEscrowSwap<T>> = IEscrowSwapDefinition<T, W, S>;
/**
* Base class for wrappers of escrow-based Bitcoin (on-chain & lightning) -> Smart chain swaps
*
* @category Swaps/Abstract
*/
export abstract class IFromBTCWrapper<
T extends ChainType,
D extends IFromBTCDefinition<T, IFromBTCWrapper<T, D>, IEscrowSwap<T, D>>,
O extends ISwapWrapperOptions = ISwapWrapperOptions
> extends IEscrowSwapWrapper<T, D, O> {
/**
* Returns a random sequence to be used for swaps
*
* @returns Random 64-bit sequence number
*
* @internal
*/
protected getRandomSequence(): bigint {
return BigIntBufferUtils.fromBuffer(randomBytes(8));
}
/**
* Pre-fetches smart chain fee rate for initiating a swap escrow on the smart chain side
*
* @param signer Address initiating the swap
* @param amountData
* @param claimHash optional claim hash of the swap or null
* @param abortController
*
* @param contractVersions
* @returns Fee rate
*
* @internal
*/
protected preFetchFeeRate(
signer: string,
amountData: AmountData,
claimHash: {[contractVersion: string]: string} | undefined,
abortController: AbortController,
contractVersions: string[]
): {[contractVersion: string]: Promise<string | undefined>} {
return mapArrayToObject(contractVersions, (contractVersion) => {
return this._contract(contractVersion).getInitFeeRate(this._chain.randomAddress(), signer, amountData.token, claimHash?.[contractVersion])
.catch(e => {
this.logger.warn("preFetchFeeRate(): Error: ", e);
abortController.abort(e);
return undefined;
});
});
}
/**
* Pre-fetches intermediary (LP) available smart chain liquidity
*
* @param amountData
* @param lp Intermediary
* @param abortController
*
* @param contractVersion
* @returns Intermediary's liquidity balance
*
* @internal
*/
protected preFetchIntermediaryLiquidity(
amountData: AmountData,
lp: Intermediary,
abortController: AbortController,
contractVersion: string
): Promise<bigint | undefined> {
return lp.getLiquidity(this.chainIdentifier, this._contract(contractVersion), amountData.token.toString(), abortController.signal).catch(e => {
this.logger.warn("preFetchIntermediaryLiquidity(): Error: ", e);
abortController.abort(e);
return undefined;
})
}
/**
* Verifies whether the intermediary (LP) has enough available liquidity such that we can initiate the swap
*
* @param amount Swap amount that the recipient should receive
* @param liquidityPromise pre-fetched liquidity promise as obtained from {@link preFetchIntermediaryLiquidity}
*
* @throws {IntermediaryError} if intermediary's liquidity is lower than what's required for the swap
*
* @internal
*/
protected async verifyIntermediaryLiquidity(
amount: bigint,
liquidityPromise: Promise<bigint>
): Promise<void> {
const liquidity = await liquidityPromise;
if(liquidity < amount) throw new IntermediaryError("Intermediary doesn't have enough liquidity");
}
}