@swapkit/helpers 1.0.0-rc.7 → 1.0.0-rc.70
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 +94 -73
- package/dist/index.es.js +988 -498
- 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 +145 -38
- package/src/modules/__tests__/bigIntArithmetics.test.ts +30 -0
- package/src/modules/__tests__/swapKitNumber.test.ts +174 -48
- package/src/modules/assetValue.ts +169 -145
- 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,40 @@ 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('fromUrl', () => {
|
|
180
|
+
test('creates AssetValue from url like format', async () => {
|
|
181
|
+
const synthETHString = 'THOR.ETH.ETH';
|
|
182
|
+
const ethString = 'ETH.ETH';
|
|
183
|
+
const thorString = 'ETH.THOR-0xa5f2211b9b8170f694421f2046281775e8468044';
|
|
184
|
+
const synthThorString = 'THOR.ETH.THOR-0xa5f2211b9b8170f694421f2046281775e8468044';
|
|
185
|
+
|
|
186
|
+
const synthETH = await AssetValue.fromUrl(synthETHString);
|
|
187
|
+
const eth = await AssetValue.fromUrl(ethString);
|
|
188
|
+
const thor = await AssetValue.fromUrl(thorString);
|
|
189
|
+
const synthThor = await AssetValue.fromUrl(synthThorString);
|
|
190
|
+
|
|
191
|
+
expect(synthETH.toString()).toBe('ETH/ETH');
|
|
192
|
+
expect(eth.toString()).toBe('ETH.ETH');
|
|
193
|
+
expect(thor.toString()).toBe('ETH.THOR-0xa5f2211b9b8170f694421f2046281775e8468044');
|
|
194
|
+
expect(synthThor.toString()).toBe('ETH/THOR-0xa5f2211b9b8170f694421f2046281775e8468044');
|
|
137
195
|
});
|
|
138
196
|
});
|
|
139
197
|
|
|
@@ -178,12 +236,42 @@ describe('AssetValue', () => {
|
|
|
178
236
|
);
|
|
179
237
|
});
|
|
180
238
|
|
|
181
|
-
test('returns
|
|
239
|
+
test('returns safe decimals if string is not in `@swapkit/tokens` lists', async () => {
|
|
182
240
|
await AssetValue.loadStaticAssets();
|
|
183
241
|
const fakeAvaxUSDCAssetString = 'AVAX.USDC-1234';
|
|
184
242
|
const fakeAvaxUSDCAsset = AssetValue.fromStringSync(fakeAvaxUSDCAssetString);
|
|
185
243
|
|
|
186
|
-
expect(fakeAvaxUSDCAsset).
|
|
244
|
+
expect(fakeAvaxUSDCAsset).toBeDefined();
|
|
245
|
+
expect(fakeAvaxUSDCAsset).toEqual(
|
|
246
|
+
expect.objectContaining({
|
|
247
|
+
address: '1234',
|
|
248
|
+
chain: Chain.Avalanche,
|
|
249
|
+
decimal: 18,
|
|
250
|
+
isGasAsset: false,
|
|
251
|
+
isSynthetic: false,
|
|
252
|
+
symbol: 'USDC-1234',
|
|
253
|
+
ticker: 'USDC',
|
|
254
|
+
}),
|
|
255
|
+
);
|
|
256
|
+
});
|
|
257
|
+
|
|
258
|
+
test('returns proper avax string with address from `@swapkit/tokens` lists', async () => {
|
|
259
|
+
await AssetValue.loadStaticAssets();
|
|
260
|
+
const avaxBTCb = 'AVAX.BTC.b-0x152b9d0fdc40c096757f570a51e494bd4b943e50';
|
|
261
|
+
const AvaxBTCb = AssetValue.fromStringSync(avaxBTCb);
|
|
262
|
+
|
|
263
|
+
expect(AvaxBTCb).toBeDefined();
|
|
264
|
+
expect(AvaxBTCb).toEqual(
|
|
265
|
+
expect.objectContaining({
|
|
266
|
+
address: '0x152b9d0fdc40c096757f570a51e494bd4b943e50',
|
|
267
|
+
chain: Chain.Avalanche,
|
|
268
|
+
decimal: 8,
|
|
269
|
+
isGasAsset: false,
|
|
270
|
+
isSynthetic: false,
|
|
271
|
+
symbol: 'BTC.b-0x152b9d0fdc40c096757f570a51e494bd4b943e50',
|
|
272
|
+
ticker: 'BTC.b',
|
|
273
|
+
}),
|
|
274
|
+
);
|
|
187
275
|
});
|
|
188
276
|
});
|
|
189
277
|
|
|
@@ -300,3 +388,22 @@ describe('AssetValue', () => {
|
|
|
300
388
|
});
|
|
301
389
|
});
|
|
302
390
|
});
|
|
391
|
+
|
|
392
|
+
describe('getMinAmountByChain', () => {
|
|
393
|
+
test('returns min amount for chain', () => {
|
|
394
|
+
expect(getMinAmountByChain(Chain.THORChain).getValue('string')).toBe('0');
|
|
395
|
+
expect(getMinAmountByChain(Chain.Maya).getValue('string')).toBe('0');
|
|
396
|
+
expect(getMinAmountByChain(Chain.Cosmos).getValue('string')).toBe('0.000001');
|
|
397
|
+
|
|
398
|
+
expect(getMinAmountByChain(Chain.Bitcoin).getValue('string')).toBe('0.00010001');
|
|
399
|
+
expect(getMinAmountByChain(Chain.Litecoin).getValue('string')).toBe('0.00010001');
|
|
400
|
+
expect(getMinAmountByChain(Chain.BitcoinCash).getValue('string')).toBe('0.00010001');
|
|
401
|
+
expect(getMinAmountByChain(Chain.Dogecoin).getValue('string')).toBe('1.00000001');
|
|
402
|
+
|
|
403
|
+
expect(getMinAmountByChain(Chain.BinanceSmartChain).getValue('string')).toBe('0.00000001');
|
|
404
|
+
expect(getMinAmountByChain(Chain.Ethereum).getValue('string')).toBe('0.00000001');
|
|
405
|
+
expect(getMinAmountByChain(Chain.Avalanche).getValue('string')).toBe('0.00000001');
|
|
406
|
+
expect(getMinAmountByChain(Chain.Arbitrum).getValue('string')).toBe('0.00000001');
|
|
407
|
+
expect(getMinAmountByChain(Chain.Optimism).getValue('string')).toBe('0.00000001');
|
|
408
|
+
});
|
|
409
|
+
});
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { describe, expect, test } from 'vitest';
|
|
2
|
+
|
|
3
|
+
import { formatBigIntToSafeValue } from '../bigIntArithmetics.ts';
|
|
4
|
+
|
|
5
|
+
describe('BigIntArithmatics', () => {
|
|
6
|
+
describe('formatBigIntToSafeValue', () => {
|
|
7
|
+
test('parse bigint with decimals to string', () => {
|
|
8
|
+
const safeValue1 = formatBigIntToSafeValue({
|
|
9
|
+
value: BigInt(0),
|
|
10
|
+
decimal: 6,
|
|
11
|
+
bigIntDecimal: 6,
|
|
12
|
+
});
|
|
13
|
+
expect(safeValue1).toBe('0');
|
|
14
|
+
|
|
15
|
+
const safeValue2 = formatBigIntToSafeValue({
|
|
16
|
+
value: BigInt(15),
|
|
17
|
+
decimal: 0,
|
|
18
|
+
bigIntDecimal: 0,
|
|
19
|
+
});
|
|
20
|
+
expect(safeValue2).toBe('15');
|
|
21
|
+
|
|
22
|
+
const safeValue3 = formatBigIntToSafeValue({
|
|
23
|
+
value: BigInt(123456789),
|
|
24
|
+
decimal: 4,
|
|
25
|
+
bigIntDecimal: 4,
|
|
26
|
+
});
|
|
27
|
+
expect(safeValue3).toBe('12345.6789');
|
|
28
|
+
});
|
|
29
|
+
});
|
|
30
|
+
});
|