@alcorexchange/alcor-swap-sdk
Version:
## Installation **npm** ``` npm i @alcorexchange/alcor-swap-sdk ``` **yarn** ``` yarn add @alcorexchange/alcor-swap-sdk ``` ## Usage ### Import:
206 lines (198 loc) • 6.52 kB
text/typescript
import fs from "fs";
import { Pool } from "entities/pool";
import { Token } from "entities/token";
import { Trade } from "entities/trade";
import { asset, symbol } from "eos-common";
import { CurrencyAmount } from "../src/entities/fractions/currencyAmount";
import JSBI from "jsbi";
import { FeeAmount, TICK_SPACINGS } from "internalConstants";
import { encodeSqrtRatioX64 } from "utils/encodeSqrtRatioX64";
import { TickMath } from "utils/tickMath";
import { nearestUsableTick } from "utils/nearestUsableTick";
import { sqrt } from "utils/sqrt";
function parseToken(token) {
return new Token(
token.contract,
asset(token.quantity).symbol.precision(),
asset(token.quantity).symbol.code().to_string()
);
}
describe("Trade", () => {
const token0 = new Token(
"0x0000000000000000000000000000000000000001",
8,
"t0",
"token0"
);
const token1 = new Token(
"0x0000000000000000000000000000000000000002",
8,
"t1",
"token1"
);
const token2 = new Token(
"0x0000000000000000000000000000000000000003",
8,
"t2",
"token2"
);
const token3 = new Token(
"0x0000000000000000000000000000000000000004",
8,
"t3",
"token3"
);
function v2StylePool(
id: number,
reserve0: CurrencyAmount<Token>,
reserve1: CurrencyAmount<Token>,
feeAmount: FeeAmount = FeeAmount.MEDIUM
) {
console.log("feeAmount", feeAmount);
const sqrtRatioX64 = encodeSqrtRatioX64(
reserve1.quotient,
reserve0.quotient
);
const liquidity = sqrt(
JSBI.multiply(reserve0.quotient, reserve1.quotient)
);
return new Pool({
id,
tokenA: reserve0.currency,
tokenB: reserve1.currency,
fee: feeAmount,
sqrtPriceX64: sqrtRatioX64,
liquidity,
tickCurrent: TickMath.getTickAtSqrtRatio(sqrtRatioX64),
ticks: [
{
id: nearestUsableTick(TickMath.MIN_TICK, TICK_SPACINGS[feeAmount]),
liquidityNet: liquidity,
liquidityGross: liquidity,
},
{
id: nearestUsableTick(TickMath.MAX_TICK, TICK_SPACINGS[feeAmount]),
liquidityNet: JSBI.multiply(liquidity, JSBI.BigInt(-1)),
liquidityGross: liquidity,
},
],
});
}
const pool_0_1 = v2StylePool(
0,
CurrencyAmount.fromRawAmount(token0, 100000),
CurrencyAmount.fromRawAmount(token1, 100000)
);
const pool_0_2 = v2StylePool(
1,
CurrencyAmount.fromRawAmount(token0, 100000),
CurrencyAmount.fromRawAmount(token2, 110000)
);
const pool_0_3 = v2StylePool(
2,
CurrencyAmount.fromRawAmount(token0, 100000),
CurrencyAmount.fromRawAmount(token3, 90000)
);
const pool_1_2 = v2StylePool(
3,
CurrencyAmount.fromRawAmount(token1, 120000),
CurrencyAmount.fromRawAmount(token2, 100000)
);
const pool_1_3 = v2StylePool(
4,
CurrencyAmount.fromRawAmount(token1, 120000),
CurrencyAmount.fromRawAmount(token3, 130000)
);
describe('#bestTradeExactIn', () => {
it('throws with empty pools', async () => {
await expect(
Trade.bestTradeExactIn([], CurrencyAmount.fromRawAmount(token0, JSBI.BigInt(10000)), token2)
).rejects.toThrow('POOLS')
})
it('throws with max hops of 0', async () => {
await expect(
Trade.bestTradeExactIn([pool_0_2], CurrencyAmount.fromRawAmount(token0, JSBI.BigInt(10000)), token2, {
maxHops: 0
})
).rejects.toThrow('MAX_HOPS')
})
it.only('provides best route', async () => {
const result = await Trade.bestTradeExactIn(
[pool_0_1, pool_0_2, pool_1_2],
CurrencyAmount.fromRawAmount(token0, 10000),
token2
)
console.log("result", result)
expect(result).toHaveLength(2)
console.log("result[0].swaps[0].route.tokenPath", result[0].swaps[0].route.tokenPath)
console.log("result[0].swaps[0].route.pools", result[0].swaps[0].route.pools)
expect(result[0].swaps[0].route.pools).toHaveLength(1) // 0 -> 2 at 10:11
expect(result[0].swaps[0].route.tokenPath).toEqual([token0, token2])
expect(result[0].inputAmount.equalTo(CurrencyAmount.fromRawAmount(token0, JSBI.BigInt(10000)))).toBeTruthy()
expect(result[0].outputAmount.equalTo(CurrencyAmount.fromRawAmount(token2, JSBI.BigInt(9971)))).toBeTruthy()
expect(result[1].swaps[0].route.pools).toHaveLength(2) // 0 -> 1 -> 2 at 12:12:10
expect(result[1].swaps[0].route.tokenPath).toEqual([token0, token1, token2])
expect(result[1].inputAmount.equalTo(CurrencyAmount.fromRawAmount(token0, JSBI.BigInt(10000)))).toBeTruthy()
expect(result[1].outputAmount.equalTo(CurrencyAmount.fromRawAmount(token2, JSBI.BigInt(7004)))).toBeTruthy()
})
})
describe("#bestTradeExactOut", () => {
it("throws with empty pools", async () => {
await expect(
Trade.bestTradeExactOut(
[],
token0,
CurrencyAmount.fromRawAmount(token2, JSBI.BigInt(100))
)
).rejects.toThrow("POOLS");
});
it("throws with max hops of 0", async () => {
await expect(
Trade.bestTradeExactOut(
[pool_0_2],
token0,
CurrencyAmount.fromRawAmount(token2, JSBI.BigInt(100)),
{
maxHops: 0,
}
)
).rejects.toThrow("MAX_HOPS");
});
it("provides best route", async () => {
const result = await Trade.bestTradeExactOut(
[pool_0_1, pool_0_2, pool_1_2],
token0,
CurrencyAmount.fromRawAmount(token2, 10000)
);
expect(result).toHaveLength(2);
expect(result[0].swaps[0].route.pools).toHaveLength(1); // 0 -> 2 at 10:11
expect(result[0].swaps[0].route.tokenPath).toEqual([token0, token2]);
expect(
result[0].inputAmount.equalTo(
CurrencyAmount.fromRawAmount(token0, 10032)
)
).toBeTruthy();
expect(
result[0].outputAmount.equalTo(
CurrencyAmount.fromRawAmount(token2, 10000)
)
).toBeTruthy();
expect(result[1].swaps[0].route.pools).toHaveLength(2); // 0 -> 1 -> 2 at 12:12:10
expect(result[1].swaps[0].route.tokenPath).toEqual([
token0,
token1,
token2,
]);
expect(
result[1].inputAmount.equalTo(
CurrencyAmount.fromRawAmount(token0, 15488)
)
).toBeTruthy();
expect(
result[1].outputAmount.equalTo(
CurrencyAmount.fromRawAmount(token2, 10000)
)
).toBeTruthy();
});
});
});