@atomiqlabs/sdk-lib
Version:
Basic SDK functionality library for atomiq
151 lines (133 loc) • 4.9 kB
text/typescript
import {SwapType} from "../swaps/SwapType";
import {SwapHandlerInfoType} from "./IntermediaryDiscovery";
import {ChainSwapType, SwapContract} from "@atomiqlabs/base";
import {LNNodeLiquidity} from "../btc/LightningNetworkApi";
import {tryWithRetries} from "../utils/Utils";
export type ServicesType = {
[key in SwapType]?: SwapHandlerInfoType
};
export type SingleChainReputationType = {
[token: string]: {
[key in ChainSwapType]: {
successVolume: bigint,
successCount: bigint,
failVolume: bigint,
failCount: bigint,
coopCloseVolume: bigint,
coopCloseCount: bigint,
}
}
};
export type SCLiquidity = {
[token: string]: bigint
};
export class Intermediary {
readonly url: string;
readonly addresses: {[chainIdentifier: string]: string};
readonly services: ServicesType;
reputation: { [chainIdentifier: string]: SingleChainReputationType } = {};
liquidity: { [chainIdentifier: string]: SCLiquidity } = {};
lnData: LNNodeLiquidity;
constructor(
url: string,
addresses: {[chainIdentifier: string]: string},
services: ServicesType,
reputation: { [chainIdentifier: string]: SingleChainReputationType } = {}
) {
this.url = url;
this.addresses = addresses;
this.services = services;
this.reputation = reputation;
}
/**
* Returns tokens supported by the intermediary, optionally constrained to the specific swap types
*
* @param chainIdentifier
* @param swapTypesArr
* @private
*/
private getSupportedTokens(chainIdentifier: string, swapTypesArr: SwapType[] = [
SwapType.TO_BTC,
SwapType.TO_BTCLN,
SwapType.FROM_BTC,
SwapType.FROM_BTCLN
]): Set<string> {
const swapTypes = new Set(swapTypesArr);
let tokens: Set<string> = new Set<string>();
swapTypes.forEach((swapType) => {
if(
this.services[swapType]!=null &&
this.services[swapType].chainTokens!=null &&
this.services[swapType].chainTokens[chainIdentifier]!=null
) this.services[swapType].chainTokens[chainIdentifier].forEach(token => tokens.add(token));
});
return tokens;
}
/**
* Fetches, returns and saves the reputation of the intermediary, either for all or just for a single token
*
* @param chainIdentifier
* @param swapContract
* @param tokens
* @param abortSignal
*/
async getReputation(
chainIdentifier: string,
swapContract: SwapContract<any>,
tokens?: string[],
abortSignal?: AbortSignal
): Promise<SingleChainReputationType> {
const checkReputationTokens: Set<string> = tokens==null ?
this.getSupportedTokens(chainIdentifier, [SwapType.TO_BTC, SwapType.TO_BTCLN]) :
new Set<string>(tokens);
const promises: Promise<void>[] = [];
const reputation: SingleChainReputationType = {};
for(let token of checkReputationTokens) {
promises.push(
tryWithRetries(() =>
swapContract.getIntermediaryReputation(this.getAddress(chainIdentifier), token),
null, null, abortSignal
).then(result => {
reputation[token] = result;
})
);
}
await Promise.all(promises);
this.reputation ??= {};
this.reputation[chainIdentifier] ??= {};
for(let key in reputation) {
this.reputation[chainIdentifier][key] = reputation[key];
}
return reputation;
}
/**
* Fetches, returns and saves the liquidity of the intermediaryfor a specific token
*
* @param chainIdentifier
* @param swapContract
* @param token
* @param abortSignal
*/
async getLiquidity(
chainIdentifier: string,
swapContract: SwapContract<any>,
token: string,
abortSignal?: AbortSignal
): Promise<bigint> {
const result = await tryWithRetries(() =>
swapContract.getBalance(this.getAddress(chainIdentifier), token, true),
null, null, abortSignal
);
this.liquidity ??= {};
this.liquidity[chainIdentifier] ??= {};
this.liquidity[chainIdentifier][token] = result;
return result;
}
supportsChain(chainIdentifier: string): boolean {
if(this.addresses[chainIdentifier]==null) return false;
return this.getSupportedTokens(chainIdentifier).size!==0;
}
getAddress(chainIdentifier: string) {
return this.addresses[chainIdentifier];
}
}