@talken/talkenkit 2.3.5 → 2.3.7

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 (110) hide show
  1. package/dist/components/ChainIndicator/ChainIndicator.css.d.ts +4 -0
  2. package/dist/components/ChainIndicator/ChainIndicator.d.ts +53 -0
  3. package/dist/components/ChainIndicator/index.d.ts +2 -0
  4. package/dist/components/ChainSelector/ChainSelector.css.d.ts +5 -0
  5. package/dist/components/ChainSelector/ChainSelector.d.ts +38 -0
  6. package/dist/components/ChainSelector/index.d.ts +2 -0
  7. package/dist/components/ConnectButton/ConnectButtonRenderer.d.ts +9 -0
  8. package/dist/components/ConnectOptions/DesktopOptions.d.ts +5 -1
  9. package/dist/components/ConnectOptions/MultiChainConnectOptions.d.ts +31 -0
  10. package/dist/components/ConnectOptions/index.d.ts +3 -0
  11. package/dist/components/ModalSelection/ModalSelection.d.ts +2 -1
  12. package/dist/components/ProfileDetails/ProfileDetails.d.ts +1 -2
  13. package/dist/components/RainbowKitProvider/RainbowKitProvider.d.ts +8 -1
  14. package/dist/components/SolanaWalletList/SolanaWalletList.css.d.ts +7 -0
  15. package/dist/components/SolanaWalletList/SolanaWalletList.d.ts +32 -0
  16. package/dist/components/SolanaWalletList/index.d.ts +2 -0
  17. package/dist/contexts/MultiChainContext.d.ts +68 -0
  18. package/dist/contexts/index.d.ts +7 -0
  19. package/dist/index.css +105 -0
  20. package/dist/index.d.ts +12 -0
  21. package/dist/index.js +1445 -899
  22. package/dist/solana/SolanaWalletProvider.d.ts +38 -0
  23. package/dist/solana/config.d.ts +57 -0
  24. package/dist/solana/index.d.ts +11 -0
  25. package/dist/solana/utils/detection.d.ts +27 -0
  26. package/dist/solana/wallets/backpackWallet.d.ts +19 -0
  27. package/dist/solana/wallets/index.d.ts +8 -0
  28. package/dist/solana/wallets/phantomSolanaWallet.d.ts +17 -0
  29. package/dist/solana/wallets/solflareWallet.d.ts +17 -0
  30. package/dist/types/solana.d.ts +97 -0
  31. package/dist/wallets/recentSolanaWalletIds.d.ts +16 -0
  32. package/dist/wallets/walletConnectors/abcWallet/abcApi.js +1 -1
  33. package/dist/wallets/walletConnectors/abcWallet/abcConnector.js +2 -2
  34. package/dist/wallets/walletConnectors/abcWallet/abcSolanaWallet.js +2 -2
  35. package/dist/wallets/walletConnectors/abcWallet/abcWallet.js +3 -3
  36. package/dist/wallets/walletConnectors/abcWallet/index.js +4 -4
  37. package/dist/wallets/walletConnectors/chunk-3SVPZCA6.js +71 -0
  38. package/dist/wallets/walletConnectors/chunk-5QEUEPNY.js +94 -0
  39. package/dist/wallets/walletConnectors/chunk-B6JLYR3I.js +66 -0
  40. package/dist/wallets/walletConnectors/{chunk-6JKWIEGA.js → chunk-BHMMHU7Y.js} +1 -1
  41. package/dist/wallets/walletConnectors/chunk-HKWBR5B7.js +102 -0
  42. package/dist/wallets/walletConnectors/chunk-K4APJ4PE.js +96 -0
  43. package/dist/wallets/walletConnectors/chunk-LJ2B47VF.js +108 -0
  44. package/dist/wallets/walletConnectors/chunk-LXINMUQC.js +186 -0
  45. package/dist/wallets/walletConnectors/chunk-MORUEOYX.js +76 -0
  46. package/dist/wallets/walletConnectors/chunk-MQTXA63X.js +27 -0
  47. package/dist/wallets/walletConnectors/{chunk-G2IHR6PW.js → chunk-NLKL4KD2.js} +11 -11
  48. package/dist/wallets/walletConnectors/{chunk-KOT7JYJR.js → chunk-OEB7MRS5.js} +1 -1
  49. package/dist/wallets/walletConnectors/{chunk-RWIZ25FJ.js → chunk-P2E4LSYH.js} +17 -23
  50. package/dist/wallets/walletConnectors/chunk-PMZJGS7X.js +73 -0
  51. package/dist/wallets/walletConnectors/{chunk-BRM4ZVXZ.js → chunk-RSZS2RMC.js} +1 -1
  52. package/dist/wallets/walletConnectors/chunk-WZZVA3LW.js +101 -0
  53. package/dist/wallets/walletConnectors/chunk-XEIKWKH7.js +63 -0
  54. package/dist/wallets/walletConnectors/chunk-XOQNQKZE.js +98 -0
  55. package/dist/wallets/walletConnectors/chunk-ZAGAF6PO.js +63 -0
  56. package/dist/wallets/walletConnectors/chunk-ZJ6OFFD5.js +95 -0
  57. package/dist/wallets/walletConnectors/index.js +24 -24
  58. package/package.json +17 -11
  59. package/LICENSE +0 -9
  60. package/dist/wallets/walletConnectors/chunk-2J66VMY5.js +0 -152
  61. package/dist/wallets/walletConnectors/chunk-2ZPGPZCP.js +0 -228
  62. package/dist/wallets/walletConnectors/chunk-3DPCIDW6.js +0 -1730
  63. package/dist/wallets/walletConnectors/chunk-4HKJ53H3.js +0 -1742
  64. package/dist/wallets/walletConnectors/chunk-5EARL7FN.js +0 -39
  65. package/dist/wallets/walletConnectors/chunk-7SXCH5TL.js +0 -1752
  66. package/dist/wallets/walletConnectors/chunk-7UZBDZZZ.js +0 -599
  67. package/dist/wallets/walletConnectors/chunk-BUDWZAL7.js +0 -44
  68. package/dist/wallets/walletConnectors/chunk-CSWWNAYR.js +0 -44
  69. package/dist/wallets/walletConnectors/chunk-E4N7SPPU.js +0 -39
  70. package/dist/wallets/walletConnectors/chunk-ENU7XLF5.js +0 -44
  71. package/dist/wallets/walletConnectors/chunk-ESRU5KCF.js +0 -151
  72. package/dist/wallets/walletConnectors/chunk-FF7ZIXKD.js +0 -39
  73. package/dist/wallets/walletConnectors/chunk-FJCL2YPU.js +0 -1737
  74. package/dist/wallets/walletConnectors/chunk-FSU3WBH3.js +0 -63
  75. package/dist/wallets/walletConnectors/chunk-HD6YCICR.js +0 -228
  76. package/dist/wallets/walletConnectors/chunk-HDYBRMYW.js +0 -194
  77. package/dist/wallets/walletConnectors/chunk-HIZCIW5L.js +0 -228
  78. package/dist/wallets/walletConnectors/chunk-JRNBDHFL.js +0 -44
  79. package/dist/wallets/walletConnectors/chunk-KIQDE4N6.js +0 -39
  80. package/dist/wallets/walletConnectors/chunk-KZOSE2PI.js +0 -228
  81. package/dist/wallets/walletConnectors/chunk-LNZJLKFB.js +0 -39
  82. package/dist/wallets/walletConnectors/chunk-LV765WZL.js +0 -1748
  83. package/dist/wallets/walletConnectors/chunk-MSI2BPP5.js +0 -1722
  84. package/dist/wallets/walletConnectors/chunk-MX2IY5CD.js +0 -44
  85. package/dist/wallets/walletConnectors/chunk-NLX2EV7O.js +0 -44
  86. package/dist/wallets/walletConnectors/chunk-NVAZ3B3V.js +0 -228
  87. package/dist/wallets/walletConnectors/chunk-OEWU3ZMN.js +0 -39
  88. package/dist/wallets/walletConnectors/chunk-P2MTINFI.js +0 -280
  89. package/dist/wallets/walletConnectors/chunk-PNMSIVVT.js +0 -44
  90. package/dist/wallets/walletConnectors/chunk-PZNYT2HC.js +0 -1722
  91. package/dist/wallets/walletConnectors/chunk-QPAE4SDS.js +0 -39
  92. package/dist/wallets/walletConnectors/chunk-QZRNNI3E.js +0 -39
  93. package/dist/wallets/walletConnectors/chunk-R4UYVU5X.js +0 -1721
  94. package/dist/wallets/walletConnectors/chunk-RLBGBBIO.js +0 -309
  95. package/dist/wallets/walletConnectors/chunk-TUUNSVKZ.js +0 -345
  96. package/dist/wallets/walletConnectors/chunk-U2CUEL35.js +0 -240
  97. package/dist/wallets/walletConnectors/chunk-V6NRLREB.js +0 -44
  98. package/dist/wallets/walletConnectors/chunk-VM7AEC7H.js +0 -39
  99. package/dist/wallets/walletConnectors/chunk-W2VDZD74.js +0 -478
  100. package/dist/wallets/walletConnectors/chunk-WAO3KL5U.js +0 -285
  101. package/dist/wallets/walletConnectors/chunk-WPHTIILX.js +0 -228
  102. package/dist/wallets/walletConnectors/chunk-WSCJY2QD.js +0 -228
  103. package/dist/wallets/walletConnectors/chunk-X3JQB5QL.js +0 -44
  104. package/dist/wallets/walletConnectors/chunk-X4CDP7L7.js +0 -228
  105. package/dist/wallets/walletConnectors/chunk-XETOVXYM.js +0 -228
  106. package/dist/wallets/walletConnectors/chunk-XYPR4BAF.js +0 -436
  107. package/dist/wallets/walletConnectors/chunk-Z2ZRPTPX.js +0 -1726
  108. package/dist/wallets/walletConnectors/{chunk-VCBVYFLJ.js → chunk-6TLWAEJV.js} +7 -7
  109. package/dist/wallets/walletConnectors/{chunk-47TQ23J4.js → chunk-74ALNZG4.js} +8 -8
  110. package/dist/wallets/walletConnectors/{chunk-66SCJ77O.js → chunk-CM5OGUJV.js} +6 -6
@@ -1,1742 +0,0 @@
1
- "use client";
2
- import {
3
- secure_default
4
- } from "./chunk-G2LI5MVX.js";
5
- import {
6
- calculateExpiryTimestamp,
7
- createAbcError,
8
- isTokenExpired,
9
- loadFromStorage,
10
- parseApiError,
11
- removeFromStorage,
12
- saveToStorage
13
- } from "./chunk-W23N7VC4.js";
14
- import {
15
- ABC_AUDIENCE,
16
- ABC_ENDPOINTS,
17
- DEFAULT_HEADERS,
18
- REQUEST_TIMEOUT
19
- } from "./chunk-VETRBBA2.js";
20
-
21
- // src/wallets/walletConnectors/abcWallet/abcApi.ts
22
- import { getAddress } from "viem";
23
- var AbcWaasClient = class {
24
- constructor(config) {
25
- this.accessToken = null;
26
- this.refreshToken = null;
27
- this.expiresAt = null;
28
- this.isRefreshing = false;
29
- this.refreshPromise = null;
30
- this.config = config;
31
- this.baseURL = config.waasUrl;
32
- this.secure = new secure_default(this.baseURL);
33
- this.loadTokens();
34
- }
35
- /**
36
- * Load tokens from storage
37
- */
38
- loadTokens() {
39
- this.accessToken = loadFromStorage("access_token" /* ACCESS_TOKEN */);
40
- this.refreshToken = loadFromStorage("refresh_token" /* REFRESH_TOKEN */);
41
- this.expiresAt = loadFromStorage("expires_at" /* EXPIRES_AT */);
42
- }
43
- /**
44
- * Save tokens to storage
45
- */
46
- saveTokens(accessToken, refreshToken, expiresIn) {
47
- this.accessToken = accessToken;
48
- this.refreshToken = refreshToken;
49
- this.expiresAt = calculateExpiryTimestamp(expiresIn);
50
- saveToStorage("access_token" /* ACCESS_TOKEN */, accessToken);
51
- saveToStorage("refresh_token" /* REFRESH_TOKEN */, refreshToken);
52
- saveToStorage("expires_at" /* EXPIRES_AT */, this.expiresAt);
53
- }
54
- /**
55
- * Clear tokens
56
- */
57
- clearTokens() {
58
- this.accessToken = null;
59
- this.refreshToken = null;
60
- this.expiresAt = null;
61
- removeFromStorage("access_token" /* ACCESS_TOKEN */);
62
- removeFromStorage("refresh_token" /* REFRESH_TOKEN */);
63
- removeFromStorage("expires_at" /* EXPIRES_AT */);
64
- }
65
- /**
66
- * Check if access token is expired
67
- */
68
- isTokenExpired() {
69
- return isTokenExpired(this.expiresAt);
70
- }
71
- /**
72
- * Get current access token
73
- */
74
- getAccessToken() {
75
- return this.accessToken;
76
- }
77
- /**
78
- * Refresh access token
79
- */
80
- async refreshAccessToken() {
81
- if (this.isRefreshing) {
82
- if (this.refreshPromise) {
83
- await this.refreshPromise;
84
- }
85
- return;
86
- }
87
- if (!this.refreshToken) {
88
- throw createAbcError(
89
- "TOKEN_EXPIRED" /* TOKEN_EXPIRED */,
90
- "No refresh token available"
91
- );
92
- }
93
- this.isRefreshing = true;
94
- this.refreshPromise = (async () => {
95
- try {
96
- const isIframe = typeof window !== "undefined" && window.self !== window.top;
97
- const talkenApiUrl = process.env.NEXT_PUBLIC_API_SERVER || "https://dev.walletapi.talken.io";
98
- const response = await fetch(
99
- `${talkenApiUrl}${ABC_ENDPOINTS.REFRESH_TOKEN}`,
100
- {
101
- method: "POST",
102
- headers: DEFAULT_HEADERS,
103
- credentials: "include",
104
- // Important: withCredentials from reference
105
- body: new URLSearchParams({
106
- refresh_token: this.refreshToken || "",
107
- // Use snake_case (reference pattern)
108
- isIframe: String(isIframe)
109
- }).toString()
110
- }
111
- );
112
- const text = await response.text();
113
- const data = text ? JSON.parse(text) : {};
114
- if (response.ok && data.access_token) {
115
- const expiresIn = data.expire_in || 3600;
116
- this.saveTokens(
117
- data.access_token,
118
- data.refresh_token || this.refreshToken,
119
- // Keep old if not provided
120
- expiresIn
121
- );
122
- } else {
123
- throw createAbcError(
124
- "TOKEN_EXPIRED" /* TOKEN_EXPIRED */,
125
- "Failed to refresh token"
126
- );
127
- }
128
- } finally {
129
- this.isRefreshing = false;
130
- this.refreshPromise = null;
131
- }
132
- })();
133
- await this.refreshPromise;
134
- }
135
- /**
136
- * Make HTTP request
137
- */
138
- async request(endpoint, options = {}) {
139
- const {
140
- method = "GET",
141
- body,
142
- headers = {},
143
- skipAuth = false,
144
- isRetry = false
145
- } = options;
146
- if (!skipAuth && this.isTokenExpired() && this.refreshToken) {
147
- await this.refreshAccessToken();
148
- }
149
- const url = `${this.baseURL}${endpoint}`;
150
- const requestHeaders = {
151
- ...DEFAULT_HEADERS,
152
- ...headers
153
- };
154
- if (!skipAuth && this.accessToken) {
155
- requestHeaders.Authorization = `Bearer ${this.accessToken}`;
156
- }
157
- if (this.config.apiKey) {
158
- requestHeaders["X-API-Key"] = this.config.apiKey;
159
- }
160
- try {
161
- const controller = new AbortController();
162
- const timeoutId = setTimeout(() => controller.abort(), REQUEST_TIMEOUT);
163
- const requestBody = body ? new URLSearchParams(body).toString() : void 0;
164
- const response = await fetch(url, {
165
- method,
166
- headers: requestHeaders,
167
- body: requestBody,
168
- signal: controller.signal
169
- });
170
- clearTimeout(timeoutId);
171
- const text = await response.text();
172
- let data;
173
- if (text) {
174
- try {
175
- data = JSON.parse(text);
176
- } catch (parseError) {
177
- console.error("[AbcWaasClient] \u274C JSON parse error:", {
178
- url,
179
- method,
180
- status: response.status,
181
- responseText: text.substring(0, 200)
182
- // Log first 200 chars
183
- });
184
- throw createAbcError(
185
- "UNKNOWN_ERROR" /* UNKNOWN_ERROR */,
186
- "Invalid JSON response from server",
187
- { text, parseError }
188
- );
189
- }
190
- } else {
191
- console.log("[AbcWaasClient] \u2139\uFE0F Empty response received:", {
192
- url,
193
- method,
194
- status: response.status
195
- });
196
- data = { status: "success" };
197
- }
198
- if (response.status === 401 && !skipAuth && this.refreshToken && !isRetry) {
199
- try {
200
- await this.refreshAccessToken();
201
- return await this.request(endpoint, {
202
- ...options,
203
- isRetry: true
204
- // Prevent infinite retry loop
205
- });
206
- } catch (refreshError) {
207
- console.error("Token refresh failed:", refreshError);
208
- throw parseApiError({
209
- response: {
210
- status: response.status,
211
- data
212
- }
213
- });
214
- }
215
- }
216
- if (!response.ok) {
217
- console.error("[AbcWaasClient] \u274C API Error:", {
218
- url,
219
- method,
220
- status: response.status,
221
- statusText: response.statusText,
222
- data
223
- });
224
- throw parseApiError({
225
- response: {
226
- status: response.status,
227
- data
228
- }
229
- });
230
- }
231
- return data;
232
- } catch (error) {
233
- console.error("[AbcWaasClient] \u274C Request failed:", {
234
- url,
235
- method,
236
- error: error.message,
237
- errorName: error.name,
238
- errorType: error.constructor.name,
239
- stack: error.stack
240
- });
241
- if (error.name === "AbortError") {
242
- throw createAbcError(
243
- "NETWORK_ERROR" /* NETWORK_ERROR */,
244
- "Request timeout",
245
- error
246
- );
247
- }
248
- if (error.code && error.message) {
249
- throw error;
250
- }
251
- throw parseApiError(error);
252
- }
253
- }
254
- /**
255
- * Login with email and password
256
- * NOTE: Tokens are stored in memory only. Call persistTokens() after PIN verification to save to localStorage.
257
- */
258
- async loginWithEmail(email, password) {
259
- const response = await this.request(
260
- ABC_ENDPOINTS.SNS_LOGIN,
261
- {
262
- method: "POST",
263
- body: {
264
- email,
265
- token: password,
266
- // Use password as token
267
- service: "email",
268
- audience: ABC_AUDIENCE
269
- },
270
- skipAuth: true
271
- }
272
- );
273
- if (response.status === "success" && response.data) {
274
- this.accessToken = response.data.accessToken;
275
- this.refreshToken = response.data.refreshToken;
276
- this.expiresAt = calculateExpiryTimestamp(response.data.expiresIn);
277
- console.log(
278
- "[AbcWaasClient] \u2705 Login successful, tokens stored in memory (not persisted yet)"
279
- );
280
- return response.data;
281
- }
282
- throw createAbcError(
283
- "INVALID_CREDENTIALS" /* INVALID_CREDENTIALS */,
284
- "Email login failed",
285
- response
286
- );
287
- }
288
- /**
289
- * Login with email and OTP (for PIN recovery)
290
- * NOTE: Tokens are stored in memory only. Call persistTokens() after PIN verification to save to localStorage.
291
- */
292
- async loginWithOtp(email, otpCode) {
293
- const response = await this.request(
294
- ABC_ENDPOINTS.SNS_LOGIN,
295
- {
296
- method: "POST",
297
- body: {
298
- email,
299
- token: otpCode,
300
- service: "email",
301
- audience: ABC_AUDIENCE
302
- },
303
- skipAuth: true
304
- }
305
- );
306
- if (response.status === "success" && response.data) {
307
- this.accessToken = response.data.accessToken;
308
- this.refreshToken = response.data.refreshToken;
309
- this.expiresAt = calculateExpiryTimestamp(response.data.expiresIn);
310
- console.log(
311
- "[AbcWaasClient] \u2705 OTP login successful, tokens stored in memory (not persisted yet)"
312
- );
313
- return response.data;
314
- }
315
- throw createAbcError(
316
- "INVALID_CREDENTIALS" /* INVALID_CREDENTIALS */,
317
- "OTP login failed",
318
- response
319
- );
320
- }
321
- /**
322
- * Login with social provider
323
- * NOTE: Tokens are stored in memory only. Call persistTokens() after PIN verification to save to localStorage.
324
- */
325
- async loginWithSocial(provider, token, email) {
326
- const response = await this.request(
327
- ABC_ENDPOINTS.SNS_LOGIN,
328
- {
329
- method: "POST",
330
- body: {
331
- token,
332
- service: provider,
333
- audience: ABC_AUDIENCE,
334
- email
335
- },
336
- skipAuth: true
337
- }
338
- );
339
- if (response.status === "success" && response.data) {
340
- this.accessToken = response.data.accessToken;
341
- this.refreshToken = response.data.refreshToken;
342
- this.expiresAt = calculateExpiryTimestamp(response.data.expiresIn);
343
- console.log(
344
- "[AbcWaasClient] \u2705 Social login successful, tokens stored in memory (not persisted yet)"
345
- );
346
- return response.data;
347
- }
348
- throw createAbcError(
349
- "INVALID_CREDENTIALS" /* INVALID_CREDENTIALS */,
350
- "Social login failed",
351
- response
352
- );
353
- }
354
- /**
355
- * Refresh access token using refresh token (public wrapper)
356
- */
357
- async refreshTokens(refreshTokenValue) {
358
- const oldRefreshToken = this.refreshToken;
359
- this.refreshToken = refreshTokenValue;
360
- try {
361
- await this.refreshAccessToken();
362
- return {
363
- accessToken: this.accessToken,
364
- refreshToken: this.refreshToken,
365
- expiresIn: Math.floor((this.expiresAt - Date.now()) / 1e3)
366
- };
367
- } catch (error) {
368
- this.refreshToken = oldRefreshToken;
369
- throw error;
370
- }
371
- }
372
- /**
373
- * Request OTP code for email
374
- */
375
- async requestOtpCode(email) {
376
- const response = await this.request(
377
- ABC_ENDPOINTS.SEND_OTP,
378
- {
379
- method: "POST",
380
- body: { email },
381
- skipAuth: true
382
- }
383
- );
384
- if (response.status === "success" && response.data) {
385
- return response.data;
386
- }
387
- throw createAbcError(
388
- "UNKNOWN_ERROR" /* UNKNOWN_ERROR */,
389
- "Failed to request OTP",
390
- response
391
- );
392
- }
393
- /**
394
- * Verify OTP code
395
- */
396
- async verifyOtpCode(email, code) {
397
- const response = await this.request(ABC_ENDPOINTS.VERIFY_OTP, {
398
- method: "POST",
399
- body: { email, code },
400
- skipAuth: true
401
- });
402
- return response.status === "success";
403
- }
404
- /**
405
- * Check if email already exists
406
- * Reference: tg-wallet-frontend src/features/user/api/index.ts:63-69
407
- */
408
- async emailCheck(email) {
409
- const talkenApiUrl = process.env.NEXT_PUBLIC_API_SERVER || "https://dev.walletapi.talken.io";
410
- const url = `${talkenApiUrl}/abc/emailCheck?email=${encodeURIComponent(email)}`;
411
- const method = "GET";
412
- console.log("[AbcWaasClient] \u{1F4EC} Checking email:", {
413
- email,
414
- url,
415
- apiServer: talkenApiUrl
416
- });
417
- try {
418
- const response = await fetch(url, {
419
- method,
420
- headers: DEFAULT_HEADERS
421
- });
422
- const text = await response.text();
423
- const data = text ? JSON.parse(text) : { status: "success" };
424
- if (!response.ok) {
425
- console.error("[AbcWaasClient] \u274C API Error:", {
426
- url,
427
- method,
428
- status: response.status,
429
- statusText: response.statusText,
430
- data
431
- });
432
- throw parseApiError({
433
- response: {
434
- status: response.status,
435
- data
436
- }
437
- });
438
- }
439
- return data;
440
- } catch (error) {
441
- if (error.name === "AbortError") {
442
- throw createAbcError(
443
- "NETWORK_ERROR" /* NETWORK_ERROR */,
444
- "Request timeout",
445
- error
446
- );
447
- }
448
- throw parseApiError(error);
449
- }
450
- }
451
- /**
452
- * Send OTP code to email for signup
453
- * Reference: tg-wallet-frontend src/features/user/api/index.ts:105-110
454
- * Note: Uses ABC WaaS endpoint, not Talken API
455
- */
456
- async sendOtpCode(email) {
457
- const endpoint = `/member/mail-service/${encodeURIComponent(email)}/sendcode`;
458
- console.log("[AbcWaasClient] \u{1F4E7} Sending OTP code:", {
459
- email,
460
- endpoint,
461
- fullUrl: `${this.baseURL}${endpoint}`
462
- });
463
- const response = await this.request(endpoint, {
464
- method: "GET",
465
- skipAuth: true
466
- });
467
- if (response.status === "success") {
468
- return response;
469
- }
470
- throw createAbcError(
471
- "UNKNOWN_ERROR" /* UNKNOWN_ERROR */,
472
- "Failed to send OTP code",
473
- response
474
- );
475
- }
476
- /**
477
- * Verify OTP code for signup
478
- * Reference: tg-wallet-frontend src/features/user/api/index.ts:112-123
479
- * Note: Uses ABC WaaS endpoint, not Talken API
480
- */
481
- async verifyOtpCodeSignup(email, code) {
482
- const endpoint = `/member/mail-service/${encodeURIComponent(email)}/verifycode`;
483
- const requestBody = {
484
- email,
485
- code,
486
- serviceid: ABC_AUDIENCE
487
- // 'https://mw.myabcwallet.com'
488
- };
489
- console.log("[AbcWaasClient] \u{1F510} Verifying OTP code:", {
490
- email,
491
- code: `${code.substring(0, 2)}****`,
492
- // Mask OTP for security
493
- serviceid: ABC_AUDIENCE,
494
- endpoint,
495
- fullUrl: `${this.baseURL}${endpoint}`,
496
- requestBody
497
- });
498
- const response = await this.request(endpoint, {
499
- method: "POST",
500
- body: requestBody,
501
- skipAuth: true
502
- });
503
- console.log("[verifyOtpCodeSignup] Response:", response);
504
- const isSuccess = response.status === "success" || response.status === 200 || response.message === "success";
505
- if (isSuccess) {
506
- return response;
507
- }
508
- console.error("[verifyOtpCodeSignup] Failed:", response);
509
- throw createAbcError(
510
- "UNKNOWN_ERROR" /* UNKNOWN_ERROR */,
511
- "Invalid or expired OTP code",
512
- response
513
- );
514
- }
515
- /**
516
- * SNS (Social) Login via Google/Apple/Kakao
517
- * Reference: tg-wallet-frontend src/features/user/api/index.ts:43-51
518
- * Note: Uses Talken API server, not ABC WaaS
519
- */
520
- async snsLogin(params) {
521
- const talkenApiUrl = process.env.NEXT_PUBLIC_API_SERVER || "https://dev.walletapi.talken.io";
522
- const url = `${talkenApiUrl}/abc/snsLogin`;
523
- console.log("[AbcWaasClient] \u{1F510} SNS Login:", {
524
- service: params.service,
525
- email: params.email,
526
- audience: params.audience,
527
- hasToken: !!params.token,
528
- url
529
- });
530
- try {
531
- const response = await fetch(url, {
532
- method: "POST",
533
- headers: {
534
- ...DEFAULT_HEADERS
535
- },
536
- credentials: "include",
537
- // withCredentials from reference
538
- body: new URLSearchParams(params).toString()
539
- });
540
- const data = await response.json();
541
- if (!response.ok) {
542
- console.error("[AbcWaasClient] \u274C SNS Login failed:", {
543
- url,
544
- status: response.status,
545
- statusText: response.statusText,
546
- data
547
- });
548
- throw parseApiError({
549
- response: {
550
- status: response.status,
551
- data
552
- }
553
- });
554
- }
555
- if (!data.access_token) {
556
- throw createAbcError(
557
- "INVALID_CREDENTIALS" /* INVALID_CREDENTIALS */,
558
- "SNS login failed: Invalid response from server",
559
- { service: params.service, response: data }
560
- );
561
- }
562
- console.log("[AbcWaasClient] \u2705 SNS login successful:", params.email);
563
- return {
564
- uid: "",
565
- // Will be fetched later via info() API
566
- email: params.email,
567
- access_token: data.access_token,
568
- refresh_token: data.refresh_token,
569
- user_type: "existing"
570
- // Default to existing, will be determined later
571
- };
572
- } catch (error) {
573
- if (error.name === "AbortError") {
574
- throw createAbcError(
575
- "NETWORK_ERROR" /* NETWORK_ERROR */,
576
- "SNS login request timeout",
577
- error
578
- );
579
- }
580
- throw error;
581
- }
582
- }
583
- /**
584
- * Register new user
585
- * Reference: tg-wallet-frontend src/features/user/api/index.ts:71-78
586
- * Note: Uses Talken API server, not ABC WaaS
587
- */
588
- async registerUser(params) {
589
- const talkenApiUrl = process.env.NEXT_PUBLIC_API_SERVER || "https://dev.walletapi.talken.io";
590
- const url = `${talkenApiUrl}/abc/adduser`;
591
- const method = "POST";
592
- console.log("[AbcWaasClient] \u{1F4DD} Registering user:", {
593
- username: params.username,
594
- name: params.name,
595
- hasPassword: !!params.password,
596
- hasSecureChannel: !!params.secureChannel,
597
- hasEmailCode: !!params.emailCode,
598
- url
599
- });
600
- try {
601
- const response = await fetch(url, {
602
- method,
603
- headers: {
604
- ...DEFAULT_HEADERS
605
- },
606
- credentials: "include",
607
- // withCredentials from reference
608
- body: new URLSearchParams(params).toString()
609
- });
610
- const text = await response.text();
611
- const data = text ? JSON.parse(text) : { status: "success" };
612
- if (!response.ok) {
613
- console.error("[AbcWaasClient] \u274C API Error:", {
614
- url,
615
- method,
616
- status: response.status,
617
- statusText: response.statusText,
618
- data
619
- });
620
- throw parseApiError({
621
- response: {
622
- status: response.status,
623
- data
624
- }
625
- });
626
- }
627
- return data;
628
- } catch (error) {
629
- if (error.name === "AbortError") {
630
- throw createAbcError(
631
- "NETWORK_ERROR" /* NETWORK_ERROR */,
632
- "Request timeout",
633
- error
634
- );
635
- }
636
- throw parseApiError(error);
637
- }
638
- }
639
- /**
640
- * Register new SNS user (email-based registration with OTP)
641
- * Reference: tg-wallet-frontend src/features/user/api/index.ts:80-87
642
- * Note: Uses Talken API server, not ABC WaaS
643
- */
644
- async registerSnsUser(params) {
645
- const talkenApiUrl = process.env.NEXT_PUBLIC_API_SERVER || "https://dev.walletapi.talken.io";
646
- const url = `${talkenApiUrl}/abc/snsAdduser`;
647
- const method = "POST";
648
- console.log("[AbcWaasClient] \u{1F4DD} Registering SNS user:", {
649
- username: params.username,
650
- name: params.name,
651
- hasOtp: !!params.sixCode,
652
- url
653
- });
654
- try {
655
- const response = await fetch(url, {
656
- method,
657
- headers: {
658
- ...DEFAULT_HEADERS
659
- },
660
- credentials: "include",
661
- // withCredentials from reference
662
- body: new URLSearchParams(params).toString()
663
- });
664
- const text = await response.text();
665
- const data = text ? JSON.parse(text) : { status: "success" };
666
- if (!response.ok) {
667
- console.error("[AbcWaasClient] \u274C API Error:", {
668
- url,
669
- method,
670
- status: response.status,
671
- statusText: response.statusText,
672
- data
673
- });
674
- throw parseApiError({
675
- response: {
676
- status: response.status,
677
- data
678
- }
679
- });
680
- }
681
- console.log("[AbcWaasClient] \u2705 SNS user registered successfully");
682
- return data;
683
- } catch (error) {
684
- if (error.name === "AbortError") {
685
- throw createAbcError(
686
- "NETWORK_ERROR" /* NETWORK_ERROR */,
687
- "Request timeout",
688
- error
689
- );
690
- }
691
- throw parseApiError(error);
692
- }
693
- }
694
- /**
695
- * Reset/Set password for existing user
696
- * Reference: tg-wallet-frontend src/features/user/api/index.ts:89-95
697
- * Note: Uses Talken API server, not ABC WaaS
698
- */
699
- async resetPassword(params) {
700
- const talkenApiUrl = process.env.NEXT_PUBLIC_API_SERVER || "https://dev.walletapi.talken.io";
701
- const url = `${talkenApiUrl}/abc/initpassword`;
702
- const method = "POST";
703
- console.log("[AbcWaasClient] \u{1F510} Setting password:", {
704
- username: params.username,
705
- hasPassword: !!params.password,
706
- hasSecureChannel: !!params.secureChannel,
707
- hasEmailCode: !!params.emailCode,
708
- url
709
- });
710
- try {
711
- const response = await fetch(url, {
712
- method,
713
- headers: {
714
- ...DEFAULT_HEADERS
715
- },
716
- credentials: "include",
717
- body: new URLSearchParams(params).toString()
718
- });
719
- const text = await response.text();
720
- const data = text ? JSON.parse(text) : { status: "success" };
721
- if (!response.ok) {
722
- console.error("[AbcWaasClient] \u274C API Error:", {
723
- url,
724
- method,
725
- status: response.status,
726
- statusText: response.statusText,
727
- data
728
- });
729
- throw parseApiError({
730
- response: {
731
- status: response.status,
732
- data
733
- }
734
- });
735
- }
736
- console.log("[AbcWaasClient] \u2705 Password set successfully");
737
- return data;
738
- } catch (error) {
739
- if (error.name === "AbortError") {
740
- throw createAbcError(
741
- "NETWORK_ERROR" /* NETWORK_ERROR */,
742
- "Request timeout",
743
- error
744
- );
745
- }
746
- throw parseApiError(error);
747
- }
748
- }
749
- /**
750
- * Generate or recover wallet
751
- */
752
- async generateOrRecoverWallet(params) {
753
- const response = await this.request(
754
- // Use 'any' to get raw API response
755
- ABC_ENDPOINTS.MPC_WALLETS,
756
- // Use correct EVM endpoint, not WALLETS_V3 (Solana only)
757
- {
758
- method: "POST",
759
- body: {
760
- uid: params.uid,
761
- pin: params.pin,
762
- chainId: params.chainId,
763
- network: params.network || "mainnet"
764
- }
765
- }
766
- );
767
- if (response.status === "success" && response.data) {
768
- const raw = response.data;
769
- console.log("[AbcWaasClient] Raw wallet API response:", {
770
- hasUid: !!raw.uid,
771
- hasSid: !!raw.sid,
772
- hasWid: !!raw.wid,
773
- hasPvencstr: !!raw.pvencstr,
774
- hasEncryptDevicePassword: !!raw.encryptDevicePassword,
775
- hasPubkey: !!raw.pubkey,
776
- allKeys: Object.keys(raw)
777
- });
778
- return {
779
- address: raw.address || "",
780
- keyId: raw.keyId || raw.key_id || raw.sid,
781
- encryptedShare: raw.encryptedShare || raw.encrypted_share || "",
782
- uid: raw.uid,
783
- sid: raw.sid,
784
- wid: raw.wid,
785
- // Preserve for Bitcoin signing
786
- pvencstr: raw.pvencstr,
787
- // Preserve for Bitcoin signing
788
- encryptDevicePassword: raw.encryptDevicePassword,
789
- // Preserve for Bitcoin signing
790
- pubkey: raw.pubkey || null
791
- };
792
- }
793
- throw createAbcError(
794
- "WALLET_NOT_FOUND" /* WALLET_NOT_FOUND */,
795
- "Failed to generate wallet",
796
- response
797
- );
798
- }
799
- /**
800
- * Sign EVM transaction (EIP-1559)
801
- * Based on ABC WaaS official documentation
802
- */
803
- async signTransaction(params) {
804
- this.loadTokens();
805
- const wallet = loadFromStorage("wallet" /* WALLET */);
806
- if (!wallet) {
807
- throw createAbcError(
808
- "WALLET_NOT_FOUND" /* WALLET_NOT_FOUND */,
809
- "Wallet information not found in storage"
810
- );
811
- }
812
- const encryptedDevicePassword = await this.secure.getEncryptPlain(
813
- wallet.encryptDevicePassword
814
- );
815
- const encryptedPvencstr = await this.secure.getEncryptPlain(
816
- wallet.pvencstr
817
- );
818
- const encryptedWid = await this.secure.getEncryptPlain(wallet.wid);
819
- const secureChannelId = await this.secure.getSecureChannelId();
820
- const networkMap = {
821
- // Ethereum Networks
822
- 1: "ethereum",
823
- // Ethereum Mainnet
824
- 11155111: "ethereum_sepolia",
825
- // Ethereum Sepolia Testnet
826
- 17e3: "ethereum_holesky",
827
- // Ethereum Holesky Testnet
828
- // Polygon Networks
829
- 137: "polygon",
830
- // Polygon Mainnet
831
- 80001: "polygon_amoy",
832
- // Polygon Amoy Testnet
833
- // Arbitrum Networks
834
- 42161: "arbitrum",
835
- // Arbitrum One
836
- 421614: "arbitrum_sepolia",
837
- // Arbitrum Sepolia
838
- // Optimism Networks
839
- 10: "optimism",
840
- // Optimism Mainnet
841
- 420: "optimism_sepolia",
842
- // Optimism Sepolia
843
- // Binance Smart Chain
844
- 56: "binance",
845
- // BSC Mainnet
846
- 97: "binance_testnet",
847
- // BSC Testnet
848
- // Avalanche
849
- 43114: "avalanche",
850
- // Avalanche C-Chain
851
- 43113: "avalanche_fuji",
852
- // Avalanche Fuji Testnet
853
- // Kaia (formerly Klaytn)
854
- 8217: "kaia",
855
- // Kaia Mainnet
856
- 1001: "kaia_kairos",
857
- // Kaia Kairos Testnet
858
- // Other EVM Networks
859
- 5e3: "mantle",
860
- // Mantle Mainnet
861
- 5001: "mantle_testnet",
862
- // Mantle Testnet
863
- 1284: "moonbeam",
864
- // Moonbeam
865
- 1285: "moonriver",
866
- // Moonriver
867
- 534352: "scroll",
868
- // Scroll Mainnet
869
- 534351: "scroll_testnet",
870
- // Scroll Testnet
871
- 2355: "silicon",
872
- // Silicon
873
- 1722641160: "silicon_sepolia",
874
- // Silicon Sepolia
875
- // Note: Taiko Mainnet has same Chain ID as Ethereum Holesky (17000)
876
- // 17000: 'taiko', // Taiko Mainnet (conflicts with ethereum_holesky)
877
- 167009: "taiko_hekla",
878
- // Taiko Hekla Testnet
879
- 1111: "wemix",
880
- // Wemix Mainnet
881
- 1112: "wemix_testnet",
882
- // Wemix Testnet
883
- 51828: "chainbounty",
884
- // ChainBounty
885
- 56580: "chainbounty_testnet"
886
- // ChainBounty Testnet
887
- };
888
- const network = networkMap[params.chainId] || "ethereum";
889
- const tx = params.transaction;
890
- const isKaiaNetwork = params.chainId === 1001 || params.chainId === 8217;
891
- if (isKaiaNetwork) {
892
- const kaiaGasPrice = "0x5d21dba00";
893
- tx.maxFeePerGas = kaiaGasPrice;
894
- tx.maxPriorityFeePerGas = kaiaGasPrice;
895
- console.log("\u{1F527} [Kaia] Overriding gas price with fixed 25 Gwei:", {
896
- chainId: params.chainId,
897
- maxFeePerGas: tx.maxFeePerGas,
898
- maxPriorityFeePerGas: tx.maxPriorityFeePerGas
899
- });
900
- }
901
- if (!tx.maxFeePerGas || !tx.maxPriorityFeePerGas || !tx.gasLimit || !tx.gas) {
902
- try {
903
- if (!tx.maxFeePerGas || !tx.maxPriorityFeePerGas) {
904
- const gasFeeUrl = `${this.baseURL}${ABC_ENDPOINTS.GAS_SUGGESTED_FEES}?network=${network}`;
905
- const gasFeeResponse = await fetch(gasFeeUrl, {
906
- method: "GET",
907
- headers: {
908
- ...this.accessToken ? { Authorization: `Bearer ${this.accessToken}` } : {}
909
- }
910
- });
911
- if (gasFeeResponse.ok) {
912
- const gasData = await gasFeeResponse.json();
913
- if (gasData.medium) {
914
- if (!tx.maxFeePerGas) {
915
- const maxFeeGwei = Number.parseFloat(
916
- gasData.medium.suggestedMaxFeePerGas
917
- );
918
- tx.maxFeePerGas = Math.floor(maxFeeGwei * 1e9).toString();
919
- }
920
- if (!tx.maxPriorityFeePerGas) {
921
- const priorityFeeGwei = Number.parseFloat(
922
- gasData.medium.suggestedMaxPriorityFeePerGas
923
- );
924
- tx.maxPriorityFeePerGas = Math.floor(
925
- priorityFeeGwei * 1e9
926
- ).toString();
927
- }
928
- }
929
- }
930
- }
931
- if (!tx.gasLimit && !tx.gas) {
932
- const estimateBody = new URLSearchParams({
933
- network,
934
- to: tx.to || "0x",
935
- // Use '0x' for contract deployment
936
- ...tx.from ? { from: tx.from } : {},
937
- ...tx.value ? { value: tx.value } : {},
938
- ...tx.data && tx.data !== "0x" ? { data: tx.data } : {},
939
- ...tx.maxFeePerGas ? { maxFeePerGas: tx.maxFeePerGas } : {},
940
- ...tx.maxPriorityFeePerGas ? { maxPriorityFeePerGas: tx.maxPriorityFeePerGas } : {}
941
- });
942
- const estimateUrl = `${this.baseURL}${ABC_ENDPOINTS.GAS_ESTIMATE_EIP1559}`;
943
- const estimateResponse = await fetch(estimateUrl, {
944
- method: "POST",
945
- headers: {
946
- "Content-Type": "application/x-www-form-urlencoded",
947
- ...this.accessToken ? { Authorization: `Bearer ${this.accessToken}` } : {}
948
- },
949
- body: estimateBody.toString()
950
- });
951
- const estimateData = await estimateResponse.json();
952
- console.log("\u26FD Gas estimate response:", {
953
- status: estimateResponse.status,
954
- ok: estimateResponse.ok,
955
- response: estimateData
956
- });
957
- if (estimateResponse.ok && estimateData.result) {
958
- const estimatedGas = estimateData.result;
959
- const estimatedGasNumber = parseInt(estimatedGas, 16);
960
- const isKaiaNetwork2 = params.chainId === 1001 || params.chainId === 8217;
961
- if (isKaiaNetwork2) {
962
- const hasContractData = tx.data && tx.data !== "0x" && tx.data.length > 2;
963
- const minGas = hasContractData ? 1e5 : 21e3;
964
- if (estimatedGasNumber < minGas) {
965
- console.warn("\u26A0\uFE0F [Kaia] Gas estimate too low, enforcing minimum:", {
966
- chainId: params.chainId,
967
- estimated: estimatedGas,
968
- estimatedDecimal: estimatedGasNumber,
969
- minimum: minGas,
970
- isContractCall: hasContractData
971
- });
972
- tx.gasLimit = `0x${minGas.toString(16)}`;
973
- } else {
974
- const bufferedGas = Math.floor(estimatedGasNumber * 1.2);
975
- tx.gasLimit = `0x${bufferedGas.toString(16)}`;
976
- console.log("\u2705 [Kaia] Gas limit with 20% buffer:", {
977
- estimated: estimatedGas,
978
- buffered: tx.gasLimit
979
- });
980
- }
981
- } else {
982
- tx.gasLimit = estimatedGas;
983
- console.log("\u2705 Gas limit from estimate:", estimatedGas);
984
- }
985
- } else {
986
- const hasContractData = tx.data && tx.data !== "0x" && tx.data.length > 2;
987
- const isKaiaNetwork2 = params.chainId === 1001 || params.chainId === 8217;
988
- if (hasContractData) {
989
- tx.gasLimit = isKaiaNetwork2 ? "0x186a0" : "0x249f0";
990
- console.warn("\u26A0\uFE0F Gas estimate failed, using contract call fallback:", {
991
- chainId: params.chainId,
992
- network,
993
- fallbackGasLimit: tx.gasLimit,
994
- isKaia: isKaiaNetwork2,
995
- error: estimateData.errorMessage || estimateData.msg
996
- });
997
- } else {
998
- tx.gasLimit = "0x5208";
999
- console.warn("\u26A0\uFE0F Gas estimate failed, using native transfer fallback:", {
1000
- chainId: params.chainId,
1001
- network,
1002
- fallbackGasLimit: tx.gasLimit
1003
- });
1004
- }
1005
- }
1006
- }
1007
- } catch (error) {
1008
- console.warn("Failed to fetch gas parameters from ABC WaaS:", error);
1009
- }
1010
- }
1011
- const isContractDeployment = !params.transaction.to || params.transaction.to === "0x" || params.transaction.to === "0x0";
1012
- const bodyData = {
1013
- network,
1014
- encryptDevicePassword: encryptedDevicePassword,
1015
- pvencstr: encryptedPvencstr,
1016
- uid: wallet.uid,
1017
- wid: encryptedWid,
1018
- sid: getAddress(wallet.address),
1019
- // EIP-55 checksum format
1020
- // For contract deployment, 'to' is '0x' (ABC WaaS convention)
1021
- // Reference: talken-nft-drops/src/libs/abc-waas-provider/index.ts:800 - to: to ?? '0x'
1022
- to: tx.to === "0x" ? "0x" : getAddress(tx.to),
1023
- // Required by ABC WaaS API
1024
- type: "EIP1559",
1025
- // ourpubkey and ucpubkey are required by ABC WaaS (empty strings for now)
1026
- // Based on successful tg-wallet payload analysis
1027
- ourpubkey: "",
1028
- ucpubkey: ""
1029
- };
1030
- bodyData.from = getAddress(tx.from || wallet.address);
1031
- if (tx.value) {
1032
- let hexValue = tx.value.startsWith("0x") ? tx.value.slice(2) : tx.value;
1033
- if (hexValue.length % 2 !== 0) {
1034
- hexValue = `0${hexValue}`;
1035
- }
1036
- bodyData.value = `0x${hexValue}`;
1037
- }
1038
- if (tx.gasLimit || tx.gas) {
1039
- const gasLimitValue = tx.gasLimit || tx.gas;
1040
- if (gasLimitValue.toString().startsWith("0x")) {
1041
- bodyData.gasLimit = gasLimitValue.toString();
1042
- } else {
1043
- bodyData.gasLimit = `0x${BigInt(gasLimitValue).toString(16)}`;
1044
- }
1045
- }
1046
- if (tx.maxFeePerGas) {
1047
- if (tx.maxFeePerGas.toString().startsWith("0x")) {
1048
- bodyData.maxFeePerGas = tx.maxFeePerGas.toString();
1049
- } else {
1050
- bodyData.maxFeePerGas = `0x${BigInt(tx.maxFeePerGas).toString(16)}`;
1051
- }
1052
- }
1053
- if (tx.maxPriorityFeePerGas) {
1054
- if (tx.maxPriorityFeePerGas.toString().startsWith("0x")) {
1055
- bodyData.maxPriorityFeePerGas = tx.maxPriorityFeePerGas.toString();
1056
- } else {
1057
- bodyData.maxPriorityFeePerGas = `0x${BigInt(tx.maxPriorityFeePerGas).toString(16)}`;
1058
- }
1059
- }
1060
- if (tx.data !== void 0 && tx.data !== null) {
1061
- bodyData.data = tx.data || "0x";
1062
- } else {
1063
- bodyData.data = "0x";
1064
- }
1065
- console.log("\u{1F50D} ABC WaaS signTransaction params:", {
1066
- isContractDeployment,
1067
- hasTo: !!bodyData.to,
1068
- to: bodyData.to,
1069
- dataLength: bodyData.data?.length,
1070
- network: bodyData.network,
1071
- type: bodyData.type,
1072
- // ✨ Show actual gas parameters
1073
- gasLimit: bodyData.gasLimit,
1074
- maxFeePerGas: bodyData.maxFeePerGas,
1075
- maxPriorityFeePerGas: bodyData.maxPriorityFeePerGas,
1076
- allKeys: Object.keys(bodyData)
1077
- });
1078
- const bodyString = new URLSearchParams(bodyData).toString();
1079
- console.log("\u{1F4E4} [Kaia Debug] Request body (URLSearchParams):", {
1080
- bodyString: bodyString.substring(0, 500) + (bodyString.length > 500 ? "..." : ""),
1081
- bodyStringLength: bodyString.length,
1082
- parsedParams: Object.fromEntries(new URLSearchParams(bodyString).entries())
1083
- });
1084
- const url = `${this.baseURL}${ABC_ENDPOINTS.SIGN_TRANSACTION}`;
1085
- const response = await fetch(url, {
1086
- method: "POST",
1087
- headers: {
1088
- "Content-Type": "application/x-www-form-urlencoded",
1089
- "Secure-Channel": secureChannelId,
1090
- ...this.accessToken ? { Authorization: `Bearer ${this.accessToken}` } : {}
1091
- },
1092
- body: bodyString
1093
- });
1094
- const res = await response.json();
1095
- console.log("\u{1F4E1} ABC WaaS /sign response:", {
1096
- status: response.status,
1097
- ok: response.ok,
1098
- response: res
1099
- });
1100
- if (!response.ok) {
1101
- console.error("\u274C ABC WaaS API error details:", {
1102
- status: response.status,
1103
- statusText: response.statusText,
1104
- errorCode: res.code,
1105
- errorMessage: res.msg || res.message || res.detail,
1106
- fullResponse: res
1107
- });
1108
- }
1109
- if (response.status === 401 && this.refreshToken) {
1110
- try {
1111
- await this.refreshAccessToken();
1112
- const retryResponse = await fetch(url, {
1113
- method: "POST",
1114
- headers: {
1115
- "Content-Type": "application/x-www-form-urlencoded",
1116
- "Secure-Channel": secureChannelId,
1117
- ...this.accessToken ? { Authorization: `Bearer ${this.accessToken}` } : {}
1118
- },
1119
- body: bodyString
1120
- });
1121
- const retryRes = await retryResponse.json();
1122
- if (retryRes.serializedTx && retryRes.rawTx) {
1123
- return {
1124
- signature: retryRes.serializedTx,
1125
- txHash: retryRes.rawTx
1126
- };
1127
- }
1128
- throw createAbcError(
1129
- "SIGNATURE_FAILED" /* SIGNATURE_FAILED */,
1130
- "Failed to sign transaction after token refresh",
1131
- retryRes
1132
- );
1133
- } catch (refreshError) {
1134
- console.error("Token refresh failed in signTransaction:", refreshError);
1135
- throw refreshError;
1136
- }
1137
- }
1138
- if (res.serializedTx && res.rawTx) {
1139
- return {
1140
- signature: res.serializedTx,
1141
- txHash: res.rawTx
1142
- };
1143
- }
1144
- throw createAbcError(
1145
- "SIGNATURE_FAILED" /* SIGNATURE_FAILED */,
1146
- "Failed to sign transaction",
1147
- res
1148
- );
1149
- }
1150
- /**
1151
- * Sign message (Personal Sign - EIP-191)
1152
- * Based on tg-wallet-frontend reference implementation
1153
- */
1154
- async signMessage(params) {
1155
- this.loadTokens();
1156
- const wallet = loadFromStorage("wallet" /* WALLET */);
1157
- if (!wallet) {
1158
- throw createAbcError(
1159
- "WALLET_NOT_FOUND" /* WALLET_NOT_FOUND */,
1160
- "Wallet information not found in storage"
1161
- );
1162
- }
1163
- const ethers = await import("ethers");
1164
- const messageHash = ethers.ethers.utils.hashMessage(params.message);
1165
- const hash = messageHash.startsWith("0x") ? messageHash.slice(2) : messageHash;
1166
- const encryptedDevicePassword = await this.secure.getEncryptPlain(
1167
- wallet.encryptDevicePassword
1168
- );
1169
- const encryptedPvencstr = await this.secure.getEncryptPlain(
1170
- wallet.pvencstr
1171
- );
1172
- const encryptedWid = await this.secure.getEncryptPlain(wallet.wid);
1173
- const secureChannelId = await this.secure.getSecureChannelId();
1174
- const bodyData = {
1175
- hash,
1176
- encryptDevicePassword: encryptedDevicePassword,
1177
- pvencstr: encryptedPvencstr,
1178
- wid: encryptedWid,
1179
- uid: wallet.uid,
1180
- sid: wallet.sid
1181
- };
1182
- const bodyString = new URLSearchParams(bodyData).toString();
1183
- const url = `${this.baseURL}${ABC_ENDPOINTS.SIGN_HASH}`;
1184
- const response = await fetch(url, {
1185
- method: "POST",
1186
- headers: {
1187
- "Content-Type": "application/x-www-form-urlencoded",
1188
- "Secure-Channel": secureChannelId,
1189
- ...this.accessToken ? { Authorization: `Bearer ${this.accessToken}` } : {}
1190
- },
1191
- body: bodyString
1192
- });
1193
- const text = await response.text();
1194
- if (!text) {
1195
- throw createAbcError(
1196
- "SIGNATURE_FAILED" /* SIGNATURE_FAILED */,
1197
- `Empty response from sign API (status: ${response.status})`,
1198
- { status: response.status }
1199
- );
1200
- }
1201
- const res = JSON.parse(text);
1202
- if (response.status === 401) {
1203
- if (!this.refreshToken) {
1204
- this.loadTokens();
1205
- }
1206
- if (this.refreshToken) {
1207
- try {
1208
- await this.refreshAccessToken();
1209
- const retryResponse = await fetch(url, {
1210
- method: "POST",
1211
- headers: {
1212
- "Content-Type": "application/x-www-form-urlencoded",
1213
- "Secure-Channel": secureChannelId,
1214
- ...this.accessToken ? { Authorization: `Bearer ${this.accessToken}` } : {}
1215
- },
1216
- body: bodyString
1217
- });
1218
- const retryText = await retryResponse.text();
1219
- if (!retryText) {
1220
- throw createAbcError(
1221
- "SIGNATURE_FAILED" /* SIGNATURE_FAILED */,
1222
- `Empty response from retry (status: ${retryResponse.status})`,
1223
- { status: retryResponse.status }
1224
- );
1225
- }
1226
- const retryRes = JSON.parse(retryText);
1227
- if (retryRes.status === "success" && retryRes.result?.signstr) {
1228
- return { signature: retryRes.result.signstr };
1229
- }
1230
- throw createAbcError(
1231
- "SIGNATURE_FAILED" /* SIGNATURE_FAILED */,
1232
- "Failed to sign message after token refresh",
1233
- retryRes
1234
- );
1235
- } catch (refreshError) {
1236
- console.error("Token refresh failed in signMessage:", refreshError);
1237
- throw refreshError;
1238
- }
1239
- }
1240
- }
1241
- if (res.signstr) {
1242
- const signData = JSON.parse(res.signstr);
1243
- const sigList = signData.sig_list?.[0];
1244
- if (!sigList || !sigList.r || !sigList.s) {
1245
- throw createAbcError(
1246
- "SIGNATURE_FAILED" /* SIGNATURE_FAILED */,
1247
- "Invalid signature format",
1248
- res
1249
- );
1250
- }
1251
- const v = (sigList.vsource || 0) + 27;
1252
- const signature = sigList.r + sigList.s.slice(2) + v.toString(16).padStart(2, "0");
1253
- return { signature };
1254
- }
1255
- throw createAbcError(
1256
- "SIGNATURE_FAILED" /* SIGNATURE_FAILED */,
1257
- "Failed to sign message",
1258
- res
1259
- );
1260
- }
1261
- /**
1262
- * Sign typed data (EIP-712)
1263
- * Reference: tg-wallet-frontend src/features/wallet/api/index.ts sign_typed_data()
1264
- */
1265
- async signTypedData(params) {
1266
- this.loadTokens();
1267
- const wallet = loadFromStorage("wallet" /* WALLET */);
1268
- if (!wallet) {
1269
- throw createAbcError(
1270
- "WALLET_NOT_FOUND" /* WALLET_NOT_FOUND */,
1271
- "Wallet information not found in storage"
1272
- );
1273
- }
1274
- const encryptedDevicePassword = await this.secure.getEncryptPlain(
1275
- wallet.encryptDevicePassword
1276
- );
1277
- const encryptedPvencstr = await this.secure.getEncryptPlain(
1278
- wallet.pvencstr
1279
- );
1280
- const encryptedWid = await this.secure.getEncryptPlain(wallet.wid);
1281
- const secureChannelId = await this.secure.getSecureChannelId();
1282
- const getNetworkName = (chainId) => {
1283
- const networkMap = {
1284
- 1: "ethereum",
1285
- // Ethereum Mainnet
1286
- 11155111: "ethereum_sepolia",
1287
- // Sepolia Testnet
1288
- 8217: "klaytn",
1289
- // Klaytn Mainnet
1290
- 1001: "klaytn_baobab",
1291
- // Klaytn Baobab Testnet
1292
- 137: "polygon",
1293
- // Polygon Mainnet
1294
- 80002: "polygon_amoy",
1295
- // Polygon Amoy Testnet
1296
- 42161: "arbitrum",
1297
- // Arbitrum One
1298
- 421614: "arbitrum_sepolia",
1299
- // Arbitrum Sepolia
1300
- 5e3: "mantle",
1301
- // Mantle Mainnet
1302
- 5003: "mantle_testnet"
1303
- // Mantle Testnet
1304
- };
1305
- return networkMap[chainId] || "ethereum";
1306
- };
1307
- const network = getNetworkName(wallet.chainId);
1308
- const bodyData = {
1309
- messageJson: params.typedData,
1310
- // Server expects "messageJson" field
1311
- version: "v4",
1312
- // EIP-712 version
1313
- network,
1314
- // Network name (required for JSON-RPC)
1315
- encryptDevicePassword: encryptedDevicePassword,
1316
- pvencstr: encryptedPvencstr,
1317
- wid: encryptedWid,
1318
- uid: wallet.uid,
1319
- sid: wallet.sid
1320
- };
1321
- const bodyString = new URLSearchParams(bodyData).toString();
1322
- const url = `${this.baseURL}${ABC_ENDPOINTS.SIGN_TYPED}`;
1323
- const response = await fetch(url, {
1324
- method: "POST",
1325
- headers: {
1326
- "Content-Type": "application/x-www-form-urlencoded",
1327
- "Secure-Channel": secureChannelId,
1328
- ...this.accessToken ? { Authorization: `Bearer ${this.accessToken}` } : {}
1329
- },
1330
- body: bodyString
1331
- });
1332
- const text = await response.text();
1333
- if (!text) {
1334
- throw createAbcError(
1335
- "SIGNATURE_FAILED" /* SIGNATURE_FAILED */,
1336
- `Empty response from signTypedData API (status: ${response.status})`,
1337
- { status: response.status }
1338
- );
1339
- }
1340
- const res = JSON.parse(text);
1341
- if (response.status === 401 && this.refreshToken) {
1342
- try {
1343
- await this.refreshAccessToken();
1344
- const retryResponse = await fetch(url, {
1345
- method: "POST",
1346
- headers: {
1347
- "Content-Type": "application/x-www-form-urlencoded",
1348
- "Secure-Channel": secureChannelId,
1349
- ...this.accessToken ? { Authorization: `Bearer ${this.accessToken}` } : {}
1350
- },
1351
- body: bodyString
1352
- });
1353
- const retryText = await retryResponse.text();
1354
- if (!retryText) {
1355
- throw createAbcError(
1356
- "SIGNATURE_FAILED" /* SIGNATURE_FAILED */,
1357
- `Empty response after retry (status: ${retryResponse.status})`,
1358
- { status: retryResponse.status }
1359
- );
1360
- }
1361
- const retryRes = JSON.parse(retryText);
1362
- if (retryRes.serializedTx) {
1363
- return { signature: retryRes.serializedTx };
1364
- }
1365
- throw createAbcError(
1366
- "SIGNATURE_FAILED" /* SIGNATURE_FAILED */,
1367
- "Failed to sign typed data after token refresh",
1368
- retryRes
1369
- );
1370
- } catch (refreshError) {
1371
- console.error("Token refresh failed in signTypedData:", refreshError);
1372
- throw refreshError;
1373
- }
1374
- }
1375
- if (res.serializedTx) {
1376
- return { signature: res.serializedTx };
1377
- }
1378
- throw createAbcError(
1379
- "SIGNATURE_FAILED" /* SIGNATURE_FAILED */,
1380
- "Failed to sign typed data",
1381
- res
1382
- );
1383
- }
1384
- /**
1385
- * Send raw transaction
1386
- * Reference: tg-wallet-frontend src/features/wallet/api/index.ts sendRawTx()
1387
- */
1388
- async sendRawTransaction(chainId, signedTransaction) {
1389
- const wallet = loadFromStorage("wallet" /* WALLET */);
1390
- if (!wallet) {
1391
- throw createAbcError(
1392
- "WALLET_NOT_FOUND" /* WALLET_NOT_FOUND */,
1393
- "Wallet information not found in storage"
1394
- );
1395
- }
1396
- const getNetworkName = (chainId2) => {
1397
- const networkMap = {
1398
- 1: "ethereum",
1399
- 11155111: "ethereum_sepolia",
1400
- 8217: "klaytn",
1401
- 1001: "klaytn_baobab",
1402
- 137: "polygon",
1403
- 80002: "polygon_amoy",
1404
- 42161: "arbitrum",
1405
- 421614: "arbitrum_sepolia",
1406
- 5e3: "mantle",
1407
- 5003: "mantle_testnet"
1408
- };
1409
- return networkMap[chainId2] || "ethereum";
1410
- };
1411
- const network = getNetworkName(chainId);
1412
- const secureChannelId = await this.secure.getSecureChannelId();
1413
- const bodyData = {
1414
- signedSerializeTx: signedTransaction,
1415
- network
1416
- // rpc parameter
1417
- };
1418
- const bodyString = new URLSearchParams(bodyData).toString();
1419
- const url = `${this.baseURL}${ABC_ENDPOINTS.SEND_RAW_TX}`;
1420
- const response = await fetch(url, {
1421
- method: "POST",
1422
- headers: {
1423
- "Content-Type": "application/x-www-form-urlencoded",
1424
- "Secure-Channel": secureChannelId,
1425
- ...this.accessToken ? { Authorization: `Bearer ${this.accessToken}` } : {}
1426
- },
1427
- body: bodyString
1428
- });
1429
- const text = await response.text();
1430
- if (!text) {
1431
- throw createAbcError(
1432
- "NETWORK_ERROR" /* NETWORK_ERROR */,
1433
- `Empty response from sendRawTx API (status: ${response.status})`,
1434
- { status: response.status }
1435
- );
1436
- }
1437
- const res = JSON.parse(text);
1438
- console.log("\u{1F4E1} sendRawTransaction response:", {
1439
- status: response.status,
1440
- ok: response.ok,
1441
- response: res
1442
- });
1443
- if (!response.ok) {
1444
- console.error("\u274C sendRawTransaction error:", {
1445
- status: response.status,
1446
- errorMessage: res.errorMessage || res.msg || res.message,
1447
- fullResponse: res
1448
- });
1449
- }
1450
- if (response.status === 401 && this.refreshToken) {
1451
- try {
1452
- await this.refreshAccessToken();
1453
- const retryResponse = await fetch(url, {
1454
- method: "POST",
1455
- headers: {
1456
- "Content-Type": "application/x-www-form-urlencoded",
1457
- "Secure-Channel": secureChannelId,
1458
- ...this.accessToken ? { Authorization: `Bearer ${this.accessToken}` } : {}
1459
- },
1460
- body: bodyString
1461
- });
1462
- const retryText = await retryResponse.text();
1463
- if (!retryText) {
1464
- throw createAbcError(
1465
- "NETWORK_ERROR" /* NETWORK_ERROR */,
1466
- `Empty response after retry (status: ${retryResponse.status})`,
1467
- { status: retryResponse.status }
1468
- );
1469
- }
1470
- const retryRes = JSON.parse(retryText);
1471
- if (retryRes.item || retryRes.txHash || retryRes.result?.txHash) {
1472
- const txHash = retryRes.item || retryRes.txHash || retryRes.result.txHash;
1473
- return { txHash };
1474
- }
1475
- throw createAbcError(
1476
- "NETWORK_ERROR" /* NETWORK_ERROR */,
1477
- "Failed to send transaction after token refresh",
1478
- retryRes
1479
- );
1480
- } catch (refreshError) {
1481
- console.error(
1482
- "Token refresh failed in sendRawTransaction:",
1483
- refreshError
1484
- );
1485
- throw refreshError;
1486
- }
1487
- }
1488
- if (res.result) {
1489
- if (typeof res.result === "string") {
1490
- console.log("\u2705 Transaction hash from result:", res.result);
1491
- return { txHash: res.result };
1492
- }
1493
- if (res.result.txHash) {
1494
- return { txHash: res.result.txHash };
1495
- }
1496
- }
1497
- if (res.item) {
1498
- return { txHash: res.item };
1499
- }
1500
- if (res.txHash) {
1501
- return { txHash: res.txHash };
1502
- }
1503
- throw createAbcError(
1504
- "NETWORK_ERROR" /* NETWORK_ERROR */,
1505
- "Failed to send transaction",
1506
- res
1507
- );
1508
- }
1509
- /**
1510
- * Get wallet info
1511
- */
1512
- async getWalletInfo(uid) {
1513
- const response = await this.request(ABC_ENDPOINTS.INFO, {
1514
- method: "POST",
1515
- body: { uid }
1516
- });
1517
- if (response.status === "success") {
1518
- return response.data;
1519
- }
1520
- throw createAbcError(
1521
- "WALLET_NOT_FOUND" /* WALLET_NOT_FOUND */,
1522
- "Failed to get wallet info",
1523
- response
1524
- );
1525
- }
1526
- /**
1527
- * Logout (clear tokens)
1528
- */
1529
- async logout() {
1530
- this.clearTokens();
1531
- }
1532
- /**
1533
- * Check if user is authenticated
1534
- */
1535
- isAuthenticated() {
1536
- return !!this.accessToken && !this.isTokenExpired();
1537
- }
1538
- /**
1539
- * Set tokens in client instance (useful when restoring from storage or state)
1540
- * Call this before persistTokens() if you need to set tokens from external source
1541
- */
1542
- setTokens(accessToken, refreshToken, expiresAt) {
1543
- this.accessToken = accessToken;
1544
- this.refreshToken = refreshToken;
1545
- this.expiresAt = expiresAt;
1546
- }
1547
- /**
1548
- * Persist tokens to localStorage
1549
- * Call this after PIN verification is complete
1550
- *
1551
- * SECURITY NOTE: This should only be called after full authentication (password + PIN)
1552
- * to ensure tokens are only persisted after the user has proven ownership of both credentials.
1553
- */
1554
- persistTokens() {
1555
- if (!this.accessToken || !this.refreshToken || !this.expiresAt) {
1556
- console.warn(
1557
- "[AbcWaasClient] \u26A0\uFE0F No tokens to persist - ensure login was successful first"
1558
- );
1559
- return;
1560
- }
1561
- console.log(
1562
- "[AbcWaasClient] \u{1F4BE} Persisting tokens to localStorage after PIN verification"
1563
- );
1564
- saveToStorage("access_token" /* ACCESS_TOKEN */, this.accessToken);
1565
- saveToStorage("refresh_token" /* REFRESH_TOKEN */, this.refreshToken);
1566
- saveToStorage("expires_at" /* EXPIRES_AT */, this.expiresAt);
1567
- }
1568
- // ==========================================================================
1569
- // Solana Methods
1570
- // ==========================================================================
1571
- /**
1572
- * Generate or recover Solana wallet (Ed25519)
1573
- * Reference: SigningService.ts:56-72, wallet/api/index.ts:56-72
1574
- */
1575
- async generateSolanaWallet(pin, isRecover = false) {
1576
- const url = `${this.baseURL}/v3/wallet/${isRecover ? "recover" : "generate"}`;
1577
- const response = await fetch(url, {
1578
- method: "POST",
1579
- headers: {
1580
- ...DEFAULT_HEADERS,
1581
- ...this.accessToken ? { Authorization: `Bearer ${this.accessToken}` } : {}
1582
- },
1583
- body: JSON.stringify({
1584
- curve: "ed25519",
1585
- password: pin
1586
- // PIN will be encrypted by Secure Channel
1587
- })
1588
- });
1589
- const data = await response.json();
1590
- if (!response.ok || data.status !== "success") {
1591
- throw createAbcError(
1592
- "WALLET_NOT_FOUND" /* WALLET_NOT_FOUND */,
1593
- "Failed to generate Solana wallet",
1594
- data
1595
- );
1596
- }
1597
- const result = data.result;
1598
- const addressResult = await this.getSolanaAddress(
1599
- result.public_key,
1600
- this.config.environment === "production" ? "solana" : "solana_devnet"
1601
- );
1602
- return {
1603
- uid: result.uid || "",
1604
- sessionId: result.share_id,
1605
- shareId: result.share_id,
1606
- publicKey: result.public_key,
1607
- address: addressResult,
1608
- keyId: result.key_id || result.share_id,
1609
- encryptedShare: result.encrypted_share || ""
1610
- };
1611
- }
1612
- /**
1613
- * Get Solana address from Ed25519 public key
1614
- * Reference: wallet/api/index.ts:74-82
1615
- */
1616
- async getSolanaAddress(publicKey, network) {
1617
- const url = `${this.baseURL}/wapi/v2/solana/wallet/getAddress`;
1618
- const response = await fetch(url, {
1619
- method: "POST",
1620
- headers: {
1621
- ...DEFAULT_HEADERS,
1622
- ...this.accessToken ? { Authorization: `Bearer ${this.accessToken}` } : {}
1623
- },
1624
- body: JSON.stringify({
1625
- network,
1626
- publicKey
1627
- })
1628
- });
1629
- const data = await response.json();
1630
- if (!response.ok || data.status !== "success") {
1631
- throw createAbcError(
1632
- "NETWORK_ERROR" /* NETWORK_ERROR */,
1633
- "Failed to get Solana address",
1634
- data
1635
- );
1636
- }
1637
- return data.result?.data?.address;
1638
- }
1639
- /**
1640
- * Sign Solana transaction with Ed25519
1641
- * Reference: SigningService.ts:587-626, wallet/api/index.ts:114-122
1642
- */
1643
- async signSolanaTransaction(params) {
1644
- const url = `${this.baseURL}/v3/wallet/sign`;
1645
- const response = await fetch(url, {
1646
- method: "POST",
1647
- headers: {
1648
- ...DEFAULT_HEADERS,
1649
- ...this.accessToken ? { Authorization: `Bearer ${this.accessToken}` } : {}
1650
- },
1651
- body: JSON.stringify({
1652
- uid: params.uid,
1653
- share_id: params.shareId,
1654
- message: params.message,
1655
- // Hex-encoded transaction
1656
- password: params.pin
1657
- // PIN will be encrypted
1658
- })
1659
- });
1660
- const data = await response.json();
1661
- if (!response.ok || data.status !== "success") {
1662
- throw createAbcError(
1663
- "SIGNATURE_FAILED" /* SIGNATURE_FAILED */,
1664
- "Failed to sign Solana transaction",
1665
- data
1666
- );
1667
- }
1668
- return {
1669
- signature: data.result?.signature
1670
- };
1671
- }
1672
- /**
1673
- * Sign Solana message with Ed25519
1674
- * Reference: SigningService.ts:546-579
1675
- */
1676
- async signSolanaMessage(params) {
1677
- const url = `${this.baseURL}/v3/wallet/sign`;
1678
- const response = await fetch(url, {
1679
- method: "POST",
1680
- headers: {
1681
- ...DEFAULT_HEADERS,
1682
- ...this.accessToken ? { Authorization: `Bearer ${this.accessToken}` } : {}
1683
- },
1684
- body: JSON.stringify({
1685
- uid: params.uid,
1686
- share_id: params.shareId,
1687
- message: params.message,
1688
- // Hex-encoded message
1689
- password: params.pin
1690
- })
1691
- });
1692
- const data = await response.json();
1693
- if (!response.ok || data.status !== "success") {
1694
- throw createAbcError(
1695
- "SIGNATURE_FAILED" /* SIGNATURE_FAILED */,
1696
- "Failed to sign Solana message",
1697
- data
1698
- );
1699
- }
1700
- return {
1701
- signature: data.result?.signature
1702
- };
1703
- }
1704
- /**
1705
- * Send Solana transaction
1706
- * Reference: SigningService.ts:418, wallet/api/index.ts:124-132
1707
- */
1708
- async sendSolanaTransaction(params) {
1709
- const url = `${this.baseURL}/wapi/v2/solana/tx/sendTransaction`;
1710
- const response = await fetch(url, {
1711
- method: "POST",
1712
- headers: {
1713
- ...DEFAULT_HEADERS,
1714
- ...this.accessToken ? { Authorization: `Bearer ${this.accessToken}` } : {}
1715
- },
1716
- body: JSON.stringify({
1717
- network: params.network,
1718
- serializedTX: params.serializedTX,
1719
- signatures: params.signatures
1720
- })
1721
- });
1722
- const data = await response.json();
1723
- if (!response.ok || data.status !== "success") {
1724
- throw createAbcError(
1725
- "NETWORK_ERROR" /* NETWORK_ERROR */,
1726
- "Failed to send Solana transaction",
1727
- data
1728
- );
1729
- }
1730
- return {
1731
- txHash: data.result?.data
1732
- };
1733
- }
1734
- };
1735
- function createAbcWaasClient(config) {
1736
- return new AbcWaasClient(config);
1737
- }
1738
-
1739
- export {
1740
- AbcWaasClient,
1741
- createAbcWaasClient
1742
- };