@rhinestone/deposit-modal 0.1.40 → 0.1.42
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/README.md +1 -0
- package/dist/{DepositModalReown-3HNOCOOO.mjs → DepositModalReown-3GPEVG26.mjs} +15 -6
- package/dist/{DepositModalReown-ZZKRN6J3.cjs → DepositModalReown-EEXNSXI4.cjs} +17 -8
- package/dist/{WithdrawModalReown-XXCOZYVU.mjs → WithdrawModalReown-7CSCY55U.mjs} +4 -4
- package/dist/{WithdrawModalReown-2CWNDVJD.cjs → WithdrawModalReown-GCOVYZN2.cjs} +7 -7
- package/dist/{chunk-K7BHCDJQ.cjs → chunk-37CTMJMO.cjs} +181 -96
- package/dist/{chunk-3O37UPSC.cjs → chunk-CDHUGROM.cjs} +1630 -362
- package/dist/{chunk-CFLZYWX7.mjs → chunk-KWAFKVV6.mjs} +120 -35
- package/dist/{chunk-AHOFT42H.cjs → chunk-LT3QKJI2.cjs} +458 -115
- package/dist/{chunk-SJEIKMVO.mjs → chunk-MBOH6XW3.mjs} +26 -13
- package/dist/{chunk-FLXTBFMZ.cjs → chunk-NELAYNA3.cjs} +11 -0
- package/dist/{chunk-F5S6RHUI.mjs → chunk-NLL42V7D.mjs} +1568 -300
- package/dist/{chunk-V7I5T4SW.cjs → chunk-PWPW7GFB.cjs} +25 -12
- package/dist/{chunk-IC2M2DZ7.mjs → chunk-QIK6ONMQ.mjs} +392 -49
- package/dist/{chunk-I7RYTI4G.mjs → chunk-ZJQZEIHA.mjs} +11 -0
- package/dist/constants.cjs +2 -2
- package/dist/constants.d.cts +6 -6
- package/dist/constants.d.ts +6 -6
- package/dist/constants.mjs +1 -1
- package/dist/deposit.cjs +4 -4
- package/dist/deposit.d.cts +2 -2
- package/dist/deposit.d.ts +2 -2
- package/dist/deposit.mjs +3 -3
- package/dist/index.cjs +5 -5
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.mjs +4 -4
- package/dist/reown.cjs +5 -5
- package/dist/reown.d.cts +1 -1
- package/dist/reown.d.ts +1 -1
- package/dist/reown.mjs +4 -4
- package/dist/styles.css +66 -0
- package/dist/{types-CIaQPR6F.d.cts → types-CyUiKQ4H.d.cts} +10 -7
- package/dist/{types-Bp2n2RQ3.d.ts → types-DQG7NEBI.d.ts} +10 -7
- package/dist/withdraw.cjs +4 -4
- package/dist/withdraw.d.cts +2 -2
- package/dist/withdraw.d.ts +2 -2
- package/dist/withdraw.mjs +3 -3
- package/package.json +25 -5
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
getTokenAddress,
|
|
8
8
|
getTokenDecimalsByAddress,
|
|
9
9
|
getTokenSymbol
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-ZJQZEIHA.mjs";
|
|
11
11
|
|
|
12
12
|
// src/components/ui/Modal.tsx
|
|
13
13
|
import {
|
|
@@ -139,6 +139,79 @@ function Modal({
|
|
|
139
139
|
}
|
|
140
140
|
Modal.displayName = "Modal";
|
|
141
141
|
|
|
142
|
+
// src/core/debug.ts
|
|
143
|
+
function truncateString(value, max = 240) {
|
|
144
|
+
if (value.length <= max) return value;
|
|
145
|
+
return `${value.slice(0, max)}...`;
|
|
146
|
+
}
|
|
147
|
+
function normalizeForLog(value, depth = 0) {
|
|
148
|
+
if (depth > 3) return "[MaxDepth]";
|
|
149
|
+
if (value === null || value === void 0) return value;
|
|
150
|
+
if (typeof value === "bigint") return value.toString();
|
|
151
|
+
if (typeof value === "string") return truncateString(value);
|
|
152
|
+
if (typeof value === "number" || typeof value === "boolean") return value;
|
|
153
|
+
if (value instanceof Error) {
|
|
154
|
+
return {
|
|
155
|
+
name: value.name,
|
|
156
|
+
message: value.message,
|
|
157
|
+
stack: value.stack ? truncateString(value.stack, 600) : void 0
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
if (Array.isArray(value)) {
|
|
161
|
+
return value.slice(0, 12).map((entry) => normalizeForLog(entry, depth + 1));
|
|
162
|
+
}
|
|
163
|
+
if (typeof value === "object") {
|
|
164
|
+
const input = value;
|
|
165
|
+
const output = {};
|
|
166
|
+
for (const [key, raw] of Object.entries(input)) {
|
|
167
|
+
const keyLower = key.toLowerCase();
|
|
168
|
+
if (keyLower.includes("signature") || keyLower.includes("privatekey") || keyLower.includes("sessiondetails")) {
|
|
169
|
+
output[key] = "[Redacted]";
|
|
170
|
+
continue;
|
|
171
|
+
}
|
|
172
|
+
output[key] = normalizeForLog(raw, depth + 1);
|
|
173
|
+
}
|
|
174
|
+
return output;
|
|
175
|
+
}
|
|
176
|
+
return String(value);
|
|
177
|
+
}
|
|
178
|
+
function debugLog(enabled, scope, message, data) {
|
|
179
|
+
if (!enabled) return;
|
|
180
|
+
if (data === void 0) {
|
|
181
|
+
console.log(`[deposit-modal:${scope}] ${message}`);
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
184
|
+
console.log(
|
|
185
|
+
`[deposit-modal:${scope}] ${message}`,
|
|
186
|
+
normalizeForLog(data)
|
|
187
|
+
);
|
|
188
|
+
}
|
|
189
|
+
function debugError(enabled, scope, message, error, data) {
|
|
190
|
+
if (!enabled) return;
|
|
191
|
+
const payload = data === void 0 ? { error: normalizeForLog(error) } : { error: normalizeForLog(error), meta: normalizeForLog(data) };
|
|
192
|
+
console.error(`[deposit-modal:${scope}] ${message}`, payload);
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
// src/core/caip.ts
|
|
196
|
+
var SOLANA_MAINNET_GENESIS = "5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp";
|
|
197
|
+
var SOLANA_MAINNET_CAIP2 = `solana:${SOLANA_MAINNET_GENESIS}`;
|
|
198
|
+
function toEvmCaip2(chainId) {
|
|
199
|
+
return `eip155:${chainId}`;
|
|
200
|
+
}
|
|
201
|
+
function parseEvmChainId(value) {
|
|
202
|
+
if (typeof value === "number" && Number.isFinite(value)) {
|
|
203
|
+
return value;
|
|
204
|
+
}
|
|
205
|
+
if (typeof value !== "string") return null;
|
|
206
|
+
const match = value.match(/^eip155:(\d+)$/);
|
|
207
|
+
if (!match?.[1]) return null;
|
|
208
|
+
const parsed = Number.parseInt(match[1], 10);
|
|
209
|
+
return Number.isFinite(parsed) ? parsed : null;
|
|
210
|
+
}
|
|
211
|
+
function isSolanaCaip2(value) {
|
|
212
|
+
return typeof value === "string" && value.startsWith("solana:");
|
|
213
|
+
}
|
|
214
|
+
|
|
142
215
|
// src/core/deposit-service.ts
|
|
143
216
|
function jsonReplacer(_key, value) {
|
|
144
217
|
return typeof value === "bigint" ? value.toString() : value;
|
|
@@ -187,6 +260,7 @@ function normalizeSetupAccountResponse(raw) {
|
|
|
187
260
|
targetChain: data.targetChain,
|
|
188
261
|
targetToken: data.targetToken,
|
|
189
262
|
needsRegistration: data.needsRegistration,
|
|
263
|
+
solanaDepositAddress: data.solanaDepositAddress,
|
|
190
264
|
accountParams: data.accountParams,
|
|
191
265
|
sessionDetailsUnsigned: data.sessionDetailsUnsigned ? {
|
|
192
266
|
hashesAndChainIds: data.sessionDetailsUnsigned.hashesAndChainIds.map(
|
|
@@ -208,30 +282,67 @@ function buildSessionDetails(unsigned, signature) {
|
|
|
208
282
|
signature
|
|
209
283
|
};
|
|
210
284
|
}
|
|
211
|
-
function createDepositService(baseUrl) {
|
|
285
|
+
function createDepositService(baseUrl, options) {
|
|
212
286
|
const normalizedBaseUrl = baseUrl.replace(/\/$/, "");
|
|
287
|
+
const debug = options?.debug === true;
|
|
288
|
+
const scope = options?.debugScope ?? "service";
|
|
213
289
|
function apiUrl(path) {
|
|
214
290
|
const normalizedPath = path.startsWith("/") ? path : `/${path}`;
|
|
215
291
|
return `${normalizedBaseUrl}${normalizedPath}`;
|
|
216
292
|
}
|
|
293
|
+
function shortRef(value) {
|
|
294
|
+
if (value.length <= 20) return value;
|
|
295
|
+
return `${value.slice(0, 10)}...${value.slice(-8)}`;
|
|
296
|
+
}
|
|
217
297
|
return {
|
|
218
298
|
async setupAccount(params) {
|
|
219
|
-
const
|
|
299
|
+
const url = apiUrl("/setup-account");
|
|
300
|
+
debugLog(debug, scope, "setupAccount:request", {
|
|
301
|
+
url,
|
|
302
|
+
ownerAddress: params.ownerAddress,
|
|
303
|
+
targetChain: params.targetChain,
|
|
304
|
+
targetToken: params.targetToken,
|
|
305
|
+
forceRegister: params.forceRegister
|
|
306
|
+
});
|
|
307
|
+
const response = await fetch(url, {
|
|
220
308
|
method: "POST",
|
|
221
309
|
headers: { "Content-Type": "application/json" },
|
|
222
310
|
body: JSON.stringify(params)
|
|
223
311
|
});
|
|
224
312
|
if (!response.ok) {
|
|
225
313
|
const error = await response.json().catch(() => ({ error: "Unknown error" }));
|
|
314
|
+
debugError(
|
|
315
|
+
debug,
|
|
316
|
+
scope,
|
|
317
|
+
"setupAccount:failed",
|
|
318
|
+
error,
|
|
319
|
+
{ status: response.status, ownerAddress: params.ownerAddress }
|
|
320
|
+
);
|
|
226
321
|
throw new Error(
|
|
227
322
|
error.error || `Setup account failed: ${response.status}`
|
|
228
323
|
);
|
|
229
324
|
}
|
|
230
|
-
|
|
325
|
+
const normalized = normalizeSetupAccountResponse(await response.json());
|
|
326
|
+
debugLog(debug, scope, "setupAccount:success", {
|
|
327
|
+
smartAccount: normalized.smartAccount,
|
|
328
|
+
needsRegistration: normalized.needsRegistration,
|
|
329
|
+
isRegistered: normalized.isRegistered,
|
|
330
|
+
hasSolanaDepositAddress: Boolean(normalized.solanaDepositAddress)
|
|
331
|
+
});
|
|
332
|
+
return normalized;
|
|
231
333
|
},
|
|
232
334
|
async registerAccount(params) {
|
|
233
335
|
const { eoaAddress, sessionOwner, ...account } = params;
|
|
234
|
-
const
|
|
336
|
+
const url = apiUrl("/register");
|
|
337
|
+
debugLog(debug, scope, "registerAccount:request", {
|
|
338
|
+
url,
|
|
339
|
+
address: params.address,
|
|
340
|
+
targetChain: params.target.chain,
|
|
341
|
+
targetToken: params.target.token,
|
|
342
|
+
eoaAddress,
|
|
343
|
+
sessionOwner
|
|
344
|
+
});
|
|
345
|
+
const response = await fetch(url, {
|
|
235
346
|
method: "POST",
|
|
236
347
|
headers: { "Content-Type": "application/json" },
|
|
237
348
|
body: JSON.stringify(
|
|
@@ -245,19 +356,41 @@ function createDepositService(baseUrl) {
|
|
|
245
356
|
});
|
|
246
357
|
if (!response.ok) {
|
|
247
358
|
const error = await response.json().catch(() => ({ error: "Unknown error" }));
|
|
359
|
+
debugError(
|
|
360
|
+
debug,
|
|
361
|
+
scope,
|
|
362
|
+
"registerAccount:failed",
|
|
363
|
+
error,
|
|
364
|
+
{ status: response.status, address: params.address }
|
|
365
|
+
);
|
|
248
366
|
throw new Error(
|
|
249
367
|
error.error || `Registration failed: ${response.status}`
|
|
250
368
|
);
|
|
251
369
|
}
|
|
252
|
-
|
|
370
|
+
const result = await response.json();
|
|
371
|
+
debugLog(debug, scope, "registerAccount:success", {
|
|
372
|
+
address: params.address,
|
|
373
|
+
evmDepositAddress: result?.evmDepositAddress,
|
|
374
|
+
hasSolanaDepositAddress: Boolean(result?.solanaDepositAddress)
|
|
375
|
+
});
|
|
376
|
+
return result;
|
|
253
377
|
},
|
|
254
378
|
async fetchPortfolio(address) {
|
|
255
|
-
const
|
|
379
|
+
const url = apiUrl(`/portfolio/${address}`);
|
|
380
|
+
debugLog(debug, scope, "fetchPortfolio:request", { url, address });
|
|
381
|
+
const response = await fetch(url, {
|
|
256
382
|
method: "GET",
|
|
257
383
|
headers: { "Content-Type": "application/json" }
|
|
258
384
|
});
|
|
259
385
|
if (!response.ok) {
|
|
260
386
|
const error = await response.json().catch(() => ({ error: "Unknown error" }));
|
|
387
|
+
debugError(
|
|
388
|
+
debug,
|
|
389
|
+
scope,
|
|
390
|
+
"fetchPortfolio:failed",
|
|
391
|
+
error,
|
|
392
|
+
{ status: response.status, address }
|
|
393
|
+
);
|
|
261
394
|
throw new Error(
|
|
262
395
|
error.error || `Portfolio fetch failed: ${response.status}`
|
|
263
396
|
);
|
|
@@ -265,18 +398,95 @@ function createDepositService(baseUrl) {
|
|
|
265
398
|
const data = await response.json();
|
|
266
399
|
const direct = normalizeDirectPortfolio(data);
|
|
267
400
|
if (direct.tokens.length > 0) {
|
|
401
|
+
debugLog(debug, scope, "fetchPortfolio:success", {
|
|
402
|
+
address,
|
|
403
|
+
source: "direct",
|
|
404
|
+
tokenCount: direct.tokens.length,
|
|
405
|
+
totalUsd: direct.totalUsd
|
|
406
|
+
});
|
|
268
407
|
return direct;
|
|
269
408
|
}
|
|
270
409
|
const portfolioData = extractOrchestratorPortfolio(data);
|
|
271
410
|
if (portfolioData) {
|
|
272
|
-
|
|
411
|
+
const normalized = normalizeOrchestratorPortfolio(portfolioData);
|
|
412
|
+
debugLog(debug, scope, "fetchPortfolio:success", {
|
|
413
|
+
address,
|
|
414
|
+
source: "orchestrator",
|
|
415
|
+
tokenCount: normalized.tokens.length,
|
|
416
|
+
totalUsd: normalized.totalUsd
|
|
417
|
+
});
|
|
418
|
+
return normalized;
|
|
273
419
|
}
|
|
420
|
+
debugLog(debug, scope, "fetchPortfolio:empty", { address });
|
|
274
421
|
return { tokens: [], totalUsd: 0 };
|
|
275
422
|
},
|
|
423
|
+
async fetchSolanaPortfolio(address) {
|
|
424
|
+
const url = apiUrl(`/portfolio/solana/${address}`);
|
|
425
|
+
debugLog(debug, scope, "fetchSolanaPortfolio:request", { url, address });
|
|
426
|
+
const response = await fetch(url, {
|
|
427
|
+
method: "GET",
|
|
428
|
+
headers: { "Content-Type": "application/json" }
|
|
429
|
+
});
|
|
430
|
+
if (!response.ok) {
|
|
431
|
+
const error = await response.json().catch(() => ({ error: "Unknown error" }));
|
|
432
|
+
debugError(
|
|
433
|
+
debug,
|
|
434
|
+
scope,
|
|
435
|
+
"fetchSolanaPortfolio:failed",
|
|
436
|
+
error,
|
|
437
|
+
{ status: response.status, address }
|
|
438
|
+
);
|
|
439
|
+
throw new Error(
|
|
440
|
+
error.error || `Solana portfolio fetch failed: ${response.status}`
|
|
441
|
+
);
|
|
442
|
+
}
|
|
443
|
+
const data = await response.json();
|
|
444
|
+
const normalized = normalizeDirectPortfolio(data);
|
|
445
|
+
debugLog(debug, scope, "fetchSolanaPortfolio:success", {
|
|
446
|
+
address,
|
|
447
|
+
tokenCount: normalized.tokens.length,
|
|
448
|
+
totalUsd: normalized.totalUsd
|
|
449
|
+
});
|
|
450
|
+
return normalized;
|
|
451
|
+
},
|
|
452
|
+
async checkAccount(address) {
|
|
453
|
+
const url = apiUrl(`/check/${address}`);
|
|
454
|
+
debugLog(debug, scope, "checkAccount:request", { url, address });
|
|
455
|
+
const response = await fetch(url, {
|
|
456
|
+
method: "GET",
|
|
457
|
+
headers: { "Content-Type": "application/json" }
|
|
458
|
+
});
|
|
459
|
+
if (!response.ok) {
|
|
460
|
+
const error = await response.json().catch(() => ({ error: "Unknown error" }));
|
|
461
|
+
debugError(
|
|
462
|
+
debug,
|
|
463
|
+
scope,
|
|
464
|
+
"checkAccount:failed",
|
|
465
|
+
error,
|
|
466
|
+
{ status: response.status, address }
|
|
467
|
+
);
|
|
468
|
+
throw new Error(error.error || `Account check failed: ${response.status}`);
|
|
469
|
+
}
|
|
470
|
+
const data = await response.json();
|
|
471
|
+
const result = {
|
|
472
|
+
isRegistered: data?.isRegistered === true,
|
|
473
|
+
targetChain: data?.targetChain,
|
|
474
|
+
targetToken: data?.targetToken
|
|
475
|
+
};
|
|
476
|
+
debugLog(debug, scope, "checkAccount:success", {
|
|
477
|
+
address,
|
|
478
|
+
isRegistered: result.isRegistered,
|
|
479
|
+
targetChain: result.targetChain,
|
|
480
|
+
targetToken: result.targetToken
|
|
481
|
+
});
|
|
482
|
+
return result;
|
|
483
|
+
},
|
|
276
484
|
async fetchStatus(address, txHash) {
|
|
277
|
-
const
|
|
485
|
+
const normalized = txHash.startsWith("0x") || txHash.startsWith("0X") ? txHash.toLowerCase() : txHash;
|
|
486
|
+
const txHashParam = encodeURIComponent(normalized);
|
|
487
|
+
const url = apiUrl(`/status/${address}?txHash=${txHashParam}`);
|
|
278
488
|
const response = await fetch(
|
|
279
|
-
|
|
489
|
+
url,
|
|
280
490
|
{
|
|
281
491
|
method: "GET",
|
|
282
492
|
headers: { "Content-Type": "application/json" },
|
|
@@ -284,24 +494,53 @@ function createDepositService(baseUrl) {
|
|
|
284
494
|
}
|
|
285
495
|
);
|
|
286
496
|
if (!response.ok) {
|
|
497
|
+
debugLog(debug, scope, "fetchStatus:miss", {
|
|
498
|
+
address,
|
|
499
|
+
txHash: shortRef(normalized),
|
|
500
|
+
status: response.status
|
|
501
|
+
});
|
|
287
502
|
return { lastEvent: void 0 };
|
|
288
503
|
}
|
|
289
|
-
|
|
504
|
+
const result = await response.json();
|
|
505
|
+
debugLog(debug, scope, "fetchStatus:success", {
|
|
506
|
+
address,
|
|
507
|
+
txHash: shortRef(normalized),
|
|
508
|
+
eventType: result?.lastEvent?.type
|
|
509
|
+
});
|
|
510
|
+
return result;
|
|
290
511
|
},
|
|
291
512
|
async fetchLatestStatus(address) {
|
|
292
|
-
const
|
|
513
|
+
const url = apiUrl(`/status/${address}`);
|
|
514
|
+
const response = await fetch(url, {
|
|
293
515
|
method: "GET",
|
|
294
516
|
headers: { "Content-Type": "application/json" },
|
|
295
517
|
cache: "no-store"
|
|
296
518
|
});
|
|
297
519
|
if (!response.ok) {
|
|
520
|
+
debugLog(debug, scope, "fetchLatestStatus:miss", {
|
|
521
|
+
address,
|
|
522
|
+
status: response.status
|
|
523
|
+
});
|
|
298
524
|
return { lastEvent: void 0 };
|
|
299
525
|
}
|
|
300
|
-
|
|
526
|
+
const result = await response.json();
|
|
527
|
+
debugLog(debug, scope, "fetchLatestStatus:success", {
|
|
528
|
+
address,
|
|
529
|
+
eventType: result?.lastEvent?.type
|
|
530
|
+
});
|
|
531
|
+
return result;
|
|
301
532
|
},
|
|
302
533
|
async relayWithdraw(params) {
|
|
303
534
|
const { smartAccount, chainId, safeAddress, safeTransaction, signature } = params;
|
|
304
|
-
const
|
|
535
|
+
const url = apiUrl(`/relay-withdraw`);
|
|
536
|
+
debugLog(debug, scope, "relayWithdraw:request", {
|
|
537
|
+
url,
|
|
538
|
+
smartAccount,
|
|
539
|
+
chainId,
|
|
540
|
+
safeAddress,
|
|
541
|
+
to: safeTransaction.to
|
|
542
|
+
});
|
|
543
|
+
const response = await fetch(url, {
|
|
305
544
|
method: "POST",
|
|
306
545
|
headers: { "Content-Type": "application/json" },
|
|
307
546
|
body: JSON.stringify(
|
|
@@ -327,11 +566,31 @@ function createDepositService(baseUrl) {
|
|
|
327
566
|
});
|
|
328
567
|
if (!response.ok) {
|
|
329
568
|
const error = await response.json().catch(() => ({ error: "Unknown error" }));
|
|
569
|
+
debugError(
|
|
570
|
+
debug,
|
|
571
|
+
scope,
|
|
572
|
+
"relayWithdraw:failed",
|
|
573
|
+
error,
|
|
574
|
+
{
|
|
575
|
+
status: response.status,
|
|
576
|
+
smartAccount,
|
|
577
|
+
chainId,
|
|
578
|
+
safeAddress,
|
|
579
|
+
signature
|
|
580
|
+
}
|
|
581
|
+
);
|
|
330
582
|
throw new Error(
|
|
331
583
|
error.error || `Relay withdraw failed: ${response.status}`
|
|
332
584
|
);
|
|
333
585
|
}
|
|
334
|
-
|
|
586
|
+
const result = await response.json();
|
|
587
|
+
debugLog(debug, scope, "relayWithdraw:success", {
|
|
588
|
+
smartAccount,
|
|
589
|
+
chainId,
|
|
590
|
+
safeAddress,
|
|
591
|
+
txHash: result?.txHash ? shortRef(result.txHash) : void 0
|
|
592
|
+
});
|
|
593
|
+
return result;
|
|
335
594
|
}
|
|
336
595
|
};
|
|
337
596
|
}
|
|
@@ -385,8 +644,10 @@ function normalizeOrchestratorPortfolio(data) {
|
|
|
385
644
|
};
|
|
386
645
|
}
|
|
387
646
|
function normalizeDirectToken(token) {
|
|
388
|
-
const
|
|
389
|
-
|
|
647
|
+
const rawChainId = extractNumber(token, "chainId") ?? extractNumber(token.chain, "id");
|
|
648
|
+
const rawChainString = extractString(token, "chainId") ?? extractString(token.chain, "id");
|
|
649
|
+
const chainId = rawChainId ?? (rawChainString ? isSolanaCaip2(rawChainString) || rawChainString.toLowerCase() === "solana" ? "solana" : parseEvmChainId(rawChainString) : null);
|
|
650
|
+
if (chainId === null) return null;
|
|
390
651
|
const symbol = extractString(token, "symbol") ?? extractString(token, "tokenSymbol") ?? extractString(token, "tokenName") ?? extractString(token, "name");
|
|
391
652
|
if (!symbol) return null;
|
|
392
653
|
const balanceValue = extractString(token, "balance") ?? extractString(token, "amount") ?? extractString(token, "value") ?? extractString(token, "rawBalance") ?? extractNumber(token, "balance")?.toString() ?? extractNumber(token, "amount")?.toString() ?? extractNumber(token, "value")?.toString() ?? extractNumber(token, "rawBalance")?.toString();
|
|
@@ -394,17 +655,17 @@ function normalizeDirectToken(token) {
|
|
|
394
655
|
const address = extractString(token, "address") ?? extractString(token, "tokenAddress") ?? extractString(
|
|
395
656
|
token.token,
|
|
396
657
|
"address"
|
|
397
|
-
) ?? getTokenAddress(symbol, chainId);
|
|
658
|
+
) ?? (typeof chainId === "number" ? getTokenAddress(symbol, chainId) : void 0);
|
|
398
659
|
if (!address) return null;
|
|
399
|
-
const addressAsToken = address;
|
|
400
660
|
const balanceUsd = extractNumber(token, "balanceUsd") ?? extractNumber(token, "usdValue") ?? extractNumber(token, "valueUsd") ?? extractNumericString(token, "balanceUsd") ?? extractNumericString(token, "usdValue") ?? extractNumericString(token, "valueUsd") ?? 0;
|
|
401
|
-
const
|
|
402
|
-
const
|
|
661
|
+
const isSolanaToken = chainId === "solana";
|
|
662
|
+
const registrySymbol = isSolanaToken ? "Token" : getTokenSymbol(address, chainId);
|
|
663
|
+
const resolvedSymbol = isSolanaToken ? symbol : registrySymbol !== "Token" ? registrySymbol : symbol;
|
|
403
664
|
const backendDecimals = extractNumber(token, "decimals") ?? extractNumber(token, "tokenDecimals");
|
|
404
|
-
const resolvedDecimals = registrySymbol !== "Token" ? getTokenDecimalsByAddress(
|
|
665
|
+
const resolvedDecimals = !isSolanaToken && registrySymbol !== "Token" ? getTokenDecimalsByAddress(address, chainId) : backendDecimals ?? 18;
|
|
405
666
|
return {
|
|
406
667
|
chainId,
|
|
407
|
-
address
|
|
668
|
+
address,
|
|
408
669
|
symbol: resolvedSymbol,
|
|
409
670
|
name: resolvedSymbol,
|
|
410
671
|
decimals: resolvedDecimals,
|
|
@@ -443,7 +704,12 @@ function extractNumericString(data, key) {
|
|
|
443
704
|
function getAssetId(asset) {
|
|
444
705
|
return `${asset.chainId}:${asset.token.toLowerCase()}`;
|
|
445
706
|
}
|
|
707
|
+
function isEvmAddress(value) {
|
|
708
|
+
return /^0x[a-fA-F0-9]{40}$/.test(value);
|
|
709
|
+
}
|
|
446
710
|
function portfolioTokenToAsset(token) {
|
|
711
|
+
if (typeof token.chainId !== "number") return null;
|
|
712
|
+
if (!isEvmAddress(token.address)) return null;
|
|
447
713
|
return {
|
|
448
714
|
id: getAssetId({ chainId: token.chainId, token: token.address }),
|
|
449
715
|
chainId: token.chainId,
|
|
@@ -456,7 +722,7 @@ function portfolioTokenToAsset(token) {
|
|
|
456
722
|
};
|
|
457
723
|
}
|
|
458
724
|
function portfolioToAssets(tokens) {
|
|
459
|
-
return tokens.map(portfolioTokenToAsset).sort((a, b) => {
|
|
725
|
+
return tokens.map(portfolioTokenToAsset).filter((token) => token !== null).sort((a, b) => {
|
|
460
726
|
const balanceA = safeBigInt(a.balance);
|
|
461
727
|
const balanceB = safeBigInt(b.balance);
|
|
462
728
|
if (balanceB > balanceA) return 1;
|
|
@@ -499,6 +765,9 @@ function formatUserError(raw) {
|
|
|
499
765
|
if (lower.includes("execution reverted")) {
|
|
500
766
|
return "Transaction would fail on-chain";
|
|
501
767
|
}
|
|
768
|
+
if (lower.includes("recent blockhash") || lower.includes("latest blockhash")) {
|
|
769
|
+
return "Solana RPC unavailable \u2014 please retry";
|
|
770
|
+
}
|
|
502
771
|
if (lower.includes("network") || lower.includes("disconnected")) {
|
|
503
772
|
return "Network error \u2014 check your connection";
|
|
504
773
|
}
|
|
@@ -698,12 +967,13 @@ function ChevronRightIcon() {
|
|
|
698
967
|
import { jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
699
968
|
function rowIcon(kind) {
|
|
700
969
|
if (kind === "connected") return /* @__PURE__ */ jsx5(WalletIcon, {});
|
|
970
|
+
if (kind === "solana") return /* @__PURE__ */ jsx5(ExternalLinkIcon, {});
|
|
701
971
|
return /* @__PURE__ */ jsx5(ExternalLinkIcon, {});
|
|
702
972
|
}
|
|
703
973
|
function ConnectStep({
|
|
704
974
|
walletOptions,
|
|
705
|
-
|
|
706
|
-
|
|
975
|
+
selectedWalletId,
|
|
976
|
+
onSelectWallet,
|
|
707
977
|
onSelectTransferCrypto,
|
|
708
978
|
onRequestConnect,
|
|
709
979
|
onConnect,
|
|
@@ -714,20 +984,23 @@ function ConnectStep({
|
|
|
714
984
|
}) {
|
|
715
985
|
const hasWalletOptions = (walletOptions?.length ?? 0) > 0;
|
|
716
986
|
if (hasWalletOptions) {
|
|
717
|
-
const
|
|
718
|
-
|
|
987
|
+
const hasReownWallet = walletOptions?.some(
|
|
988
|
+
(option) => option.kind === "external" || option.kind === "solana"
|
|
989
|
+
) ?? false;
|
|
990
|
+
const showConnectDifferentWalletOption = Boolean(onConnect) && !hasReownWallet;
|
|
719
991
|
return /* @__PURE__ */ jsxs4("div", { className: "rs-step", children: [
|
|
720
992
|
/* @__PURE__ */ jsxs4("div", { className: "rs-connect-centered rs-connect-centered--wallets", children: [
|
|
721
993
|
/* @__PURE__ */ jsxs4("div", { className: "rs-connect-wallet-list", children: [
|
|
722
994
|
walletOptions?.map((option) => {
|
|
723
|
-
const isSelected = option.
|
|
724
|
-
const
|
|
995
|
+
const isSelected = option.id === selectedWalletId;
|
|
996
|
+
const rawAddress = option.address ?? option.solanaAddress ?? option.id;
|
|
997
|
+
const shortAddress = rawAddress.length > 12 ? `${rawAddress.slice(0, 6)}...${rawAddress.slice(-4)}` : rawAddress;
|
|
725
998
|
return /* @__PURE__ */ jsxs4(
|
|
726
999
|
"button",
|
|
727
1000
|
{
|
|
728
1001
|
type: "button",
|
|
729
1002
|
className: `rs-connect-wallet-row ${isSelected ? "rs-connect-wallet-row--selected" : ""}`,
|
|
730
|
-
onClick: () =>
|
|
1003
|
+
onClick: () => onSelectWallet?.(option.id),
|
|
731
1004
|
children: [
|
|
732
1005
|
/* @__PURE__ */ jsx5(
|
|
733
1006
|
"div",
|
|
@@ -750,7 +1023,7 @@ function ConnectStep({
|
|
|
750
1023
|
/* @__PURE__ */ jsx5("div", { className: "rs-connect-wallet-indicator", children: isSelected ? /* @__PURE__ */ jsx5(CheckIcon, {}) : /* @__PURE__ */ jsx5(ChevronRightIcon, {}) })
|
|
751
1024
|
]
|
|
752
1025
|
},
|
|
753
|
-
|
|
1026
|
+
option.id
|
|
754
1027
|
);
|
|
755
1028
|
}),
|
|
756
1029
|
showConnectDifferentWalletOption && /* @__PURE__ */ jsxs4(
|
|
@@ -786,7 +1059,9 @@ function ConnectStep({
|
|
|
786
1059
|
}
|
|
787
1060
|
)
|
|
788
1061
|
] }),
|
|
789
|
-
(onDisconnect || onConnect) && walletOptions?.some(
|
|
1062
|
+
(onDisconnect || onConnect) && walletOptions?.some(
|
|
1063
|
+
(option) => option.kind === "external" || option.kind === "solana"
|
|
1064
|
+
) && /* @__PURE__ */ jsx5(
|
|
790
1065
|
"button",
|
|
791
1066
|
{
|
|
792
1067
|
type: "button",
|
|
@@ -802,7 +1077,7 @@ function ConnectStep({
|
|
|
802
1077
|
onClick: onContinue,
|
|
803
1078
|
variant: "accent",
|
|
804
1079
|
fullWidth: true,
|
|
805
|
-
disabled: !
|
|
1080
|
+
disabled: !selectedWalletId || !onContinue,
|
|
806
1081
|
children: continueButtonLabel
|
|
807
1082
|
}
|
|
808
1083
|
) })
|
|
@@ -1059,6 +1334,15 @@ function getEventSourceDetails(event) {
|
|
|
1059
1334
|
function isDepositEvent(event) {
|
|
1060
1335
|
return event?.type === "deposit-received" || event?.type === "bridge-started" || event?.type === "bridge-complete" || event?.type === "bridge-failed" || event?.type === "error";
|
|
1061
1336
|
}
|
|
1337
|
+
function isHexString(value) {
|
|
1338
|
+
return value.startsWith("0x") || value.startsWith("0X");
|
|
1339
|
+
}
|
|
1340
|
+
function txRefsMatch(a, b) {
|
|
1341
|
+
if (isHexString(a) && isHexString(b)) {
|
|
1342
|
+
return a.toLowerCase() === b.toLowerCase();
|
|
1343
|
+
}
|
|
1344
|
+
return a === b;
|
|
1345
|
+
}
|
|
1062
1346
|
|
|
1063
1347
|
// src/components/steps/ProcessingStep.tsx
|
|
1064
1348
|
import { Fragment, jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
@@ -1069,15 +1353,32 @@ var PROCESS_TIMEOUT_MS = 10 * 60 * 1e3;
|
|
|
1069
1353
|
function isEventForTx(event, txHash) {
|
|
1070
1354
|
const eventTxHash = getEventTxHash(event);
|
|
1071
1355
|
if (!eventTxHash) return false;
|
|
1072
|
-
return eventTxHash
|
|
1356
|
+
return txRefsMatch(eventTxHash, txHash);
|
|
1073
1357
|
}
|
|
1074
1358
|
function formatBridgeFailedMessage(event) {
|
|
1075
1359
|
const eventData = event?.data ?? {};
|
|
1076
1360
|
const code = typeof eventData.errorCode === "string" ? eventData.errorCode : void 0;
|
|
1077
1361
|
const backendMessage = typeof eventData.message === "string" ? eventData.message.trim() : "";
|
|
1362
|
+
function toUserFacingFailure(raw) {
|
|
1363
|
+
const lower = raw.toLowerCase();
|
|
1364
|
+
if (lower.includes("insufficient funds")) {
|
|
1365
|
+
return "Deposit was received, but processing could not continue due to insufficient funds. Please retry.";
|
|
1366
|
+
}
|
|
1367
|
+
if (lower.includes("no valid quote available")) {
|
|
1368
|
+
return "No bridge route is currently available for this transfer. Please try again shortly.";
|
|
1369
|
+
}
|
|
1370
|
+
if (lower.includes("simulation failed")) {
|
|
1371
|
+
return "Transfer processing failed during simulation. Please retry.";
|
|
1372
|
+
}
|
|
1373
|
+
if (raw.length > 220) {
|
|
1374
|
+
return "Transfer processing failed. Please retry.";
|
|
1375
|
+
}
|
|
1376
|
+
return raw;
|
|
1377
|
+
}
|
|
1078
1378
|
if (backendMessage.length > 0) {
|
|
1379
|
+
const userMessage = toUserFacingFailure(backendMessage);
|
|
1079
1380
|
return {
|
|
1080
|
-
message:
|
|
1381
|
+
message: userMessage,
|
|
1081
1382
|
code
|
|
1082
1383
|
};
|
|
1083
1384
|
}
|
|
@@ -1093,6 +1394,8 @@ function ProcessingStep({
|
|
|
1093
1394
|
sourceToken,
|
|
1094
1395
|
targetChain,
|
|
1095
1396
|
amount,
|
|
1397
|
+
sourceSymbol: providedSourceSymbol,
|
|
1398
|
+
sourceDecimals: providedSourceDecimals,
|
|
1096
1399
|
waitForFinalTx,
|
|
1097
1400
|
service,
|
|
1098
1401
|
directTransfer,
|
|
@@ -1112,10 +1415,14 @@ function ProcessingStep({
|
|
|
1112
1415
|
const intervalRef = useRef2(null);
|
|
1113
1416
|
useEffect2(() => {
|
|
1114
1417
|
if (directTransfer) {
|
|
1418
|
+
debugLog(debug, "processing", "direct-transfer:complete", {
|
|
1419
|
+
txHash,
|
|
1420
|
+
flowLabel
|
|
1421
|
+
});
|
|
1115
1422
|
onDepositComplete?.(txHash);
|
|
1116
1423
|
return;
|
|
1117
1424
|
}
|
|
1118
|
-
}, [directTransfer, txHash, onDepositComplete]);
|
|
1425
|
+
}, [debug, directTransfer, flowLabel, txHash, onDepositComplete]);
|
|
1119
1426
|
useEffect2(() => {
|
|
1120
1427
|
if (directTransfer) return;
|
|
1121
1428
|
startTimeRef.current = Date.now();
|
|
@@ -1146,28 +1453,41 @@ function ProcessingStep({
|
|
|
1146
1453
|
let isMounted = true;
|
|
1147
1454
|
async function pollStatus() {
|
|
1148
1455
|
try {
|
|
1456
|
+
debugLog(debug, "processing", "poll:request", {
|
|
1457
|
+
smartAccount,
|
|
1458
|
+
txHash,
|
|
1459
|
+
intervalMs: pollIntervalRef.current
|
|
1460
|
+
});
|
|
1149
1461
|
const data = await service.fetchStatus(smartAccount, txHash);
|
|
1150
1462
|
const lastEvent2 = data.lastEvent;
|
|
1151
1463
|
const eventMatchesTx = isEventForTx(lastEvent2, txHash);
|
|
1152
1464
|
const eventForCurrentTx = eventMatchesTx ? lastEvent2 : void 0;
|
|
1153
|
-
if (
|
|
1465
|
+
if (lastEvent2) {
|
|
1154
1466
|
const eventData = lastEvent2.data;
|
|
1155
|
-
|
|
1467
|
+
debugLog(debug, "processing", "poll:event", {
|
|
1156
1468
|
type: lastEvent2.type,
|
|
1157
1469
|
matchesTx: eventMatchesTx,
|
|
1158
|
-
intentId: eventData?.intentId
|
|
1159
|
-
data: eventData
|
|
1470
|
+
intentId: eventData?.intentId
|
|
1160
1471
|
});
|
|
1161
1472
|
}
|
|
1162
1473
|
if (!isMounted) return;
|
|
1163
1474
|
if (eventForCurrentTx?.type === "bridge-complete") {
|
|
1164
1475
|
setState({ type: "complete", lastEvent: eventForCurrentTx });
|
|
1165
1476
|
const destinationTxHash2 = eventForCurrentTx.data?.destination?.transactionHash;
|
|
1477
|
+
debugLog(debug, "processing", "state:complete", {
|
|
1478
|
+
txHash,
|
|
1479
|
+
destinationTxHash: destinationTxHash2,
|
|
1480
|
+
event: eventForCurrentTx.type
|
|
1481
|
+
});
|
|
1166
1482
|
onDepositComplete?.(txHash, destinationTxHash2);
|
|
1167
1483
|
return;
|
|
1168
1484
|
}
|
|
1169
1485
|
if (!waitForFinalTx && eventForCurrentTx?.type === "bridge-started") {
|
|
1170
1486
|
setState({ type: "complete", lastEvent: eventForCurrentTx });
|
|
1487
|
+
debugLog(debug, "processing", "state:early-complete", {
|
|
1488
|
+
txHash,
|
|
1489
|
+
event: eventForCurrentTx.type
|
|
1490
|
+
});
|
|
1171
1491
|
onDepositComplete?.(txHash);
|
|
1172
1492
|
return;
|
|
1173
1493
|
}
|
|
@@ -1178,6 +1498,11 @@ function ProcessingStep({
|
|
|
1178
1498
|
message: formatted.message,
|
|
1179
1499
|
lastEvent: eventForCurrentTx
|
|
1180
1500
|
});
|
|
1501
|
+
debugLog(debug, "processing", "state:failed", {
|
|
1502
|
+
txHash,
|
|
1503
|
+
message: formatted.message,
|
|
1504
|
+
code: formatted.code
|
|
1505
|
+
});
|
|
1181
1506
|
onDepositFailed?.(txHash, formatted.message);
|
|
1182
1507
|
return;
|
|
1183
1508
|
}
|
|
@@ -1188,12 +1513,21 @@ function ProcessingStep({
|
|
|
1188
1513
|
message: errorMessage,
|
|
1189
1514
|
lastEvent: eventForCurrentTx
|
|
1190
1515
|
});
|
|
1516
|
+
debugLog(debug, "processing", "state:error-event", {
|
|
1517
|
+
txHash,
|
|
1518
|
+
message: errorMessage
|
|
1519
|
+
});
|
|
1191
1520
|
onDepositFailed?.(txHash, errorMessage);
|
|
1192
1521
|
return;
|
|
1193
1522
|
}
|
|
1194
1523
|
setState({ type: "processing", lastEvent: eventForCurrentTx });
|
|
1195
1524
|
scheduleNextPoll();
|
|
1196
|
-
} catch {
|
|
1525
|
+
} catch (error) {
|
|
1526
|
+
debugError(debug, "processing", "poll:failure", error, {
|
|
1527
|
+
smartAccount,
|
|
1528
|
+
txHash,
|
|
1529
|
+
intervalMs: pollIntervalRef.current
|
|
1530
|
+
});
|
|
1197
1531
|
scheduleNextPoll();
|
|
1198
1532
|
}
|
|
1199
1533
|
}
|
|
@@ -1204,6 +1538,9 @@ function ProcessingStep({
|
|
|
1204
1538
|
pollIntervalRef.current * BACKOFF_MULTIPLIER,
|
|
1205
1539
|
MAX_POLL_INTERVAL
|
|
1206
1540
|
);
|
|
1541
|
+
debugLog(debug, "processing", "poll:scheduled", {
|
|
1542
|
+
nextIntervalMs: pollIntervalRef.current
|
|
1543
|
+
});
|
|
1207
1544
|
pollStatus();
|
|
1208
1545
|
}, pollIntervalRef.current);
|
|
1209
1546
|
}
|
|
@@ -1215,6 +1552,7 @@ function ProcessingStep({
|
|
|
1215
1552
|
}
|
|
1216
1553
|
};
|
|
1217
1554
|
}, [
|
|
1555
|
+
debug,
|
|
1218
1556
|
directTransfer,
|
|
1219
1557
|
state.type,
|
|
1220
1558
|
smartAccount,
|
|
@@ -1235,6 +1573,10 @@ function ProcessingStep({
|
|
|
1235
1573
|
}
|
|
1236
1574
|
processTimeoutRef.current = setTimeout(() => {
|
|
1237
1575
|
const message = "We couldn't confirm your transfer. Please contact support if funds do not arrive.";
|
|
1576
|
+
debugLog(debug, "processing", "state:timeout", {
|
|
1577
|
+
txHash,
|
|
1578
|
+
timeoutMs: PROCESS_TIMEOUT_MS
|
|
1579
|
+
});
|
|
1238
1580
|
setState({ type: "error", message });
|
|
1239
1581
|
onError?.(message, "PROCESS_TIMEOUT");
|
|
1240
1582
|
}, PROCESS_TIMEOUT_MS);
|
|
@@ -1244,7 +1586,7 @@ function ProcessingStep({
|
|
|
1244
1586
|
processTimeoutRef.current = null;
|
|
1245
1587
|
}
|
|
1246
1588
|
};
|
|
1247
|
-
}, [directTransfer, state.type, onError]);
|
|
1589
|
+
}, [debug, directTransfer, state.type, txHash, onError]);
|
|
1248
1590
|
const isError = state.type === "error" || state.type === "failed";
|
|
1249
1591
|
const isComplete = state.type === "complete";
|
|
1250
1592
|
const isProcessing = state.type === "processing";
|
|
@@ -1266,11 +1608,9 @@ function ProcessingStep({
|
|
|
1266
1608
|
const secs = seconds % 60;
|
|
1267
1609
|
return `${mins}m ${secs}s`;
|
|
1268
1610
|
};
|
|
1269
|
-
const
|
|
1270
|
-
const
|
|
1271
|
-
|
|
1272
|
-
displaySourceChain
|
|
1273
|
-
);
|
|
1611
|
+
const isEvmSourceToken = /^0x[a-fA-F0-9]{40}$/.test(displaySourceToken);
|
|
1612
|
+
const sourceSymbol = displaySourceChain === "solana" ? providedSourceSymbol ?? "SOL" : isEvmSourceToken ? getTokenSymbol(displaySourceToken, displaySourceChain) : providedSourceSymbol ?? "Token";
|
|
1613
|
+
const sourceDecimals = displaySourceChain === "solana" ? providedSourceDecimals ?? 9 : isEvmSourceToken ? getTokenDecimalsByAddress(displaySourceToken, displaySourceChain) : providedSourceDecimals ?? 18;
|
|
1274
1614
|
const formattedReceivedAmount = (() => {
|
|
1275
1615
|
try {
|
|
1276
1616
|
const raw = formatUnits(BigInt(displayAmount), sourceDecimals);
|
|
@@ -1645,6 +1985,9 @@ export {
|
|
|
1645
1985
|
Spinner,
|
|
1646
1986
|
Button,
|
|
1647
1987
|
ConnectStep,
|
|
1988
|
+
debugLog,
|
|
1989
|
+
debugError,
|
|
1990
|
+
toEvmCaip2,
|
|
1648
1991
|
buildSessionDetails,
|
|
1649
1992
|
createDepositService,
|
|
1650
1993
|
getAssetId,
|
|
@@ -1659,8 +2002,8 @@ export {
|
|
|
1659
2002
|
tokenFormatter,
|
|
1660
2003
|
formatUserError,
|
|
1661
2004
|
getEventTxHash,
|
|
1662
|
-
getEventSourceDetails,
|
|
1663
2005
|
isDepositEvent,
|
|
2006
|
+
txRefsMatch,
|
|
1664
2007
|
ProcessingStep,
|
|
1665
2008
|
getPublicClient,
|
|
1666
2009
|
applyTheme
|