@swapkit/helpers 1.0.0-rc.4 → 1.0.0-rc.41

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/package.json CHANGED
@@ -1,20 +1,23 @@
1
1
  {
2
2
  "author": "swapkit-oss-team",
3
3
  "description": "SwapKit Lib swapkit-helpers",
4
+ "dependencies": {
5
+ "ky": "1.1.3"
6
+ },
4
7
  "devDependencies": {
5
- "@vitest/coverage-istanbul": "0.34.4",
6
- "vite": "4.4.9",
7
- "vitest": "0.34.4",
8
- "@internal/config": "0.0.0-internal.0",
9
- "@swapkit/tokens": "1.0.0-rc.3",
10
- "@swapkit/types": "1.0.0-rc.3"
8
+ "@vitest/coverage-istanbul": "0.34.6",
9
+ "vite": "4.5.0",
10
+ "vitest": "0.34.6",
11
+ "@internal/config": "0.0.0-rc.7",
12
+ "@swapkit/tokens": "1.0.0-rc.22",
13
+ "@swapkit/types": "1.0.0-rc.21"
11
14
  },
12
15
  "eslintConfig": {
13
16
  "extends": "../../../internal/eslint-config"
14
17
  },
15
18
  "peerDependencies": {
16
- "@swapkit/tokens": "1.0.0-rc.3",
17
- "@swapkit/types": "1.0.0-rc.3"
19
+ "@swapkit/tokens": "1.0.0-rc.22",
20
+ "@swapkit/types": "1.0.0-rc.21"
18
21
  },
19
22
  "exports": {
20
23
  ".": {
@@ -39,7 +42,7 @@
39
42
  "repository": "https://github.com/thorswap/SwapKit.git",
40
43
  "type": "module",
41
44
  "types": "./dist/index.d.ts",
42
- "version": "1.0.0-rc.4",
45
+ "version": "1.0.0-rc.41",
43
46
  "scripts": {
44
47
  "build": "vite build",
45
48
  "clean": "rm -rf dist vite.config.ts.* .turbo node_modules",
@@ -1,7 +1,7 @@
1
1
  import type { EVMChain } from '@swapkit/types';
2
- import { BaseDecimal, Chain, ChainToRPC, FeeOption } from '@swapkit/types';
2
+ import { BaseDecimal, Chain, ChainToRPC, EVMChainList, FeeOption } from '@swapkit/types';
3
3
 
4
- import { postRequest } from './others.ts';
4
+ import { RequestClient } from '../index.ts';
5
5
 
6
6
  const getDecimalMethodHex = '0x313ce567';
7
7
 
@@ -9,19 +9,19 @@ export type CommonAssetString = 'MAYA.MAYA' | 'ETH.THOR' | 'ETH.vTHOR' | Chain;
9
9
 
10
10
  const getContractDecimals = async ({ chain, to }: { chain: EVMChain; to: string }) => {
11
11
  try {
12
- const response = await postRequest<string>(
13
- ChainToRPC[chain],
14
- JSON.stringify({
15
- method: 'eth_call',
16
- params: [{ to: to.toLowerCase(), data: getDecimalMethodHex }, 'latest'],
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({
17
19
  id: 44,
18
20
  jsonrpc: '2.0',
21
+ method: 'eth_call',
22
+ params: [{ to: to.toLowerCase(), data: getDecimalMethodHex }, 'latest'],
19
23
  }),
20
- { accept: '*/*', 'cache-control': 'no-cache', 'content-type': 'application/json' },
21
- true,
22
- );
23
-
24
- const { result } = JSON.parse(response) as { result: string };
24
+ });
25
25
 
26
26
  return parseInt(BigInt(result).toString());
27
27
  } catch (error) {
@@ -152,9 +152,9 @@ export const getAssetType = ({ chain, symbol }: { chain: Chain; symbol: string }
152
152
  return 'Native';
153
153
 
154
154
  case Chain.Cosmos:
155
- return symbol === 'ATOM' ? 'Native' : 'GAIA';
155
+ return symbol === 'ATOM' ? 'Native' : Chain.Cosmos;
156
156
  case Chain.Kujira:
157
- return symbol === 'KUJI' ? 'Native' : 'KUJI';
157
+ return symbol === Chain.Kujira ? 'Native' : Chain.Kujira;
158
158
  case Chain.Binance:
159
159
  return symbol === Chain.Binance ? 'Native' : 'BEP2';
160
160
  case Chain.BinanceSmartChain:
@@ -162,7 +162,7 @@ export const getAssetType = ({ chain, symbol }: { chain: Chain; symbol: string }
162
162
  case Chain.Ethereum:
163
163
  return symbol === Chain.Ethereum ? 'Native' : 'ERC20';
164
164
  case Chain.Avalanche:
165
- return symbol === Chain.Avalanche ? 'Native' : 'AVAX';
165
+ return symbol === Chain.Avalanche ? 'Native' : Chain.Avalanche;
166
166
  case Chain.Polygon:
167
167
  return symbol === Chain.Polygon ? 'Native' : 'POLYGON';
168
168
 
@@ -181,3 +181,34 @@ export const assetFromString = (assetString: string) => {
181
181
 
182
182
  return { chain, symbol, ticker, synth };
183
183
  };
184
+
185
+ const potentialScamRegex = new RegExp(
186
+ /(.)\1{6}|\.ORG|\.NET|\.FINANCE|\.COM|WWW|HTTP|\\\\|\/\/|[\s$%:[\]]/,
187
+ 'gmi',
188
+ );
189
+
190
+ const evmAssetHasAddress = (assetString: string) => {
191
+ const [chain, symbol] = assetString.split('.') as [EVMChain, string];
192
+ if (!EVMChainList.includes(chain as EVMChain)) return true;
193
+ const [, address] = symbol.split('-') as [string, string?];
194
+
195
+ return isGasAsset({ chain: chain as Chain, symbol }) || !!address;
196
+ };
197
+
198
+ export const filterAssets = (
199
+ tokens: {
200
+ value: string;
201
+ decimal: number;
202
+ chain: Chain;
203
+ symbol: string;
204
+ }[],
205
+ ) =>
206
+ tokens.filter((token) => {
207
+ const assetString = `${token.chain}.${token.symbol}`;
208
+
209
+ return (
210
+ !potentialScamRegex.test(assetString) &&
211
+ evmAssetHasAddress(assetString) &&
212
+ token.value !== '0'
213
+ );
214
+ });
@@ -81,7 +81,7 @@ export const getAsymmetricAssetWithdrawAmount = ({
81
81
  getAsymmetricAssetShare({ assetDepth, liquidityUnits, poolUnits }).mul(percent);
82
82
 
83
83
  const toTCSwapKitNumber = (value: string) =>
84
- new SwapKitNumber({ value, decimal: BaseDecimal.THOR });
84
+ SwapKitNumber.fromBigInt(BigInt(value), BaseDecimal.THOR);
85
85
 
86
86
  export const getSymmetricPoolShare = ({
87
87
  liquidityUnits,
@@ -126,11 +126,11 @@ export const getEstimatedPoolShare = ({
126
126
  runeDepth: string;
127
127
  assetDepth: string;
128
128
  }>) => {
129
- const R = toTCSwapKitNumber(runeDepth);
130
- const A = toTCSwapKitNumber(assetDepth);
131
- const P = toTCSwapKitNumber(poolUnits);
132
- const runeAddAmount = toTCSwapKitNumber(runeAmount);
133
- const assetAddAmount = toTCSwapKitNumber(assetAmount);
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
134
 
135
135
  // liquidityUnits = P * (r*A + a*R + 2*r*a) / (r*A + a*R + 2*R*A)
136
136
  const rA = runeAddAmount.mul(A);
@@ -142,14 +142,14 @@ export const getEstimatedPoolShare = ({
142
142
  const liquidityUnitsAfterAdd = numerator.div(denominator);
143
143
  const estimatedLiquidityUnits = toTCSwapKitNumber(liquidityUnits).add(liquidityUnitsAfterAdd);
144
144
 
145
- if (liquidityUnitsAfterAdd.baseValueNumber === 0) {
146
- return estimatedLiquidityUnits.div(P).baseValueNumber;
145
+ if (liquidityUnitsAfterAdd.getBaseValue('number') === 0) {
146
+ return estimatedLiquidityUnits.div(P).getBaseValue('number');
147
147
  }
148
148
 
149
149
  // get pool units after add
150
150
  const newPoolUnits = P.add(estimatedLiquidityUnits);
151
151
 
152
- return estimatedLiquidityUnits.div(newPoolUnits).baseValueNumber;
152
+ return estimatedLiquidityUnits.div(newPoolUnits).getBaseValue('number');
153
153
  };
154
154
 
155
155
  export const getLiquiditySlippage = ({
@@ -158,6 +158,8 @@ export const getLiquiditySlippage = ({
158
158
  runeDepth,
159
159
  assetDepth,
160
160
  }: PoolParams) => {
161
+ if (runeAmount === '0' || assetAmount === '0' || runeDepth === '0' || assetDepth === '0')
162
+ return 0;
161
163
  // formula: (t * R - T * r)/ (T*r + R*T)
162
164
  const R = toTCSwapKitNumber(runeDepth);
163
165
  const T = toTCSwapKitNumber(assetDepth);
@@ -168,5 +170,5 @@ export const getLiquiditySlippage = ({
168
170
  const denominator = T.mul(runeAddAmount).add(R.mul(T));
169
171
 
170
172
  // set absolute value of percent, no negative allowed
171
- return Math.abs(numerator.div(denominator).baseValueNumber);
173
+ return Math.abs(numerator.div(denominator).getBaseValue('number'));
172
174
  };
@@ -18,51 +18,3 @@ export const derivationPathToString = ([network, chainId, account, change, index
18
18
 
19
19
  return `${network}'/${chainId}'/${account}'/${change}${shortPath ? '' : `/${index}`}`;
20
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
- };
@@ -0,0 +1,15 @@
1
+ import type { Options } from 'ky';
2
+ import ky from 'ky';
3
+
4
+ const headers =
5
+ typeof window !== 'undefined'
6
+ ? {}
7
+ : { referrer: 'https://sk.thorswap.net', referer: 'https://sk.thorswap.net' };
8
+
9
+ const kyClient = ky.create({ headers });
10
+
11
+ export const RequestClient = {
12
+ get: <T>(url: string | URL | Request, options?: Options) => kyClient.get(url, options).json<T>(),
13
+ post: <T>(url: string | URL | Request, options?: Options) =>
14
+ kyClient.post(url, options).json<T>(),
15
+ };
package/src/index.ts CHANGED
@@ -5,6 +5,7 @@ export * from './helpers/asset.ts';
5
5
  export * from './helpers/liquidity.ts';
6
6
  export * from './helpers/memo.ts';
7
7
  export * from './helpers/others.ts';
8
+ export * from './helpers/request.ts';
8
9
 
9
10
  /**
10
11
  * Modules
@@ -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,10 +12,13 @@ describe('AssetValue', () => {
12
12
  chain: Chain.Avalanche,
13
13
  symbol: 'USDC-0xb97ef9ef8734c71904d8002f8b6bc66dd9c48a6e',
14
14
  });
15
- expect(fakeAvaxUSDCAsset.assetValue).toBe('1234567890 USDC');
15
+ expect(fakeAvaxUSDCAsset.toString(true)).toBe('USDC');
16
+ expect(fakeAvaxUSDCAsset.toString()).toBe(
17
+ 'AVAX.USDC-0xb97ef9ef8734c71904d8002f8b6bc66dd9c48a6e',
18
+ );
16
19
 
17
20
  const thor = AssetValue.fromChainOrSignature('ETH.THOR');
18
- expect(thor.assetValue).toBe('0 THOR');
21
+ expect(thor.toString(true)).toBe('THOR');
19
22
 
20
23
  const ethSynth = new AssetValue({
21
24
  chain: Chain.THORChain,
@@ -24,8 +27,22 @@ describe('AssetValue', () => {
24
27
  value: 1234567890,
25
28
  });
26
29
 
27
- expect(ethSynth.assetValue).toBe('1234567890 ETH/ETH');
28
30
  expect(ethSynth.toString()).toBe('THOR.ETH/ETH');
31
+ expect(ethSynth.toString(true)).toBe('ETH/ETH');
32
+ expect(ethSynth.mul(21.37).getValue('string')).toBe('26382715809.3');
33
+
34
+ const ethThorSynth = new AssetValue({
35
+ chain: Chain.THORChain,
36
+ symbol: 'ETH/THOR-0xa5f2211b9b8170f694421f2046281775e8468044',
37
+ decimal: 8,
38
+ value: 1234567890,
39
+ });
40
+ expect(ethThorSynth.toString()).toBe(
41
+ 'THOR.ETH/THOR-0xa5f2211b9b8170f694421f2046281775e8468044',
42
+ );
43
+ expect(ethThorSynth.toString(true)).toBe(
44
+ 'ETH/THOR-0xa5f2211b9b8170f694421f2046281775e8468044',
45
+ );
29
46
 
30
47
  const atomDerived = new AssetValue({
31
48
  identifier: 'THOR.ATOM',
@@ -33,11 +50,44 @@ describe('AssetValue', () => {
33
50
  value: 123456789,
34
51
  });
35
52
 
36
- expect(atomDerived.assetValue).toBe('123456789 ATOM');
53
+ expect(atomDerived.toString(true)).toBe('ATOM');
37
54
  expect(atomDerived.toString()).toBe('THOR.ATOM');
38
55
  });
39
56
  });
40
57
 
58
+ describe('toUrl', () => {
59
+ test('returns asset compliance with url', () => {
60
+ const fakeAvaxUSDCAsset = new AssetValue({
61
+ decimal: 6,
62
+ value: 1234567890,
63
+ chain: Chain.Avalanche,
64
+ symbol: 'USDC-0xb97ef9ef8734c71904d8002f8b6bc66dd9c48a6e',
65
+ });
66
+ expect(fakeAvaxUSDCAsset.toUrl()).toBe(
67
+ 'AVAX.USDC-0xb97ef9ef8734c71904d8002f8b6bc66dd9c48a6e',
68
+ );
69
+
70
+ const thor = AssetValue.fromChainOrSignature('ETH.THOR');
71
+ expect(thor.toUrl()).toBe('ETH.THOR-0xa5f2211b9b8170f694421f2046281775e8468044');
72
+
73
+ const ethSynth = new AssetValue({
74
+ chain: Chain.THORChain,
75
+ symbol: 'ETH/ETH',
76
+ decimal: 8,
77
+ value: 1234567890,
78
+ });
79
+ expect(ethSynth.toUrl()).toBe('THOR.ETH.ETH');
80
+
81
+ const ethThorSynth = new AssetValue({
82
+ chain: Chain.THORChain,
83
+ symbol: 'ETH/THOR-0xa5f2211b9b8170f694421f2046281775e8468044',
84
+ decimal: 8,
85
+ value: 1234567890,
86
+ });
87
+ expect(ethThorSynth.toUrl()).toBe('THOR.ETH.THOR-0xa5f2211b9b8170f694421f2046281775e8468044');
88
+ });
89
+ });
90
+
41
91
  describe('eq', () => {
42
92
  test('checks if assets are same chain and symbol', () => {
43
93
  const firstThor = AssetValue.fromChainOrSignature('ETH.THOR');
@@ -70,17 +120,25 @@ describe('AssetValue', () => {
70
120
  });
71
121
  });
72
122
 
123
+ describe('from bigint', () => {
124
+ test('returns asset value with correct decimal', async () => {
125
+ const avaxUSDCAsset = await AssetValue.fromIdentifier(
126
+ `${Chain.Avalanche}.USDC-0xb97ef9ef8734c71904d8002f8b6bc66dd9c48a6e`,
127
+ 1234567800n,
128
+ );
129
+ expect(avaxUSDCAsset.getValue('string')).toBe('1234.5678');
130
+ });
131
+ });
132
+
73
133
  describe('toString', () => {
74
134
  test('returns asset value string/identifier', async () => {
75
- const fakeAvaxUSDCAsset = new AssetValue({
135
+ const avaxUSDCAsset = new AssetValue({
76
136
  decimal: 6,
77
137
  value: 1234567890,
78
138
  chain: Chain.Avalanche,
79
139
  symbol: 'USDC-0xb97ef9ef8734c71904d8002f8b6bc66dd9c48a6e',
80
140
  });
81
- expect(fakeAvaxUSDCAsset.toString()).toBe(
82
- 'AVAX.USDC-0xb97ef9ef8734c71904d8002f8b6bc66dd9c48a6e',
83
- );
141
+ expect(avaxUSDCAsset.toString()).toBe('AVAX.USDC-0xb97ef9ef8734c71904d8002f8b6bc66dd9c48a6e');
84
142
 
85
143
  const thor = AssetValue.fromChainOrSignature('ETH.THOR');
86
144
  expect(thor.toString()).toBe('ETH.THOR-0xa5f2211b9b8170f694421f2046281775e8468044');
@@ -92,10 +150,11 @@ describe('AssetValue', () => {
92
150
 
93
151
  describe('fromIdentifier', () => {
94
152
  test('creates AssetValue from string', async () => {
95
- const fakeAvaxUSDCAssetString = 'AVAX.USDC-0xb97ef9ef8734c71904d8002f8b6bc66dd9c48a6e';
96
- const fakeAvaxUSDCAsset = await AssetValue.fromIdentifier(fakeAvaxUSDCAssetString);
153
+ const avaxUSDCAsset = await AssetValue.fromIdentifier(
154
+ 'AVAX.USDC-0xb97ef9ef8734c71904d8002f8b6bc66dd9c48a6e',
155
+ );
97
156
 
98
- expect(fakeAvaxUSDCAsset).toEqual(
157
+ expect(avaxUSDCAsset).toEqual(
99
158
  expect.objectContaining({
100
159
  address: '0xb97ef9ef8734c71904d8002f8b6bc66dd9c48a6e',
101
160
  chain: Chain.Avalanche,
@@ -293,3 +352,22 @@ describe('AssetValue', () => {
293
352
  });
294
353
  });
295
354
  });
355
+
356
+ describe('getMinAmountByChain', () => {
357
+ test('returns min amount for chain', () => {
358
+ expect(getMinAmountByChain(Chain.THORChain).getValue('string')).toBe('0');
359
+ expect(getMinAmountByChain(Chain.Maya).getValue('string')).toBe('0');
360
+ expect(getMinAmountByChain(Chain.Cosmos).getValue('string')).toBe('0');
361
+
362
+ expect(getMinAmountByChain(Chain.Bitcoin).getValue('string')).toBe('0.00010001');
363
+ expect(getMinAmountByChain(Chain.Litecoin).getValue('string')).toBe('0.00010001');
364
+ expect(getMinAmountByChain(Chain.BitcoinCash).getValue('string')).toBe('0.00010001');
365
+ expect(getMinAmountByChain(Chain.Dogecoin).getValue('string')).toBe('1.00000001');
366
+
367
+ expect(getMinAmountByChain(Chain.BinanceSmartChain).getValue('string')).toBe('0.00000001');
368
+ expect(getMinAmountByChain(Chain.Ethereum).getValue('string')).toBe('0.00000001');
369
+ expect(getMinAmountByChain(Chain.Avalanche).getValue('string')).toBe('0.00000001');
370
+ expect(getMinAmountByChain(Chain.Arbitrum).getValue('string')).toBe('0.00000001');
371
+ expect(getMinAmountByChain(Chain.Optimism).getValue('string')).toBe('0.00000001');
372
+ });
373
+ });