@galacticcouncil/sdk 0.0.1-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (81) hide show
  1. package/.eslintignore +1 -0
  2. package/.eslintrc.json +20 -0
  3. package/.nvmrc +1 -0
  4. package/.prettierrc.json +12 -0
  5. package/.vscode/settings.json +15 -0
  6. package/README.md +101 -0
  7. package/dist/cjs/hydra_dx_wasm_bg-ZX7K4FM7.wasm +0 -0
  8. package/dist/cjs/index.js +2 -0
  9. package/dist/cjs/index.js.map +7 -0
  10. package/dist/esm/hydra_dx_wasm_bg-ZX7K4FM7.wasm +0 -0
  11. package/dist/esm/index.js +2 -0
  12. package/dist/esm/index.js.map +7 -0
  13. package/dist/types/api/index.d.ts +1 -0
  14. package/dist/types/api/router.d.ts +129 -0
  15. package/dist/types/api/trader.d.ts +0 -0
  16. package/dist/types/client/capi.d.ts +0 -0
  17. package/dist/types/client/index.d.ts +1 -0
  18. package/dist/types/client/polkadot.d.ts +14 -0
  19. package/dist/types/client/types.d.ts +7 -0
  20. package/dist/types/index.d.ts +4 -0
  21. package/dist/types/pool/index.d.ts +3 -0
  22. package/dist/types/pool/polkadotPoolService.d.ts +7 -0
  23. package/dist/types/pool/poolFactory.d.ts +4 -0
  24. package/dist/types/pool/xyk/math/bundler.d.ts +9 -0
  25. package/dist/types/pool/xyk/math/nodejs.d.ts +9 -0
  26. package/dist/types/pool/xyk/xykPolkadotClient.d.ts +8 -0
  27. package/dist/types/pool/xyk/xykPool.d.ts +16 -0
  28. package/dist/types/suggester/bfs.d.ts +37 -0
  29. package/dist/types/suggester/graph.d.ts +12 -0
  30. package/dist/types/suggester/index.d.ts +3 -0
  31. package/dist/types/suggester/suggester.d.ts +24 -0
  32. package/dist/types/types.d.ts +55 -0
  33. package/dist/types/utils/bignumber.d.ts +8 -0
  34. package/dist/types/utils/math.d.ts +4 -0
  35. package/dist/types/utils/queue.d.ts +13 -0
  36. package/dist/types/utils/stack.d.ts +15 -0
  37. package/dist/types/utils/traversal/bfs.d.ts +27 -0
  38. package/esbuild.mjs +36 -0
  39. package/jest.config.mjs +16 -0
  40. package/package.json +35 -0
  41. package/src/api/index.ts +1 -0
  42. package/src/api/router.ts +359 -0
  43. package/src/api/trader.ts +0 -0
  44. package/src/client/capi.ts +0 -0
  45. package/src/client/index.ts +1 -0
  46. package/src/client/polkadot.ts +47 -0
  47. package/src/client/types.ts +8 -0
  48. package/src/index.ts +4 -0
  49. package/src/pool/index.ts +3 -0
  50. package/src/pool/polkadotPoolService.ts +19 -0
  51. package/src/pool/poolFactory.ts +14 -0
  52. package/src/pool/xyk/math/bundler.ts +19 -0
  53. package/src/pool/xyk/math/nodejs.ts +19 -0
  54. package/src/pool/xyk/xykPolkadotClient.ts +58 -0
  55. package/src/pool/xyk/xykPool.ts +82 -0
  56. package/src/suggester/bfs.ts +106 -0
  57. package/src/suggester/graph.ts +31 -0
  58. package/src/suggester/index.ts +3 -0
  59. package/src/suggester/suggester.ts +66 -0
  60. package/src/types.ts +61 -0
  61. package/src/utils/bignumber.ts +25 -0
  62. package/src/utils/math.ts +24 -0
  63. package/src/utils/queue.ts +26 -0
  64. package/src/utils/stack.ts +31 -0
  65. package/src/utils/traversal/bfs.ts +74 -0
  66. package/test/api/router.spec.ts +87 -0
  67. package/test/data/xykPool.ts +21 -0
  68. package/test/data/xykPools.ts +61 -0
  69. package/test/lib/mockXykPoolService.ts +8 -0
  70. package/test/pool/xyk/xykPool.spec.ts +26 -0
  71. package/test/script/examples/router/getAllAssets.ts +14 -0
  72. package/test/script/examples/router/getAllPaths.ts +14 -0
  73. package/test/script/examples/router/getAssetPairs.ts +14 -0
  74. package/test/script/examples/router/getBestBuyPrice.ts +19 -0
  75. package/test/script/examples/router/getBestSellPrice.ts +19 -0
  76. package/test/script/executor.ts +45 -0
  77. package/test/suggester/bfs.spec.ts +34 -0
  78. package/test/suggester/graph.spec.ts +30 -0
  79. package/test/suggester/suggester.spec.ts +25 -0
  80. package/test/utils/traversal/bfs.spec.ts +28 -0
  81. package/tsconfig.json +14 -0
@@ -0,0 +1,106 @@
1
+ import { Queue } from '../utils/queue';
2
+
3
+ export type Path = Node[];
4
+ export type Node = [id: number, from: string];
5
+
6
+ /**
7
+ * Breadth First Search.
8
+ *
9
+ * - uses Queue to find the shortest path
10
+ * - slower than DFS (Depth First Search)
11
+ * - better when dst is closer to src
12
+ * - complexity O(N+E) where N are nodes and E are edges
13
+ */
14
+ export class Bfs {
15
+ /**
16
+ * Check if current node is already present in path
17
+ *
18
+ * @param x - current node
19
+ * @param path - path
20
+ * @returns true if node in path, otherwise false
21
+ */
22
+ isNotVisited(x: number, path: Path): boolean {
23
+ let notVisited: boolean = true;
24
+ path.forEach((pv) => {
25
+ if (pv[0] === x) {
26
+ notVisited = false;
27
+ }
28
+ });
29
+ return notVisited;
30
+ }
31
+
32
+ /**
33
+ * Finding paths in graph from given source to destination
34
+ *
35
+ * @param g - routes graph containing nodes & corresponding edges
36
+ * @param src - source node
37
+ * @param dst - destination node or null if requesting all posible paths from src
38
+ * @returns paths
39
+ */
40
+ findPaths(g: Path[], src: number, dst: number | null): Path[] {
41
+ // Store the result paths
42
+ const paths: Path[] = [];
43
+ // Store the traversing paths
44
+ const queue = new Queue<Path>();
45
+ // Store the current path
46
+ const currentPath: Path = [];
47
+
48
+ // First node of path has no from (initial)
49
+ currentPath.push([src, '']);
50
+ queue.enqueue(currentPath);
51
+
52
+ while (queue.size() > 0) {
53
+ const path = queue.dequeue();
54
+
55
+ if (path == null) {
56
+ return paths;
57
+ }
58
+
59
+ const last = path[path.length - 1];
60
+
61
+ // If destination is undefined save all traversal to paths
62
+ // If last node is the desired destination save to paths
63
+ if (dst === null) {
64
+ paths.push(path);
65
+ } else if (last[0] === dst) {
66
+ paths.push(path);
67
+ }
68
+
69
+ // Traverse to all nodes connected to current one and push path to queue
70
+ const lastNode = g[last[0]];
71
+ lastNode.forEach((segment) => {
72
+ if (this.isNotVisited(segment[0], path)) {
73
+ const newpath = [...path];
74
+ newpath.push(segment);
75
+ queue.enqueue(newpath);
76
+ }
77
+ });
78
+ }
79
+ return paths;
80
+ }
81
+
82
+ /**
83
+ * Build and populate graph
84
+ *
85
+ * @param nodes - list of pool assets
86
+ * @param edges - list of all edges [id, from, to] between assets
87
+ * @returns - traversal graph
88
+ */
89
+ buildAndPopulateGraph(
90
+ nodes: string[],
91
+ edges: [string, string, string][]
92
+ ): Path[] {
93
+ const graph: Path[] = [];
94
+ for (let j = 0; j < nodes.length; j++) {
95
+ graph.push([]);
96
+ }
97
+
98
+ for (const [address, from, to] of edges) {
99
+ const fromNumber = parseInt(from);
100
+ const toNumber = parseInt(to);
101
+ graph[fromNumber].push([toNumber, address]);
102
+ }
103
+
104
+ return graph;
105
+ }
106
+ }
@@ -0,0 +1,31 @@
1
+ import { PoolBase } from '../types';
2
+
3
+ export type Edge = [address: string, from: string, to: string];
4
+
5
+ export type NodeEdges = {
6
+ [node: string]: Edge[];
7
+ };
8
+
9
+ /**
10
+ * Calculate nodes & edges from substrate pools
11
+ *
12
+ * @param pools - given substrate pools
13
+ * @returns nodes & corresponding edges
14
+ */
15
+ export function getNodesAndEdges(pools: PoolBase[]): NodeEdges {
16
+ const edgesFromNode: NodeEdges = {};
17
+ for (const pool of pools) {
18
+ const n = pool.tokens.length;
19
+ for (let i = 0; i < n; i++) {
20
+ if (!edgesFromNode[pool.tokens[i].id]) {
21
+ edgesFromNode[pool.tokens[i].id] = [];
22
+ }
23
+ for (let j = 0; j < n; j++) {
24
+ if (i == j) continue;
25
+ const edge: Edge = [pool.address, pool.tokens[i].id, pool.tokens[j].id];
26
+ edgesFromNode[pool.tokens[i].id].push(edge);
27
+ }
28
+ }
29
+ }
30
+ return edgesFromNode;
31
+ }
@@ -0,0 +1,3 @@
1
+ export { RouteSuggester } from './suggester';
2
+ export { Bfs, Path } from './bfs';
3
+ export { Edge, getNodesAndEdges } from './graph';
@@ -0,0 +1,66 @@
1
+ import { PoolBase } from '../types';
2
+ import { Bfs, Node, Path } from './bfs';
3
+
4
+ import { getNodesAndEdges, Edge } from './graph';
5
+
6
+ export class RouteSuggester {
7
+ /**
8
+ * Proposals are ideal paths from
9
+ * 1) tokenIn to tokenOut
10
+ * 2) tokenIn to *(all possible paths are requested)
11
+ *
12
+ * calculated from all permutations of tokens of given pools.
13
+ *
14
+ * E.g. permutation of pool A={1,3} is 2, such as {1,3}, {3,1} where 1 are 3
15
+ * are pool assets(tokens)
16
+ *
17
+ * Filtering of valid paths and corresponding asset pairs is done by router itself!!!
18
+ *
19
+ * @param tokenIn - tokenIn
20
+ * @param tokenOut - tokenOut or null if all possible paths from tokenIn are requested
21
+ * @param pools - substrate based pools
22
+ * @returns all possible path proposals
23
+ */
24
+ getProposals(
25
+ tokenIn: string,
26
+ tokenOut: string | null,
27
+ pools: PoolBase[]
28
+ ): Edge[][] {
29
+ const nodeEdges = getNodesAndEdges(pools);
30
+ const poolAssets = Object.keys(nodeEdges);
31
+ const possiblePairs: Edge[] = poolAssets
32
+ .map((node) => nodeEdges[node])
33
+ .flat();
34
+
35
+ const bfs = new Bfs();
36
+ const bfsGraph = bfs.buildAndPopulateGraph(poolAssets, possiblePairs);
37
+ const possiblePaths = bfs.findPaths(
38
+ bfsGraph,
39
+ parseInt(tokenIn),
40
+ tokenOut ? parseInt(tokenOut) : null
41
+ );
42
+ return this.parsePaths(possiblePaths);
43
+ }
44
+
45
+ private parsePaths(possiblePaths: Path[]): Edge[][] {
46
+ const paths: Edge[][] = [];
47
+ for (const path of possiblePaths) {
48
+ const edges: Edge[] = [];
49
+ for (let i = 0; i < path.length; i++) {
50
+ const from = path[i];
51
+ const to = path[i + 1];
52
+ if (to == null) {
53
+ break;
54
+ } else {
55
+ edges.push(this.toEdge(from, to));
56
+ }
57
+ }
58
+ paths.push(edges);
59
+ }
60
+ return paths;
61
+ }
62
+
63
+ private toEdge(from: Node, to: Node): Edge {
64
+ return [to[1], from[0].toString(), to[0].toString()] as Edge;
65
+ }
66
+ }
package/src/types.ts ADDED
@@ -0,0 +1,61 @@
1
+ import { BigNumber } from './utils/bignumber';
2
+
3
+ export type PoolAsset = { token: string; symbol: string };
4
+
5
+ export enum PoolType {
6
+ XYK = 'XYK',
7
+ LBP = 'LBP',
8
+ Stable = 'Stable',
9
+ Omni = 'Omni',
10
+ }
11
+
12
+ export interface PoolPair {
13
+ swapFee: BigNumber;
14
+ tokenIn: string;
15
+ tokenOut: string;
16
+ balanceIn: BigNumber;
17
+ balanceOut: BigNumber;
18
+ }
19
+
20
+ export type PoolBase = {
21
+ address: string;
22
+ type: PoolType;
23
+ swapFee: string;
24
+ tokens: PoolToken[];
25
+ };
26
+
27
+ export type PoolToken = {
28
+ id: string;
29
+ balance: string;
30
+ decimals: number;
31
+ symbol: string;
32
+ };
33
+
34
+ export interface Pool extends PoolBase {
35
+ validPair(tokenIn: string, tokenOut: string): boolean;
36
+ parsePoolPair(tokenIn: string, tokenOut: string): PoolPair;
37
+ calculateInGivenOut(poolPair: PoolPair, amountOut: BigNumber): BigNumber;
38
+ calculateOutGivenIn(poolPair: PoolPair, amountIn: BigNumber): BigNumber;
39
+ getSpotPriceIn(poolPair: PoolPair): BigNumber;
40
+ getSpotPriceOut(poolPair: PoolPair): BigNumber;
41
+ }
42
+
43
+ export interface PoolService {
44
+ getPools(): Promise<PoolBase[]>;
45
+ }
46
+
47
+ export type Hop = {
48
+ poolType: PoolType;
49
+ poolId: string;
50
+ tokenIn: string;
51
+ tokenOut: string;
52
+ fee: string;
53
+ };
54
+
55
+ export type Swap = Hop & {
56
+ swapAmount: BigNumber;
57
+ returnAmount: BigNumber;
58
+ returnFinalAmount: BigNumber;
59
+ swapFee: BigNumber;
60
+ spotPrice: BigNumber;
61
+ };
@@ -0,0 +1,25 @@
1
+ import { BigNumber } from 'bignumber.js';
2
+
3
+ export const DECIMAL_PLACES = 12;
4
+
5
+ BigNumber.config({
6
+ EXPONENTIAL_AT: [-100, 100],
7
+ ROUNDING_MODE: 1,
8
+ DECIMAL_PLACES: DECIMAL_PLACES,
9
+ });
10
+
11
+ export const ZERO = bnum(0);
12
+ export const ONE = bnum(1);
13
+ export const INFINITY = bnum('Infinity');
14
+
15
+ export function scale(input: BigNumber, decimalPlaces: number): BigNumber {
16
+ const scalePow = new BigNumber(decimalPlaces.toString());
17
+ const scaleMul = new BigNumber(10).pow(scalePow);
18
+ return input.times(scaleMul);
19
+ }
20
+
21
+ export function bnum(val: string | number | BigNumber): BigNumber {
22
+ return new BigNumber(val.toString());
23
+ }
24
+
25
+ export { BigNumber };
@@ -0,0 +1,24 @@
1
+ import { BigNumber, bnum, scale, DECIMAL_PLACES } from './bignumber';
2
+
3
+ export function tradeFee(percentage: string): BigNumber {
4
+ return bnum(parseFloat(percentage) / 100);
5
+ }
6
+
7
+ export function calculateTradeFee(
8
+ amount: BigNumber,
9
+ tradeFee: BigNumber
10
+ ): BigNumber {
11
+ return amount.multipliedBy(tradeFee).decimalPlaces(0, 1);
12
+ }
13
+
14
+ export function normalizeAmount(
15
+ amount: BigNumber,
16
+ decimals: number
17
+ ): BigNumber {
18
+ if (decimals == DECIMAL_PLACES) {
19
+ return amount;
20
+ }
21
+
22
+ const normalizedAmount = amount.shiftedBy(-1 * decimals);
23
+ return scale(normalizedAmount, 12);
24
+ }
@@ -0,0 +1,26 @@
1
+ export interface IQueue<T> {
2
+ enqueue(item: T): void;
3
+ dequeue(): T | undefined;
4
+ size(): number;
5
+ }
6
+
7
+ export class Queue<T> implements IQueue<T> {
8
+ private storage: T[] = [];
9
+
10
+ constructor(private capacity: number = Infinity) {}
11
+
12
+ enqueue(item: T): void {
13
+ if (this.size() === this.capacity) {
14
+ throw Error('Queue has reached max capacity, you cannot add more items');
15
+ }
16
+ this.storage.push(item);
17
+ }
18
+
19
+ dequeue(): T | undefined {
20
+ return this.storage.shift();
21
+ }
22
+
23
+ size(): number {
24
+ return this.storage.length;
25
+ }
26
+ }
@@ -0,0 +1,31 @@
1
+ export interface IStack<T> {
2
+ push(item: T): void;
3
+ pop(): T | undefined;
4
+ peek(): T | undefined;
5
+ size(): number;
6
+ }
7
+
8
+ export class Stack<T> implements IStack<T> {
9
+ private storage: T[] = [];
10
+
11
+ constructor(private capacity: number = Infinity) {}
12
+
13
+ push(item: T): void {
14
+ if (this.size() === this.capacity) {
15
+ throw Error('Stack has reached max capacity, you cannot add more items');
16
+ }
17
+ this.storage.push(item);
18
+ }
19
+
20
+ pop(): T | undefined {
21
+ return this.storage.pop();
22
+ }
23
+
24
+ peek(): T | undefined {
25
+ return this.storage[this.size() - 1];
26
+ }
27
+
28
+ size(): number {
29
+ return this.storage.length;
30
+ }
31
+ }
@@ -0,0 +1,74 @@
1
+ import { Queue } from '../queue';
2
+
3
+ /**
4
+ * Breadth First Search.
5
+ *
6
+ * - uses Queue to find the shortest path
7
+ * - slower than DFS (Depth First Search)
8
+ * - better when dst is closer to src
9
+ * - complexity O(N+E) where N are nodes and E are edges
10
+ */
11
+ export class Bfs {
12
+ /**
13
+ * Check if current node is already present in path
14
+ *
15
+ * @param x - current node
16
+ * @param path - path
17
+ * @returns true if node in path, otherwise false
18
+ */
19
+ isNotVisited(x: number, path: number[]): boolean {
20
+ let notVisited: boolean = true;
21
+ path.forEach((pv) => {
22
+ if (pv === x) {
23
+ notVisited = false;
24
+ }
25
+ });
26
+ return notVisited;
27
+ }
28
+
29
+ /**
30
+ * Finding paths in graph from given source to destination
31
+ *
32
+ * @param g - routes graph containing nodes & corresponding edges
33
+ * @param src - source node
34
+ * @param dst - destination node
35
+ * @returns paths
36
+ */
37
+ findPaths(g: number[][], src: number, dst: number): number[][] {
38
+ // Store the results
39
+ const paths: number[][] = [];
40
+ // Store the traversing paths
41
+ const queue = new Queue<number[]>();
42
+ // Store the current path
43
+ const currentPath: number[] = [];
44
+
45
+ currentPath.push(src);
46
+ queue.enqueue(currentPath);
47
+
48
+ while (queue.size() > 0) {
49
+ const path = queue.dequeue();
50
+
51
+ if (path === undefined) {
52
+ return paths;
53
+ }
54
+
55
+ const last = path[path.length - 1];
56
+
57
+ // If last node is the desired destination save to paths
58
+ if (last === dst) {
59
+ paths.push(path);
60
+ }
61
+
62
+ // Traverse to all nodes connected to current node and push path to queue
63
+ const lastNode = g[last];
64
+ lastNode.forEach((segment) => {
65
+ if (this.isNotVisited(segment, path)) {
66
+ const newpath = [...path];
67
+ newpath.push(segment);
68
+ queue.enqueue(newpath);
69
+ }
70
+ });
71
+ }
72
+ return paths;
73
+ }
74
+ }
@@ -0,0 +1,87 @@
1
+ import { Router } from '../../src/api';
2
+ import { PoolService, PoolType } from '../../src/types';
3
+ import { bnum, scale } from '../../src/utils/bignumber';
4
+ import { MockXykPoolService } from '../lib/mockXykPoolService';
5
+
6
+ describe('Router', () => {
7
+ let poolService: PoolService;
8
+ let router: Router;
9
+
10
+ beforeEach(() => {
11
+ poolService = new MockXykPoolService();
12
+ router = new Router(poolService);
13
+ });
14
+
15
+ it('Should return suggested hops from token 1 to 2 for given XYK pool', async () => {
16
+ expect(poolService).toBeDefined();
17
+ expect(router).toBeDefined();
18
+ const result = await router.getAllPaths('1', '2');
19
+ expect(result).toStrictEqual([
20
+ [
21
+ {
22
+ poolId: 'bXi1mHNp4jSRUNXuX3sY1fjCF9Um2EezkpzkFmQuLHaChdPM3',
23
+ poolType: PoolType.XYK,
24
+ tokenIn: '1',
25
+ tokenOut: '2',
26
+ fee: '0.3',
27
+ },
28
+ ],
29
+ [
30
+ {
31
+ poolId: 'bXn6KCrv8k2JV7B2c5jzLttBDqL4BurPCTcLa3NQk5SWDVXCJ',
32
+ poolType: PoolType.XYK,
33
+ tokenIn: '1',
34
+ tokenOut: '0',
35
+ fee: '0.3',
36
+ },
37
+ {
38
+ poolId: 'bXjT2D2cuxUuP2JzddMxYusg4cKo3wENje5Xdk3jbNwtRvStq',
39
+ poolType: PoolType.XYK,
40
+ tokenIn: '0',
41
+ tokenOut: '2',
42
+ fee: '0.3',
43
+ },
44
+ ],
45
+ ]);
46
+ });
47
+
48
+ it('Should return all assets from given XYK pool', async () => {
49
+ expect(poolService).toBeDefined();
50
+ expect(router).toBeDefined();
51
+ const result = await router.getAllAssets();
52
+ expect(result).toStrictEqual([
53
+ { token: '0', symbol: 'BSX' },
54
+ { token: '2', symbol: 'AUSD' },
55
+ { token: '1', symbol: 'KSM' },
56
+ ]);
57
+ });
58
+
59
+ it('Should return all assets pair reacheable from token 1 in given XYK pool', async () => {
60
+ expect(poolService).toBeDefined();
61
+ expect(router).toBeDefined();
62
+ const result = await router.getAssetPairs('1');
63
+ expect(result).toStrictEqual([
64
+ { token: '2', symbol: 'AUSD' },
65
+ { token: '0', symbol: 'BSX' },
66
+ ]);
67
+ });
68
+
69
+ it('Should throw error if not-existing asset used in given XYK pool', async () => {
70
+ expect(poolService).toBeDefined();
71
+ expect(router).toBeDefined();
72
+ await expect(async () => {
73
+ await router.getAssetPairs('not-existing');
74
+ }).rejects.toThrow('not-existing is not supported token');
75
+ });
76
+
77
+ it('Should return best sell price swaps', async () => {
78
+ expect(poolService).toBeDefined();
79
+ expect(router).toBeDefined();
80
+ const result = await router.getBestSellPrice(
81
+ '1',
82
+ '2',
83
+ scale(bnum('1'), 12)
84
+ );
85
+ // TODO write test assertions
86
+ });
87
+ });
@@ -0,0 +1,21 @@
1
+ import { PoolType } from '../../src/types';
2
+
3
+ export const xykPool = {
4
+ address: 'bXi1mHNp4jSRUNXuX3sY1fjCF9Um2EezkpzkFmQuLHaChdPM3',
5
+ type: PoolType.XYK,
6
+ swapFee: '0.3',
7
+ tokens: [
8
+ {
9
+ id: '1',
10
+ balance: '3684960401086',
11
+ decimals: 12,
12
+ symbol: 'KSM',
13
+ },
14
+ {
15
+ id: '2',
16
+ balance: '174291804564300',
17
+ decimals: 12,
18
+ symbol: 'AUSD',
19
+ },
20
+ ],
21
+ };
@@ -0,0 +1,61 @@
1
+ import { PoolType } from '../../src/types';
2
+
3
+ export const xykPools = [
4
+ {
5
+ address: 'bXjT2D2cuxUuP2JzddMxYusg4cKo3wENje5Xdk3jbNwtRvStq',
6
+ type: PoolType.XYK,
7
+ swapFee: '0.3',
8
+ tokens: [
9
+ {
10
+ id: '0',
11
+ balance: '235315220453344458259',
12
+ decimals: 12,
13
+ symbol: 'BSX',
14
+ },
15
+ {
16
+ id: '2',
17
+ balance: '34783100690381537',
18
+ decimals: 12,
19
+ symbol: 'AUSD',
20
+ },
21
+ ],
22
+ },
23
+ {
24
+ address: 'bXi1mHNp4jSRUNXuX3sY1fjCF9Um2EezkpzkFmQuLHaChdPM3',
25
+ type: PoolType.XYK,
26
+ swapFee: '0.3',
27
+ tokens: [
28
+ {
29
+ id: '1',
30
+ balance: '3684960401086',
31
+ decimals: 12,
32
+ symbol: 'KSM',
33
+ },
34
+ {
35
+ id: '2',
36
+ balance: '174291804564300',
37
+ decimals: 12,
38
+ symbol: 'AUSD',
39
+ },
40
+ ],
41
+ },
42
+ {
43
+ address: 'bXn6KCrv8k2JV7B2c5jzLttBDqL4BurPCTcLa3NQk5SWDVXCJ',
44
+ type: PoolType.XYK,
45
+ swapFee: '0.3',
46
+ tokens: [
47
+ {
48
+ id: '0',
49
+ balance: '261138390134511806721',
50
+ decimals: 12,
51
+ symbol: 'BSX',
52
+ },
53
+ {
54
+ id: '1',
55
+ balance: '842366824680338',
56
+ decimals: 12,
57
+ symbol: 'KSM',
58
+ },
59
+ ],
60
+ },
61
+ ];
@@ -0,0 +1,8 @@
1
+ import { PoolBase, PoolService } from '../../src/types';
2
+ import { xykPools } from '../data/xykPools';
3
+
4
+ export class MockXykPoolService implements PoolService {
5
+ getPools(): Promise<PoolBase[]> {
6
+ return Promise.resolve(xykPools);
7
+ }
8
+ }
@@ -0,0 +1,26 @@
1
+ import { XykPool } from '../../../src/pool';
2
+ import { xykPool } from '../../data/xykPool';
3
+
4
+ describe('Xyk Pool', () => {
5
+ let pool: XykPool;
6
+
7
+ beforeEach(() => {
8
+ pool = XykPool.fromPool(xykPool);
9
+ });
10
+
11
+ it('Should return valid PoolPair for assets 1 & 2', async () => {
12
+ expect(pool).toBeDefined();
13
+ const result = pool.parsePoolPair('1', '2');
14
+ expect(result.swapFee.toString()).toStrictEqual(
15
+ (parseFloat(xykPool.swapFee) / 100).toString()
16
+ );
17
+ expect(result.tokenIn).toStrictEqual(xykPool.tokens[0].id);
18
+ expect(result.balanceIn.toString()).toStrictEqual(
19
+ xykPool.tokens[0].balance
20
+ );
21
+ expect(result.tokenOut).toStrictEqual(xykPool.tokens[1].id);
22
+ expect(result.balanceOut.toString()).toStrictEqual(
23
+ xykPool.tokens[1].balance
24
+ );
25
+ });
26
+ });
@@ -0,0 +1,14 @@
1
+ import { ApiPromise } from '@polkadot/api';
2
+ import { PolkadotExecutor } from '../../executor';
3
+ import { PolkadotPoolService } from '../../../../src/pool';
4
+ import { Router } from '../../../../src/api';
5
+
6
+ class GetAllAssetsExample extends PolkadotExecutor {
7
+ async script(api: ApiPromise): Promise<any> {
8
+ const poolService = new PolkadotPoolService(api);
9
+ const router = new Router(poolService);
10
+ return router.getAllAssets();
11
+ }
12
+ }
13
+
14
+ new GetAllAssetsExample('wss://rpc.basilisk.cloud', 'Get all paths').run();
@@ -0,0 +1,14 @@
1
+ import { ApiPromise } from '@polkadot/api';
2
+ import { PolkadotExecutor } from '../../executor';
3
+ import { PolkadotPoolService } from '../../../../src/pool';
4
+ import { Router } from '../../../../src/api';
5
+
6
+ class GetAllPathsExample extends PolkadotExecutor {
7
+ async script(api: ApiPromise): Promise<any> {
8
+ const poolService = new PolkadotPoolService(api);
9
+ const router = new Router(poolService);
10
+ return router.getAllPaths('1', '2');
11
+ }
12
+ }
13
+
14
+ new GetAllPathsExample('wss://rpc.basilisk.cloud', 'Get all paths').run();