@tomo-inc/chains-service 0.0.22 → 0.0.24

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.
Files changed (50) hide show
  1. package/dist/index.cjs +50 -26
  2. package/dist/index.d.cts +5 -1
  3. package/dist/index.d.ts +5 -1
  4. package/dist/index.js +51 -27
  5. package/package.json +2 -1
  6. package/project.json +1 -1
  7. package/src/__tests__/config.test.ts +46 -0
  8. package/src/__tests__/dogecoin-utils.test.ts +147 -0
  9. package/src/__tests__/evm-utils.test.ts +133 -0
  10. package/src/__tests__/index.test.ts +40 -0
  11. package/src/__tests__/services.test.ts +285 -0
  12. package/src/__tests__/solana-utils.test.ts +131 -0
  13. package/src/__tests__/utils.test.ts +52 -0
  14. package/src/__tests__/wallet.test.ts +350 -0
  15. package/src/api/__tests__/base.test.ts +146 -0
  16. package/src/api/__tests__/index.test.ts +51 -0
  17. package/src/api/__tests__/network.test.ts +153 -0
  18. package/src/api/__tests__/token.test.ts +231 -2
  19. package/src/api/__tests__/transaction.test.ts +121 -6
  20. package/src/api/__tests__/user.test.ts +237 -3
  21. package/src/api/__tests__/wallet.test.ts +174 -4
  22. package/src/api/network.ts +9 -1
  23. package/src/api/utils/__tests__/index.test.ts +91 -0
  24. package/src/api/utils/__tests__/signature.test.ts +124 -0
  25. package/src/api/utils/index.ts +6 -2
  26. package/src/base/__tests__/network.test.ts +119 -0
  27. package/src/base/__tests__/service.test.ts +68 -0
  28. package/src/base/__tests__/token.test.ts +123 -0
  29. package/src/base/__tests__/transaction.test.ts +210 -0
  30. package/src/config.ts +1 -1
  31. package/src/dogecoin/__tests__/base.test.ts +76 -0
  32. package/src/dogecoin/__tests__/rpc.test.ts +465 -0
  33. package/src/dogecoin/__tests__/service-extended.test.ts +420 -0
  34. package/src/dogecoin/__tests__/utils-doge.test.ts +244 -0
  35. package/src/dogecoin/__tests__/utils-extended.test.ts +323 -0
  36. package/src/dogecoin/base.ts +1 -0
  37. package/src/dogecoin/config.ts +2 -1
  38. package/src/dogecoin/rpc.ts +33 -7
  39. package/src/dogecoin/service.ts +9 -5
  40. package/src/evm/__tests__/rpc.test.ts +132 -0
  41. package/src/evm/__tests__/service.test.ts +535 -0
  42. package/src/evm/__tests__/utils.test.ts +170 -0
  43. package/src/evm/utils.ts +2 -2
  44. package/src/solana/__tests__/service.test.ts +425 -0
  45. package/src/solana/__tests__/utils.test.ts +937 -0
  46. package/src/solana/config.ts +1 -1
  47. package/src/solana/service.ts +2 -0
  48. package/src/solana/utils.ts +2 -16
  49. package/src/utils/index.ts +1 -1
  50. package/vitest.config.ts +13 -0
@@ -1,6 +1,31 @@
1
1
  import { CONFIG, jwtToken } from "./config";
2
2
  import { UserAPIs } from "../user";
3
3
  import { beforeEach, describe, it, expect, vi, afterEach } from "vitest";
4
+ import axios from "axios";
5
+
6
+ // Mock axios
7
+ vi.mock("axios", () => ({
8
+ default: {
9
+ create: vi.fn(() => ({
10
+ post: vi.fn(),
11
+ get: vi.fn(),
12
+ interceptors: {
13
+ request: { use: vi.fn() },
14
+ response: { use: vi.fn() },
15
+ },
16
+ })),
17
+ },
18
+ }));
19
+
20
+ // Mock signature utility
21
+ vi.mock("../utils", () => ({
22
+ signature: {
23
+ generateCubeSignature: vi.fn().mockResolvedValue({
24
+ timestamp: "1234567890",
25
+ signature: "test-signature",
26
+ }),
27
+ },
28
+ }));
4
29
 
5
30
  describe("api", () => {
6
31
  let service: UserAPIs;
@@ -12,7 +37,8 @@ describe("api", () => {
12
37
  };
13
38
 
14
39
  beforeEach(() => {
15
- service = UserAPIs.getInstance(CONFIG, jwtToken);
40
+ // Reset instance before each test
41
+ (UserAPIs as any).instance = undefined;
16
42
  vi.clearAllMocks();
17
43
  });
18
44
 
@@ -22,13 +48,57 @@ describe("api", () => {
22
48
 
23
49
  describe("user", () => {
24
50
  it("getUserInfo", async () => {
51
+ const mockResponse = {
52
+ data: {
53
+ code: "10000",
54
+ data: {
55
+ user: {
56
+ userID: "test-user-id",
57
+ nickname: "Test User",
58
+ },
59
+ account: {},
60
+ },
61
+ },
62
+ };
63
+ const mockPost = vi.fn().mockResolvedValue(mockResponse);
64
+ vi.mocked(axios.create).mockReturnValue({
65
+ post: mockPost,
66
+ get: vi.fn(),
67
+ interceptors: {
68
+ request: { use: vi.fn() },
69
+ response: { use: vi.fn() },
70
+ },
71
+ } as any);
72
+
73
+ // Create service instance after mock is set
74
+ service = UserAPIs.getInstance(CONFIG, jwtToken);
25
75
  const result = await service.getUserInfo();
26
76
  console.log("getUserInfo", result);
27
77
 
28
78
  expect(typeof result.success).toBe("boolean");
29
79
  expect(typeof result.data).toBe("object");
30
- expect(typeof result.data?.userID).toBe("string");
31
- expect(typeof result.data?.nickname).toBe("string");
80
+ expect(result.data).toHaveProperty("user");
81
+ expect(result.data?.user).toHaveProperty("userID");
82
+ expect(result.data?.user).toHaveProperty("nickname");
83
+ });
84
+
85
+ it("getUserInfo should set success false when code is not 10000", async () => {
86
+ const mockPost = vi.fn().mockResolvedValue({
87
+ data: {
88
+ code: "10001",
89
+ message: "Unauthorized",
90
+ data: null,
91
+ },
92
+ });
93
+ vi.mocked(axios.create).mockReturnValue({
94
+ post: mockPost,
95
+ get: vi.fn(),
96
+ interceptors: { request: { use: vi.fn() }, response: { use: vi.fn() } },
97
+ } as any);
98
+ service = UserAPIs.getInstance(CONFIG, jwtToken);
99
+ const result = await service.getUserInfo();
100
+ expect(result.success).toBe(false);
101
+ expect(result.message).toBe("Unauthorized");
32
102
  });
33
103
 
34
104
  it("updateUserInfo", async () => {
@@ -38,6 +108,28 @@ describe("api", () => {
38
108
  username: `${params.username}_${r}`,
39
109
  };
40
110
 
111
+ const mockResponse = {
112
+ data: {
113
+ code: "10000",
114
+ data: {
115
+ userID: "test-user-id",
116
+ nickname: userInfo.nickname,
117
+ username: userInfo.username,
118
+ },
119
+ },
120
+ };
121
+ const mockPost = vi.fn().mockResolvedValue(mockResponse);
122
+ vi.mocked(axios.create).mockReturnValue({
123
+ post: mockPost,
124
+ get: vi.fn(),
125
+ interceptors: {
126
+ request: { use: vi.fn() },
127
+ response: { use: vi.fn() },
128
+ },
129
+ } as any);
130
+
131
+ // Create service instance after mock is set
132
+ service = UserAPIs.getInstance(CONFIG, jwtToken);
41
133
  const result = await service.updateUserInfo(userInfo);
42
134
  console.log("updateUserInfo", result);
43
135
 
@@ -84,6 +176,29 @@ describe("api", () => {
84
176
  // });
85
177
 
86
178
  it("getUserWallet", async () => {
179
+ const mockResponse = {
180
+ data: {
181
+ success: true,
182
+ data: {
183
+ id: "test-wallet-id",
184
+ bitcoinP2shPubKeyMain: "test-pubkey",
185
+ deleted: false,
186
+ solanaAddress: "test-solana-address",
187
+ },
188
+ },
189
+ };
190
+ const mockPost = vi.fn().mockResolvedValue(mockResponse);
191
+ vi.mocked(axios.create).mockReturnValue({
192
+ post: mockPost,
193
+ get: vi.fn(),
194
+ interceptors: {
195
+ request: { use: vi.fn() },
196
+ response: { use: vi.fn() },
197
+ },
198
+ } as any);
199
+
200
+ // Create service instance after mock is set
201
+ service = UserAPIs.getInstance(CONFIG, jwtToken);
87
202
  const result = await service.getUserWallet();
88
203
  console.log("getUserWallet", result);
89
204
 
@@ -96,10 +211,129 @@ describe("api", () => {
96
211
  });
97
212
 
98
213
  it("isExistEmail", async () => {
214
+ const mockResponse = {
215
+ data: {
216
+ code: "10000",
217
+ data: {},
218
+ },
219
+ };
220
+ const mockPost = vi.fn().mockResolvedValue(mockResponse);
221
+ vi.mocked(axios.create).mockReturnValue({
222
+ post: mockPost,
223
+ get: vi.fn(),
224
+ interceptors: {
225
+ request: { use: vi.fn() },
226
+ response: { use: vi.fn() },
227
+ },
228
+ } as any);
229
+
230
+ // Create service instance after mock is set
231
+ service = UserAPIs.getInstance(CONFIG, jwtToken);
99
232
  const result = await service.isExistEmail(params.email);
100
233
  console.log("isExistEmail", result);
101
234
 
102
235
  expect(typeof result).toBe("object");
103
236
  });
237
+
238
+ it("should throw error when updateUserInfo is called without userInfo", async () => {
239
+ service = UserAPIs.getInstance(CONFIG, jwtToken);
240
+ await expect(service.updateUserInfo(null as any)).rejects.toThrow("User info is required");
241
+ });
242
+
243
+ it("sendExportSeedPhraseEmail", async () => {
244
+ const mockResponse = {
245
+ data: {
246
+ code: "10000",
247
+ data: {},
248
+ },
249
+ };
250
+ const mockPost = vi.fn().mockResolvedValue(mockResponse);
251
+ vi.mocked(axios.create).mockReturnValue({
252
+ post: mockPost,
253
+ get: vi.fn(),
254
+ interceptors: {
255
+ request: { use: vi.fn() },
256
+ response: { use: vi.fn() },
257
+ },
258
+ } as any);
259
+
260
+ service = UserAPIs.getInstance(CONFIG, jwtToken);
261
+ const result = await service.sendExportSeedPhraseEmail(params.exportTime);
262
+ expect(mockPost).toHaveBeenCalled();
263
+ expect(result).toBeDefined();
264
+ });
265
+
266
+ it("sendCancelExportSeedPhraseEmail", async () => {
267
+ const mockResponse = {
268
+ data: {
269
+ code: "10000",
270
+ data: {},
271
+ },
272
+ };
273
+ const mockPost = vi.fn().mockResolvedValue(mockResponse);
274
+ vi.mocked(axios.create).mockReturnValue({
275
+ post: mockPost,
276
+ get: vi.fn(),
277
+ interceptors: {
278
+ request: { use: vi.fn() },
279
+ response: { use: vi.fn() },
280
+ },
281
+ } as any);
282
+
283
+ service = UserAPIs.getInstance(CONFIG, jwtToken);
284
+ const result = await service.sendCancelExportSeedPhraseEmail();
285
+ expect(mockPost).toHaveBeenCalled();
286
+ expect(result).toBeDefined();
287
+ });
288
+
289
+ it("sendChangeDeviceEmail", async () => {
290
+ const mockResponse = {
291
+ data: {
292
+ code: "10000",
293
+ data: {},
294
+ },
295
+ };
296
+ const mockPost = vi.fn().mockResolvedValue(mockResponse);
297
+ vi.mocked(axios.create).mockReturnValue({
298
+ post: mockPost,
299
+ get: vi.fn(),
300
+ interceptors: {
301
+ request: { use: vi.fn() },
302
+ response: { use: vi.fn() },
303
+ },
304
+ } as any);
305
+
306
+ service = UserAPIs.getInstance(CONFIG, jwtToken);
307
+ const result = await service.sendChangeDeviceEmail(params.exportTime);
308
+ expect(mockPost).toHaveBeenCalled();
309
+ expect(result).toBeDefined();
310
+ });
311
+
312
+ it("addUserToCube", async () => {
313
+ const mockResponse = {
314
+ data: {
315
+ code: "10000",
316
+ data: {},
317
+ },
318
+ };
319
+ const mockPost = vi.fn().mockResolvedValue(mockResponse);
320
+ vi.mocked(axios.create).mockReturnValue({
321
+ post: mockPost,
322
+ get: vi.fn(),
323
+ interceptors: {
324
+ request: { use: vi.fn() },
325
+ response: { use: vi.fn() },
326
+ },
327
+ } as any);
328
+
329
+ service = UserAPIs.getInstance(CONFIG, jwtToken);
330
+ const req = {
331
+ iss: "https://accounts.google.com",
332
+ sub: "test-sub",
333
+ };
334
+ const result = await service.addUserToCube(req, "test-salt");
335
+ expect(mockPost).toHaveBeenCalled();
336
+ expect(result).toBeDefined();
337
+ });
104
338
  });
105
339
  });
@@ -1,6 +1,21 @@
1
1
  import { CONFIG, SIGN_CONFIG } from "./config";
2
2
  import { WalletAPIs } from "../wallet";
3
3
  import { beforeEach, describe, it, expect, vi, afterEach } from "vitest";
4
+ import axios from "axios";
5
+
6
+ // Mock axios
7
+ vi.mock("axios", () => ({
8
+ default: {
9
+ create: vi.fn(() => ({
10
+ post: vi.fn(),
11
+ get: vi.fn(),
12
+ interceptors: {
13
+ request: { use: vi.fn() },
14
+ response: { use: vi.fn() },
15
+ },
16
+ })),
17
+ },
18
+ }));
4
19
 
5
20
  describe("api", () => {
6
21
  let service: WalletAPIs;
@@ -13,7 +28,8 @@ describe("api", () => {
13
28
  };
14
29
 
15
30
  beforeEach(() => {
16
- service = WalletAPIs.getInstance(CONFIG, SIGN_CONFIG);
31
+ // Reset instance before each test
32
+ (WalletAPIs as any).instance = undefined;
17
33
  vi.clearAllMocks();
18
34
  });
19
35
 
@@ -22,6 +38,69 @@ describe("api", () => {
22
38
  });
23
39
 
24
40
  describe("wallet", () => {
41
+ it("createWallet should throw when params is missing", async () => {
42
+ vi.mocked(axios.create).mockReturnValue({
43
+ post: vi.fn(),
44
+ get: vi.fn(),
45
+ interceptors: { request: { use: vi.fn() }, response: { use: vi.fn() } },
46
+ } as any);
47
+ service = WalletAPIs.getInstance(CONFIG, SIGN_CONFIG);
48
+ await expect(service.createWallet(null as any)).rejects.toThrow("Params is required");
49
+ });
50
+
51
+ it("createWallet should return wallet already exists when code 60003", async () => {
52
+ const mockPost = vi.fn().mockRejectedValue({
53
+ response: { data: { code: "60003" } },
54
+ });
55
+ vi.mocked(axios.create).mockReturnValue({
56
+ post: mockPost,
57
+ get: vi.fn(),
58
+ interceptors: { request: { use: vi.fn() }, response: { use: vi.fn() } },
59
+ } as any);
60
+ service = WalletAPIs.getInstance(CONFIG, SIGN_CONFIG);
61
+ const result = await service.createWallet({
62
+ walletId: params.walletId,
63
+ chainIndex: params.chainIndex,
64
+ address: params.address,
65
+ publicKey: params.publicKey,
66
+ path: params.path,
67
+ userId: "5001704",
68
+ source: 2,
69
+ type: 2,
70
+ clientType: 4,
71
+ addressList: [],
72
+ });
73
+ expect(result.success).toBe(false);
74
+ expect(result.message).toBe("Wallet already exists");
75
+ expect(result.data).toBeNull();
76
+ });
77
+
78
+ it("createWallet should throw on other request error", async () => {
79
+ const mockPost = vi.fn().mockRejectedValue(new Error("API error"));
80
+ vi.mocked(axios.create).mockReturnValue({
81
+ post: mockPost,
82
+ get: vi.fn(),
83
+ interceptors: { request: { use: vi.fn() }, response: { use: vi.fn() } },
84
+ } as any);
85
+ service = WalletAPIs.getInstance(CONFIG, SIGN_CONFIG);
86
+ const consoleSpy = vi.spyOn(console, "error").mockImplementation(() => {});
87
+ await expect(
88
+ service.createWallet({
89
+ walletId: params.walletId,
90
+ chainIndex: params.chainIndex,
91
+ address: params.address,
92
+ publicKey: params.publicKey,
93
+ path: params.path,
94
+ userId: "5001704",
95
+ source: 2,
96
+ type: 2,
97
+ clientType: 4,
98
+ addressList: [],
99
+ }),
100
+ ).rejects.toThrow("API error");
101
+ consoleSpy.mockRestore();
102
+ });
103
+
25
104
  it("createWallet", async () => {
26
105
  const createParams = {
27
106
  walletId: params.walletId,
@@ -36,10 +115,50 @@ describe("api", () => {
36
115
  addressList: [],
37
116
  };
38
117
 
118
+ const mockResponse = {
119
+ data: {
120
+ code: 0,
121
+ data: {},
122
+ },
123
+ };
124
+ const mockPost = vi.fn().mockResolvedValue(mockResponse);
125
+ vi.mocked(axios.create).mockReturnValue({
126
+ post: mockPost,
127
+ get: vi.fn(),
128
+ interceptors: {
129
+ request: { use: vi.fn() },
130
+ response: { use: vi.fn() },
131
+ },
132
+ } as any);
133
+
134
+ // Create service instance after mock is set
135
+ service = WalletAPIs.getInstance(CONFIG, SIGN_CONFIG);
39
136
  const result = await service.createWallet(createParams);
40
137
  console.log("createWallet", result);
41
138
 
42
- expect(result).toEqual(typeof result.data === "object");
139
+ expect(typeof result.data).toBe("object");
140
+ });
141
+
142
+ it("syncWallet should throw on request error", async () => {
143
+ const mockPost = vi.fn().mockRejectedValue(new Error("API error"));
144
+ vi.mocked(axios.create).mockReturnValue({
145
+ post: mockPost,
146
+ get: vi.fn(),
147
+ interceptors: { request: { use: vi.fn() }, response: { use: vi.fn() } },
148
+ } as any);
149
+ service = WalletAPIs.getInstance(CONFIG, SIGN_CONFIG);
150
+ const consoleSpy = vi.spyOn(console, "error").mockImplementation(() => {});
151
+ await expect(
152
+ service.syncWallet({
153
+ walletId: params.walletId,
154
+ chainIndex: params.chainIndex,
155
+ address: params.address,
156
+ publicKey: params.publicKey,
157
+ path: params.path,
158
+ addressList: [],
159
+ }),
160
+ ).rejects.toThrow("API error");
161
+ consoleSpy.mockRestore();
43
162
  });
44
163
 
45
164
  it("syncWallet", async () => {
@@ -52,10 +171,43 @@ describe("api", () => {
52
171
  addressList: [],
53
172
  };
54
173
 
174
+ const mockResponse = {
175
+ data: {
176
+ code: 0,
177
+ data: {},
178
+ },
179
+ };
180
+ const mockPost = vi.fn().mockResolvedValue(mockResponse);
181
+ vi.mocked(axios.create).mockReturnValue({
182
+ post: mockPost,
183
+ get: vi.fn(),
184
+ interceptors: {
185
+ request: { use: vi.fn() },
186
+ response: { use: vi.fn() },
187
+ },
188
+ } as any);
189
+
190
+ // Create service instance after mock is set
191
+ service = WalletAPIs.getInstance(CONFIG, SIGN_CONFIG);
55
192
  const result = await service.syncWallet(syncParams);
56
193
  console.log("syncWallet", result);
57
194
 
58
- expect(result).toEqual(typeof result.data === "object");
195
+ expect(typeof result.data).toBe("object");
196
+ });
197
+
198
+ it("deleteWallet should throw on request error", async () => {
199
+ const mockPost = vi.fn().mockRejectedValue(new Error("API error"));
200
+ vi.mocked(axios.create).mockReturnValue({
201
+ post: mockPost,
202
+ get: vi.fn(),
203
+ interceptors: { request: { use: vi.fn() }, response: { use: vi.fn() } },
204
+ } as any);
205
+ service = WalletAPIs.getInstance(CONFIG, SIGN_CONFIG);
206
+ const consoleSpy = vi.spyOn(console, "error").mockImplementation(() => {});
207
+ await expect(
208
+ service.deleteWallet({ walletId: params.walletId, chainIndex: params.chainIndex }),
209
+ ).rejects.toThrow("API error");
210
+ consoleSpy.mockRestore();
59
211
  });
60
212
 
61
213
  it("deleteWallet", async () => {
@@ -64,10 +216,28 @@ describe("api", () => {
64
216
  chainIndex: params.chainIndex,
65
217
  };
66
218
 
219
+ const mockResponse = {
220
+ data: {
221
+ code: 0,
222
+ data: {},
223
+ },
224
+ };
225
+ const mockPost = vi.fn().mockResolvedValue(mockResponse);
226
+ vi.mocked(axios.create).mockReturnValue({
227
+ post: mockPost,
228
+ get: vi.fn(),
229
+ interceptors: {
230
+ request: { use: vi.fn() },
231
+ response: { use: vi.fn() },
232
+ },
233
+ } as any);
234
+
235
+ // Create service instance after mock is set
236
+ service = WalletAPIs.getInstance(CONFIG, SIGN_CONFIG);
67
237
  const result = await service.deleteWallet(deleteParams);
68
238
  console.log("deleteWallet", result);
69
239
 
70
- expect(result).toEqual(typeof result.data === "object");
240
+ expect(typeof result.data).toBe("object");
71
241
  });
72
242
  });
73
243
  });
@@ -43,11 +43,19 @@ export class NetworkAPIs extends BasePublicService {
43
43
  return `tomo-${chainType}-currentChainId`;
44
44
  }
45
45
 
46
+ /** Map ChainTypeEnum to network-data platformType where they differ */
47
+ private static readonly platformTypeForChain: Partial<Record<ChainTypeEnum, string>> = {
48
+ [ChainTypeEnum.DOGECOIN]: "DOGE",
49
+ [ChainTypeEnum.BITCOIN]: "BTC",
50
+ };
51
+
46
52
  public getAllNetworks(chainType: ChainTypeEnum | ""): any[] {
47
53
  if (chainType === "") {
48
54
  return this.chains;
49
55
  }
50
- return this.chains.filter((chain) => chain.platformType === chainType.toUpperCase());
56
+ const platformType =
57
+ NetworkAPIs.platformTypeForChain[chainType as ChainTypeEnum] ?? chainType.toUpperCase();
58
+ return this.chains.filter((chain) => chain.platformType === platformType);
51
59
  }
52
60
 
53
61
  public async getCurrentNetwork(chainType: ChainTypeEnum): Promise<string> {
@@ -0,0 +1,91 @@
1
+ import { describe, it, expect, vi } from "vitest";
2
+ import { signRequest, formatJwtToken } from "../index";
3
+
4
+ // Mock signature utils
5
+ vi.mock("../signature", () => ({
6
+ generateSignature: vi.fn(() => ({
7
+ signature: "test-signature",
8
+ timestamp: "1234567890",
9
+ })),
10
+ }));
11
+
12
+ describe("api utils", () => {
13
+ describe("formatJwtToken", () => {
14
+ it("should format JWT token with Bearer prefix", () => {
15
+ const result = formatJwtToken("test-token");
16
+ expect(result).toBe("Bearer test-token");
17
+ });
18
+
19
+ it("should handle empty token", () => {
20
+ const result = formatJwtToken("");
21
+ expect(result).toBe("Bearer ");
22
+ });
23
+ });
24
+
25
+ describe("signRequest", () => {
26
+ it("should sign request with JWT token string", () => {
27
+ const params = {
28
+ method: "GET",
29
+ url: "/api/test",
30
+ headers: {},
31
+ };
32
+ const clientId = "test-client-id";
33
+ const jwtToken = "test-jwt-token";
34
+
35
+ const result = signRequest(params, clientId, jwtToken);
36
+ expect(result.headers["client-id"]).toBe(clientId);
37
+ expect(result.headers.Authorization).toBe("Bearer test-jwt-token");
38
+ });
39
+
40
+ it("should sign request with sign config object", () => {
41
+ const params = {
42
+ method: "POST",
43
+ url: "/api/test",
44
+ data: { key: "value" },
45
+ headers: {},
46
+ };
47
+ const clientId = "test-client-id";
48
+ const signConfig = {
49
+ apiKey: "test-api-key",
50
+ apiSecret: "test-api-secret",
51
+ salt: "test-salt",
52
+ };
53
+
54
+ const result = signRequest(params, clientId, signConfig);
55
+ expect(result.headers["X-APP-Key"]).toBe("test-api-key");
56
+ expect(result.headers["X-Signature"]).toBe("test-signature");
57
+ expect(result.headers["X-Timestamp"]).toBe("1234567890");
58
+ expect(result.headers["client-id"]).toBe(clientId);
59
+ });
60
+
61
+ it("should create headers object if not exists", () => {
62
+ const params: any = {
63
+ method: "GET",
64
+ url: "/api/test",
65
+ };
66
+ const clientId = "test-client-id";
67
+ const jwtToken = "test-jwt-token";
68
+
69
+ const result = signRequest(params, clientId, jwtToken);
70
+ expect(result.headers).toBeDefined();
71
+ expect(result.headers["client-id"]).toBe(clientId);
72
+ expect(result.headers.Authorization).toBe("Bearer test-jwt-token");
73
+ });
74
+
75
+ it("should merge with existing headers", () => {
76
+ const params = {
77
+ method: "GET",
78
+ url: "/api/test",
79
+ headers: {
80
+ "Content-Type": "application/json",
81
+ },
82
+ };
83
+ const clientId = "test-client-id";
84
+ const jwtToken = "test-jwt-token";
85
+
86
+ const result = signRequest(params, clientId, jwtToken);
87
+ expect(result.headers["Content-Type"]).toBe("application/json");
88
+ expect(result.headers["client-id"]).toBe(clientId);
89
+ });
90
+ });
91
+ });