@swapkit/helpers 1.0.0-rc.7 → 1.0.0-rc.71
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/dist/index.cjs +2 -1
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.ts +96 -73
- package/dist/index.es.js +1015 -502
- package/dist/index.es.js.map +1 -0
- package/package.json +16 -13
- package/src/helpers/__tests__/memo.test.ts +3 -3
- package/src/helpers/asset.ts +56 -56
- package/src/helpers/liquidity.ts +46 -38
- package/src/helpers/memo.ts +19 -16
- package/src/helpers/others.ts +6 -54
- package/src/helpers/validators.ts +4 -3
- package/src/index.ts +2 -0
- package/src/modules/__tests__/assetValue.test.ts +232 -38
- package/src/modules/__tests__/bigIntArithmetics.test.ts +30 -0
- package/src/modules/__tests__/swapKitNumber.test.ts +174 -48
- package/src/modules/assetValue.ts +203 -141
- package/src/modules/bigIntArithmetics.ts +185 -116
- package/src/modules/swapKitError.ts +13 -4
- package/src/modules/swapKitNumber.ts +8 -1
- package/src/types.ts +30 -0
package/src/helpers/liquidity.ts
CHANGED
|
@@ -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
|
+
}
|
package/src/helpers/memo.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { MemoType } from '@swapkit/types';
|
|
1
|
+
import { Chain, MemoType } from '@swapkit/types';
|
|
3
2
|
|
|
4
3
|
export type ThornameRegisterParam = {
|
|
5
4
|
name: string;
|
|
@@ -10,16 +9,6 @@ export type ThornameRegisterParam = {
|
|
|
10
9
|
expiryBlock?: string;
|
|
11
10
|
};
|
|
12
11
|
|
|
13
|
-
const getShortenedSymbol = ({
|
|
14
|
-
symbol,
|
|
15
|
-
ticker,
|
|
16
|
-
chain,
|
|
17
|
-
}: {
|
|
18
|
-
ticker: string;
|
|
19
|
-
symbol: string;
|
|
20
|
-
chain: string | Chain;
|
|
21
|
-
}) => (chain === 'ETH' && ticker !== 'ETH' ? `${ticker}-${symbol.slice(-3)}` : symbol);
|
|
22
|
-
|
|
23
12
|
type WithAddress<T = {}> = T & { address: string };
|
|
24
13
|
type WithChain<T = {}> = T & { chain: Chain };
|
|
25
14
|
|
|
@@ -50,7 +39,7 @@ export const getMemoFor = <T extends MemoType>(memoType: T, options: MemoOptions
|
|
|
50
39
|
|
|
51
40
|
case MemoType.UNBOND: {
|
|
52
41
|
const { address, unbondAmount } = options as MemoOptions<MemoType.UNBOND>;
|
|
53
|
-
return `${memoType}:${address}:${unbondAmount
|
|
42
|
+
return `${memoType}:${address}:${unbondAmount}`;
|
|
54
43
|
}
|
|
55
44
|
|
|
56
45
|
case MemoType.THORNAME_REGISTER: {
|
|
@@ -61,17 +50,31 @@ export const getMemoFor = <T extends MemoType>(memoType: T, options: MemoOptions
|
|
|
61
50
|
case MemoType.DEPOSIT: {
|
|
62
51
|
const { chain, symbol, address, singleSide } = options as MemoOptions<MemoType.DEPOSIT>;
|
|
63
52
|
|
|
53
|
+
const getPoolIdentifier = (chain: Chain, symbol: string): string => {
|
|
54
|
+
switch (chain) {
|
|
55
|
+
case Chain.Litecoin:
|
|
56
|
+
return 'l';
|
|
57
|
+
case Chain.Dogecoin:
|
|
58
|
+
return 'd';
|
|
59
|
+
case Chain.BitcoinCash:
|
|
60
|
+
return 'c';
|
|
61
|
+
default:
|
|
62
|
+
return `${chain}.${symbol}`;
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
|
|
64
66
|
return singleSide
|
|
65
|
-
? `${memoType}:${chain}/${symbol}
|
|
66
|
-
: `${memoType}:${chain
|
|
67
|
+
? `${memoType}:${chain}/${symbol}`
|
|
68
|
+
: `${memoType}:${getPoolIdentifier(chain, symbol)}:${address || ''}`;
|
|
67
69
|
}
|
|
68
70
|
|
|
69
71
|
case MemoType.WITHDRAW: {
|
|
70
72
|
const { chain, ticker, symbol, basisPoints, targetAssetString, singleSide } =
|
|
71
73
|
options as MemoOptions<MemoType.WITHDRAW>;
|
|
72
74
|
|
|
75
|
+
const shortenedSymbol =
|
|
76
|
+
chain === 'ETH' && ticker !== 'ETH' ? `${ticker}-${symbol.slice(-3)}` : symbol;
|
|
73
77
|
const target = !singleSide && targetAssetString ? `:${targetAssetString}` : '';
|
|
74
|
-
const shortenedSymbol = getShortenedSymbol({ chain, symbol, ticker });
|
|
75
78
|
const assetDivider = singleSide ? '/' : '.';
|
|
76
79
|
|
|
77
80
|
return `${memoType}:${chain}${assetDivider}${shortenedSymbol}:${basisPoints}${target}`;
|
package/src/helpers/others.ts
CHANGED
|
@@ -1,68 +1,20 @@
|
|
|
1
1
|
// 10 rune for register, 1 rune per year
|
|
2
2
|
// MINIMUM_REGISTRATION_FEE = 11
|
|
3
|
-
export
|
|
3
|
+
export function getTHORNameCost(year: number) {
|
|
4
4
|
if (year < 0) throw new Error('Invalid number of year');
|
|
5
5
|
return 10 + year;
|
|
6
|
-
}
|
|
6
|
+
}
|
|
7
7
|
|
|
8
|
-
export
|
|
8
|
+
export function validateTHORName(name: string) {
|
|
9
9
|
if (name.length > 30) return false;
|
|
10
10
|
|
|
11
11
|
const regex = /^[a-zA-Z0-9+_-]+$/g;
|
|
12
12
|
|
|
13
13
|
return !!name.match(regex);
|
|
14
|
-
}
|
|
14
|
+
}
|
|
15
15
|
|
|
16
|
-
export
|
|
16
|
+
export function derivationPathToString([network, chainId, account, change, index]: number[]) {
|
|
17
17
|
const shortPath = typeof index !== 'number';
|
|
18
18
|
|
|
19
19
|
return `${network}'/${chainId}'/${account}'/${change}${shortPath ? '' : `/${index}`}`;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
export const getRequest = async <T>(
|
|
23
|
-
url: string,
|
|
24
|
-
params?: { [key in string]?: any },
|
|
25
|
-
): Promise<T> => {
|
|
26
|
-
try {
|
|
27
|
-
const queryParams = Object.entries(params || {}).reduce(
|
|
28
|
-
(acc, [key, value]) => {
|
|
29
|
-
if (value) {
|
|
30
|
-
acc[key] = value;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
return acc;
|
|
34
|
-
},
|
|
35
|
-
{} as { [key in string]: any },
|
|
36
|
-
);
|
|
37
|
-
|
|
38
|
-
const response = await fetch(
|
|
39
|
-
`${url}${params ? `?${new URLSearchParams(queryParams).toString()}` : ''}`,
|
|
40
|
-
{ method: 'GET', mode: 'cors', credentials: 'omit', referrer: 'https://sk.thorswap.net' },
|
|
41
|
-
);
|
|
42
|
-
|
|
43
|
-
return response.json();
|
|
44
|
-
} catch (error) {
|
|
45
|
-
console.error(error);
|
|
46
|
-
return {} as T;
|
|
47
|
-
}
|
|
48
|
-
};
|
|
49
|
-
|
|
50
|
-
export const postRequest = async <T>(
|
|
51
|
-
url: string,
|
|
52
|
-
body: string,
|
|
53
|
-
headers?: Record<string, string>,
|
|
54
|
-
parseAsString = false,
|
|
55
|
-
): Promise<T> => {
|
|
56
|
-
try {
|
|
57
|
-
const response = await fetch(`${url}`, {
|
|
58
|
-
body,
|
|
59
|
-
headers,
|
|
60
|
-
method: 'POST',
|
|
61
|
-
referrer: 'https://sk.thorswap.net',
|
|
62
|
-
});
|
|
63
|
-
|
|
64
|
-
return parseAsString ? response.text() : response.json();
|
|
65
|
-
} catch (error) {
|
|
66
|
-
return {} as T;
|
|
67
|
-
}
|
|
68
|
-
};
|
|
20
|
+
}
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { Chain } from '@swapkit/types';
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
// Backward compatibility
|
|
4
|
+
const supportedChains = [...Object.values(Chain), 'TERRA'];
|
|
4
5
|
|
|
5
|
-
export
|
|
6
|
+
export function validateIdentifier(identifier = '') {
|
|
6
7
|
const uppercasedIdentifier = identifier.toUpperCase();
|
|
7
8
|
|
|
8
9
|
const [chain] = uppercasedIdentifier.split('.') as [Chain, string];
|
|
@@ -14,4 +15,4 @@ export const validateIdentifier = (identifier: string = '') => {
|
|
|
14
15
|
throw new Error(
|
|
15
16
|
`Invalid identifier: ${identifier}. Expected format: <Chain>.<Ticker> or <Chain>.<Ticker>-<ContractAddress>`,
|
|
16
17
|
);
|
|
17
|
-
}
|
|
18
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { BaseDecimal, Chain } from '@swapkit/types';
|
|
2
2
|
import { describe, expect, test } from 'vitest';
|
|
3
3
|
|
|
4
|
-
import { AssetValue } from '../assetValue.ts';
|
|
4
|
+
import { AssetValue, getMinAmountByChain } from '../assetValue.ts';
|
|
5
5
|
|
|
6
6
|
describe('AssetValue', () => {
|
|
7
7
|
describe('assetValue', () => {
|
|
@@ -12,14 +12,9 @@ describe('AssetValue', () => {
|
|
|
12
12
|
chain: Chain.Avalanche,
|
|
13
13
|
symbol: 'USDC-0xb97ef9ef8734c71904d8002f8b6bc66dd9c48a6e',
|
|
14
14
|
});
|
|
15
|
-
expect(fakeAvaxUSDCAsset.assetValue).toBe('1234567890 USDC');
|
|
16
15
|
expect(fakeAvaxUSDCAsset.toString()).toBe(
|
|
17
16
|
'AVAX.USDC-0xb97ef9ef8734c71904d8002f8b6bc66dd9c48a6e',
|
|
18
17
|
);
|
|
19
|
-
expect(fakeAvaxUSDCAsset.toString(true)).toBe('AVAX.USDC');
|
|
20
|
-
|
|
21
|
-
const thor = AssetValue.fromChainOrSignature('ETH.THOR');
|
|
22
|
-
expect(thor.assetValue).toBe('0 THOR');
|
|
23
18
|
|
|
24
19
|
const ethSynth = new AssetValue({
|
|
25
20
|
chain: Chain.THORChain,
|
|
@@ -28,20 +23,57 @@ describe('AssetValue', () => {
|
|
|
28
23
|
value: 1234567890,
|
|
29
24
|
});
|
|
30
25
|
|
|
31
|
-
expect(ethSynth.
|
|
32
|
-
expect(ethSynth.toString()).toBe('THOR.ETH/ETH');
|
|
33
|
-
expect(ethSynth.toString(true)).toBe('ETH/ETH');
|
|
26
|
+
expect(ethSynth.toString()).toBe('ETH/ETH');
|
|
34
27
|
expect(ethSynth.mul(21.37).getValue('string')).toBe('26382715809.3');
|
|
35
28
|
|
|
29
|
+
const ethThorSynth = new AssetValue({
|
|
30
|
+
chain: Chain.THORChain,
|
|
31
|
+
symbol: 'ETH/THOR-0xa5f2211b9b8170f694421f2046281775e8468044',
|
|
32
|
+
decimal: 8,
|
|
33
|
+
value: 1234567890,
|
|
34
|
+
});
|
|
35
|
+
expect(ethThorSynth.toString()).toBe('ETH/THOR-0xa5f2211b9b8170f694421f2046281775e8468044');
|
|
36
|
+
|
|
36
37
|
const atomDerived = new AssetValue({
|
|
37
38
|
identifier: 'THOR.ATOM',
|
|
38
39
|
decimal: 6,
|
|
39
40
|
value: 123456789,
|
|
40
41
|
});
|
|
41
42
|
|
|
42
|
-
expect(atomDerived.assetValue).toBe('123456789 ATOM');
|
|
43
43
|
expect(atomDerived.toString()).toBe('THOR.ATOM');
|
|
44
|
-
|
|
44
|
+
});
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
describe('toUrl', () => {
|
|
48
|
+
test('returns asset compliance with url', () => {
|
|
49
|
+
const fakeAvaxUSDCAsset = new AssetValue({
|
|
50
|
+
decimal: 6,
|
|
51
|
+
value: 1234567890,
|
|
52
|
+
chain: Chain.Avalanche,
|
|
53
|
+
symbol: 'USDC-0xb97ef9ef8734c71904d8002f8b6bc66dd9c48a6e',
|
|
54
|
+
});
|
|
55
|
+
expect(fakeAvaxUSDCAsset.toUrl()).toBe(
|
|
56
|
+
'AVAX.USDC-0xb97ef9ef8734c71904d8002f8b6bc66dd9c48a6e',
|
|
57
|
+
);
|
|
58
|
+
|
|
59
|
+
const thor = AssetValue.fromChainOrSignature('ETH.THOR');
|
|
60
|
+
expect(thor.toUrl()).toBe('ETH.THOR-0xa5f2211b9b8170f694421f2046281775e8468044');
|
|
61
|
+
|
|
62
|
+
const ethSynth = new AssetValue({
|
|
63
|
+
chain: Chain.THORChain,
|
|
64
|
+
symbol: 'ETH/ETH',
|
|
65
|
+
decimal: 8,
|
|
66
|
+
value: 1234567890,
|
|
67
|
+
});
|
|
68
|
+
expect(ethSynth.toUrl()).toBe('THOR.ETH.ETH');
|
|
69
|
+
|
|
70
|
+
const ethThorSynth = new AssetValue({
|
|
71
|
+
chain: Chain.THORChain,
|
|
72
|
+
symbol: 'ETH/THOR-0xa5f2211b9b8170f694421f2046281775e8468044',
|
|
73
|
+
decimal: 8,
|
|
74
|
+
value: 1234567890,
|
|
75
|
+
});
|
|
76
|
+
expect(ethThorSynth.toUrl()).toBe('THOR.ETH.THOR-0xa5f2211b9b8170f694421f2046281775e8468044');
|
|
45
77
|
});
|
|
46
78
|
});
|
|
47
79
|
|
|
@@ -77,32 +109,41 @@ describe('AssetValue', () => {
|
|
|
77
109
|
});
|
|
78
110
|
});
|
|
79
111
|
|
|
112
|
+
describe('from bigint', () => {
|
|
113
|
+
test('returns asset value with correct decimal', async () => {
|
|
114
|
+
const avaxUSDCAsset = await AssetValue.fromIdentifier(
|
|
115
|
+
`${Chain.Avalanche}.USDC-0xb97ef9ef8734c71904d8002f8b6bc66dd9c48a6e`,
|
|
116
|
+
1234567800n,
|
|
117
|
+
);
|
|
118
|
+
expect(avaxUSDCAsset.getValue('string')).toBe('1234.5678');
|
|
119
|
+
});
|
|
120
|
+
});
|
|
121
|
+
|
|
80
122
|
describe('toString', () => {
|
|
81
123
|
test('returns asset value string/identifier', async () => {
|
|
82
|
-
const
|
|
124
|
+
const avaxUSDCAsset = new AssetValue({
|
|
83
125
|
decimal: 6,
|
|
84
126
|
value: 1234567890,
|
|
85
127
|
chain: Chain.Avalanche,
|
|
86
128
|
symbol: 'USDC-0xb97ef9ef8734c71904d8002f8b6bc66dd9c48a6e',
|
|
87
129
|
});
|
|
88
|
-
expect(
|
|
89
|
-
'AVAX.USDC-0xb97ef9ef8734c71904d8002f8b6bc66dd9c48a6e',
|
|
90
|
-
);
|
|
130
|
+
expect(avaxUSDCAsset.toString()).toBe('AVAX.USDC-0xb97ef9ef8734c71904d8002f8b6bc66dd9c48a6e');
|
|
91
131
|
|
|
92
132
|
const thor = AssetValue.fromChainOrSignature('ETH.THOR');
|
|
93
133
|
expect(thor.toString()).toBe('ETH.THOR-0xa5f2211b9b8170f694421f2046281775e8468044');
|
|
94
134
|
|
|
95
135
|
const ethSynth = await AssetValue.fromIdentifier('ETH/ETH');
|
|
96
|
-
expect(ethSynth.toString()).toBe('
|
|
136
|
+
expect(ethSynth.toString()).toBe('ETH/ETH');
|
|
97
137
|
});
|
|
98
138
|
});
|
|
99
139
|
|
|
100
140
|
describe('fromIdentifier', () => {
|
|
101
141
|
test('creates AssetValue from string', async () => {
|
|
102
|
-
const
|
|
103
|
-
|
|
142
|
+
const avaxUSDCAsset = await AssetValue.fromIdentifier(
|
|
143
|
+
'AVAX.USDC-0xb97ef9ef8734c71904d8002f8b6bc66dd9c48a6e',
|
|
144
|
+
);
|
|
104
145
|
|
|
105
|
-
expect(
|
|
146
|
+
expect(avaxUSDCAsset).toEqual(
|
|
106
147
|
expect.objectContaining({
|
|
107
148
|
address: '0xb97ef9ef8734c71904d8002f8b6bc66dd9c48a6e',
|
|
108
149
|
chain: Chain.Avalanche,
|
|
@@ -117,23 +158,61 @@ describe('AssetValue', () => {
|
|
|
117
158
|
});
|
|
118
159
|
|
|
119
160
|
describe('fromString', () => {
|
|
120
|
-
test('creates AssetValue from string', () => {
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
expect
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
161
|
+
test('creates AssetValue from string', async () => {
|
|
162
|
+
const fakeAvaxAssetString = 'AVAX.ASDF-1234';
|
|
163
|
+
const fakeAvaxAsset = await AssetValue.fromString(fakeAvaxAssetString);
|
|
164
|
+
|
|
165
|
+
expect(fakeAvaxAsset).toEqual(
|
|
166
|
+
expect.objectContaining({
|
|
167
|
+
address: '1234',
|
|
168
|
+
chain: Chain.Avalanche,
|
|
169
|
+
decimal: 18,
|
|
170
|
+
isGasAsset: false,
|
|
171
|
+
isSynthetic: false,
|
|
172
|
+
symbol: 'ASDF-1234',
|
|
173
|
+
ticker: 'ASDF',
|
|
174
|
+
}),
|
|
175
|
+
);
|
|
176
|
+
});
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
describe('fromStringWithBase', () => {
|
|
180
|
+
test('creates AssetValue from string with base', async () => {
|
|
181
|
+
const fakeAvaxAssetString = 'AVAX.ASDF-1234';
|
|
182
|
+
const fakeAvaxAsset = await AssetValue.fromStringWithBase(fakeAvaxAssetString, 1, 8);
|
|
183
|
+
|
|
184
|
+
expect(fakeAvaxAsset).toEqual(
|
|
185
|
+
expect.objectContaining({
|
|
186
|
+
address: '1234',
|
|
187
|
+
chain: Chain.Avalanche,
|
|
188
|
+
decimal: 18,
|
|
189
|
+
isGasAsset: false,
|
|
190
|
+
isSynthetic: false,
|
|
191
|
+
symbol: 'ASDF-1234',
|
|
192
|
+
ticker: 'ASDF',
|
|
193
|
+
}),
|
|
194
|
+
);
|
|
195
|
+
expect(fakeAvaxAsset.getValue('string')).toBe('100000000');
|
|
196
|
+
expect(fakeAvaxAsset.getBaseValue('string')).toBe('100000000000000000000000000');
|
|
197
|
+
});
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
describe('fromUrl', () => {
|
|
201
|
+
test('creates AssetValue from url like format', async () => {
|
|
202
|
+
const synthETHString = 'THOR.ETH.ETH';
|
|
203
|
+
const ethString = 'ETH.ETH';
|
|
204
|
+
const thorString = 'ETH.THOR-0xa5f2211b9b8170f694421f2046281775e8468044';
|
|
205
|
+
const synthThorString = 'THOR.ETH.THOR-0xa5f2211b9b8170f694421f2046281775e8468044';
|
|
206
|
+
|
|
207
|
+
const synthETH = await AssetValue.fromUrl(synthETHString);
|
|
208
|
+
const eth = await AssetValue.fromUrl(ethString);
|
|
209
|
+
const thor = await AssetValue.fromUrl(thorString);
|
|
210
|
+
const synthThor = await AssetValue.fromUrl(synthThorString);
|
|
211
|
+
|
|
212
|
+
expect(synthETH.toString()).toBe('ETH/ETH');
|
|
213
|
+
expect(eth.toString()).toBe('ETH.ETH');
|
|
214
|
+
expect(thor.toString()).toBe('ETH.THOR-0xa5f2211b9b8170f694421f2046281775e8468044');
|
|
215
|
+
expect(synthThor.toString()).toBe('ETH/THOR-0xa5f2211b9b8170f694421f2046281775e8468044');
|
|
137
216
|
});
|
|
138
217
|
});
|
|
139
218
|
|
|
@@ -178,12 +257,108 @@ describe('AssetValue', () => {
|
|
|
178
257
|
);
|
|
179
258
|
});
|
|
180
259
|
|
|
181
|
-
test('returns
|
|
260
|
+
test('returns safe decimals if string is not in `@swapkit/tokens` lists', async () => {
|
|
182
261
|
await AssetValue.loadStaticAssets();
|
|
183
262
|
const fakeAvaxUSDCAssetString = 'AVAX.USDC-1234';
|
|
184
263
|
const fakeAvaxUSDCAsset = AssetValue.fromStringSync(fakeAvaxUSDCAssetString);
|
|
185
264
|
|
|
186
|
-
expect(fakeAvaxUSDCAsset).
|
|
265
|
+
expect(fakeAvaxUSDCAsset).toBeDefined();
|
|
266
|
+
expect(fakeAvaxUSDCAsset).toEqual(
|
|
267
|
+
expect.objectContaining({
|
|
268
|
+
address: '1234',
|
|
269
|
+
chain: Chain.Avalanche,
|
|
270
|
+
decimal: 18,
|
|
271
|
+
isGasAsset: false,
|
|
272
|
+
isSynthetic: false,
|
|
273
|
+
symbol: 'USDC-1234',
|
|
274
|
+
ticker: 'USDC',
|
|
275
|
+
}),
|
|
276
|
+
);
|
|
277
|
+
});
|
|
278
|
+
|
|
279
|
+
test('returns proper avax string with address from `@swapkit/tokens` lists', async () => {
|
|
280
|
+
await AssetValue.loadStaticAssets();
|
|
281
|
+
const avaxBTCb = 'AVAX.BTC.b-0x152b9d0fdc40c096757f570a51e494bd4b943e50';
|
|
282
|
+
const AvaxBTCb = AssetValue.fromStringSync(avaxBTCb);
|
|
283
|
+
|
|
284
|
+
expect(AvaxBTCb).toBeDefined();
|
|
285
|
+
expect(AvaxBTCb).toEqual(
|
|
286
|
+
expect.objectContaining({
|
|
287
|
+
address: '0x152b9d0fdc40c096757f570a51e494bd4b943e50',
|
|
288
|
+
chain: Chain.Avalanche,
|
|
289
|
+
decimal: 8,
|
|
290
|
+
isGasAsset: false,
|
|
291
|
+
isSynthetic: false,
|
|
292
|
+
symbol: 'BTC.b-0x152b9d0fdc40c096757f570a51e494bd4b943e50',
|
|
293
|
+
ticker: 'BTC.b',
|
|
294
|
+
}),
|
|
295
|
+
);
|
|
296
|
+
});
|
|
297
|
+
});
|
|
298
|
+
|
|
299
|
+
describe('fromStringWithBaseSync', () => {
|
|
300
|
+
test('creates AssetValue from string with base decimals via `@swapkit/tokens` lists', async () => {
|
|
301
|
+
await AssetValue.loadStaticAssets();
|
|
302
|
+
const btc = AssetValue.fromStringWithBaseSync('BTC.BTC', 5200000000000, 8);
|
|
303
|
+
|
|
304
|
+
expect(btc).toBeDefined();
|
|
305
|
+
expect(btc).toEqual(
|
|
306
|
+
expect.objectContaining({
|
|
307
|
+
chain: Chain.Bitcoin,
|
|
308
|
+
decimal: 8,
|
|
309
|
+
isGasAsset: true,
|
|
310
|
+
isSynthetic: false,
|
|
311
|
+
symbol: 'BTC',
|
|
312
|
+
ticker: 'BTC',
|
|
313
|
+
}),
|
|
314
|
+
);
|
|
315
|
+
|
|
316
|
+
expect(btc.getValue('string')).toBe('52000');
|
|
317
|
+
expect(btc.getBaseValue('string')).toBe('5200000000000');
|
|
318
|
+
});
|
|
319
|
+
|
|
320
|
+
test('returns safe decimals if string is not in `@swapkit/tokens` lists', async () => {
|
|
321
|
+
await AssetValue.loadStaticAssets();
|
|
322
|
+
const fakeAvaxUSDCAssetString = 'AVAX.USDC-1234';
|
|
323
|
+
const fakeAvaxUSDCAsset = AssetValue.fromStringWithBaseSync(fakeAvaxUSDCAssetString, 1, 8);
|
|
324
|
+
|
|
325
|
+
expect(fakeAvaxUSDCAsset).toBeDefined();
|
|
326
|
+
expect(fakeAvaxUSDCAsset).toEqual(
|
|
327
|
+
expect.objectContaining({
|
|
328
|
+
address: '1234',
|
|
329
|
+
chain: Chain.Avalanche,
|
|
330
|
+
decimal: 18,
|
|
331
|
+
isGasAsset: false,
|
|
332
|
+
isSynthetic: false,
|
|
333
|
+
symbol: 'USDC-1234',
|
|
334
|
+
ticker: 'USDC',
|
|
335
|
+
}),
|
|
336
|
+
);
|
|
337
|
+
|
|
338
|
+
expect(fakeAvaxUSDCAsset.getValue('string')).toBe('0.00000001');
|
|
339
|
+
expect(fakeAvaxUSDCAsset.getBaseValue('string')).toBe('10000000000');
|
|
340
|
+
});
|
|
341
|
+
|
|
342
|
+
test('returns proper avax string with address from `@swapkit/tokens` lists', async () => {
|
|
343
|
+
await AssetValue.loadStaticAssets();
|
|
344
|
+
const avaxUSDC = 'AVAX.USDC-0xb97ef9ef8734c71904d8002f8b6bc66dd9c48a6e';
|
|
345
|
+
const AvaxUSDC = AssetValue.fromStringWithBaseSync(avaxUSDC, 100000000, 8);
|
|
346
|
+
|
|
347
|
+
expect(AvaxUSDC).toBeDefined();
|
|
348
|
+
expect(AvaxUSDC).toEqual(
|
|
349
|
+
expect.objectContaining({
|
|
350
|
+
address: '0xb97ef9ef8734c71904d8002f8b6bc66dd9c48a6e',
|
|
351
|
+
chain: Chain.Avalanche,
|
|
352
|
+
decimal: 6,
|
|
353
|
+
isGasAsset: false,
|
|
354
|
+
isSynthetic: false,
|
|
355
|
+
symbol: 'USDC-0xb97ef9ef8734c71904d8002f8b6bc66dd9c48a6e',
|
|
356
|
+
ticker: 'USDC',
|
|
357
|
+
}),
|
|
358
|
+
);
|
|
359
|
+
|
|
360
|
+
expect(AvaxUSDC.getValue('string')).toBe('1');
|
|
361
|
+
expect(AvaxUSDC.getBaseValue('string')).toBe('1000000');
|
|
187
362
|
});
|
|
188
363
|
});
|
|
189
364
|
|
|
@@ -300,3 +475,22 @@ describe('AssetValue', () => {
|
|
|
300
475
|
});
|
|
301
476
|
});
|
|
302
477
|
});
|
|
478
|
+
|
|
479
|
+
describe('getMinAmountByChain', () => {
|
|
480
|
+
test('returns min amount for chain', () => {
|
|
481
|
+
expect(getMinAmountByChain(Chain.THORChain).getValue('string')).toBe('0');
|
|
482
|
+
expect(getMinAmountByChain(Chain.Maya).getValue('string')).toBe('0');
|
|
483
|
+
expect(getMinAmountByChain(Chain.Cosmos).getValue('string')).toBe('0.000001');
|
|
484
|
+
|
|
485
|
+
expect(getMinAmountByChain(Chain.Bitcoin).getValue('string')).toBe('0.00010001');
|
|
486
|
+
expect(getMinAmountByChain(Chain.Litecoin).getValue('string')).toBe('0.00010001');
|
|
487
|
+
expect(getMinAmountByChain(Chain.BitcoinCash).getValue('string')).toBe('0.00010001');
|
|
488
|
+
expect(getMinAmountByChain(Chain.Dogecoin).getValue('string')).toBe('1.00000001');
|
|
489
|
+
|
|
490
|
+
expect(getMinAmountByChain(Chain.BinanceSmartChain).getValue('string')).toBe('0.00000001');
|
|
491
|
+
expect(getMinAmountByChain(Chain.Ethereum).getValue('string')).toBe('0.00000001');
|
|
492
|
+
expect(getMinAmountByChain(Chain.Avalanche).getValue('string')).toBe('0.00000001');
|
|
493
|
+
expect(getMinAmountByChain(Chain.Arbitrum).getValue('string')).toBe('0.00000001');
|
|
494
|
+
expect(getMinAmountByChain(Chain.Optimism).getValue('string')).toBe('0.00000001');
|
|
495
|
+
});
|
|
496
|
+
});
|