@pioneer-platform/helpers 0.0.0-development.114 → 0.0.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/lib/helpers/asset.d.ts +36 -0
- package/lib/helpers/asset.js +270 -0
- package/lib/helpers/liquidity.d.ts +58 -0
- package/lib/helpers/liquidity.js +112 -0
- package/lib/helpers/memo.d.ts +46 -0
- package/lib/helpers/memo.js +46 -0
- package/lib/helpers/others.d.ts +3 -0
- package/lib/helpers/others.js +24 -0
- package/lib/helpers/request.d.ts +5 -0
- package/lib/helpers/request.js +74 -0
- package/lib/helpers/validators.d.ts +1 -0
- package/lib/helpers/validators.js +17 -0
- package/lib/index.d.ts +15 -0
- package/lib/index.js +31 -0
- package/lib/modules/__tests__/assetValue.test.d.ts +1 -0
- package/lib/modules/__tests__/assetValue.test.js +399 -0
- package/lib/modules/__tests__/swapKitNumber.test.d.ts +1 -0
- package/lib/modules/__tests__/swapKitNumber.test.js +425 -0
- package/lib/modules/assetValue.d.ts +55 -0
- package/lib/modules/assetValue.js +389 -0
- package/lib/modules/bigIntArithmetics.d.ts +58 -0
- package/lib/modules/bigIntArithmetics.js +344 -0
- package/lib/modules/swapKitError.d.ts +64 -0
- package/lib/modules/swapKitError.js +90 -0
- package/lib/modules/swapKitNumber.d.ts +6 -0
- package/lib/modules/swapKitNumber.js +36 -0
- package/package.json +20 -33
- package/src/helpers/asset.ts +232 -0
- package/src/helpers/liquidity.ts +174 -0
- package/src/helpers/memo.ts +90 -0
- package/src/helpers/others.ts +20 -0
- package/src/helpers/request.ts +33 -0
- package/src/helpers/validators.ts +17 -0
- package/src/index.ts +16 -6
- package/src/modules/assetValue.ts +358 -0
- package/src/modules/bigIntArithmetics.ts +416 -0
- package/src/{exceptions/SwapKitError.ts → modules/swapKitError.ts} +15 -4
- package/src/modules/swapKitNumber.ts +16 -0
- package/tsconfig.json +13 -0
- package/src/__tests__/asset.test.ts +0 -33
- package/src/__tests__/derivationPath.test.ts +0 -16
- package/src/amount.ts +0 -29
- package/src/asset.ts +0 -13
- package/src/derivationPath.ts +0 -5
- package/src/exceptions/index.ts +0 -1
- package/src/fees.ts +0 -13
- package/src/request.ts +0 -34
@@ -0,0 +1,232 @@
|
|
1
|
+
import type { EVMChain } from '@coinmasters/types';
|
2
|
+
import { BaseDecimal, Chain, ChainToRPC, EVMChainList, FeeOption } from '@coinmasters/types';
|
3
|
+
|
4
|
+
import { RequestClient } from '../index';
|
5
|
+
|
6
|
+
const getDecimalMethodHex = '0x313ce567';
|
7
|
+
|
8
|
+
export type CommonAssetString = 'MAYA.MAYA' | 'ETH.THOR' | 'ETH.vTHOR' | Chain;
|
9
|
+
|
10
|
+
const getContractDecimals = async ({ chain, to }: { chain: EVMChain; to: string }) => {
|
11
|
+
try {
|
12
|
+
const { result } = await RequestClient.post<{ result: string }>(ChainToRPC[chain], {
|
13
|
+
headers: {
|
14
|
+
accept: '*/*',
|
15
|
+
'content-type': 'application/json',
|
16
|
+
'cache-control': 'no-cache',
|
17
|
+
},
|
18
|
+
body: JSON.stringify({
|
19
|
+
id: 44,
|
20
|
+
jsonrpc: '2.0',
|
21
|
+
method: 'eth_call',
|
22
|
+
params: [{ to: to.toLowerCase(), data: getDecimalMethodHex }, 'latest'],
|
23
|
+
}),
|
24
|
+
});
|
25
|
+
|
26
|
+
return parseInt(BigInt(result).toString());
|
27
|
+
} catch (error) {
|
28
|
+
console.error(error);
|
29
|
+
// @ts-ignore
|
30
|
+
return BaseDecimal[chain];
|
31
|
+
}
|
32
|
+
};
|
33
|
+
|
34
|
+
const getETHAssetDecimal = async (symbol: string) => {
|
35
|
+
if (symbol === Chain.Ethereum) return BaseDecimal.ETH;
|
36
|
+
const [, address] = symbol.split('-');
|
37
|
+
|
38
|
+
return address?.startsWith('0x')
|
39
|
+
? getContractDecimals({ chain: Chain.Ethereum, to: address })
|
40
|
+
: BaseDecimal.ETH;
|
41
|
+
};
|
42
|
+
|
43
|
+
const getAVAXAssetDecimal = async (symbol: string) => {
|
44
|
+
const [, address] = symbol.split('-');
|
45
|
+
|
46
|
+
return address?.startsWith('0x')
|
47
|
+
? getContractDecimals({ chain: Chain.Avalanche, to: address.toLowerCase() })
|
48
|
+
: BaseDecimal.AVAX;
|
49
|
+
};
|
50
|
+
|
51
|
+
const getBSCAssetDecimal = async (symbol: string) => {
|
52
|
+
if (symbol === Chain.BinanceSmartChain) return BaseDecimal.BSC;
|
53
|
+
|
54
|
+
return BaseDecimal.BSC;
|
55
|
+
};
|
56
|
+
|
57
|
+
export const getDecimal = async ({ chain, symbol }: { chain: Chain; symbol: string }) => {
|
58
|
+
switch (chain) {
|
59
|
+
case Chain.Ethereum:
|
60
|
+
return getETHAssetDecimal(symbol);
|
61
|
+
case Chain.Avalanche:
|
62
|
+
return getAVAXAssetDecimal(symbol);
|
63
|
+
case Chain.BinanceSmartChain:
|
64
|
+
return getBSCAssetDecimal(symbol);
|
65
|
+
default:
|
66
|
+
// @ts-ignore
|
67
|
+
return BaseDecimal[chain];
|
68
|
+
}
|
69
|
+
};
|
70
|
+
|
71
|
+
export const gasFeeMultiplier: Record<FeeOption, number> = {
|
72
|
+
[FeeOption.Average]: 1.2,
|
73
|
+
[FeeOption.Fast]: 1.5,
|
74
|
+
[FeeOption.Fastest]: 2,
|
75
|
+
};
|
76
|
+
|
77
|
+
export const isGasAsset = ({ chain, symbol }: { chain: Chain; symbol: string }) => {
|
78
|
+
|
79
|
+
switch (chain) {
|
80
|
+
case Chain.Bitcoin:
|
81
|
+
case Chain.BitcoinCash:
|
82
|
+
case Chain.Dash:
|
83
|
+
case Chain.Digibyte:
|
84
|
+
case Chain.Zcash:
|
85
|
+
case Chain.Ripple:
|
86
|
+
case Chain.Litecoin:
|
87
|
+
case Chain.Dogecoin:
|
88
|
+
case Chain.Binance:
|
89
|
+
case Chain.Ethereum:
|
90
|
+
case Chain.Avalanche:
|
91
|
+
return symbol === chain;
|
92
|
+
case Chain.Arbitrum:
|
93
|
+
case Chain.Optimism:
|
94
|
+
case Chain.Base:
|
95
|
+
return 'ETH' === symbol;
|
96
|
+
// @ts-ignore
|
97
|
+
case Chain.Mayachain:
|
98
|
+
return symbol === 'CACAO';
|
99
|
+
case Chain.Kujira:
|
100
|
+
return symbol === 'KUJI';
|
101
|
+
case Chain.Cosmos:
|
102
|
+
return symbol === 'ATOM';
|
103
|
+
case Chain.Polygon:
|
104
|
+
return symbol === 'MATIC';
|
105
|
+
case Chain.BinanceSmartChain:
|
106
|
+
return symbol === 'BNB';
|
107
|
+
case Chain.THORChain:
|
108
|
+
return symbol === 'RUNE';
|
109
|
+
}
|
110
|
+
};
|
111
|
+
|
112
|
+
export const getCommonAssetInfo = (
|
113
|
+
assetString: CommonAssetString,
|
114
|
+
// @ts-ignore
|
115
|
+
): { identifier: string; decimal: number } => {
|
116
|
+
switch (assetString) {
|
117
|
+
case 'ETH.THOR':
|
118
|
+
return { identifier: 'ETH.THOR-0xa5f2211b9b8170f694421f2046281775e8468044', decimal: 18 };
|
119
|
+
case 'ETH.vTHOR':
|
120
|
+
return { identifier: 'ETH.vTHOR-0x815c23eca83261b6ec689b60cc4a58b54bc24d8d', decimal: 18 };
|
121
|
+
case Chain.Cosmos:
|
122
|
+
return { identifier: 'GAIA.ATOM', decimal: BaseDecimal[assetString] };
|
123
|
+
case Chain.THORChain:
|
124
|
+
return { identifier: 'THOR.RUNE', decimal: BaseDecimal[assetString] };
|
125
|
+
case Chain.BinanceSmartChain:
|
126
|
+
return { identifier: 'BSC.BNB', decimal: BaseDecimal[assetString] };
|
127
|
+
// @ts-ignore
|
128
|
+
case Chain.Mayachain:
|
129
|
+
return { identifier: 'MAYA.CACAO', decimal: BaseDecimal.MAYA };
|
130
|
+
case 'MAYA.MAYA':
|
131
|
+
return { identifier: 'MAYA.MAYA', decimal: 4 };
|
132
|
+
case Chain.Arbitrum:
|
133
|
+
return { identifier: 'ARB.ETH', decimal: 18 };
|
134
|
+
case Chain.Base:
|
135
|
+
return { identifier: 'BASE.ETH', decimal: 18 };
|
136
|
+
case Chain.Optimism:
|
137
|
+
return { identifier: 'OP.ETH', decimal: 18 };
|
138
|
+
case Chain.Avalanche:
|
139
|
+
return { identifier: 'AVAX.ETH', decimal: 18 };
|
140
|
+
case Chain.Ripple:
|
141
|
+
case Chain.Kujira:
|
142
|
+
case Chain.BitcoinCash:
|
143
|
+
case Chain.Zcash:
|
144
|
+
case Chain.Dash:
|
145
|
+
case Chain.Litecoin:
|
146
|
+
case Chain.Dogecoin:
|
147
|
+
case Chain.Binance:
|
148
|
+
case Chain.Polygon:
|
149
|
+
case Chain.Bitcoin:
|
150
|
+
case Chain.Ethereum:
|
151
|
+
return { identifier: `${assetString}.${assetString}`, decimal: BaseDecimal[assetString] };
|
152
|
+
}
|
153
|
+
};
|
154
|
+
|
155
|
+
export const getAssetType = ({ chain, symbol }: { chain: Chain; symbol: string }) => {
|
156
|
+
if (symbol.includes('/')) return 'Synth';
|
157
|
+
|
158
|
+
switch (chain) {
|
159
|
+
case Chain.Bitcoin:
|
160
|
+
case Chain.BitcoinCash:
|
161
|
+
case Chain.Dogecoin:
|
162
|
+
case Chain.Dash:
|
163
|
+
case Chain.Zcash:
|
164
|
+
case Chain.Litecoin:
|
165
|
+
// @ts-ignore
|
166
|
+
case Chain.Mayachain:
|
167
|
+
case Chain.THORChain:
|
168
|
+
return 'Native';
|
169
|
+
case Chain.Osmosis:
|
170
|
+
return 'Native';
|
171
|
+
case Chain.Cosmos:
|
172
|
+
return symbol === 'ATOM' ? 'Native' : Chain.Cosmos;
|
173
|
+
case Chain.Kujira:
|
174
|
+
return symbol === Chain.Kujira ? 'Native' : Chain.Kujira;
|
175
|
+
case Chain.Binance:
|
176
|
+
return symbol === Chain.Binance ? 'Native' : 'BEP2';
|
177
|
+
case Chain.BinanceSmartChain:
|
178
|
+
return symbol === Chain.Binance ? 'Native' : 'BEP20';
|
179
|
+
case Chain.Ethereum:
|
180
|
+
return symbol === Chain.Ethereum ? 'Native' : 'ERC20';
|
181
|
+
case Chain.Avalanche:
|
182
|
+
return symbol === Chain.Avalanche ? 'Native' : Chain.Avalanche;
|
183
|
+
case Chain.Polygon:
|
184
|
+
return symbol === Chain.Polygon ? 'Native' : 'POLYGON';
|
185
|
+
case Chain.Base:
|
186
|
+
return symbol === Chain.Ethereum ? 'Native' : 'ERC20';
|
187
|
+
case Chain.Arbitrum:
|
188
|
+
return [Chain.Ethereum, Chain.Arbitrum].includes(symbol as Chain) ? 'Native' : 'ARBITRUM';
|
189
|
+
case Chain.Optimism:
|
190
|
+
return [Chain.Ethereum, Chain.Optimism].includes(symbol as Chain) ? 'Native' : 'OPTIMISM';
|
191
|
+
}
|
192
|
+
};
|
193
|
+
|
194
|
+
export const assetFromString = (assetString: string) => {
|
195
|
+
const [chain, ...symbolArray] = assetString.split('.') as [Chain, ...(string | undefined)[]];
|
196
|
+
const synth = assetString.includes('/');
|
197
|
+
const symbol = symbolArray.join('.');
|
198
|
+
const ticker = symbol?.split('-')?.[0];
|
199
|
+
|
200
|
+
return { chain, symbol, ticker, synth };
|
201
|
+
};
|
202
|
+
|
203
|
+
const potentialScamRegex = new RegExp(
|
204
|
+
/(.)\1{6}|\.ORG|\.NET|\.FINANCE|\.COM|WWW|HTTP|\\\\|\/\/|[\s$%:[\]]/,
|
205
|
+
'gmi',
|
206
|
+
);
|
207
|
+
|
208
|
+
const evmAssetHasAddress = (assetString: string) => {
|
209
|
+
const [chain, symbol] = assetString.split('.') as [EVMChain, string];
|
210
|
+
if (!EVMChainList.includes(chain as EVMChain)) return true;
|
211
|
+
const [, address] = symbol.split('-') as [string, string?];
|
212
|
+
|
213
|
+
return isGasAsset({ chain: chain as Chain, symbol }) || !!address;
|
214
|
+
};
|
215
|
+
|
216
|
+
export const filterAssets = (
|
217
|
+
tokens: {
|
218
|
+
value: string;
|
219
|
+
decimal: number;
|
220
|
+
chain: Chain;
|
221
|
+
symbol: string;
|
222
|
+
}[],
|
223
|
+
) =>
|
224
|
+
tokens.filter((token) => {
|
225
|
+
const assetString = `${token.chain}.${token.symbol}`;
|
226
|
+
|
227
|
+
return (
|
228
|
+
!potentialScamRegex.test(assetString) &&
|
229
|
+
evmAssetHasAddress(assetString) &&
|
230
|
+
token.value !== '0'
|
231
|
+
);
|
232
|
+
});
|
@@ -0,0 +1,174 @@
|
|
1
|
+
import { BaseDecimal } from '@coinmasters/types';
|
2
|
+
|
3
|
+
import { SwapKitNumber } from '../index';
|
4
|
+
|
5
|
+
type ShareParams<T = {}> = T & {
|
6
|
+
liquidityUnits: string;
|
7
|
+
poolUnits: string;
|
8
|
+
};
|
9
|
+
|
10
|
+
type PoolParams<T = {}> = T & {
|
11
|
+
runeAmount: string;
|
12
|
+
assetAmount: string;
|
13
|
+
runeDepth: string;
|
14
|
+
assetDepth: string;
|
15
|
+
};
|
16
|
+
|
17
|
+
/**
|
18
|
+
* Ref: https://gitlab.com/thorchain/thornode/-/issues/657
|
19
|
+
* share = (s * A * (2 * T^2 - 2 * T * s + s^2))/T^3
|
20
|
+
* s = stakeUnits for member (after factoring in withdrawBasisPoints)
|
21
|
+
* T = totalPoolUnits for pool
|
22
|
+
* A = assetDepth to be withdrawn
|
23
|
+
*
|
24
|
+
* Formula:
|
25
|
+
* share = (s * A * (2 * T^2 - 2 * T * s + s^2))/T^3
|
26
|
+
* (part1 * (part2 - part3 + part4)) / part5
|
27
|
+
*/
|
28
|
+
export const getAsymmetricRuneShare = ({
|
29
|
+
liquidityUnits,
|
30
|
+
poolUnits,
|
31
|
+
runeDepth,
|
32
|
+
}: ShareParams<{ runeDepth: string }>) => {
|
33
|
+
const s = toTCSwapKitNumber(liquidityUnits);
|
34
|
+
const T = toTCSwapKitNumber(poolUnits);
|
35
|
+
const A = toTCSwapKitNumber(runeDepth);
|
36
|
+
|
37
|
+
const part1 = s.mul(A);
|
38
|
+
const part2 = T.mul(T).mul(2);
|
39
|
+
const part3 = T.mul(s).mul(2);
|
40
|
+
const part4 = s.mul(s);
|
41
|
+
const part5 = T.mul(T).mul(T);
|
42
|
+
|
43
|
+
const numerator = part1.mul(part2.sub(part3).add(part4));
|
44
|
+
|
45
|
+
return numerator.div(part5);
|
46
|
+
};
|
47
|
+
|
48
|
+
export const getAsymmetricAssetShare = ({
|
49
|
+
liquidityUnits,
|
50
|
+
poolUnits,
|
51
|
+
assetDepth,
|
52
|
+
}: ShareParams<{ assetDepth: string }>) => {
|
53
|
+
const s = toTCSwapKitNumber(liquidityUnits);
|
54
|
+
const T = toTCSwapKitNumber(poolUnits);
|
55
|
+
const A = toTCSwapKitNumber(assetDepth);
|
56
|
+
|
57
|
+
const part1 = s.mul(A);
|
58
|
+
const part2 = T.mul(T).mul(2);
|
59
|
+
const part3 = T.mul(s).mul(2);
|
60
|
+
const part4 = s.mul(s);
|
61
|
+
const numerator = part1.mul(part2.sub(part3).add(part4));
|
62
|
+
const part5 = T.mul(T).mul(T);
|
63
|
+
|
64
|
+
return numerator.div(part5);
|
65
|
+
};
|
66
|
+
|
67
|
+
export const getAsymmetricRuneWithdrawAmount = ({
|
68
|
+
percent,
|
69
|
+
runeDepth,
|
70
|
+
liquidityUnits,
|
71
|
+
poolUnits,
|
72
|
+
}: ShareParams<{ percent: number; runeDepth: string }>) =>
|
73
|
+
getAsymmetricRuneShare({ runeDepth, liquidityUnits, poolUnits }).mul(percent);
|
74
|
+
|
75
|
+
export const getAsymmetricAssetWithdrawAmount = ({
|
76
|
+
percent,
|
77
|
+
assetDepth,
|
78
|
+
liquidityUnits,
|
79
|
+
poolUnits,
|
80
|
+
}: ShareParams<{ percent: number; assetDepth: string }>) =>
|
81
|
+
getAsymmetricAssetShare({ assetDepth, liquidityUnits, poolUnits }).mul(percent);
|
82
|
+
|
83
|
+
const toTCSwapKitNumber = (value: string) =>
|
84
|
+
SwapKitNumber.fromBigInt(BigInt(value), BaseDecimal.THOR);
|
85
|
+
|
86
|
+
export const getSymmetricPoolShare = ({
|
87
|
+
liquidityUnits,
|
88
|
+
poolUnits,
|
89
|
+
runeDepth,
|
90
|
+
assetDepth,
|
91
|
+
}: ShareParams<{
|
92
|
+
runeDepth: string;
|
93
|
+
assetDepth: string;
|
94
|
+
}>) => ({
|
95
|
+
assetAmount: toTCSwapKitNumber(assetDepth).mul(liquidityUnits).div(poolUnits),
|
96
|
+
runeAmount: toTCSwapKitNumber(runeDepth).mul(liquidityUnits).div(poolUnits),
|
97
|
+
});
|
98
|
+
|
99
|
+
export const getSymmetricWithdraw = ({
|
100
|
+
liquidityUnits,
|
101
|
+
poolUnits,
|
102
|
+
runeDepth,
|
103
|
+
assetDepth,
|
104
|
+
percent,
|
105
|
+
}: ShareParams<{
|
106
|
+
runeDepth: string;
|
107
|
+
assetDepth: string;
|
108
|
+
percent: number;
|
109
|
+
}>) =>
|
110
|
+
Object.fromEntries(
|
111
|
+
Object.entries(getSymmetricPoolShare({ liquidityUnits, poolUnits, runeDepth, assetDepth })).map(
|
112
|
+
([name, value]) => [name, value.mul(percent)],
|
113
|
+
),
|
114
|
+
);
|
115
|
+
|
116
|
+
export const getEstimatedPoolShare = ({
|
117
|
+
runeDepth,
|
118
|
+
poolUnits,
|
119
|
+
assetDepth,
|
120
|
+
liquidityUnits,
|
121
|
+
runeAmount,
|
122
|
+
assetAmount,
|
123
|
+
}: ShareParams<{
|
124
|
+
runeAmount: string;
|
125
|
+
assetAmount: string;
|
126
|
+
runeDepth: string;
|
127
|
+
assetDepth: string;
|
128
|
+
}>) => {
|
129
|
+
const R = new SwapKitNumber({ value: runeDepth, decimal: 8 });
|
130
|
+
const A = new SwapKitNumber({ value: assetDepth, decimal: 8 });
|
131
|
+
const P = new SwapKitNumber({ value: poolUnits, decimal: 8 });
|
132
|
+
const runeAddAmount = new SwapKitNumber({ value: runeAmount, decimal: 8 });
|
133
|
+
const assetAddAmount = new SwapKitNumber({ value: assetAmount, decimal: 8 });
|
134
|
+
|
135
|
+
// liquidityUnits = P * (r*A + a*R + 2*r*a) / (r*A + a*R + 2*R*A)
|
136
|
+
const rA = runeAddAmount.mul(A);
|
137
|
+
const aR = assetAddAmount.mul(R);
|
138
|
+
const ra = runeAddAmount.mul(assetAddAmount);
|
139
|
+
const RA = R.mul(A);
|
140
|
+
const numerator = P.mul(rA.add(aR.add(ra.mul(2))));
|
141
|
+
const denominator = rA.add(aR.add(RA.mul(2)));
|
142
|
+
const liquidityUnitsAfterAdd = numerator.div(denominator);
|
143
|
+
const estimatedLiquidityUnits = toTCSwapKitNumber(liquidityUnits).add(liquidityUnitsAfterAdd);
|
144
|
+
|
145
|
+
if (liquidityUnitsAfterAdd.getBaseValue('number') === 0) {
|
146
|
+
return estimatedLiquidityUnits.div(P).getBaseValue('number');
|
147
|
+
}
|
148
|
+
|
149
|
+
// get pool units after add
|
150
|
+
const newPoolUnits = P.add(estimatedLiquidityUnits);
|
151
|
+
|
152
|
+
return estimatedLiquidityUnits.div(newPoolUnits).getBaseValue('number');
|
153
|
+
};
|
154
|
+
|
155
|
+
export const getLiquiditySlippage = ({
|
156
|
+
runeAmount,
|
157
|
+
assetAmount,
|
158
|
+
runeDepth,
|
159
|
+
assetDepth,
|
160
|
+
}: PoolParams) => {
|
161
|
+
if (runeAmount === '0' || assetAmount === '0' || runeDepth === '0' || assetDepth === '0')
|
162
|
+
return 0;
|
163
|
+
// formula: (t * R - T * r)/ (T*r + R*T)
|
164
|
+
const R = toTCSwapKitNumber(runeDepth);
|
165
|
+
const T = toTCSwapKitNumber(assetDepth);
|
166
|
+
const assetAddAmount = toTCSwapKitNumber(assetAmount);
|
167
|
+
const runeAddAmount = toTCSwapKitNumber(runeAmount);
|
168
|
+
|
169
|
+
const numerator = assetAddAmount.mul(R).sub(T.mul(runeAddAmount));
|
170
|
+
const denominator = T.mul(runeAddAmount).add(R.mul(T));
|
171
|
+
|
172
|
+
// set absolute value of percent, no negative allowed
|
173
|
+
return Math.abs(numerator.div(denominator).getBaseValue('number'));
|
174
|
+
};
|
@@ -0,0 +1,90 @@
|
|
1
|
+
import type { Chain } from '@coinmasters/types';
|
2
|
+
import { MemoType } from '@coinmasters/types';
|
3
|
+
|
4
|
+
export type ThornameRegisterParam = {
|
5
|
+
name: string;
|
6
|
+
chain: string;
|
7
|
+
address: string;
|
8
|
+
owner?: string;
|
9
|
+
preferredAsset?: string;
|
10
|
+
expiryBlock?: string;
|
11
|
+
};
|
12
|
+
|
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
|
+
type WithAddress<T = {}> = T & { address: string };
|
24
|
+
type WithChain<T = {}> = T & { chain: Chain };
|
25
|
+
|
26
|
+
export type MemoOptions<T extends MemoType> = {
|
27
|
+
[MemoType.BOND]: WithAddress;
|
28
|
+
[MemoType.LEAVE]: WithAddress;
|
29
|
+
[MemoType.CLOSE_LOAN]: WithAddress<{ asset: string; minAmount?: string }>;
|
30
|
+
[MemoType.OPEN_LOAN]: WithAddress<{ asset: string; minAmount?: string }>;
|
31
|
+
[MemoType.UNBOND]: WithAddress<{ unbondAmount: number }>;
|
32
|
+
[MemoType.DEPOSIT]: WithChain<{ symbol: string; address?: string; singleSide?: boolean }>;
|
33
|
+
[MemoType.WITHDRAW]: WithChain<{
|
34
|
+
ticker: string;
|
35
|
+
symbol: string;
|
36
|
+
basisPoints: number;
|
37
|
+
targetAssetString?: string;
|
38
|
+
singleSide?: boolean;
|
39
|
+
}>;
|
40
|
+
[MemoType.THORNAME_REGISTER]: Omit<ThornameRegisterParam, 'preferredAsset' | 'expiryBlock'>;
|
41
|
+
}[T];
|
42
|
+
|
43
|
+
export const getMemoFor = <T extends MemoType>(memoType: T, options: MemoOptions<T>) => {
|
44
|
+
switch (memoType) {
|
45
|
+
case MemoType.LEAVE:
|
46
|
+
case MemoType.BOND: {
|
47
|
+
const { address } = options as MemoOptions<MemoType.BOND>;
|
48
|
+
return `${memoType}:${address}`;
|
49
|
+
}
|
50
|
+
|
51
|
+
case MemoType.UNBOND: {
|
52
|
+
const { address, unbondAmount } = options as MemoOptions<MemoType.UNBOND>;
|
53
|
+
return `${memoType}:${address}:${unbondAmount * 10 ** 8}`;
|
54
|
+
}
|
55
|
+
|
56
|
+
case MemoType.THORNAME_REGISTER: {
|
57
|
+
const { name, chain, address, owner } = options as MemoOptions<MemoType.THORNAME_REGISTER>;
|
58
|
+
return `${memoType}:${name}:${chain}:${address}${owner ? `:${owner}` : ''}`;
|
59
|
+
}
|
60
|
+
|
61
|
+
case MemoType.DEPOSIT: {
|
62
|
+
const { chain, symbol, address, singleSide } = options as MemoOptions<MemoType.DEPOSIT>;
|
63
|
+
|
64
|
+
return singleSide
|
65
|
+
? `${memoType}:${chain}/${symbol}::t:0`
|
66
|
+
: `${memoType}:${chain}.${symbol}:${address || ''}:t:0`;
|
67
|
+
}
|
68
|
+
|
69
|
+
case MemoType.WITHDRAW: {
|
70
|
+
const { chain, ticker, symbol, basisPoints, targetAssetString, singleSide } =
|
71
|
+
options as MemoOptions<MemoType.WITHDRAW>;
|
72
|
+
|
73
|
+
const target = !singleSide && targetAssetString ? `:${targetAssetString}` : '';
|
74
|
+
const shortenedSymbol = getShortenedSymbol({ chain, symbol, ticker });
|
75
|
+
const assetDivider = singleSide ? '/' : '.';
|
76
|
+
|
77
|
+
return `${memoType}:${chain}${assetDivider}${shortenedSymbol}:${basisPoints}${target}`;
|
78
|
+
}
|
79
|
+
|
80
|
+
case MemoType.OPEN_LOAN:
|
81
|
+
case MemoType.CLOSE_LOAN: {
|
82
|
+
const { asset, address } = options as MemoOptions<MemoType.OPEN_LOAN>;
|
83
|
+
|
84
|
+
return `${memoType}:${asset}:${address}`; //:${minAmount ? `${minAmount}` : ''}:t:0`;
|
85
|
+
}
|
86
|
+
|
87
|
+
default:
|
88
|
+
return '';
|
89
|
+
}
|
90
|
+
};
|
@@ -0,0 +1,20 @@
|
|
1
|
+
// 10 rune for register, 1 rune per year
|
2
|
+
// MINIMUM_REGISTRATION_FEE = 11
|
3
|
+
export const getTHORNameCost = (year: number) => {
|
4
|
+
if (year < 0) throw new Error('Invalid number of year');
|
5
|
+
return 10 + year;
|
6
|
+
};
|
7
|
+
|
8
|
+
export const validateTHORName = (name: string) => {
|
9
|
+
if (name.length > 30) return false;
|
10
|
+
|
11
|
+
const regex = /^[a-zA-Z0-9+_-]+$/g;
|
12
|
+
|
13
|
+
return !!name.match(regex);
|
14
|
+
};
|
15
|
+
|
16
|
+
export const derivationPathToString = ([network, chainId, account, change, index]: number[]) => {
|
17
|
+
const shortPath = typeof index !== 'number';
|
18
|
+
|
19
|
+
return `${network}'/${chainId}'/${account}'/${change}${shortPath ? '' : `/${index}`}`;
|
20
|
+
};
|
@@ -0,0 +1,33 @@
|
|
1
|
+
import ky, { type Options } from 'ky';
|
2
|
+
|
3
|
+
const headers =
|
4
|
+
typeof window !== 'undefined'
|
5
|
+
? {}
|
6
|
+
: {
|
7
|
+
Referrer: 'https://sk.thorswap.net',
|
8
|
+
Referer: 'https://sk.thorswap.net',
|
9
|
+
};
|
10
|
+
|
11
|
+
// Define default options for the new ky instance
|
12
|
+
const defaultOptions: Options = {
|
13
|
+
headers: headers,
|
14
|
+
timeout: 30000, // Example: 10000 milliseconds = 10 seconds
|
15
|
+
retry: {
|
16
|
+
limit: 2, // Maximum number of retry attempts
|
17
|
+
methods: ['get', 'post', 'put', 'patch', 'head', 'delete'], // HTTP methods to retry
|
18
|
+
statusCodes: [408, 500, 502, 503, 504], // HTTP status codes to retry
|
19
|
+
},
|
20
|
+
};
|
21
|
+
|
22
|
+
// Create a new ky instance with the default options
|
23
|
+
const kyInstance = ky.create(defaultOptions);
|
24
|
+
|
25
|
+
export const RequestClient = {
|
26
|
+
get: async <T>(url: string | URL | Request, options?: Options): Promise<T> => {
|
27
|
+
return kyInstance.get(url, options).json<T>();
|
28
|
+
},
|
29
|
+
post: async <T>(url: string | URL | Request, options?: Options): Promise<T> => {
|
30
|
+
return kyInstance.post(url, options).json<T>();
|
31
|
+
},
|
32
|
+
// Implement other methods (put, delete, patch, head) as needed
|
33
|
+
};
|
@@ -0,0 +1,17 @@
|
|
1
|
+
import { Chain } from '@coinmasters/types';
|
2
|
+
|
3
|
+
const supportedChains = Object.values(Chain);
|
4
|
+
|
5
|
+
export const validateIdentifier = (identifier: string = '') => {
|
6
|
+
const uppercasedIdentifier = identifier.toUpperCase();
|
7
|
+
|
8
|
+
const [chain] = uppercasedIdentifier.split('.') as [Chain, string];
|
9
|
+
if (supportedChains.includes(chain)) return true;
|
10
|
+
|
11
|
+
const [synthChain] = uppercasedIdentifier.split('/') as [Chain, string];
|
12
|
+
if (supportedChains.includes(synthChain)) return true;
|
13
|
+
|
14
|
+
throw new Error(
|
15
|
+
`Invalid identifier: ${identifier}. Expected format: <Chain>.<Ticker> or <Chain>.<Ticker>-<ContractAddress>`,
|
16
|
+
);
|
17
|
+
};
|
package/src/index.ts
CHANGED
@@ -1,6 +1,16 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
export * from './
|
5
|
-
export * from './
|
6
|
-
export * from './
|
1
|
+
/**
|
2
|
+
* Helpers
|
3
|
+
*/
|
4
|
+
export * from './helpers/asset';
|
5
|
+
export * from './helpers/liquidity';
|
6
|
+
export * from './helpers/memo';
|
7
|
+
export * from './helpers/others';
|
8
|
+
export * from './helpers/request';
|
9
|
+
|
10
|
+
/**
|
11
|
+
* Modules
|
12
|
+
*/
|
13
|
+
export * from './modules/assetValue';
|
14
|
+
export * from './modules/bigIntArithmetics';
|
15
|
+
export * from './modules/swapKitError';
|
16
|
+
export * from './modules/swapKitNumber';
|