counterstake-sdk
Version:
Counterstake SDK for integrating cross-chain transactions in your dapps
130 lines (114 loc) • 4.34 kB
JavaScript
/*jslint node: true */
;
const { getPoolState, getSwapParams } = require('oswap-v2-sdk');
const { isValidAddress } = require('obyte/lib/utils');
const { getEnvironment } = require("./environment.js");
const { getObyteClient } = require("./obyte-client.js");
const oswap_factory_aas = {
testnet: 'OQLU4HOAIVJ32SDVBJA6AKD52OVTHAOF',
mainnet: 'OQLU4HOAIVJ32SDVBJA6AKD52OVTHAOF',
};
let poolParams = {};
let cachedPoolsByPair = {};
const pools_by_pair_cache_timeout = 24 * 3600 * 1000; // 24 hours
let cachedPoolVars = {};
const pool_vars_cache_timeout = 5 * 60 * 1000; // 5 min
/**
* Find an Oswap pool that connects `from_asset` and `to_asset`
* @memberOf counterstake-sdk
* @param {string} from_asset
* @param {string} to_asset
* @param {boolean} testnet
* @param {Object} obyteClient
* @return {Promise<?string>}
* @example
* const pool = await findOswapPool(from_asset, to_asset, testnet, obyteClient);
*/
async function findOswapPool(from_asset, to_asset, testnet, obyteClient) {
if (!from_asset || !to_asset)
throw Error("from_asset or to_asset isn't valid");
const pair = from_asset > to_asset ? from_asset + '_' + to_asset : to_asset + '_' + from_asset;
if (cachedPoolsByPair[pair] && cachedPoolsByPair[pair].ts > Date.now() - pools_by_pair_cache_timeout)
return cachedPoolsByPair[pair].pool;
const client = obyteClient || getObyteClient(testnet);
const var_prefix = 'pool_';
const vars = await client.api.getAaStateVars({ address: oswap_factory_aas[getEnvironment(testnet)], var_prefix });
let pools = [];
for (let var_name in vars) {
const pool = var_name.substring(var_prefix.length);
const { x_asset, y_asset } = vars[var_name];
if (x_asset === from_asset && y_asset === to_asset || x_asset === to_asset && y_asset === from_asset)
pools.push(pool);
}
console.log(`oswap pools for ${from_asset} to ${to_asset}`, pools);
if (pools.length === 0)
return null;
let best_pool;
if (pools.length === 1) {
best_pool = pools[0];
}
else {
// find the pool with most liquidity
const balances = await client.api.getBalances(pools);
let max_balance_from = 0;
for (let pool of pools) {
const balance = balances[pool][from_asset] ? balances[pool][from_asset].total : 0;
if (balance > max_balance_from) {
max_balance_from = balance;
best_pool = pool;
}
}
// best_pool can stay undefined if all pools are empty
}
if (best_pool) {
cachedPoolsByPair[pair] = {
pool: best_pool,
ts: Date.now(),
};
}
return best_pool;
}
async function getPoolParams(pool, testnet, obyteClient) {
if (typeof pool !== "string" || !isValidAddress(pool))
throw Error("pool isn't valid")
if (!poolParams[pool]) {
const client = obyteClient || getObyteClient(testnet);
const definition = await client.api.getDefinition(pool);
const { params } = definition[1];
poolParams[pool] = params;
}
return poolParams[pool];
}
async function getPoolVars(pool, testnet, obyteClient) {
if (typeof pool !== "string" || !isValidAddress(pool))
throw Error("pool isn't valid")
if (cachedPoolVars[pool] && cachedPoolVars[pool].ts > Date.now() - pool_vars_cache_timeout)
return cachedPoolVars[pool].vars;
const client = obyteClient || getObyteClient(testnet);
const vars = await client.api.getAaStateVars({ address: pool, var_prefix: ''});
cachedPoolVars[pool] = { vars, ts: Date.now() };
return vars;
}
/**
* Get the output amount from swapping `in_asset` through `pool`
* @memberOf counterstake-sdk
* @param {string} pool
* @param {number} in_amount_in_pennies
* @param {string} in_asset
* @param {boolean} testnet
* @param {Object} obyteClient
* @return {Promise<number>}
* @example
* const out_amount_in_pennies = await getOswapOutput(pool, in_amount_in_pennies, in_asset, testnet, obyteClient);
*/
async function getOswapOutput(pool, in_amount_in_pennies, in_asset, testnet, obyteClient) {
const params = await getPoolParams(pool, testnet, obyteClient);
const stateVars = await getPoolVars(pool, testnet, obyteClient);
const poolState = getPoolState(params, stateVars);
const swapParams = getSwapParams(in_amount_in_pennies, in_asset, poolState);
const { res, delta_Yn } = swapParams;
const net_amount_out = res.net_amount_X;
return net_amount_out;
}
exports.findOswapPool = findOswapPool;
exports.getOswapOutput = getOswapOutput;