@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.
- package/.eslintignore +1 -0
- package/.eslintrc.json +20 -0
- package/.nvmrc +1 -0
- package/.prettierrc.json +12 -0
- package/.vscode/settings.json +15 -0
- package/README.md +101 -0
- package/dist/cjs/hydra_dx_wasm_bg-ZX7K4FM7.wasm +0 -0
- package/dist/cjs/index.js +2 -0
- package/dist/cjs/index.js.map +7 -0
- package/dist/esm/hydra_dx_wasm_bg-ZX7K4FM7.wasm +0 -0
- package/dist/esm/index.js +2 -0
- package/dist/esm/index.js.map +7 -0
- package/dist/types/api/index.d.ts +1 -0
- package/dist/types/api/router.d.ts +129 -0
- package/dist/types/api/trader.d.ts +0 -0
- package/dist/types/client/capi.d.ts +0 -0
- package/dist/types/client/index.d.ts +1 -0
- package/dist/types/client/polkadot.d.ts +14 -0
- package/dist/types/client/types.d.ts +7 -0
- package/dist/types/index.d.ts +4 -0
- package/dist/types/pool/index.d.ts +3 -0
- package/dist/types/pool/polkadotPoolService.d.ts +7 -0
- package/dist/types/pool/poolFactory.d.ts +4 -0
- package/dist/types/pool/xyk/math/bundler.d.ts +9 -0
- package/dist/types/pool/xyk/math/nodejs.d.ts +9 -0
- package/dist/types/pool/xyk/xykPolkadotClient.d.ts +8 -0
- package/dist/types/pool/xyk/xykPool.d.ts +16 -0
- package/dist/types/suggester/bfs.d.ts +37 -0
- package/dist/types/suggester/graph.d.ts +12 -0
- package/dist/types/suggester/index.d.ts +3 -0
- package/dist/types/suggester/suggester.d.ts +24 -0
- package/dist/types/types.d.ts +55 -0
- package/dist/types/utils/bignumber.d.ts +8 -0
- package/dist/types/utils/math.d.ts +4 -0
- package/dist/types/utils/queue.d.ts +13 -0
- package/dist/types/utils/stack.d.ts +15 -0
- package/dist/types/utils/traversal/bfs.d.ts +27 -0
- package/esbuild.mjs +36 -0
- package/jest.config.mjs +16 -0
- package/package.json +35 -0
- package/src/api/index.ts +1 -0
- package/src/api/router.ts +359 -0
- package/src/api/trader.ts +0 -0
- package/src/client/capi.ts +0 -0
- package/src/client/index.ts +1 -0
- package/src/client/polkadot.ts +47 -0
- package/src/client/types.ts +8 -0
- package/src/index.ts +4 -0
- package/src/pool/index.ts +3 -0
- package/src/pool/polkadotPoolService.ts +19 -0
- package/src/pool/poolFactory.ts +14 -0
- package/src/pool/xyk/math/bundler.ts +19 -0
- package/src/pool/xyk/math/nodejs.ts +19 -0
- package/src/pool/xyk/xykPolkadotClient.ts +58 -0
- package/src/pool/xyk/xykPool.ts +82 -0
- package/src/suggester/bfs.ts +106 -0
- package/src/suggester/graph.ts +31 -0
- package/src/suggester/index.ts +3 -0
- package/src/suggester/suggester.ts +66 -0
- package/src/types.ts +61 -0
- package/src/utils/bignumber.ts +25 -0
- package/src/utils/math.ts +24 -0
- package/src/utils/queue.ts +26 -0
- package/src/utils/stack.ts +31 -0
- package/src/utils/traversal/bfs.ts +74 -0
- package/test/api/router.spec.ts +87 -0
- package/test/data/xykPool.ts +21 -0
- package/test/data/xykPools.ts +61 -0
- package/test/lib/mockXykPoolService.ts +8 -0
- package/test/pool/xyk/xykPool.spec.ts +26 -0
- package/test/script/examples/router/getAllAssets.ts +14 -0
- package/test/script/examples/router/getAllPaths.ts +14 -0
- package/test/script/examples/router/getAssetPairs.ts +14 -0
- package/test/script/examples/router/getBestBuyPrice.ts +19 -0
- package/test/script/examples/router/getBestSellPrice.ts +19 -0
- package/test/script/executor.ts +45 -0
- package/test/suggester/bfs.spec.ts +34 -0
- package/test/suggester/graph.spec.ts +30 -0
- package/test/suggester/suggester.spec.ts +25 -0
- package/test/utils/traversal/bfs.spec.ts +28 -0
- package/tsconfig.json +14 -0
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { ApiPromise } from '@polkadot/api';
|
|
2
|
+
import type { StorageKey } from '@polkadot/types';
|
|
3
|
+
import type { AnyTuple, Codec } from '@polkadot/types/types';
|
|
4
|
+
import type { AssetMetadata } from '@polkadot/types/interfaces';
|
|
5
|
+
import '@polkadot/api-augment';
|
|
6
|
+
export declare class PolkadotClient {
|
|
7
|
+
protected readonly api: ApiPromise;
|
|
8
|
+
constructor(api: ApiPromise);
|
|
9
|
+
getStorageKey(asset: [StorageKey<AnyTuple>, Codec], index: number): string;
|
|
10
|
+
getStorageEntryArray(asset: [StorageKey<AnyTuple>, Codec]): string[];
|
|
11
|
+
getAssetMetadata(tokenKey: string): Promise<AssetMetadata>;
|
|
12
|
+
getSystemAccountBalance(accountId: string): Promise<string>;
|
|
13
|
+
getTokenAccountBalance(accountId: string, tokenKey: string): Promise<string>;
|
|
14
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
declare function getSpotPrice(a: string, b: string, c: string): string;
|
|
2
|
+
declare function calculateInGivenOut(a: string, b: string, c: string): string;
|
|
3
|
+
declare function calculateOutGivenIn(a: string, b: string, c: string): string;
|
|
4
|
+
declare const _default: {
|
|
5
|
+
getSpotPrice: typeof getSpotPrice;
|
|
6
|
+
calculateInGivenOut: typeof calculateInGivenOut;
|
|
7
|
+
calculateOutGivenIn: typeof calculateOutGivenIn;
|
|
8
|
+
};
|
|
9
|
+
export default _default;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
declare function getSpotPrice(a: string, b: string, c: string): string;
|
|
2
|
+
declare function calculateInGivenOut(a: string, b: string, c: string): string;
|
|
3
|
+
declare function calculateOutGivenIn(a: string, b: string, c: string): string;
|
|
4
|
+
declare const _default: {
|
|
5
|
+
getSpotPrice: typeof getSpotPrice;
|
|
6
|
+
calculateInGivenOut: typeof calculateInGivenOut;
|
|
7
|
+
calculateOutGivenIn: typeof calculateOutGivenIn;
|
|
8
|
+
};
|
|
9
|
+
export default _default;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { PolkadotClient } from '../../client';
|
|
2
|
+
import { PoolBase, PoolToken } from '../../types';
|
|
3
|
+
export declare class XykPolkadotClient extends PolkadotClient {
|
|
4
|
+
getPools(): Promise<PoolBase[]>;
|
|
5
|
+
getPoolTokens(poolAddress: string, assetKeys: string[]): Promise<PoolToken[]>;
|
|
6
|
+
getBalance(poolAddress: string, assetKey: string): Promise<string>;
|
|
7
|
+
getSwapFee(): string;
|
|
8
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { Pool, PoolBase, PoolPair, PoolToken, PoolType } from '../../types';
|
|
2
|
+
import { BigNumber } from '../../utils/bignumber';
|
|
3
|
+
export declare class XykPool implements Pool {
|
|
4
|
+
type: PoolType;
|
|
5
|
+
address: string;
|
|
6
|
+
swapFee: string;
|
|
7
|
+
tokens: PoolToken[];
|
|
8
|
+
static fromPool(pool: PoolBase): XykPool;
|
|
9
|
+
constructor(address: string, swapFee: string, tokens: PoolToken[]);
|
|
10
|
+
validPair(_tokenIn: string, _tokenOut: string): boolean;
|
|
11
|
+
parsePoolPair(tokenIn: string, tokenOut: string): PoolPair;
|
|
12
|
+
calculateInGivenOut(poolPair: PoolPair, amountOut: BigNumber): BigNumber;
|
|
13
|
+
getSpotPriceIn(poolPair: PoolPair): BigNumber;
|
|
14
|
+
calculateOutGivenIn(poolPair: PoolPair, amountIn: BigNumber): BigNumber;
|
|
15
|
+
getSpotPriceOut(poolPair: PoolPair): BigNumber;
|
|
16
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
export declare type Path = Node[];
|
|
2
|
+
export declare type Node = [id: number, from: string];
|
|
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 declare 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: Path): boolean;
|
|
20
|
+
/**
|
|
21
|
+
* Finding paths in graph from given source to destination
|
|
22
|
+
*
|
|
23
|
+
* @param g - routes graph containing nodes & corresponding edges
|
|
24
|
+
* @param src - source node
|
|
25
|
+
* @param dst - destination node or null if requesting all posible paths from src
|
|
26
|
+
* @returns paths
|
|
27
|
+
*/
|
|
28
|
+
findPaths(g: Path[], src: number, dst: number | null): Path[];
|
|
29
|
+
/**
|
|
30
|
+
* Build and populate graph
|
|
31
|
+
*
|
|
32
|
+
* @param nodes - list of pool assets
|
|
33
|
+
* @param edges - list of all edges [id, from, to] between assets
|
|
34
|
+
* @returns - traversal graph
|
|
35
|
+
*/
|
|
36
|
+
buildAndPopulateGraph(nodes: string[], edges: [string, string, string][]): Path[];
|
|
37
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { PoolBase } from '../types';
|
|
2
|
+
export declare type Edge = [address: string, from: string, to: string];
|
|
3
|
+
export declare type NodeEdges = {
|
|
4
|
+
[node: string]: Edge[];
|
|
5
|
+
};
|
|
6
|
+
/**
|
|
7
|
+
* Calculate nodes & edges from substrate pools
|
|
8
|
+
*
|
|
9
|
+
* @param pools - given substrate pools
|
|
10
|
+
* @returns nodes & corresponding edges
|
|
11
|
+
*/
|
|
12
|
+
export declare function getNodesAndEdges(pools: PoolBase[]): NodeEdges;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { PoolBase } from '../types';
|
|
2
|
+
import { Edge } from './graph';
|
|
3
|
+
export declare class RouteSuggester {
|
|
4
|
+
/**
|
|
5
|
+
* Proposals are ideal paths from
|
|
6
|
+
* 1) tokenIn to tokenOut
|
|
7
|
+
* 2) tokenIn to *(all possible paths are requested)
|
|
8
|
+
*
|
|
9
|
+
* calculated from all permutations of tokens of given pools.
|
|
10
|
+
*
|
|
11
|
+
* E.g. permutation of pool A={1,3} is 2, such as {1,3}, {3,1} where 1 are 3
|
|
12
|
+
* are pool assets(tokens)
|
|
13
|
+
*
|
|
14
|
+
* Filtering of valid paths and corresponding asset pairs is done by router itself!!!
|
|
15
|
+
*
|
|
16
|
+
* @param tokenIn - tokenIn
|
|
17
|
+
* @param tokenOut - tokenOut or null if all possible paths from tokenIn are requested
|
|
18
|
+
* @param pools - substrate based pools
|
|
19
|
+
* @returns all possible path proposals
|
|
20
|
+
*/
|
|
21
|
+
getProposals(tokenIn: string, tokenOut: string | null, pools: PoolBase[]): Edge[][];
|
|
22
|
+
private parsePaths;
|
|
23
|
+
private toEdge;
|
|
24
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { BigNumber } from './utils/bignumber';
|
|
2
|
+
export declare type PoolAsset = {
|
|
3
|
+
token: string;
|
|
4
|
+
symbol: string;
|
|
5
|
+
};
|
|
6
|
+
export declare enum PoolType {
|
|
7
|
+
XYK = "XYK",
|
|
8
|
+
LBP = "LBP",
|
|
9
|
+
Stable = "Stable",
|
|
10
|
+
Omni = "Omni"
|
|
11
|
+
}
|
|
12
|
+
export interface PoolPair {
|
|
13
|
+
swapFee: BigNumber;
|
|
14
|
+
tokenIn: string;
|
|
15
|
+
tokenOut: string;
|
|
16
|
+
balanceIn: BigNumber;
|
|
17
|
+
balanceOut: BigNumber;
|
|
18
|
+
}
|
|
19
|
+
export declare type PoolBase = {
|
|
20
|
+
address: string;
|
|
21
|
+
type: PoolType;
|
|
22
|
+
swapFee: string;
|
|
23
|
+
tokens: PoolToken[];
|
|
24
|
+
};
|
|
25
|
+
export declare type PoolToken = {
|
|
26
|
+
id: string;
|
|
27
|
+
balance: string;
|
|
28
|
+
decimals: number;
|
|
29
|
+
symbol: string;
|
|
30
|
+
};
|
|
31
|
+
export interface Pool extends PoolBase {
|
|
32
|
+
validPair(tokenIn: string, tokenOut: string): boolean;
|
|
33
|
+
parsePoolPair(tokenIn: string, tokenOut: string): PoolPair;
|
|
34
|
+
calculateInGivenOut(poolPair: PoolPair, amountOut: BigNumber): BigNumber;
|
|
35
|
+
calculateOutGivenIn(poolPair: PoolPair, amountIn: BigNumber): BigNumber;
|
|
36
|
+
getSpotPriceIn(poolPair: PoolPair): BigNumber;
|
|
37
|
+
getSpotPriceOut(poolPair: PoolPair): BigNumber;
|
|
38
|
+
}
|
|
39
|
+
export interface PoolService {
|
|
40
|
+
getPools(): Promise<PoolBase[]>;
|
|
41
|
+
}
|
|
42
|
+
export declare type Hop = {
|
|
43
|
+
poolType: PoolType;
|
|
44
|
+
poolId: string;
|
|
45
|
+
tokenIn: string;
|
|
46
|
+
tokenOut: string;
|
|
47
|
+
fee: string;
|
|
48
|
+
};
|
|
49
|
+
export declare type Swap = Hop & {
|
|
50
|
+
swapAmount: BigNumber;
|
|
51
|
+
returnAmount: BigNumber;
|
|
52
|
+
returnFinalAmount: BigNumber;
|
|
53
|
+
swapFee: BigNumber;
|
|
54
|
+
spotPrice: BigNumber;
|
|
55
|
+
};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { BigNumber } from 'bignumber.js';
|
|
2
|
+
export declare const DECIMAL_PLACES = 12;
|
|
3
|
+
export declare const ZERO: BigNumber;
|
|
4
|
+
export declare const ONE: BigNumber;
|
|
5
|
+
export declare const INFINITY: BigNumber;
|
|
6
|
+
export declare function scale(input: BigNumber, decimalPlaces: number): BigNumber;
|
|
7
|
+
export declare function bnum(val: string | number | BigNumber): BigNumber;
|
|
8
|
+
export { BigNumber };
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { BigNumber } from './bignumber';
|
|
2
|
+
export declare function tradeFee(percentage: string): BigNumber;
|
|
3
|
+
export declare function calculateTradeFee(amount: BigNumber, tradeFee: BigNumber): BigNumber;
|
|
4
|
+
export declare function normalizeAmount(amount: BigNumber, decimals: number): BigNumber;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export interface IQueue<T> {
|
|
2
|
+
enqueue(item: T): void;
|
|
3
|
+
dequeue(): T | undefined;
|
|
4
|
+
size(): number;
|
|
5
|
+
}
|
|
6
|
+
export declare class Queue<T> implements IQueue<T> {
|
|
7
|
+
private capacity;
|
|
8
|
+
private storage;
|
|
9
|
+
constructor(capacity?: number);
|
|
10
|
+
enqueue(item: T): void;
|
|
11
|
+
dequeue(): T | undefined;
|
|
12
|
+
size(): number;
|
|
13
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export interface IStack<T> {
|
|
2
|
+
push(item: T): void;
|
|
3
|
+
pop(): T | undefined;
|
|
4
|
+
peek(): T | undefined;
|
|
5
|
+
size(): number;
|
|
6
|
+
}
|
|
7
|
+
export declare class Stack<T> implements IStack<T> {
|
|
8
|
+
private capacity;
|
|
9
|
+
private storage;
|
|
10
|
+
constructor(capacity?: number);
|
|
11
|
+
push(item: T): void;
|
|
12
|
+
pop(): T | undefined;
|
|
13
|
+
peek(): T | undefined;
|
|
14
|
+
size(): number;
|
|
15
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Breadth First Search.
|
|
3
|
+
*
|
|
4
|
+
* - uses Queue to find the shortest path
|
|
5
|
+
* - slower than DFS (Depth First Search)
|
|
6
|
+
* - better when dst is closer to src
|
|
7
|
+
* - complexity O(N+E) where N are nodes and E are edges
|
|
8
|
+
*/
|
|
9
|
+
export declare class Bfs {
|
|
10
|
+
/**
|
|
11
|
+
* Check if current node is already present in path
|
|
12
|
+
*
|
|
13
|
+
* @param x - current node
|
|
14
|
+
* @param path - path
|
|
15
|
+
* @returns true if node in path, otherwise false
|
|
16
|
+
*/
|
|
17
|
+
isNotVisited(x: number, path: number[]): boolean;
|
|
18
|
+
/**
|
|
19
|
+
* Finding paths in graph from given source to destination
|
|
20
|
+
*
|
|
21
|
+
* @param g - routes graph containing nodes & corresponding edges
|
|
22
|
+
* @param src - source node
|
|
23
|
+
* @param dst - destination node
|
|
24
|
+
* @returns paths
|
|
25
|
+
*/
|
|
26
|
+
findPaths(g: number[][], src: number, dst: number): number[][];
|
|
27
|
+
}
|
package/esbuild.mjs
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import esbuild from 'esbuild';
|
|
2
|
+
import resolve from 'esbuild-plugin-resolve';
|
|
3
|
+
import { wasmLoader } from 'esbuild-plugin-wasm';
|
|
4
|
+
|
|
5
|
+
// ESM bundle
|
|
6
|
+
esbuild
|
|
7
|
+
.build({
|
|
8
|
+
entryPoints: ['src/index.ts'],
|
|
9
|
+
outdir: 'dist/esm',
|
|
10
|
+
bundle: true,
|
|
11
|
+
sourcemap: true,
|
|
12
|
+
minify: true,
|
|
13
|
+
splitting: true,
|
|
14
|
+
plugins: [
|
|
15
|
+
resolve({
|
|
16
|
+
'./math/nodejs': './math/bundler',
|
|
17
|
+
}),
|
|
18
|
+
wasmLoader({ mode: 'deferred' }),
|
|
19
|
+
],
|
|
20
|
+
format: 'esm',
|
|
21
|
+
target: ['esnext'],
|
|
22
|
+
})
|
|
23
|
+
.catch(() => process.exit(1));
|
|
24
|
+
|
|
25
|
+
// CJS bundle
|
|
26
|
+
esbuild
|
|
27
|
+
.build({
|
|
28
|
+
entryPoints: ['src/index.ts'],
|
|
29
|
+
outfile: 'dist/cjs/index.js',
|
|
30
|
+
bundle: true,
|
|
31
|
+
sourcemap: true,
|
|
32
|
+
minify: true,
|
|
33
|
+
platform: 'node',
|
|
34
|
+
target: ['node18'],
|
|
35
|
+
})
|
|
36
|
+
.catch(() => process.exit(1));
|
package/jest.config.mjs
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export default {
|
|
2
|
+
roots: ['<rootDir>/test'],
|
|
3
|
+
modulePaths: ['<rootDir>'],
|
|
4
|
+
moduleDirectories: ['node_modules'],
|
|
5
|
+
moduleNameMapper: {},
|
|
6
|
+
testMatch: ['**/__tests__/**/*.+(ts|js)', '**/?(*.)+(spec|test).+(ts|js)'],
|
|
7
|
+
transform: {
|
|
8
|
+
'^.+\\.(ts)$': 'es-jest',
|
|
9
|
+
},
|
|
10
|
+
collectCoverageFrom: ['**/*.{js,ts}', '!**/*.d.ts', '!**/node_modules/**'],
|
|
11
|
+
globals: {
|
|
12
|
+
'ts-jest': {
|
|
13
|
+
tsconfig: 'tsconfig.json',
|
|
14
|
+
},
|
|
15
|
+
},
|
|
16
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@galacticcouncil/sdk",
|
|
3
|
+
"version": "0.0.1-beta.1",
|
|
4
|
+
"private": false,
|
|
5
|
+
"description": "Galactic SDK",
|
|
6
|
+
"author": "Pavol Noha <palo@hydradx.io>",
|
|
7
|
+
"main": "dist/cjs/index.js",
|
|
8
|
+
"module": "dist/esm/index.js",
|
|
9
|
+
"types": "dist/types/index.d.ts",
|
|
10
|
+
"scripts": {
|
|
11
|
+
"test": "jest",
|
|
12
|
+
"build": "node ./esbuild.mjs && tsc --emitDeclarationOnly --outDir dist/types/",
|
|
13
|
+
"cleanup": "rimraf out && rimraf dist"
|
|
14
|
+
},
|
|
15
|
+
"devDependencies": {
|
|
16
|
+
"@types/jest": "^28.1.8",
|
|
17
|
+
"es-jest": "^2.0.0",
|
|
18
|
+
"esbuild": "^0.14.53",
|
|
19
|
+
"esbuild-plugin-resolve": "^1.0.3",
|
|
20
|
+
"esbuild-plugin-wasm": "^1.0.0",
|
|
21
|
+
"fs-extra": "^10.1.0",
|
|
22
|
+
"prettier": "^2.3.2",
|
|
23
|
+
"rimraf": "^3.0.2",
|
|
24
|
+
"ts-jest": "^28.0.8",
|
|
25
|
+
"tsx": "^3.8.2",
|
|
26
|
+
"typescript": "^4.7.4"
|
|
27
|
+
},
|
|
28
|
+
"dependencies": {
|
|
29
|
+
"@polkadot/api": "^9.0.1",
|
|
30
|
+
"bignumber.js": "^9.1.0",
|
|
31
|
+
"capi": "^0.1.0-beta.12",
|
|
32
|
+
"hydra-dx-wasm": "https://github.com/galacticcouncil/HydraDX-wasm#0e3d625c22c32525a4619047223cac019c0cfa46",
|
|
33
|
+
"lodash.clonedeep": "^4.5.0"
|
|
34
|
+
}
|
|
35
|
+
}
|
package/src/api/index.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { Router } from './router';
|