@swapkit/helpers 1.0.0-rc.99 → 1.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/package.json CHANGED
@@ -2,16 +2,9 @@
2
2
  "author": "swapkit-oss",
3
3
  "description": "SwapKit - Helpers",
4
4
  "dependencies": {
5
- "ky": "1.2.3"
6
- },
7
- "devDependencies": {
8
- "@swapkit/tokens": "1.0.0-rc.51",
9
- "bun-types": "1.1.2",
10
- "ethers": "6.11.1"
11
- },
12
- "peerDependencies": {
13
- "@swapkit/tokens": "1.0.0-rc.51",
14
- "ky": "1.2.3"
5
+ "@swapkit/tokens": "1.0.1",
6
+ "ky": "1.4.0",
7
+ "zod": "3.23.8"
15
8
  },
16
9
  "files": [
17
10
  "src/",
@@ -28,13 +21,13 @@
28
21
  },
29
22
  "scripts": {
30
23
  "build": "bun run ./build.ts",
31
- "clean": "rm -rf .turbo dist node_modules *.tsbuildinfo",
32
- "lint": "biome check --apply ./src",
24
+ "clean": "rm -rf dist node_modules *.tsbuildinfo",
25
+ "lint": "biome check --write ./src",
33
26
  "test": "bun test",
34
- "test:coverage": "echo 'bun test --coverage'",
27
+ "test:coverage": "bun test --coverage",
35
28
  "type-check": "tsc --noEmit"
36
29
  },
37
30
  "type": "module",
38
31
  "types": "./src/index.ts",
39
- "version": "1.0.0-rc.99"
32
+ "version": "1.0.1"
40
33
  }
@@ -1,5 +1,5 @@
1
1
  import { describe, expect, test } from "bun:test";
2
- import { BaseDecimal, Chain } from "@swapkit/helpers";
2
+ import { BaseDecimal, Chain } from "../../types";
3
3
 
4
4
  import { assetFromString, getAssetType, getDecimal } from "../asset.ts";
5
5
 
@@ -36,13 +36,6 @@ describe("getAssetType", () => {
36
36
  });
37
37
  });
38
38
 
39
- describe("for Binance chain", () => {
40
- test('should return "BEP2" for non-BNB tickers', () => {
41
- const result = getAssetType({ chain: Chain.Binance, symbol: "NOT_BNB" });
42
- expect(result).toBe("BEP2");
43
- });
44
- });
45
-
46
39
  describe("for Binance Smart Chain", () => {
47
40
  test('should return "BEP20" for non-BNB tickers', () => {
48
41
  const result = getAssetType({ chain: Chain.BinanceSmartChain, symbol: "NOT_BNB" });
@@ -63,6 +56,13 @@ describe("getAssetType", () => {
63
56
  expect(result).toBe("AVAX");
64
57
  });
65
58
  });
59
+
60
+ describe("for Radix chain", () => {
61
+ test('should return "RADIX" for non-XRD tickers', () => {
62
+ const result = getAssetType({ chain: Chain.Radix, symbol: "NOT_XRD" });
63
+ expect(result).toBe("RADIX");
64
+ });
65
+ });
66
66
  });
67
67
  });
68
68
 
@@ -172,6 +172,25 @@ describe("getDecimal", () => {
172
172
  { retry: 3 },
173
173
  );
174
174
  });
175
+
176
+ describe("Radix", () => {
177
+ test(
178
+ "returns proper decimal for radix and it's assets",
179
+ async () => {
180
+ const radixDecimal = await getDecimal({ chain: Chain.Radix, symbol: "XRD" });
181
+ expect(radixDecimal).toBe(BaseDecimal.XRD);
182
+ await Bun.sleep(500);
183
+
184
+ const xwBTCDecimal = await getDecimal({
185
+ chain: Chain.Radix,
186
+ symbol: "xwBTC-resource_rdx1t580qxc7upat7lww4l2c4jckacafjeudxj5wpjrrct0p3e82sq4y75",
187
+ });
188
+ expect(xwBTCDecimal).toBe(8);
189
+ await Bun.sleep(500);
190
+ },
191
+ { retry: 3 },
192
+ );
193
+ });
175
194
  });
176
195
 
177
196
  describe("assetFromString", () => {
@@ -198,4 +217,17 @@ describe("assetFromString", () => {
198
217
  synth: false,
199
218
  });
200
219
  });
220
+
221
+ test("should return the correct object for Radix resource", () => {
222
+ const assetString =
223
+ "XRD.xwBTC-resource_rdx1t580qxc7upat7lww4l2c4jckacafjeudxj5wpjrrct0p3e82sq4y75";
224
+ const result = assetFromString(assetString);
225
+
226
+ expect(result).toEqual({
227
+ chain: Chain.Radix,
228
+ symbol: "xwBTC-resource_rdx1t580qxc7upat7lww4l2c4jckacafjeudxj5wpjrrct0p3e82sq4y75",
229
+ ticker: "xwBTC",
230
+ synth: false,
231
+ });
232
+ });
201
233
  });
@@ -1,91 +1,72 @@
1
1
  import { describe, expect, test } from "bun:test";
2
- import { Chain, MemoType } from "@swapkit/helpers";
2
+ import { Chain, MemoType } from "../../types";
3
3
 
4
- import { getMemoFor } from "../memo.ts";
4
+ import {
5
+ getMemoForDeposit,
6
+ getMemoForLeaveAndBond,
7
+ getMemoForNameRegister,
8
+ getMemoForSaverDeposit,
9
+ getMemoForSaverWithdraw,
10
+ getMemoForWithdraw,
11
+ } from "../memo.ts";
5
12
 
6
- describe("getMemoFor", () => {
7
- describe("for Leave, Upgrade, and Bond", () => {
8
- const nodeMemos = [
9
- [MemoType.LEAVE, "LEAVE:ABC123"],
10
- [MemoType.BOND, "BOND:ABC123"],
11
- ];
12
-
13
- for (const [memoType, expected = ""] of nodeMemos) {
14
- test(`returns correct memo for ${memoType}`, () => {
15
- const result = getMemoFor(memoType as MemoType, { address: "ABC123" });
16
- expect(result).toBe(expected);
17
- });
18
- }
13
+ describe("getMemoForSaverDeposit", () => {
14
+ test("returns correct memo for single side", () => {
15
+ const result = getMemoForSaverDeposit({ chain: Chain.Ethereum, symbol: "ETH" });
16
+ expect(result).toBe("+:ETH/ETH");
19
17
  });
18
+ });
20
19
 
21
- describe("for Unbond and Thorname/Mayaname Register", () => {
22
- test("returns correct memo for Unbond", () => {
23
- const result = getMemoFor(MemoType.UNBOND, { address: "ABC123", unbondAmount: 1000000000 });
24
- expect(result).toBe("UNBOND:ABC123:1000000000");
25
- });
26
-
27
- test("returns correct memo for Thorname Register", () => {
28
- const result = getMemoFor(MemoType.THORNAME_REGISTER, {
29
- name: "thorname",
30
- chain: "BNB",
31
- address: "0xABC123",
32
- owner: "0xDEF456",
33
- });
34
- expect(result).toBe("~:thorname:BNB:0xABC123:0xDEF456");
20
+ describe("getMemoForSaverWithdraw", () => {
21
+ test("returns correct memo for single side", () => {
22
+ const result = getMemoForSaverWithdraw({
23
+ basisPoints: 5000,
24
+ chain: Chain.Ethereum,
25
+ symbol: "ETH",
35
26
  });
27
+ expect(result).toBe("-:ETH/ETH:5000");
28
+ });
29
+ });
36
30
 
37
- test("returns correct memo for Mayaname Register", () => {
38
- const result = getMemoFor(MemoType.THORNAME_REGISTER, {
39
- name: "mayaname",
40
- chain: "BNB",
41
- address: "0xABC123",
42
- owner: "0xDEF456",
43
- });
44
- expect(result).toBe("~:mayaname:BNB:0xABC123:0xDEF456");
45
- });
31
+ describe("getMemoForLeaveAndBond", () => {
32
+ test("returns correct memo for Leave", () => {
33
+ const result = getMemoForLeaveAndBond({ address: "ABC123", type: MemoType.LEAVE });
34
+ expect(result).toBe("LEAVE:ABC123");
46
35
  });
47
36
 
48
- describe("for Deposit", () => {
49
- test("returns correct memo for Deposit (single side)", () => {
50
- const result = getMemoFor(MemoType.DEPOSIT, {
51
- chain: Chain.Ethereum,
52
- symbol: "ETH",
53
- singleSide: true,
54
- });
55
- expect(result).toBe("+:ETH/ETH");
56
- });
37
+ test("returns correct memo for Bond", () => {
38
+ const result = getMemoForLeaveAndBond({ address: "ABC123", type: MemoType.BOND });
39
+ expect(result).toBe("BOND:ABC123");
40
+ });
41
+ });
57
42
 
58
- test("returns correct memo for Deposit (dual side)", () => {
59
- const result = getMemoFor(MemoType.DEPOSIT, {
60
- chain: Chain.Avalanche,
61
- symbol: "AVAX",
62
- address: "0xABC123",
63
- });
64
- expect(result).toBe("+:AVAX.AVAX:0xABC123");
43
+ describe("getMemoForNameRegister", () => {
44
+ test("returns correct memo for single side", () => {
45
+ const result = getMemoForNameRegister({
46
+ name: "asdfg",
47
+ chain: Chain.Ethereum,
48
+ owner: "thor1234",
49
+ address: "0xaasd123",
65
50
  });
51
+ expect(result).toBe("~:asdfg:ETH:0xaasd123:thor1234");
66
52
  });
53
+ });
67
54
 
68
- describe("for Withdraw", () => {
69
- test("returns correct memo for Withdraw (single side)", () => {
70
- const result = getMemoFor(MemoType.WITHDRAW, {
71
- chain: Chain.Bitcoin,
72
- ticker: "BTC",
73
- symbol: "BTC",
74
- basisPoints: 10000,
75
- singleSide: true,
76
- });
77
- expect(result).toBe("-:BTC/BTC:10000");
78
- });
55
+ describe("getMemoForDeposit", () => {
56
+ test("returns correct memo for single side", () => {
57
+ const result = getMemoForDeposit({ chain: Chain.Ethereum, symbol: "ETH" });
58
+ expect(result).toBe("+:ETH.ETH");
59
+ });
60
+ });
79
61
 
80
- test("returns correct memo for Withdraw (dual side)", () => {
81
- const result = getMemoFor(MemoType.WITHDRAW, {
82
- chain: Chain.Ethereum,
83
- ticker: "ETH",
84
- symbol: "ETH",
85
- basisPoints: 100,
86
- targetAssetString: "ETH.ETH",
87
- });
88
- expect(result).toBe("-:ETH.ETH:100:ETH.ETH");
62
+ describe("getMemoForWithdraw", () => {
63
+ test("returns correct memo for single side", () => {
64
+ const result = getMemoForWithdraw({
65
+ chain: Chain.Ethereum,
66
+ symbol: "ETH",
67
+ ticker: "ETH",
68
+ basisPoints: 100,
89
69
  });
70
+ expect(result).toBe("-:ETH.ETH:100");
90
71
  });
91
72
  });
@@ -1,5 +1,5 @@
1
1
  import { describe, expect, test } from "bun:test";
2
- import { Chain, type DerivationPathArray } from "@swapkit/helpers";
2
+ import { Chain, type DerivationPathArray } from "../../types";
3
3
 
4
4
  import { findAssetBy } from "../asset.ts";
5
5
  import { derivationPathToString, getTHORNameCost } from "../others.ts";
@@ -34,7 +34,7 @@ describe("getTHORNameCost", () => {
34
34
  });
35
35
 
36
36
  test("throws an error for negative years", () => {
37
- expect(() => getTHORNameCost(-1)).toThrow("Invalid number of year");
37
+ expect(() => getTHORNameCost(-1)).toThrow("helpers_invalid_number_of_years");
38
38
  });
39
39
  });
40
40
 
@@ -49,7 +49,9 @@ describe("getAssetBy", () => {
49
49
  chain: Chain.Ethereum,
50
50
  contract: "0XA0B86991C6218B36C1D19D4A2E9EB0CE3606EB48",
51
51
  });
52
- expect(assetByChainAndContract).toBe("ETH.USDC-0XA0B86991C6218B36C1D19D4A2E9EB0CE3606EB48");
52
+ expect(assetByChainAndContract?.toUpperCase()).toBe(
53
+ "ETH.USDC-0XA0B86991C6218B36C1D19D4A2E9EB0CE3606EB48",
54
+ );
53
55
  });
54
56
 
55
57
  test("return undefined if asset can't be found", async () => {
@@ -1,15 +1,19 @@
1
+ import { AssetValue } from "../modules/assetValue.ts";
1
2
  import { RequestClient } from "../modules/requestClient.ts";
2
3
  import { BaseDecimal, Chain, ChainToRPC, type EVMChain, EVMChains } from "../types/chains.ts";
4
+ import type { RadixCoreStateResourceDTO } from "../types/radix.ts";
3
5
  import type { TokenNames } from "../types/tokens.ts";
4
6
 
5
7
  const getDecimalMethodHex = "0x313ce567";
6
8
 
7
- export type CommonAssetString =
8
- | `${Chain.Maya}.MAYA`
9
- | `${Chain.Ethereum}.THOR`
10
- | `${Chain.Ethereum}.vTHOR`
11
- | `${Chain.Kujira}.USK`
12
- | Chain;
9
+ export type CommonAssetString = (typeof CommonAssetStrings)[number] | Chain;
10
+
11
+ export const CommonAssetStrings = [
12
+ `${Chain.Maya}.MAYA`,
13
+ `${Chain.Ethereum}.THOR`,
14
+ `${Chain.Ethereum}.vTHOR`,
15
+ `${Chain.Kujira}.USK`,
16
+ ] as const;
13
17
 
14
18
  const getContractDecimals = async ({ chain, to }: { chain: EVMChain; to: string }) => {
15
19
  try {
@@ -34,10 +38,36 @@ const getContractDecimals = async ({ chain, to }: { chain: EVMChain; to: string
34
38
  }
35
39
  };
36
40
 
41
+ const getRadixResourceDecimals = async ({ symbol }: { symbol: string }) => {
42
+ try {
43
+ const resourceAddress = symbol.split("-")[1]?.toLowerCase();
44
+
45
+ const { manager } = await RequestClient.post<RadixCoreStateResourceDTO>(
46
+ `${ChainToRPC[Chain.Radix]}/state/resource`,
47
+ {
48
+ headers: {
49
+ Accept: "*/*",
50
+ "Content-Type": "application/json",
51
+ },
52
+ body: JSON.stringify({
53
+ network: "mainnet",
54
+ resource_address: resourceAddress,
55
+ }),
56
+ },
57
+ );
58
+
59
+ return manager.divisibility.value.divisibility;
60
+ } catch (error) {
61
+ console.error(error);
62
+ return BaseDecimal[Chain.Radix];
63
+ }
64
+ };
65
+
37
66
  const getETHAssetDecimal = (symbol: string) => {
38
67
  if (symbol === Chain.Ethereum) return BaseDecimal.ETH;
39
68
  const splitSymbol = symbol.split("-");
40
- const address = splitSymbol.length === 1 ? undefined : splitSymbol[splitSymbol.length - 1];
69
+ const address =
70
+ splitSymbol.length === 1 ? undefined : splitSymbol[splitSymbol.length - 1]?.toLowerCase();
41
71
 
42
72
  return address?.startsWith("0x")
43
73
  ? getContractDecimals({ chain: Chain.Ethereum, to: address })
@@ -59,6 +89,12 @@ const getBSCAssetDecimal = (symbol: string) => {
59
89
  return BaseDecimal.BSC;
60
90
  };
61
91
 
92
+ const getRadixAssetDecimal = (symbol: string) => {
93
+ if (symbol === Chain.Radix) return BaseDecimal.XRD;
94
+
95
+ return getRadixResourceDecimals({ symbol });
96
+ };
97
+
62
98
  export const getDecimal = ({ chain, symbol }: { chain: Chain; symbol: string }) => {
63
99
  switch (chain) {
64
100
  case Chain.Ethereum:
@@ -67,11 +103,32 @@ export const getDecimal = ({ chain, symbol }: { chain: Chain; symbol: string })
67
103
  return getAVAXAssetDecimal(symbol);
68
104
  case Chain.BinanceSmartChain:
69
105
  return getBSCAssetDecimal(symbol);
106
+ case Chain.Radix:
107
+ return getRadixAssetDecimal(symbol);
70
108
  default:
71
109
  return BaseDecimal[chain];
72
110
  }
73
111
  };
74
112
 
113
+ export const getGasAsset = ({ chain }: { chain: Chain }) => {
114
+ switch (chain) {
115
+ case Chain.Arbitrum:
116
+ case Chain.Optimism:
117
+ return AssetValue.from({ asset: `${chain}.ETH` });
118
+ case Chain.Maya:
119
+ return AssetValue.from({ asset: `${chain}.CACAO` });
120
+ case Chain.Cosmos:
121
+ return AssetValue.from({ asset: `${chain}.ATOM` });
122
+ case Chain.BinanceSmartChain:
123
+ return AssetValue.from({ asset: `${chain}.BNB` });
124
+ case Chain.THORChain:
125
+ return AssetValue.from({ asset: `${chain}.RUNE` });
126
+
127
+ default:
128
+ return AssetValue.from({ asset: `${chain}.${chain}` });
129
+ }
130
+ };
131
+
75
132
  export const isGasAsset = ({ chain, symbol }: { chain: Chain; symbol: string }) => {
76
133
  switch (chain) {
77
134
  case Chain.Arbitrum:
@@ -79,12 +136,8 @@ export const isGasAsset = ({ chain, symbol }: { chain: Chain; symbol: string })
79
136
  return symbol === "ETH";
80
137
  case Chain.Maya:
81
138
  return symbol === "CACAO";
82
- case Chain.Kujira:
83
- return symbol === "KUJI";
84
139
  case Chain.Cosmos:
85
140
  return symbol === "ATOM";
86
- case Chain.Polygon:
87
- return symbol === "MATIC";
88
141
  case Chain.BinanceSmartChain:
89
142
  return symbol === "BNB";
90
143
  case Chain.THORChain:
@@ -99,27 +152,29 @@ export const getCommonAssetInfo = (
99
152
  assetString: CommonAssetString,
100
153
  ): { identifier: string; decimal: number } => {
101
154
  switch (assetString) {
155
+ case Chain.Arbitrum:
156
+ case Chain.Optimism:
157
+ return { identifier: `${assetString}.ETH`, decimal: BaseDecimal[assetString] };
158
+
102
159
  case `${Chain.Ethereum}.THOR`:
103
160
  return { identifier: "ETH.THOR-0xa5f2211b9b8170f694421f2046281775e8468044", decimal: 18 };
104
161
  case `${Chain.Ethereum}.vTHOR`:
105
162
  return { identifier: "ETH.vTHOR-0x815c23eca83261b6ec689b60cc4a58b54bc24d8d", decimal: 18 };
106
- case Chain.Arbitrum:
107
- return { identifier: `${Chain.Arbitrum}.ETH`, decimal: BaseDecimal[assetString] };
108
- case Chain.Optimism:
109
- return { identifier: `${Chain.Optimism}.ETH`, decimal: BaseDecimal[assetString] };
110
163
  case Chain.Cosmos:
111
- return { identifier: "GAIA.ATOM", decimal: BaseDecimal[assetString] };
164
+ return { identifier: `${assetString}.ATOM`, decimal: BaseDecimal[assetString] };
112
165
  case Chain.THORChain:
113
- return { identifier: "THOR.RUNE", decimal: BaseDecimal[assetString] };
166
+ return { identifier: `${assetString}.RUNE`, decimal: BaseDecimal[assetString] };
114
167
  case Chain.BinanceSmartChain:
115
- return { identifier: "BSC.BNB", decimal: BaseDecimal[assetString] };
168
+ return { identifier: `${assetString}.BNB`, decimal: BaseDecimal[assetString] };
116
169
  case Chain.Maya:
117
- return { identifier: "MAYA.CACAO", decimal: BaseDecimal.MAYA };
118
- case `${Chain.Maya}.MAYA`:
119
- return { identifier: "MAYA.MAYA", decimal: 4 };
170
+ return { identifier: `${assetString}.CACAO`, decimal: BaseDecimal[assetString] };
171
+ case Chain.Radix:
172
+ return { identifier: `${Chain.Radix}.XRD`, decimal: BaseDecimal[assetString] };
120
173
 
174
+ case `${Chain.Maya}.MAYA`:
175
+ return { identifier: assetString, decimal: 4 };
121
176
  case `${Chain.Kujira}.USK`:
122
- return { identifier: `${Chain.Kujira}.USK`, decimal: 6 };
177
+ return { identifier: assetString, decimal: 6 };
123
178
 
124
179
  default:
125
180
  return { identifier: `${assetString}.${assetString}`, decimal: BaseDecimal[assetString] };
@@ -135,21 +190,20 @@ export const getAssetType = ({ chain, symbol }: { chain: Chain; symbol: string }
135
190
  return symbol === "ATOM" ? "Native" : Chain.Cosmos;
136
191
  case Chain.Kujira:
137
192
  return symbol === Chain.Kujira ? "Native" : Chain.Kujira;
138
- case Chain.Binance:
139
- return symbol === Chain.Binance ? "Native" : "BEP2";
140
193
  case Chain.BinanceSmartChain:
141
- return symbol === Chain.Binance ? "Native" : "BEP20";
194
+ return symbol === "BNB" ? "Native" : "BEP20";
142
195
  case Chain.Ethereum:
143
196
  return symbol === Chain.Ethereum ? "Native" : "ERC20";
144
197
  case Chain.Avalanche:
145
198
  return symbol === Chain.Avalanche ? "Native" : Chain.Avalanche;
146
199
  case Chain.Polygon:
147
200
  return symbol === Chain.Polygon ? "Native" : "POLYGON";
148
-
149
201
  case Chain.Arbitrum:
150
202
  return [Chain.Ethereum, Chain.Arbitrum].includes(symbol as Chain) ? "Native" : "ARBITRUM";
151
203
  case Chain.Optimism:
152
204
  return [Chain.Ethereum, Chain.Optimism].includes(symbol as Chain) ? "Native" : "OPTIMISM";
205
+ case Chain.Radix:
206
+ return symbol === Chain.Radix ? "Native" : "RADIX";
153
207
 
154
208
  default:
155
209
  return "Native";
@@ -7,8 +7,9 @@ import {
7
7
  } from "../types";
8
8
 
9
9
  type Params = {
10
- index: number;
11
10
  chain: Chain;
11
+ index: number;
12
+ addressIndex?: number;
12
13
  type?: "legacy" | "ledgerLive" | "nativeSegwitMiddleAccount" | "segwit";
13
14
  };
14
15
 
@@ -17,17 +18,17 @@ const updatedLastIndex = (path: DerivationPathArray, index: number) => [
17
18
  index,
18
19
  ];
19
20
 
20
- export function getDerivationPathFor({ chain, index, type }: Params) {
21
+ export function getDerivationPathFor({ chain, index, addressIndex = 0, type }: Params) {
21
22
  if (EVMChains.includes(chain as EVMChain)) {
22
23
  if (type === "legacy") return [44, 60, 0, index];
23
- if (type === "ledgerLive") return [44, 60, index, 0, 0];
24
+ if (type === "ledgerLive") return [44, 60, index, 0, addressIndex];
24
25
  return updatedLastIndex(NetworkDerivationPath[chain], index);
25
26
  }
26
27
 
27
28
  if ([Chain.Bitcoin, Chain.Litecoin].includes(chain)) {
28
29
  const chainId = chain === Chain.Bitcoin ? 0 : 2;
29
30
 
30
- if (type === "nativeSegwitMiddleAccount") return [84, chainId, index, 0, 0];
31
+ if (type === "nativeSegwitMiddleAccount") return [84, chainId, index, 0, addressIndex];
31
32
  if (type === "segwit") return [49, chainId, 0, 0, index];
32
33
  if (type === "legacy") return [44, chainId, 0, 0, index];
33
34
  return updatedLastIndex(NetworkDerivationPath[chain], index);