@swapkit/helpers 1.0.0-rc.8 → 1.0.0-rc.81
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/LICENSE +1 -1
- package/dist/index.cjs +2 -1
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.ts +143 -89
- package/dist/index.es.js +578 -446
- package/dist/index.es.js.map +1 -0
- package/package.json +19 -19
- package/src/helpers/__tests__/asset.test.ts +64 -62
- package/src/helpers/__tests__/memo.test.ts +52 -40
- package/src/helpers/__tests__/others.test.ts +57 -30
- package/src/helpers/asset.ts +122 -96
- package/src/helpers/liquidity.ts +50 -42
- package/src/helpers/memo.ts +30 -28
- package/src/helpers/others.ts +30 -56
- package/src/helpers/validators.ts +7 -6
- package/src/index.ts +10 -8
- package/src/modules/__tests__/assetValue.test.ts +329 -121
- package/src/modules/__tests__/bigIntArithmetics.test.ts +30 -0
- package/src/modules/__tests__/swapKitNumber.test.ts +306 -183
- package/src/modules/assetValue.ts +214 -152
- package/src/modules/bigIntArithmetics.ts +214 -146
- package/src/modules/swapKitError.ts +30 -5
- package/src/modules/swapKitNumber.ts +8 -1
- package/src/types.ts +30 -0
|
@@ -1,59 +1,86 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Chain } from "@swapkit/types";
|
|
2
|
+
import { describe, expect, test } from "vitest";
|
|
2
3
|
|
|
3
|
-
import {
|
|
4
|
+
import { findAssetBy } from "../asset.ts";
|
|
5
|
+
import { derivationPathToString, getTHORNameCost, validateTHORName } from "../others.ts";
|
|
4
6
|
|
|
5
|
-
describe(
|
|
6
|
-
|
|
7
|
+
describe("derivationPathToString", () => {
|
|
8
|
+
test("should return the correct string for a full path", () => {
|
|
7
9
|
const path = [1, 2, 3, 4, 5];
|
|
8
|
-
|
|
9
|
-
expect(result).toEqual("1'/2'/3'/4/5");
|
|
10
|
+
expect(derivationPathToString(path)).toEqual("1'/2'/3'/4/5");
|
|
10
11
|
});
|
|
11
12
|
|
|
12
|
-
|
|
13
|
+
test("should return the correct string for a short path", () => {
|
|
13
14
|
const path = [1, 2, 3, 4];
|
|
14
|
-
|
|
15
|
-
expect(result).toEqual("1'/2'/3'/4");
|
|
15
|
+
expect(derivationPathToString(path)).toEqual("1'/2'/3'/4");
|
|
16
16
|
});
|
|
17
17
|
});
|
|
18
18
|
|
|
19
|
-
describe(
|
|
20
|
-
describe(
|
|
21
|
-
[
|
|
19
|
+
describe("getTHORNameCost", () => {
|
|
20
|
+
describe("for correct values", () => {
|
|
21
|
+
const costCases = [
|
|
22
22
|
[1, 11],
|
|
23
23
|
[2, 12],
|
|
24
24
|
[3, 13],
|
|
25
25
|
[10, 20],
|
|
26
|
-
]
|
|
27
|
-
|
|
26
|
+
];
|
|
27
|
+
|
|
28
|
+
for (const [years, expected] of costCases) {
|
|
29
|
+
test(`returns correct ${expected} cost for ${years} years`, () => {
|
|
28
30
|
const result = getTHORNameCost(years);
|
|
29
31
|
expect(result).toBe(expected);
|
|
30
32
|
});
|
|
31
|
-
}
|
|
33
|
+
}
|
|
32
34
|
});
|
|
33
35
|
|
|
34
|
-
|
|
35
|
-
expect(() => getTHORNameCost(-1)).toThrowError(
|
|
36
|
+
test("throws an error for negative years", () => {
|
|
37
|
+
expect(() => getTHORNameCost(-1)).toThrowError("Invalid number of year");
|
|
36
38
|
});
|
|
37
39
|
});
|
|
38
40
|
|
|
39
|
-
describe(
|
|
41
|
+
describe("validateTHORName", () => {
|
|
40
42
|
const casesWithExpectation: [string, boolean][] = [
|
|
41
|
-
[
|
|
42
|
-
[
|
|
43
|
-
[
|
|
44
|
-
[
|
|
45
|
-
[
|
|
46
|
-
[
|
|
47
|
-
[
|
|
48
|
-
[
|
|
49
|
-
[
|
|
50
|
-
[
|
|
43
|
+
["validname", true],
|
|
44
|
+
["valid-name", true],
|
|
45
|
+
["valid_name", true],
|
|
46
|
+
["valid+name", true],
|
|
47
|
+
["name_with_numbers123", true],
|
|
48
|
+
["UPPER_CASE", true],
|
|
49
|
+
["toolongname123456789012345678901", false],
|
|
50
|
+
["invalid@name", false],
|
|
51
|
+
["invalid!name", false],
|
|
52
|
+
["invalid#name", false],
|
|
51
53
|
];
|
|
52
54
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
+
for (const [name, expected] of casesWithExpectation) {
|
|
56
|
+
test(`returns ${expected} for THORName "${name}"`, () => {
|
|
55
57
|
const result = validateTHORName(name);
|
|
56
58
|
expect(result).toBe(expected);
|
|
57
59
|
});
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
describe("getAssetBy", () => {
|
|
64
|
+
test("find asset by identifier", async () => {
|
|
65
|
+
const assetByIdentifier = await findAssetBy({ identifier: "ETH.ETH" });
|
|
66
|
+
expect(assetByIdentifier).toBe("ETH.ETH");
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
test("find asset by chain and contract", async () => {
|
|
70
|
+
const assetByChainAndContract = await findAssetBy({
|
|
71
|
+
chain: Chain.Ethereum,
|
|
72
|
+
contract: "0XA0B86991C6218B36C1D19D4A2E9EB0CE3606EB48",
|
|
73
|
+
});
|
|
74
|
+
expect(assetByChainAndContract).toBe("ETH.USDC-0XA0B86991C6218B36C1D19D4A2E9EB0CE3606EB48");
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
test("return undefined if asset can't be found", async () => {
|
|
78
|
+
const assetByIdentifier = await findAssetBy({ identifier: "ARB.NOTEXISTINGTOKEN" });
|
|
79
|
+
const assetByChainAndContract = await findAssetBy({
|
|
80
|
+
chain: Chain.Ethereum,
|
|
81
|
+
contract: "NOTFOUND",
|
|
82
|
+
});
|
|
83
|
+
expect(assetByIdentifier).toBe(undefined);
|
|
84
|
+
expect(assetByChainAndContract).toBe(undefined);
|
|
58
85
|
});
|
|
59
86
|
});
|
package/src/helpers/asset.ts
CHANGED
|
@@ -1,61 +1,64 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
1
|
+
import { RequestClient } from "@swapkit/api";
|
|
2
|
+
import type { EVMChain } from "@swapkit/types";
|
|
3
|
+
import { BaseDecimal, Chain, ChainToRPC, EVMChains, FeeOption } from "@swapkit/types";
|
|
4
|
+
import type { TokenNames } from "../types.ts";
|
|
3
5
|
|
|
4
|
-
|
|
6
|
+
const getDecimalMethodHex = "0x313ce567";
|
|
5
7
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
8
|
+
export type CommonAssetString =
|
|
9
|
+
| `${Chain.Maya}.MAYA`
|
|
10
|
+
| `${Chain.Ethereum}.THOR`
|
|
11
|
+
| `${Chain.Ethereum}.vTHOR`
|
|
12
|
+
| `${Chain.Kujira}.USK`
|
|
13
|
+
| Chain;
|
|
11
14
|
|
|
12
15
|
const getContractDecimals = async ({ chain, to }: { chain: EVMChain; to: string }) => {
|
|
13
16
|
try {
|
|
14
|
-
const
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
17
|
+
const { result } = await RequestClient.post<{ result: string }>(ChainToRPC[chain], {
|
|
18
|
+
headers: {
|
|
19
|
+
accept: "*/*",
|
|
20
|
+
"content-type": "application/json",
|
|
21
|
+
"cache-control": "no-cache",
|
|
22
|
+
},
|
|
23
|
+
body: JSON.stringify({
|
|
19
24
|
id: 44,
|
|
20
|
-
jsonrpc:
|
|
25
|
+
jsonrpc: "2.0",
|
|
26
|
+
method: "eth_call",
|
|
27
|
+
params: [{ to: to.toLowerCase(), data: getDecimalMethodHex }, "latest"],
|
|
21
28
|
}),
|
|
22
|
-
|
|
23
|
-
true,
|
|
24
|
-
);
|
|
29
|
+
});
|
|
25
30
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
return parseInt(BigInt(result).toString());
|
|
31
|
+
return Number.parseInt(BigInt(result).toString());
|
|
29
32
|
} catch (error) {
|
|
30
33
|
console.error(error);
|
|
31
34
|
return BaseDecimal[chain];
|
|
32
35
|
}
|
|
33
36
|
};
|
|
34
37
|
|
|
35
|
-
const getETHAssetDecimal =
|
|
38
|
+
const getETHAssetDecimal = (symbol: string) => {
|
|
36
39
|
if (symbol === Chain.Ethereum) return BaseDecimal.ETH;
|
|
37
|
-
const [, address] = symbol.split(
|
|
40
|
+
const [, address] = symbol.split("-");
|
|
38
41
|
|
|
39
|
-
return address?.startsWith(
|
|
42
|
+
return address?.startsWith("0x")
|
|
40
43
|
? getContractDecimals({ chain: Chain.Ethereum, to: address })
|
|
41
44
|
: BaseDecimal.ETH;
|
|
42
45
|
};
|
|
43
46
|
|
|
44
|
-
const getAVAXAssetDecimal =
|
|
45
|
-
const [, address] = symbol.split(
|
|
47
|
+
const getAVAXAssetDecimal = (symbol: string) => {
|
|
48
|
+
const [, address] = symbol.split("-");
|
|
46
49
|
|
|
47
|
-
return address?.startsWith(
|
|
50
|
+
return address?.startsWith("0x")
|
|
48
51
|
? getContractDecimals({ chain: Chain.Avalanche, to: address.toLowerCase() })
|
|
49
52
|
: BaseDecimal.AVAX;
|
|
50
53
|
};
|
|
51
54
|
|
|
52
|
-
const getBSCAssetDecimal =
|
|
55
|
+
const getBSCAssetDecimal = (symbol: string) => {
|
|
53
56
|
if (symbol === Chain.BinanceSmartChain) return BaseDecimal.BSC;
|
|
54
57
|
|
|
55
58
|
return BaseDecimal.BSC;
|
|
56
59
|
};
|
|
57
60
|
|
|
58
|
-
export const getDecimal =
|
|
61
|
+
export const getDecimal = ({ chain, symbol }: { chain: Chain; symbol: string }) => {
|
|
59
62
|
switch (chain) {
|
|
60
63
|
case Chain.Ethereum:
|
|
61
64
|
return getETHAssetDecimal(symbol);
|
|
@@ -76,33 +79,24 @@ export const gasFeeMultiplier: Record<FeeOption, number> = {
|
|
|
76
79
|
|
|
77
80
|
export const isGasAsset = ({ chain, symbol }: { chain: Chain; symbol: string }) => {
|
|
78
81
|
switch (chain) {
|
|
79
|
-
case Chain.Bitcoin:
|
|
80
|
-
case Chain.BitcoinCash:
|
|
81
|
-
case Chain.Litecoin:
|
|
82
|
-
case Chain.Dogecoin:
|
|
83
|
-
case Chain.Binance:
|
|
84
|
-
case Chain.Ethereum:
|
|
85
|
-
case Chain.Avalanche:
|
|
86
|
-
return symbol === chain;
|
|
87
|
-
|
|
88
82
|
case Chain.Arbitrum:
|
|
89
83
|
case Chain.Optimism:
|
|
90
|
-
return
|
|
91
|
-
|
|
84
|
+
return symbol === "ETH";
|
|
92
85
|
case Chain.Maya:
|
|
93
|
-
return symbol ===
|
|
94
|
-
|
|
86
|
+
return symbol === "CACAO";
|
|
95
87
|
case Chain.Kujira:
|
|
96
|
-
return symbol ===
|
|
97
|
-
|
|
88
|
+
return symbol === "KUJI";
|
|
98
89
|
case Chain.Cosmos:
|
|
99
|
-
return symbol ===
|
|
90
|
+
return symbol === "ATOM";
|
|
100
91
|
case Chain.Polygon:
|
|
101
|
-
return symbol ===
|
|
92
|
+
return symbol === "MATIC";
|
|
102
93
|
case Chain.BinanceSmartChain:
|
|
103
|
-
return symbol ===
|
|
94
|
+
return symbol === "BNB";
|
|
104
95
|
case Chain.THORChain:
|
|
105
|
-
return symbol ===
|
|
96
|
+
return symbol === "RUNE";
|
|
97
|
+
|
|
98
|
+
default:
|
|
99
|
+
return symbol === chain;
|
|
106
100
|
}
|
|
107
101
|
};
|
|
108
102
|
|
|
@@ -110,86 +104,118 @@ export const getCommonAssetInfo = (
|
|
|
110
104
|
assetString: CommonAssetString,
|
|
111
105
|
): { identifier: string; decimal: number } => {
|
|
112
106
|
switch (assetString) {
|
|
113
|
-
case
|
|
114
|
-
return { identifier:
|
|
115
|
-
case
|
|
116
|
-
return { identifier:
|
|
107
|
+
case `${Chain.Ethereum}.THOR`:
|
|
108
|
+
return { identifier: "ETH.THOR-0xa5f2211b9b8170f694421f2046281775e8468044", decimal: 18 };
|
|
109
|
+
case `${Chain.Ethereum}.vTHOR`:
|
|
110
|
+
return { identifier: "ETH.vTHOR-0x815c23eca83261b6ec689b60cc4a58b54bc24d8d", decimal: 18 };
|
|
117
111
|
|
|
118
112
|
case Chain.Cosmos:
|
|
119
|
-
return { identifier:
|
|
113
|
+
return { identifier: "GAIA.ATOM", decimal: BaseDecimal[assetString] };
|
|
120
114
|
case Chain.THORChain:
|
|
121
|
-
return { identifier:
|
|
115
|
+
return { identifier: "THOR.RUNE", decimal: BaseDecimal[assetString] };
|
|
122
116
|
case Chain.BinanceSmartChain:
|
|
123
|
-
return { identifier:
|
|
117
|
+
return { identifier: "BSC.BNB", decimal: BaseDecimal[assetString] };
|
|
124
118
|
case Chain.Maya:
|
|
125
|
-
return { identifier:
|
|
126
|
-
case
|
|
127
|
-
return { identifier:
|
|
119
|
+
return { identifier: "MAYA.CACAO", decimal: BaseDecimal.MAYA };
|
|
120
|
+
case `${Chain.Maya}.MAYA`:
|
|
121
|
+
return { identifier: "MAYA.MAYA", decimal: 4 };
|
|
128
122
|
|
|
129
|
-
case Chain.Kujira
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
case Chain.Litecoin:
|
|
134
|
-
case Chain.Dogecoin:
|
|
135
|
-
case Chain.Binance:
|
|
136
|
-
case Chain.Avalanche:
|
|
137
|
-
case Chain.Polygon:
|
|
138
|
-
case Chain.Bitcoin:
|
|
139
|
-
case Chain.Ethereum:
|
|
123
|
+
case `${Chain.Kujira}.USK`:
|
|
124
|
+
return { identifier: `${Chain.Kujira}.USK`, decimal: 6 };
|
|
125
|
+
|
|
126
|
+
default:
|
|
140
127
|
return { identifier: `${assetString}.${assetString}`, decimal: BaseDecimal[assetString] };
|
|
141
128
|
}
|
|
142
129
|
};
|
|
143
130
|
|
|
131
|
+
// biome-ignore lint/complexity/noExcessiveCognitiveComplexity: TODO: Refactor
|
|
144
132
|
export const getAssetType = ({ chain, symbol }: { chain: Chain; symbol: string }) => {
|
|
145
|
-
if (symbol.includes(
|
|
133
|
+
if (symbol.includes("/")) return "Synth";
|
|
146
134
|
|
|
147
135
|
switch (chain) {
|
|
148
|
-
case Chain.Bitcoin:
|
|
149
|
-
case Chain.BitcoinCash:
|
|
150
|
-
case Chain.Dogecoin:
|
|
151
|
-
case Chain.Litecoin:
|
|
152
|
-
case Chain.Maya:
|
|
153
|
-
case Chain.THORChain:
|
|
154
|
-
return 'Native';
|
|
155
|
-
|
|
156
136
|
case Chain.Cosmos:
|
|
157
|
-
return symbol ===
|
|
137
|
+
return symbol === "ATOM" ? "Native" : Chain.Cosmos;
|
|
158
138
|
case Chain.Kujira:
|
|
159
|
-
return symbol === Chain.Kujira ?
|
|
139
|
+
return symbol === Chain.Kujira ? "Native" : Chain.Kujira;
|
|
160
140
|
case Chain.Binance:
|
|
161
|
-
return symbol === Chain.Binance ?
|
|
141
|
+
return symbol === Chain.Binance ? "Native" : "BEP2";
|
|
162
142
|
case Chain.BinanceSmartChain:
|
|
163
|
-
return symbol === Chain.Binance ?
|
|
143
|
+
return symbol === Chain.Binance ? "Native" : "BEP20";
|
|
164
144
|
case Chain.Ethereum:
|
|
165
|
-
return symbol === Chain.Ethereum ?
|
|
145
|
+
return symbol === Chain.Ethereum ? "Native" : "ERC20";
|
|
166
146
|
case Chain.Avalanche:
|
|
167
|
-
return symbol === Chain.Avalanche ?
|
|
147
|
+
return symbol === Chain.Avalanche ? "Native" : Chain.Avalanche;
|
|
168
148
|
case Chain.Polygon:
|
|
169
|
-
return symbol === Chain.Polygon ?
|
|
149
|
+
return symbol === Chain.Polygon ? "Native" : "POLYGON";
|
|
170
150
|
|
|
171
151
|
case Chain.Arbitrum:
|
|
172
|
-
return [Chain.Ethereum, Chain.Arbitrum].includes(symbol as Chain) ?
|
|
152
|
+
return [Chain.Ethereum, Chain.Arbitrum].includes(symbol as Chain) ? "Native" : "ARBITRUM";
|
|
173
153
|
case Chain.Optimism:
|
|
174
|
-
return [Chain.Ethereum, Chain.Optimism].includes(symbol as Chain) ?
|
|
154
|
+
return [Chain.Ethereum, Chain.Optimism].includes(symbol as Chain) ? "Native" : "OPTIMISM";
|
|
155
|
+
|
|
156
|
+
default:
|
|
157
|
+
return "Native";
|
|
175
158
|
}
|
|
176
159
|
};
|
|
177
160
|
|
|
178
161
|
export const assetFromString = (assetString: string) => {
|
|
179
|
-
const [chain, ...symbolArray] = assetString.split(
|
|
180
|
-
const synth = assetString.includes(
|
|
181
|
-
const symbol = symbolArray.join(
|
|
182
|
-
const ticker = symbol?.split(
|
|
162
|
+
const [chain, ...symbolArray] = assetString.split(".") as [Chain, ...(string | undefined)[]];
|
|
163
|
+
const synth = assetString.includes("/");
|
|
164
|
+
const symbol = symbolArray.join(".");
|
|
165
|
+
const ticker = symbol?.split("-")?.[0];
|
|
183
166
|
|
|
184
167
|
return { chain, symbol, ticker, synth };
|
|
185
168
|
};
|
|
186
169
|
|
|
187
170
|
const potentialScamRegex = new RegExp(
|
|
188
171
|
/(.)\1{6}|\.ORG|\.NET|\.FINANCE|\.COM|WWW|HTTP|\\\\|\/\/|[\s$%:[\]]/,
|
|
189
|
-
|
|
172
|
+
"gmi",
|
|
190
173
|
);
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
);
|
|
174
|
+
|
|
175
|
+
const evmAssetHasAddress = (assetString: string) => {
|
|
176
|
+
const [chain, symbol] = assetString.split(".") as [EVMChain, string];
|
|
177
|
+
if (!EVMChains.includes(chain as EVMChain)) return true;
|
|
178
|
+
const [, address] = symbol.split("-") as [string, string?];
|
|
179
|
+
|
|
180
|
+
return isGasAsset({ chain: chain as Chain, symbol }) || !!address;
|
|
181
|
+
};
|
|
182
|
+
|
|
183
|
+
export const filterAssets = (
|
|
184
|
+
tokens: {
|
|
185
|
+
value: string;
|
|
186
|
+
decimal: number;
|
|
187
|
+
chain: Chain;
|
|
188
|
+
symbol: string;
|
|
189
|
+
}[],
|
|
190
|
+
) =>
|
|
191
|
+
tokens.filter(({ chain, value, symbol }) => {
|
|
192
|
+
const assetString = `${chain}.${symbol}`;
|
|
193
|
+
|
|
194
|
+
return (
|
|
195
|
+
!potentialScamRegex.test(assetString) && evmAssetHasAddress(assetString) && value !== "0"
|
|
196
|
+
);
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
export async function findAssetBy(
|
|
200
|
+
params: { chain: EVMChain; contract: string } | { identifier: `${Chain}.${string}` },
|
|
201
|
+
) {
|
|
202
|
+
const tokenPackages = await import("@swapkit/tokens");
|
|
203
|
+
|
|
204
|
+
for (const tokenList of Object.values(tokenPackages)) {
|
|
205
|
+
for (const { identifier, chain: tokenChain, ...rest } of tokenList.tokens) {
|
|
206
|
+
if ("identifier" in params && identifier === params.identifier) {
|
|
207
|
+
return identifier as TokenNames;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
if (
|
|
211
|
+
"address" in rest &&
|
|
212
|
+
"chain" in params &&
|
|
213
|
+
tokenChain === params.chain &&
|
|
214
|
+
rest.address.toLowerCase() === params.contract.toLowerCase()
|
|
215
|
+
)
|
|
216
|
+
return identifier as TokenNames;
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
return;
|
|
221
|
+
}
|
package/src/helpers/liquidity.ts
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import { BaseDecimal } from
|
|
1
|
+
import { BaseDecimal } from "@swapkit/types";
|
|
2
2
|
|
|
3
|
-
import { SwapKitNumber } from
|
|
3
|
+
import { SwapKitNumber } from "../index.ts";
|
|
4
4
|
|
|
5
|
-
type ShareParams<T
|
|
5
|
+
type ShareParams<T extends {}> = T & {
|
|
6
6
|
liquidityUnits: string;
|
|
7
7
|
poolUnits: string;
|
|
8
8
|
};
|
|
9
9
|
|
|
10
|
-
type PoolParams
|
|
10
|
+
type PoolParams = {
|
|
11
11
|
runeAmount: string;
|
|
12
12
|
assetAmount: string;
|
|
13
13
|
runeDepth: string;
|
|
@@ -25,11 +25,11 @@ type PoolParams<T = {}> = T & {
|
|
|
25
25
|
* share = (s * A * (2 * T^2 - 2 * T * s + s^2))/T^3
|
|
26
26
|
* (part1 * (part2 - part3 + part4)) / part5
|
|
27
27
|
*/
|
|
28
|
-
export
|
|
28
|
+
export function getAsymmetricRuneShare({
|
|
29
29
|
liquidityUnits,
|
|
30
30
|
poolUnits,
|
|
31
31
|
runeDepth,
|
|
32
|
-
}: ShareParams<{ runeDepth: string }>)
|
|
32
|
+
}: ShareParams<{ runeDepth: string }>) {
|
|
33
33
|
const s = toTCSwapKitNumber(liquidityUnits);
|
|
34
34
|
const T = toTCSwapKitNumber(poolUnits);
|
|
35
35
|
const A = toTCSwapKitNumber(runeDepth);
|
|
@@ -43,13 +43,13 @@ export const getAsymmetricRuneShare = ({
|
|
|
43
43
|
const numerator = part1.mul(part2.sub(part3).add(part4));
|
|
44
44
|
|
|
45
45
|
return numerator.div(part5);
|
|
46
|
-
}
|
|
46
|
+
}
|
|
47
47
|
|
|
48
|
-
export
|
|
48
|
+
export function getAsymmetricAssetShare({
|
|
49
49
|
liquidityUnits,
|
|
50
50
|
poolUnits,
|
|
51
51
|
assetDepth,
|
|
52
|
-
}: ShareParams<{ assetDepth: string }>)
|
|
52
|
+
}: ShareParams<{ assetDepth: string }>) {
|
|
53
53
|
const s = toTCSwapKitNumber(liquidityUnits);
|
|
54
54
|
const T = toTCSwapKitNumber(poolUnits);
|
|
55
55
|
const A = toTCSwapKitNumber(assetDepth);
|
|
@@ -62,28 +62,31 @@ export const getAsymmetricAssetShare = ({
|
|
|
62
62
|
const part5 = T.mul(T).mul(T);
|
|
63
63
|
|
|
64
64
|
return numerator.div(part5);
|
|
65
|
-
}
|
|
65
|
+
}
|
|
66
66
|
|
|
67
|
-
export
|
|
67
|
+
export function getAsymmetricRuneWithdrawAmount({
|
|
68
68
|
percent,
|
|
69
69
|
runeDepth,
|
|
70
70
|
liquidityUnits,
|
|
71
71
|
poolUnits,
|
|
72
|
-
}: ShareParams<{ percent: number; runeDepth: string }>)
|
|
73
|
-
getAsymmetricRuneShare({ runeDepth, liquidityUnits, poolUnits }).mul(percent);
|
|
72
|
+
}: ShareParams<{ percent: number; runeDepth: string }>) {
|
|
73
|
+
return getAsymmetricRuneShare({ runeDepth, liquidityUnits, poolUnits }).mul(percent);
|
|
74
|
+
}
|
|
74
75
|
|
|
75
|
-
export
|
|
76
|
+
export function getAsymmetricAssetWithdrawAmount({
|
|
76
77
|
percent,
|
|
77
78
|
assetDepth,
|
|
78
79
|
liquidityUnits,
|
|
79
80
|
poolUnits,
|
|
80
|
-
}: ShareParams<{ percent: number; assetDepth: string }>)
|
|
81
|
-
getAsymmetricAssetShare({ assetDepth, liquidityUnits, poolUnits }).mul(percent);
|
|
81
|
+
}: ShareParams<{ percent: number; assetDepth: string }>) {
|
|
82
|
+
return getAsymmetricAssetShare({ assetDepth, liquidityUnits, poolUnits }).mul(percent);
|
|
83
|
+
}
|
|
82
84
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
+
function toTCSwapKitNumber(value: string) {
|
|
86
|
+
return SwapKitNumber.fromBigInt(BigInt(value), BaseDecimal.THOR);
|
|
87
|
+
}
|
|
85
88
|
|
|
86
|
-
export
|
|
89
|
+
export function getSymmetricPoolShare({
|
|
87
90
|
liquidityUnits,
|
|
88
91
|
poolUnits,
|
|
89
92
|
runeDepth,
|
|
@@ -91,12 +94,14 @@ export const getSymmetricPoolShare = ({
|
|
|
91
94
|
}: ShareParams<{
|
|
92
95
|
runeDepth: string;
|
|
93
96
|
assetDepth: string;
|
|
94
|
-
}>)
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
97
|
+
}>) {
|
|
98
|
+
return {
|
|
99
|
+
assetAmount: toTCSwapKitNumber(assetDepth).mul(liquidityUnits).div(poolUnits),
|
|
100
|
+
runeAmount: toTCSwapKitNumber(runeDepth).mul(liquidityUnits).div(poolUnits),
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
export function getSymmetricWithdraw({
|
|
100
105
|
liquidityUnits,
|
|
101
106
|
poolUnits,
|
|
102
107
|
runeDepth,
|
|
@@ -106,14 +111,15 @@ export const getSymmetricWithdraw = ({
|
|
|
106
111
|
runeDepth: string;
|
|
107
112
|
assetDepth: string;
|
|
108
113
|
percent: number;
|
|
109
|
-
}>)
|
|
110
|
-
Object.fromEntries(
|
|
114
|
+
}>) {
|
|
115
|
+
return Object.fromEntries(
|
|
111
116
|
Object.entries(getSymmetricPoolShare({ liquidityUnits, poolUnits, runeDepth, assetDepth })).map(
|
|
112
117
|
([name, value]) => [name, value.mul(percent)],
|
|
113
118
|
),
|
|
114
119
|
);
|
|
120
|
+
}
|
|
115
121
|
|
|
116
|
-
export
|
|
122
|
+
export function getEstimatedPoolShare({
|
|
117
123
|
runeDepth,
|
|
118
124
|
poolUnits,
|
|
119
125
|
assetDepth,
|
|
@@ -125,12 +131,12 @@ export const getEstimatedPoolShare = ({
|
|
|
125
131
|
assetAmount: string;
|
|
126
132
|
runeDepth: string;
|
|
127
133
|
assetDepth: string;
|
|
128
|
-
}>)
|
|
129
|
-
const R =
|
|
130
|
-
const A =
|
|
131
|
-
const P =
|
|
132
|
-
const runeAddAmount =
|
|
133
|
-
const assetAddAmount =
|
|
134
|
+
}>) {
|
|
135
|
+
const R = new SwapKitNumber({ value: runeDepth, decimal: 8 });
|
|
136
|
+
const A = new SwapKitNumber({ value: assetDepth, decimal: 8 });
|
|
137
|
+
const P = new SwapKitNumber({ value: poolUnits, decimal: 8 });
|
|
138
|
+
const runeAddAmount = new SwapKitNumber({ value: runeAmount, decimal: 8 });
|
|
139
|
+
const assetAddAmount = new SwapKitNumber({ value: assetAmount, decimal: 8 });
|
|
134
140
|
|
|
135
141
|
// liquidityUnits = P * (r*A + a*R + 2*r*a) / (r*A + a*R + 2*R*A)
|
|
136
142
|
const rA = runeAddAmount.mul(A);
|
|
@@ -142,22 +148,24 @@ export const getEstimatedPoolShare = ({
|
|
|
142
148
|
const liquidityUnitsAfterAdd = numerator.div(denominator);
|
|
143
149
|
const estimatedLiquidityUnits = toTCSwapKitNumber(liquidityUnits).add(liquidityUnitsAfterAdd);
|
|
144
150
|
|
|
145
|
-
if (liquidityUnitsAfterAdd.
|
|
146
|
-
return estimatedLiquidityUnits.div(P).
|
|
151
|
+
if (liquidityUnitsAfterAdd.getBaseValue("number") === 0) {
|
|
152
|
+
return estimatedLiquidityUnits.div(P).getBaseValue("number");
|
|
147
153
|
}
|
|
148
154
|
|
|
149
155
|
// get pool units after add
|
|
150
156
|
const newPoolUnits = P.add(estimatedLiquidityUnits);
|
|
151
157
|
|
|
152
|
-
return estimatedLiquidityUnits.div(newPoolUnits).
|
|
153
|
-
}
|
|
158
|
+
return estimatedLiquidityUnits.div(newPoolUnits).getBaseValue("number");
|
|
159
|
+
}
|
|
154
160
|
|
|
155
|
-
export
|
|
161
|
+
export function getLiquiditySlippage({
|
|
156
162
|
runeAmount,
|
|
157
163
|
assetAmount,
|
|
158
164
|
runeDepth,
|
|
159
165
|
assetDepth,
|
|
160
|
-
}: PoolParams)
|
|
166
|
+
}: PoolParams) {
|
|
167
|
+
if (runeAmount === "0" || assetAmount === "0" || runeDepth === "0" || assetDepth === "0")
|
|
168
|
+
return 0;
|
|
161
169
|
// formula: (t * R - T * r)/ (T*r + R*T)
|
|
162
170
|
const R = toTCSwapKitNumber(runeDepth);
|
|
163
171
|
const T = toTCSwapKitNumber(assetDepth);
|
|
@@ -168,5 +176,5 @@ export const getLiquiditySlippage = ({
|
|
|
168
176
|
const denominator = T.mul(runeAddAmount).add(R.mul(T));
|
|
169
177
|
|
|
170
178
|
// set absolute value of percent, no negative allowed
|
|
171
|
-
return Math.abs(numerator.div(denominator).
|
|
172
|
-
}
|
|
179
|
+
return Math.abs(numerator.div(denominator).getBaseValue("number"));
|
|
180
|
+
}
|