@swype-org/react-sdk 0.1.132 → 0.1.142
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/dist/index.cjs +1227 -919
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +4 -5
- package/dist/index.d.ts +4 -5
- package/dist/index.js +1228 -920
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -156,261 +156,6 @@ function useSwypeDepositAmount() {
|
|
|
156
156
|
};
|
|
157
157
|
}
|
|
158
158
|
|
|
159
|
-
// src/api.ts
|
|
160
|
-
var api_exports = {};
|
|
161
|
-
__export(api_exports, {
|
|
162
|
-
createAccount: () => createAccount,
|
|
163
|
-
createAccountAuthorizationSession: () => createAccountAuthorizationSession,
|
|
164
|
-
createTransfer: () => createTransfer,
|
|
165
|
-
fetchAccount: () => fetchAccount,
|
|
166
|
-
fetchAccounts: () => fetchAccounts,
|
|
167
|
-
fetchAuthorizationSession: () => fetchAuthorizationSession,
|
|
168
|
-
fetchChains: () => fetchChains,
|
|
169
|
-
fetchMerchantPublicKey: () => fetchMerchantPublicKey,
|
|
170
|
-
fetchProviders: () => fetchProviders,
|
|
171
|
-
fetchTransfer: () => fetchTransfer,
|
|
172
|
-
fetchUserConfig: () => fetchUserConfig,
|
|
173
|
-
registerPasskey: () => registerPasskey,
|
|
174
|
-
reportActionCompletion: () => reportActionCompletion,
|
|
175
|
-
reportPasskeyActivity: () => reportPasskeyActivity,
|
|
176
|
-
signTransfer: () => signTransfer,
|
|
177
|
-
updateUserConfig: () => updateUserConfig,
|
|
178
|
-
updateUserConfigBySession: () => updateUserConfigBySession
|
|
179
|
-
});
|
|
180
|
-
async function throwApiError(res) {
|
|
181
|
-
const body = await res.json().catch(() => null);
|
|
182
|
-
const detail = body?.error ?? body;
|
|
183
|
-
const msg = detail?.message ?? res.statusText;
|
|
184
|
-
const code = detail?.code ?? String(res.status);
|
|
185
|
-
throw new Error(`${res.status} \u2014 ${code}: ${msg}`);
|
|
186
|
-
}
|
|
187
|
-
async function fetchProviders(apiBaseUrl, token) {
|
|
188
|
-
const res = await fetch(`${apiBaseUrl}/v1/providers`, {
|
|
189
|
-
headers: { Authorization: `Bearer ${token}` }
|
|
190
|
-
});
|
|
191
|
-
if (!res.ok) await throwApiError(res);
|
|
192
|
-
const data = await res.json();
|
|
193
|
-
return data.items;
|
|
194
|
-
}
|
|
195
|
-
async function fetchChains(apiBaseUrl, token) {
|
|
196
|
-
const res = await fetch(`${apiBaseUrl}/v1/chains`, {
|
|
197
|
-
headers: { Authorization: `Bearer ${token}` }
|
|
198
|
-
});
|
|
199
|
-
if (!res.ok) await throwApiError(res);
|
|
200
|
-
const data = await res.json();
|
|
201
|
-
return data.items;
|
|
202
|
-
}
|
|
203
|
-
async function fetchAccounts(apiBaseUrl, token, credentialId) {
|
|
204
|
-
const params = new URLSearchParams({ credentialId });
|
|
205
|
-
const res = await fetch(`${apiBaseUrl}/v1/accounts?${params.toString()}`, {
|
|
206
|
-
headers: { Authorization: `Bearer ${token}` }
|
|
207
|
-
});
|
|
208
|
-
if (!res.ok) await throwApiError(res);
|
|
209
|
-
const data = await res.json();
|
|
210
|
-
return data.items;
|
|
211
|
-
}
|
|
212
|
-
async function fetchAccount(apiBaseUrl, token, accountId, credentialId) {
|
|
213
|
-
const params = new URLSearchParams({ credentialId });
|
|
214
|
-
const res = await fetch(`${apiBaseUrl}/v1/accounts/${accountId}?${params.toString()}`, {
|
|
215
|
-
headers: { Authorization: `Bearer ${token}` }
|
|
216
|
-
});
|
|
217
|
-
if (!res.ok) await throwApiError(res);
|
|
218
|
-
return await res.json();
|
|
219
|
-
}
|
|
220
|
-
async function createAccount(apiBaseUrl, token, params) {
|
|
221
|
-
const body = {
|
|
222
|
-
id: params.id ?? crypto.randomUUID(),
|
|
223
|
-
name: params.name,
|
|
224
|
-
credentialId: params.credentialId,
|
|
225
|
-
providerId: params.providerId
|
|
226
|
-
};
|
|
227
|
-
if (params.nickname) {
|
|
228
|
-
body.nickname = params.nickname;
|
|
229
|
-
}
|
|
230
|
-
const res = await fetch(`${apiBaseUrl}/v1/accounts`, {
|
|
231
|
-
method: "POST",
|
|
232
|
-
headers: {
|
|
233
|
-
"Content-Type": "application/json",
|
|
234
|
-
Authorization: `Bearer ${token}`
|
|
235
|
-
},
|
|
236
|
-
body: JSON.stringify(body)
|
|
237
|
-
});
|
|
238
|
-
if (!res.ok) await throwApiError(res);
|
|
239
|
-
return await res.json();
|
|
240
|
-
}
|
|
241
|
-
async function createAccountAuthorizationSession(apiBaseUrl, token, accountId, credentialId, options) {
|
|
242
|
-
const body = { credentialId };
|
|
243
|
-
if (options?.tokenAddress) body.tokenAddress = options.tokenAddress;
|
|
244
|
-
if (options?.chainId != null) body.chainId = options.chainId;
|
|
245
|
-
const res = await fetch(
|
|
246
|
-
`${apiBaseUrl}/v1/accounts/${accountId}/authorization-sessions`,
|
|
247
|
-
{
|
|
248
|
-
method: "POST",
|
|
249
|
-
headers: {
|
|
250
|
-
"Content-Type": "application/json",
|
|
251
|
-
Authorization: `Bearer ${token}`
|
|
252
|
-
},
|
|
253
|
-
body: JSON.stringify(body)
|
|
254
|
-
}
|
|
255
|
-
);
|
|
256
|
-
if (!res.ok) await throwApiError(res);
|
|
257
|
-
return await res.json();
|
|
258
|
-
}
|
|
259
|
-
async function createTransfer(apiBaseUrl, token, params) {
|
|
260
|
-
if (!params.merchantAuthorization) {
|
|
261
|
-
throw new Error("merchantAuthorization is required for transfer creation.");
|
|
262
|
-
}
|
|
263
|
-
const body = {
|
|
264
|
-
id: params.id ?? crypto.randomUUID(),
|
|
265
|
-
credentialId: params.credentialId,
|
|
266
|
-
merchantAuthorization: params.merchantAuthorization,
|
|
267
|
-
sources: [{ [params.sourceType]: params.sourceId }],
|
|
268
|
-
destinations: [
|
|
269
|
-
{
|
|
270
|
-
chainId: params.destination.chainId,
|
|
271
|
-
token: { address: params.destination.token.address },
|
|
272
|
-
address: params.destination.address
|
|
273
|
-
}
|
|
274
|
-
],
|
|
275
|
-
amount: {
|
|
276
|
-
amount: params.amount,
|
|
277
|
-
currency: params.currency ?? "USD"
|
|
278
|
-
}
|
|
279
|
-
};
|
|
280
|
-
const res = await fetch(`${apiBaseUrl}/v1/transfers`, {
|
|
281
|
-
method: "POST",
|
|
282
|
-
headers: {
|
|
283
|
-
"Content-Type": "application/json",
|
|
284
|
-
Authorization: `Bearer ${token}`
|
|
285
|
-
},
|
|
286
|
-
body: JSON.stringify(body)
|
|
287
|
-
});
|
|
288
|
-
if (!res.ok) await throwApiError(res);
|
|
289
|
-
return await res.json();
|
|
290
|
-
}
|
|
291
|
-
async function fetchMerchantPublicKey(apiBaseUrl, merchantId) {
|
|
292
|
-
const res = await fetch(
|
|
293
|
-
`${apiBaseUrl}/v1/merchants/${encodeURIComponent(merchantId)}/public-key`
|
|
294
|
-
);
|
|
295
|
-
if (!res.ok) await throwApiError(res);
|
|
296
|
-
return await res.json();
|
|
297
|
-
}
|
|
298
|
-
async function fetchTransfer(apiBaseUrl, token, transferId, authorizationSessionToken) {
|
|
299
|
-
if (!token && !authorizationSessionToken) {
|
|
300
|
-
throw new Error("Missing auth credentials for transfer fetch.");
|
|
301
|
-
}
|
|
302
|
-
const res = await fetch(`${apiBaseUrl}/v1/transfers/${transferId}`, {
|
|
303
|
-
headers: {
|
|
304
|
-
...token ? { Authorization: `Bearer ${token}` } : {},
|
|
305
|
-
...authorizationSessionToken ? { "x-authorization-session-token": authorizationSessionToken } : {}
|
|
306
|
-
}
|
|
307
|
-
});
|
|
308
|
-
if (!res.ok) await throwApiError(res);
|
|
309
|
-
return await res.json();
|
|
310
|
-
}
|
|
311
|
-
async function signTransfer(apiBaseUrl, token, transferId, signedUserOp, authorizationSessionToken) {
|
|
312
|
-
if (!token && !authorizationSessionToken) {
|
|
313
|
-
throw new Error("Missing auth credentials for transfer signing.");
|
|
314
|
-
}
|
|
315
|
-
const res = await fetch(`${apiBaseUrl}/v1/transfers/${transferId}`, {
|
|
316
|
-
method: "PATCH",
|
|
317
|
-
headers: {
|
|
318
|
-
"Content-Type": "application/json",
|
|
319
|
-
...token ? { Authorization: `Bearer ${token}` } : {},
|
|
320
|
-
...authorizationSessionToken ? { "x-authorization-session-token": authorizationSessionToken } : {}
|
|
321
|
-
},
|
|
322
|
-
body: JSON.stringify({ signedUserOp })
|
|
323
|
-
});
|
|
324
|
-
if (!res.ok) await throwApiError(res);
|
|
325
|
-
return await res.json();
|
|
326
|
-
}
|
|
327
|
-
async function fetchAuthorizationSession(apiBaseUrl, sessionId) {
|
|
328
|
-
const res = await fetch(
|
|
329
|
-
`${apiBaseUrl}/v1/authorization-sessions/${sessionId}`
|
|
330
|
-
);
|
|
331
|
-
if (!res.ok) await throwApiError(res);
|
|
332
|
-
return await res.json();
|
|
333
|
-
}
|
|
334
|
-
async function registerPasskey(apiBaseUrl, token, credentialId, publicKey) {
|
|
335
|
-
const res = await fetch(`${apiBaseUrl}/v1/users/config/passkey`, {
|
|
336
|
-
method: "POST",
|
|
337
|
-
headers: {
|
|
338
|
-
"Content-Type": "application/json",
|
|
339
|
-
Authorization: `Bearer ${token}`
|
|
340
|
-
},
|
|
341
|
-
body: JSON.stringify({ credentialId, publicKey })
|
|
342
|
-
});
|
|
343
|
-
if (!res.ok) await throwApiError(res);
|
|
344
|
-
}
|
|
345
|
-
async function reportPasskeyActivity(apiBaseUrl, token, credentialId) {
|
|
346
|
-
const res = await fetch(`${apiBaseUrl}/v1/users/config/passkey`, {
|
|
347
|
-
method: "PATCH",
|
|
348
|
-
headers: {
|
|
349
|
-
"Content-Type": "application/json",
|
|
350
|
-
Authorization: `Bearer ${token}`
|
|
351
|
-
},
|
|
352
|
-
body: JSON.stringify({ credentialId })
|
|
353
|
-
});
|
|
354
|
-
if (!res.ok) await throwApiError(res);
|
|
355
|
-
}
|
|
356
|
-
async function fetchUserConfig(apiBaseUrl, token) {
|
|
357
|
-
const res = await fetch(`${apiBaseUrl}/v1/users/config`, {
|
|
358
|
-
headers: { Authorization: `Bearer ${token}` }
|
|
359
|
-
});
|
|
360
|
-
if (!res.ok) await throwApiError(res);
|
|
361
|
-
return await res.json();
|
|
362
|
-
}
|
|
363
|
-
async function updateUserConfig(apiBaseUrl, token, config) {
|
|
364
|
-
const res = await fetch(`${apiBaseUrl}/v1/users`, {
|
|
365
|
-
method: "PATCH",
|
|
366
|
-
headers: {
|
|
367
|
-
"Content-Type": "application/json",
|
|
368
|
-
Authorization: `Bearer ${token}`
|
|
369
|
-
},
|
|
370
|
-
body: JSON.stringify({ config })
|
|
371
|
-
});
|
|
372
|
-
if (!res.ok) await throwApiError(res);
|
|
373
|
-
}
|
|
374
|
-
async function updateUserConfigBySession(apiBaseUrl, sessionId, config) {
|
|
375
|
-
const res = await fetch(
|
|
376
|
-
`${apiBaseUrl}/v1/authorization-sessions/${sessionId}/user-config`,
|
|
377
|
-
{
|
|
378
|
-
method: "PATCH",
|
|
379
|
-
headers: { "Content-Type": "application/json" },
|
|
380
|
-
body: JSON.stringify({ config })
|
|
381
|
-
}
|
|
382
|
-
);
|
|
383
|
-
if (!res.ok) await throwApiError(res);
|
|
384
|
-
}
|
|
385
|
-
async function reportActionCompletion(apiBaseUrl, actionId, result) {
|
|
386
|
-
const res = await fetch(
|
|
387
|
-
`${apiBaseUrl}/v1/authorization-actions/${actionId}`,
|
|
388
|
-
{
|
|
389
|
-
method: "PATCH",
|
|
390
|
-
headers: { "Content-Type": "application/json" },
|
|
391
|
-
body: JSON.stringify({ status: "COMPLETED", result })
|
|
392
|
-
}
|
|
393
|
-
);
|
|
394
|
-
if (!res.ok) await throwApiError(res);
|
|
395
|
-
return await res.json();
|
|
396
|
-
}
|
|
397
|
-
|
|
398
|
-
// src/sentry.ts
|
|
399
|
-
var _mod;
|
|
400
|
-
function captureException(error) {
|
|
401
|
-
if (_mod === null) return;
|
|
402
|
-
if (_mod) {
|
|
403
|
-
_mod.captureException(error);
|
|
404
|
-
return;
|
|
405
|
-
}
|
|
406
|
-
import('@sentry/react').then((m) => {
|
|
407
|
-
_mod = m;
|
|
408
|
-
m.captureException(error);
|
|
409
|
-
}).catch(() => {
|
|
410
|
-
_mod = null;
|
|
411
|
-
});
|
|
412
|
-
}
|
|
413
|
-
|
|
414
159
|
// node_modules/@wagmi/core/dist/esm/version.js
|
|
415
160
|
var version = "2.22.1";
|
|
416
161
|
|
|
@@ -671,8 +416,250 @@ async function getWalletClient(config, parameters = {}) {
|
|
|
671
416
|
return client.extend(viem.walletActions);
|
|
672
417
|
}
|
|
673
418
|
|
|
674
|
-
// src/
|
|
675
|
-
|
|
419
|
+
// src/api.ts
|
|
420
|
+
var api_exports = {};
|
|
421
|
+
__export(api_exports, {
|
|
422
|
+
createAccount: () => createAccount,
|
|
423
|
+
createAccountAuthorizationSession: () => createAccountAuthorizationSession,
|
|
424
|
+
createTransfer: () => createTransfer,
|
|
425
|
+
fetchAccount: () => fetchAccount,
|
|
426
|
+
fetchAccounts: () => fetchAccounts,
|
|
427
|
+
fetchAuthorizationSession: () => fetchAuthorizationSession,
|
|
428
|
+
fetchChains: () => fetchChains,
|
|
429
|
+
fetchMerchantPublicKey: () => fetchMerchantPublicKey,
|
|
430
|
+
fetchProviders: () => fetchProviders,
|
|
431
|
+
fetchTransfer: () => fetchTransfer,
|
|
432
|
+
fetchUserConfig: () => fetchUserConfig,
|
|
433
|
+
registerPasskey: () => registerPasskey,
|
|
434
|
+
reportActionCompletion: () => reportActionCompletion,
|
|
435
|
+
reportPasskeyActivity: () => reportPasskeyActivity,
|
|
436
|
+
signTransfer: () => signTransfer,
|
|
437
|
+
updateUserConfig: () => updateUserConfig,
|
|
438
|
+
updateUserConfigBySession: () => updateUserConfigBySession
|
|
439
|
+
});
|
|
440
|
+
async function throwApiError(res) {
|
|
441
|
+
const body = await res.json().catch(() => null);
|
|
442
|
+
const detail = body?.error ?? body;
|
|
443
|
+
const msg = detail?.message ?? res.statusText;
|
|
444
|
+
const code = detail?.code ?? String(res.status);
|
|
445
|
+
throw new Error(`${res.status} \u2014 ${code}: ${msg}`);
|
|
446
|
+
}
|
|
447
|
+
async function fetchProviders(apiBaseUrl, token) {
|
|
448
|
+
const res = await fetch(`${apiBaseUrl}/v1/providers`, {
|
|
449
|
+
headers: { Authorization: `Bearer ${token}` }
|
|
450
|
+
});
|
|
451
|
+
if (!res.ok) await throwApiError(res);
|
|
452
|
+
const data = await res.json();
|
|
453
|
+
return data.items;
|
|
454
|
+
}
|
|
455
|
+
async function fetchChains(apiBaseUrl, token) {
|
|
456
|
+
const res = await fetch(`${apiBaseUrl}/v1/chains`, {
|
|
457
|
+
headers: { Authorization: `Bearer ${token}` }
|
|
458
|
+
});
|
|
459
|
+
if (!res.ok) await throwApiError(res);
|
|
460
|
+
const data = await res.json();
|
|
461
|
+
return data.items;
|
|
462
|
+
}
|
|
463
|
+
async function fetchAccounts(apiBaseUrl, token, credentialId) {
|
|
464
|
+
const params = new URLSearchParams({ credentialId });
|
|
465
|
+
const res = await fetch(`${apiBaseUrl}/v1/accounts?${params.toString()}`, {
|
|
466
|
+
headers: { Authorization: `Bearer ${token}` }
|
|
467
|
+
});
|
|
468
|
+
if (!res.ok) await throwApiError(res);
|
|
469
|
+
const data = await res.json();
|
|
470
|
+
return data.items;
|
|
471
|
+
}
|
|
472
|
+
async function fetchAccount(apiBaseUrl, token, accountId, credentialId) {
|
|
473
|
+
const params = new URLSearchParams({ credentialId });
|
|
474
|
+
const res = await fetch(`${apiBaseUrl}/v1/accounts/${accountId}?${params.toString()}`, {
|
|
475
|
+
headers: { Authorization: `Bearer ${token}` }
|
|
476
|
+
});
|
|
477
|
+
if (!res.ok) await throwApiError(res);
|
|
478
|
+
return await res.json();
|
|
479
|
+
}
|
|
480
|
+
async function createAccount(apiBaseUrl, token, params) {
|
|
481
|
+
const body = {
|
|
482
|
+
id: params.id ?? crypto.randomUUID(),
|
|
483
|
+
name: params.name,
|
|
484
|
+
credentialId: params.credentialId,
|
|
485
|
+
providerId: params.providerId
|
|
486
|
+
};
|
|
487
|
+
if (params.nickname) {
|
|
488
|
+
body.nickname = params.nickname;
|
|
489
|
+
}
|
|
490
|
+
const res = await fetch(`${apiBaseUrl}/v1/accounts`, {
|
|
491
|
+
method: "POST",
|
|
492
|
+
headers: {
|
|
493
|
+
"Content-Type": "application/json",
|
|
494
|
+
Authorization: `Bearer ${token}`
|
|
495
|
+
},
|
|
496
|
+
body: JSON.stringify(body)
|
|
497
|
+
});
|
|
498
|
+
if (!res.ok) await throwApiError(res);
|
|
499
|
+
return await res.json();
|
|
500
|
+
}
|
|
501
|
+
async function createAccountAuthorizationSession(apiBaseUrl, token, accountId, credentialId, options) {
|
|
502
|
+
const body = { credentialId };
|
|
503
|
+
if (options?.tokenAddress) body.tokenAddress = options.tokenAddress;
|
|
504
|
+
if (options?.chainId != null) body.chainId = options.chainId;
|
|
505
|
+
const res = await fetch(
|
|
506
|
+
`${apiBaseUrl}/v1/accounts/${accountId}/authorization-sessions`,
|
|
507
|
+
{
|
|
508
|
+
method: "POST",
|
|
509
|
+
headers: {
|
|
510
|
+
"Content-Type": "application/json",
|
|
511
|
+
Authorization: `Bearer ${token}`
|
|
512
|
+
},
|
|
513
|
+
body: JSON.stringify(body)
|
|
514
|
+
}
|
|
515
|
+
);
|
|
516
|
+
if (!res.ok) await throwApiError(res);
|
|
517
|
+
return await res.json();
|
|
518
|
+
}
|
|
519
|
+
async function createTransfer(apiBaseUrl, token, params) {
|
|
520
|
+
if (!params.merchantAuthorization) {
|
|
521
|
+
throw new Error("merchantAuthorization is required for transfer creation.");
|
|
522
|
+
}
|
|
523
|
+
const body = {
|
|
524
|
+
id: params.id ?? crypto.randomUUID(),
|
|
525
|
+
credentialId: params.credentialId,
|
|
526
|
+
merchantAuthorization: params.merchantAuthorization,
|
|
527
|
+
sources: [{
|
|
528
|
+
[params.sourceType]: params.sourceId,
|
|
529
|
+
...params.sourceTokenAddress ? { tokenAddress: params.sourceTokenAddress } : {}
|
|
530
|
+
}],
|
|
531
|
+
destinations: [
|
|
532
|
+
{
|
|
533
|
+
chainId: params.destination.chainId,
|
|
534
|
+
token: { address: params.destination.token.address },
|
|
535
|
+
address: params.destination.address
|
|
536
|
+
}
|
|
537
|
+
],
|
|
538
|
+
amount: {
|
|
539
|
+
amount: params.amount,
|
|
540
|
+
currency: params.currency ?? "USD"
|
|
541
|
+
}
|
|
542
|
+
};
|
|
543
|
+
const res = await fetch(`${apiBaseUrl}/v1/transfers`, {
|
|
544
|
+
method: "POST",
|
|
545
|
+
headers: {
|
|
546
|
+
"Content-Type": "application/json",
|
|
547
|
+
Authorization: `Bearer ${token}`
|
|
548
|
+
},
|
|
549
|
+
body: JSON.stringify(body)
|
|
550
|
+
});
|
|
551
|
+
if (!res.ok) await throwApiError(res);
|
|
552
|
+
return await res.json();
|
|
553
|
+
}
|
|
554
|
+
async function fetchMerchantPublicKey(apiBaseUrl, merchantId) {
|
|
555
|
+
const res = await fetch(
|
|
556
|
+
`${apiBaseUrl}/v1/merchants/${encodeURIComponent(merchantId)}/public-key`
|
|
557
|
+
);
|
|
558
|
+
if (!res.ok) await throwApiError(res);
|
|
559
|
+
return await res.json();
|
|
560
|
+
}
|
|
561
|
+
async function fetchTransfer(apiBaseUrl, token, transferId, authorizationSessionToken) {
|
|
562
|
+
if (!token && !authorizationSessionToken) {
|
|
563
|
+
throw new Error("Missing auth credentials for transfer fetch.");
|
|
564
|
+
}
|
|
565
|
+
const res = await fetch(`${apiBaseUrl}/v1/transfers/${transferId}`, {
|
|
566
|
+
headers: {
|
|
567
|
+
...token ? { Authorization: `Bearer ${token}` } : {},
|
|
568
|
+
...authorizationSessionToken ? { "x-authorization-session-token": authorizationSessionToken } : {}
|
|
569
|
+
}
|
|
570
|
+
});
|
|
571
|
+
if (!res.ok) await throwApiError(res);
|
|
572
|
+
return await res.json();
|
|
573
|
+
}
|
|
574
|
+
async function signTransfer(apiBaseUrl, token, transferId, signedUserOp, authorizationSessionToken) {
|
|
575
|
+
if (!token && !authorizationSessionToken) {
|
|
576
|
+
throw new Error("Missing auth credentials for transfer signing.");
|
|
577
|
+
}
|
|
578
|
+
const res = await fetch(`${apiBaseUrl}/v1/transfers/${transferId}`, {
|
|
579
|
+
method: "PATCH",
|
|
580
|
+
headers: {
|
|
581
|
+
"Content-Type": "application/json",
|
|
582
|
+
...token ? { Authorization: `Bearer ${token}` } : {},
|
|
583
|
+
...authorizationSessionToken ? { "x-authorization-session-token": authorizationSessionToken } : {}
|
|
584
|
+
},
|
|
585
|
+
body: JSON.stringify({ signedUserOp })
|
|
586
|
+
});
|
|
587
|
+
if (!res.ok) await throwApiError(res);
|
|
588
|
+
return await res.json();
|
|
589
|
+
}
|
|
590
|
+
async function fetchAuthorizationSession(apiBaseUrl, sessionId) {
|
|
591
|
+
const res = await fetch(
|
|
592
|
+
`${apiBaseUrl}/v1/authorization-sessions/${sessionId}`
|
|
593
|
+
);
|
|
594
|
+
if (!res.ok) await throwApiError(res);
|
|
595
|
+
return await res.json();
|
|
596
|
+
}
|
|
597
|
+
async function registerPasskey(apiBaseUrl, token, credentialId, publicKey) {
|
|
598
|
+
const res = await fetch(`${apiBaseUrl}/v1/users/config/passkey`, {
|
|
599
|
+
method: "POST",
|
|
600
|
+
headers: {
|
|
601
|
+
"Content-Type": "application/json",
|
|
602
|
+
Authorization: `Bearer ${token}`
|
|
603
|
+
},
|
|
604
|
+
body: JSON.stringify({ credentialId, publicKey })
|
|
605
|
+
});
|
|
606
|
+
if (!res.ok) await throwApiError(res);
|
|
607
|
+
}
|
|
608
|
+
async function reportPasskeyActivity(apiBaseUrl, token, credentialId) {
|
|
609
|
+
const res = await fetch(`${apiBaseUrl}/v1/users/config/passkey`, {
|
|
610
|
+
method: "PATCH",
|
|
611
|
+
headers: {
|
|
612
|
+
"Content-Type": "application/json",
|
|
613
|
+
Authorization: `Bearer ${token}`
|
|
614
|
+
},
|
|
615
|
+
body: JSON.stringify({ credentialId })
|
|
616
|
+
});
|
|
617
|
+
if (!res.ok) await throwApiError(res);
|
|
618
|
+
}
|
|
619
|
+
async function fetchUserConfig(apiBaseUrl, token) {
|
|
620
|
+
const res = await fetch(`${apiBaseUrl}/v1/users/config`, {
|
|
621
|
+
headers: { Authorization: `Bearer ${token}` }
|
|
622
|
+
});
|
|
623
|
+
if (!res.ok) await throwApiError(res);
|
|
624
|
+
return await res.json();
|
|
625
|
+
}
|
|
626
|
+
async function updateUserConfig(apiBaseUrl, token, config) {
|
|
627
|
+
const res = await fetch(`${apiBaseUrl}/v1/users`, {
|
|
628
|
+
method: "PATCH",
|
|
629
|
+
headers: {
|
|
630
|
+
"Content-Type": "application/json",
|
|
631
|
+
Authorization: `Bearer ${token}`
|
|
632
|
+
},
|
|
633
|
+
body: JSON.stringify({ config })
|
|
634
|
+
});
|
|
635
|
+
if (!res.ok) await throwApiError(res);
|
|
636
|
+
}
|
|
637
|
+
async function updateUserConfigBySession(apiBaseUrl, sessionId, config) {
|
|
638
|
+
const res = await fetch(
|
|
639
|
+
`${apiBaseUrl}/v1/authorization-sessions/${sessionId}/user-config`,
|
|
640
|
+
{
|
|
641
|
+
method: "PATCH",
|
|
642
|
+
headers: { "Content-Type": "application/json" },
|
|
643
|
+
body: JSON.stringify({ config })
|
|
644
|
+
}
|
|
645
|
+
);
|
|
646
|
+
if (!res.ok) await throwApiError(res);
|
|
647
|
+
}
|
|
648
|
+
async function reportActionCompletion(apiBaseUrl, actionId, result) {
|
|
649
|
+
const res = await fetch(
|
|
650
|
+
`${apiBaseUrl}/v1/authorization-actions/${actionId}`,
|
|
651
|
+
{
|
|
652
|
+
method: "PATCH",
|
|
653
|
+
headers: { "Content-Type": "application/json" },
|
|
654
|
+
body: JSON.stringify({ status: "COMPLETED", result })
|
|
655
|
+
}
|
|
656
|
+
);
|
|
657
|
+
if (!res.ok) await throwApiError(res);
|
|
658
|
+
return await res.json();
|
|
659
|
+
}
|
|
660
|
+
|
|
661
|
+
// src/passkeyRpId.ts
|
|
662
|
+
function normalizeConfiguredDomain(value) {
|
|
676
663
|
return value.replace(/^https?:\/\//, "").replace(/\/.*$/, "").replace(/^\./, "").trim();
|
|
677
664
|
}
|
|
678
665
|
function resolveRootDomainFromHostname(hostname) {
|
|
@@ -1656,170 +1643,6 @@ function useTransferSigning(pollIntervalMs = 2e3, options) {
|
|
|
1656
1643
|
return { signing, signPayload, error, signTransfer: signTransfer2 };
|
|
1657
1644
|
}
|
|
1658
1645
|
|
|
1659
|
-
// src/auth.ts
|
|
1660
|
-
var EMAIL_PATTERN = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
1661
|
-
var PHONE_DIGIT_PATTERN = /^\d{7,15}$/;
|
|
1662
|
-
function normalizePhoneNumber(rawValue) {
|
|
1663
|
-
const trimmed = rawValue.trim();
|
|
1664
|
-
if (!trimmed) return null;
|
|
1665
|
-
const hasExplicitCountryCode = trimmed.startsWith("+");
|
|
1666
|
-
const digits = trimmed.replace(/\D/g, "");
|
|
1667
|
-
if (!PHONE_DIGIT_PATTERN.test(digits)) return null;
|
|
1668
|
-
return hasExplicitCountryCode ? `+${digits}` : digits;
|
|
1669
|
-
}
|
|
1670
|
-
function normalizeAuthIdentifier(rawValue) {
|
|
1671
|
-
const trimmed = rawValue.trim();
|
|
1672
|
-
if (!trimmed) return null;
|
|
1673
|
-
if (EMAIL_PATTERN.test(trimmed)) {
|
|
1674
|
-
return {
|
|
1675
|
-
kind: "email",
|
|
1676
|
-
value: trimmed.toLowerCase()
|
|
1677
|
-
};
|
|
1678
|
-
}
|
|
1679
|
-
const normalizedPhoneNumber = normalizePhoneNumber(trimmed);
|
|
1680
|
-
if (normalizedPhoneNumber) {
|
|
1681
|
-
return {
|
|
1682
|
-
kind: "phone",
|
|
1683
|
-
value: normalizedPhoneNumber
|
|
1684
|
-
};
|
|
1685
|
-
}
|
|
1686
|
-
return null;
|
|
1687
|
-
}
|
|
1688
|
-
function maskAuthIdentifier(identifier) {
|
|
1689
|
-
if (identifier.kind === "email") {
|
|
1690
|
-
const [localPart, domain = ""] = identifier.value.split("@");
|
|
1691
|
-
const localPrefix = localPart.slice(0, 2);
|
|
1692
|
-
return `${localPrefix}${"*".repeat(Math.max(localPart.length - 2, 0))}@${domain}`;
|
|
1693
|
-
}
|
|
1694
|
-
const digits = identifier.value.replace(/\D/g, "");
|
|
1695
|
-
const visibleSuffix = digits.slice(-4);
|
|
1696
|
-
return `***-***-${visibleSuffix}`;
|
|
1697
|
-
}
|
|
1698
|
-
|
|
1699
|
-
// src/processingStatus.ts
|
|
1700
|
-
var PROCESSING_TIMEOUT_MS = 18e4;
|
|
1701
|
-
function resolvePreferredTransfer(polledTransfer, localTransfer) {
|
|
1702
|
-
return polledTransfer ?? localTransfer;
|
|
1703
|
-
}
|
|
1704
|
-
function getTransferStatus(polledTransfer, localTransfer) {
|
|
1705
|
-
const transfer = resolvePreferredTransfer(polledTransfer, localTransfer);
|
|
1706
|
-
return transfer?.status ?? "UNKNOWN";
|
|
1707
|
-
}
|
|
1708
|
-
function hasProcessingTimedOut(processingStartedAtMs, nowMs) {
|
|
1709
|
-
if (!processingStartedAtMs) return false;
|
|
1710
|
-
return nowMs - processingStartedAtMs >= PROCESSING_TIMEOUT_MS;
|
|
1711
|
-
}
|
|
1712
|
-
var STATUS_DISPLAY_LABELS = {
|
|
1713
|
-
CREATED: "created",
|
|
1714
|
-
AUTHORIZED: "authorized",
|
|
1715
|
-
SENDING: "sending",
|
|
1716
|
-
SENT: "confirming delivery",
|
|
1717
|
-
COMPLETED: "completed",
|
|
1718
|
-
FAILED: "failed"
|
|
1719
|
-
};
|
|
1720
|
-
function getStatusDisplayLabel(status) {
|
|
1721
|
-
return STATUS_DISPLAY_LABELS[status] ?? status;
|
|
1722
|
-
}
|
|
1723
|
-
function buildProcessingTimeoutMessage(status) {
|
|
1724
|
-
const label = getStatusDisplayLabel(status);
|
|
1725
|
-
return `Payment is taking longer than expected (status: ${label}). Please try again.`;
|
|
1726
|
-
}
|
|
1727
|
-
|
|
1728
|
-
// src/walletFlow.ts
|
|
1729
|
-
var MOBILE_USER_AGENT_PATTERN = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i;
|
|
1730
|
-
function isMobileUserAgent(userAgent) {
|
|
1731
|
-
if (!userAgent) {
|
|
1732
|
-
return false;
|
|
1733
|
-
}
|
|
1734
|
-
return MOBILE_USER_AGENT_PATTERN.test(userAgent);
|
|
1735
|
-
}
|
|
1736
|
-
function shouldUseWalletConnector(options) {
|
|
1737
|
-
return options.useWalletConnector ?? !isMobileUserAgent(options.userAgent);
|
|
1738
|
-
}
|
|
1739
|
-
|
|
1740
|
-
// src/deeplink.ts
|
|
1741
|
-
var IFRAME_CLEANUP_DELAY_MS = 3e3;
|
|
1742
|
-
var LOCATION_FALLBACK_DELAY_MS = 100;
|
|
1743
|
-
function triggerDeeplink(uri) {
|
|
1744
|
-
try {
|
|
1745
|
-
const iframe = document.createElement("iframe");
|
|
1746
|
-
iframe.style.display = "none";
|
|
1747
|
-
iframe.src = uri;
|
|
1748
|
-
document.body.appendChild(iframe);
|
|
1749
|
-
setTimeout(() => {
|
|
1750
|
-
try {
|
|
1751
|
-
document.body.removeChild(iframe);
|
|
1752
|
-
} catch {
|
|
1753
|
-
}
|
|
1754
|
-
}, IFRAME_CLEANUP_DELAY_MS);
|
|
1755
|
-
} catch {
|
|
1756
|
-
}
|
|
1757
|
-
setTimeout(() => {
|
|
1758
|
-
window.location.href = uri;
|
|
1759
|
-
}, LOCATION_FALLBACK_DELAY_MS);
|
|
1760
|
-
}
|
|
1761
|
-
|
|
1762
|
-
// src/mobileFlow.ts
|
|
1763
|
-
function hasActiveWallet(accounts) {
|
|
1764
|
-
return accounts.some((account) => account.wallets.some((wallet) => wallet.status === "ACTIVE"));
|
|
1765
|
-
}
|
|
1766
|
-
function resolvePostAuthStep(state) {
|
|
1767
|
-
if (!state.hasPasskey) {
|
|
1768
|
-
return { step: "create-passkey", clearPersistedFlow: false };
|
|
1769
|
-
}
|
|
1770
|
-
if (state.persistedMobileFlow) {
|
|
1771
|
-
if (state.persistedMobileFlow.isReauthorization) {
|
|
1772
|
-
return { step: "open-wallet", clearPersistedFlow: false };
|
|
1773
|
-
}
|
|
1774
|
-
if (state.persistedMobileFlow.isSetup && hasActiveWallet(state.accounts)) {
|
|
1775
|
-
return { step: "deposit", clearPersistedFlow: true };
|
|
1776
|
-
}
|
|
1777
|
-
return { step: "open-wallet", clearPersistedFlow: false };
|
|
1778
|
-
}
|
|
1779
|
-
if (state.mobileSetupInProgress && !hasActiveWallet(state.accounts)) {
|
|
1780
|
-
return { step: "open-wallet", clearPersistedFlow: false };
|
|
1781
|
-
}
|
|
1782
|
-
if ((state.accounts.length === 0 || !hasActiveWallet(state.accounts)) && !state.connectingNewAccount) {
|
|
1783
|
-
return { step: "wallet-picker", clearPersistedFlow: false };
|
|
1784
|
-
}
|
|
1785
|
-
return { step: "deposit", clearPersistedFlow: false };
|
|
1786
|
-
}
|
|
1787
|
-
function resolveRestoredMobileFlow(transferStatus, isSetup) {
|
|
1788
|
-
if (transferStatus === "AUTHORIZED") {
|
|
1789
|
-
return isSetup ? { kind: "resume-setup-deposit", step: "deposit", clearPersistedFlow: true } : { kind: "resume-confirm-sign", step: "confirm-sign", clearPersistedFlow: true };
|
|
1790
|
-
}
|
|
1791
|
-
if (transferStatus === "COMPLETED") {
|
|
1792
|
-
return { kind: "resume-success", step: "success", clearPersistedFlow: true };
|
|
1793
|
-
}
|
|
1794
|
-
if (transferStatus === "FAILED") {
|
|
1795
|
-
return { kind: "resume-failed", step: "success", clearPersistedFlow: true };
|
|
1796
|
-
}
|
|
1797
|
-
if (transferStatus === "SENDING" || transferStatus === "SENT") {
|
|
1798
|
-
return { kind: "resume-processing", step: "processing", clearPersistedFlow: true };
|
|
1799
|
-
}
|
|
1800
|
-
if (isSetup) {
|
|
1801
|
-
return { kind: "resume-stale-setup", step: "wallet-picker", clearPersistedFlow: true };
|
|
1802
|
-
}
|
|
1803
|
-
return { kind: "resume-open-wallet", step: "open-wallet", clearPersistedFlow: false };
|
|
1804
|
-
}
|
|
1805
|
-
|
|
1806
|
-
// src/dataLoading.ts
|
|
1807
|
-
function resolveDataLoadAction({
|
|
1808
|
-
authenticated,
|
|
1809
|
-
step,
|
|
1810
|
-
accountsCount,
|
|
1811
|
-
hasActiveCredential,
|
|
1812
|
-
loading
|
|
1813
|
-
}) {
|
|
1814
|
-
if (!authenticated || step === "login" || step === "otp-verify" || accountsCount > 0 || !hasActiveCredential) {
|
|
1815
|
-
return "reset";
|
|
1816
|
-
}
|
|
1817
|
-
if (loading) {
|
|
1818
|
-
return "wait";
|
|
1819
|
-
}
|
|
1820
|
-
return "load";
|
|
1821
|
-
}
|
|
1822
|
-
|
|
1823
1646
|
// src/paymentHelpers.ts
|
|
1824
1647
|
var ACTIVE_CREDENTIAL_STORAGE_KEY = "swype_active_credential_id";
|
|
1825
1648
|
var MOBILE_FLOW_STORAGE_KEY = "swype_mobile_flow";
|
|
@@ -2235,6 +2058,46 @@ function paymentReducer(state, action) {
|
|
|
2235
2058
|
return state;
|
|
2236
2059
|
}
|
|
2237
2060
|
}
|
|
2061
|
+
|
|
2062
|
+
// src/auth.ts
|
|
2063
|
+
var EMAIL_PATTERN = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
2064
|
+
var PHONE_DIGIT_PATTERN = /^\d{7,15}$/;
|
|
2065
|
+
function normalizePhoneNumber(rawValue) {
|
|
2066
|
+
const trimmed = rawValue.trim();
|
|
2067
|
+
if (!trimmed) return null;
|
|
2068
|
+
const hasExplicitCountryCode = trimmed.startsWith("+");
|
|
2069
|
+
const digits = trimmed.replace(/\D/g, "");
|
|
2070
|
+
if (!PHONE_DIGIT_PATTERN.test(digits)) return null;
|
|
2071
|
+
return hasExplicitCountryCode ? `+${digits}` : digits;
|
|
2072
|
+
}
|
|
2073
|
+
function normalizeAuthIdentifier(rawValue) {
|
|
2074
|
+
const trimmed = rawValue.trim();
|
|
2075
|
+
if (!trimmed) return null;
|
|
2076
|
+
if (EMAIL_PATTERN.test(trimmed)) {
|
|
2077
|
+
return {
|
|
2078
|
+
kind: "email",
|
|
2079
|
+
value: trimmed.toLowerCase()
|
|
2080
|
+
};
|
|
2081
|
+
}
|
|
2082
|
+
const normalizedPhoneNumber = normalizePhoneNumber(trimmed);
|
|
2083
|
+
if (normalizedPhoneNumber) {
|
|
2084
|
+
return {
|
|
2085
|
+
kind: "phone",
|
|
2086
|
+
value: normalizedPhoneNumber
|
|
2087
|
+
};
|
|
2088
|
+
}
|
|
2089
|
+
return null;
|
|
2090
|
+
}
|
|
2091
|
+
function maskAuthIdentifier(identifier) {
|
|
2092
|
+
if (identifier.kind === "email") {
|
|
2093
|
+
const [localPart, domain = ""] = identifier.value.split("@");
|
|
2094
|
+
const localPrefix = localPart.slice(0, 2);
|
|
2095
|
+
return `${localPrefix}${"*".repeat(Math.max(localPart.length - 2, 0))}@${domain}`;
|
|
2096
|
+
}
|
|
2097
|
+
const digits = identifier.value.replace(/\D/g, "");
|
|
2098
|
+
const visibleSuffix = digits.slice(-4);
|
|
2099
|
+
return `***-***-${visibleSuffix}`;
|
|
2100
|
+
}
|
|
2238
2101
|
var ACCENT = "#28b67a";
|
|
2239
2102
|
var BG_RING = "#d2e4ea";
|
|
2240
2103
|
function SwypeLoadingScreen() {
|
|
@@ -3860,7 +3723,7 @@ var dividerTextStyle = (color) => ({
|
|
|
3860
3723
|
color,
|
|
3861
3724
|
whiteSpace: "nowrap"
|
|
3862
3725
|
});
|
|
3863
|
-
var DEFAULT_MAX =
|
|
3726
|
+
var DEFAULT_MAX = 1e7;
|
|
3864
3727
|
var ABSOLUTE_MIN = 0.01;
|
|
3865
3728
|
function SetupScreen({
|
|
3866
3729
|
availableBalance,
|
|
@@ -3875,7 +3738,7 @@ function SetupScreen({
|
|
|
3875
3738
|
error
|
|
3876
3739
|
}) {
|
|
3877
3740
|
const { tokens } = useSwypeConfig();
|
|
3878
|
-
const effectiveMax =
|
|
3741
|
+
const effectiveMax = DEFAULT_MAX;
|
|
3879
3742
|
const effectiveMin = Math.min(ABSOLUTE_MIN, effectiveMax);
|
|
3880
3743
|
const [limit, setLimit] = react.useState(() => Math.min(availableBalance, effectiveMax));
|
|
3881
3744
|
const [editing, setEditing] = react.useState(false);
|
|
@@ -4251,7 +4114,8 @@ function DepositScreen({
|
|
|
4251
4114
|
onSelectAccount,
|
|
4252
4115
|
onAuthorizeAccount,
|
|
4253
4116
|
onAddProvider,
|
|
4254
|
-
onSelectToken
|
|
4117
|
+
onSelectToken,
|
|
4118
|
+
selectedSourceLabel
|
|
4255
4119
|
}) {
|
|
4256
4120
|
const { tokens } = useSwypeConfig();
|
|
4257
4121
|
const amount = initialAmount;
|
|
@@ -4296,7 +4160,7 @@ function DepositScreen({
|
|
|
4296
4160
|
/* @__PURE__ */ jsxRuntime.jsx("text", { x: "12", y: "16", textAnchor: "middle", fontSize: "12", fill: "#fff", fontWeight: "700", children: "$" })
|
|
4297
4161
|
] }) }),
|
|
4298
4162
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4299
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { style: balanceLabelStyle2(tokens.textMuted), children: "Available" }),
|
|
4163
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { style: balanceLabelStyle2(tokens.textMuted), children: selectedSourceLabel ?? "Available" }),
|
|
4300
4164
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: { ...balanceAmountStyle, color: tokens.warning }, children: [
|
|
4301
4165
|
"$",
|
|
4302
4166
|
availableBalance.toFixed(2)
|
|
@@ -4371,10 +4235,7 @@ function DepositScreen({
|
|
|
4371
4235
|
/* @__PURE__ */ jsxRuntime.jsx("text", { x: "12", y: "16", textAnchor: "middle", fontSize: "12", fill: "#fff", fontWeight: "700", children: "$" })
|
|
4372
4236
|
] }) }),
|
|
4373
4237
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4374
|
-
/* @__PURE__ */ jsxRuntime.
|
|
4375
|
-
"Paying from ",
|
|
4376
|
-
sourceName
|
|
4377
|
-
] }),
|
|
4238
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { style: balanceLabelStyle2(tokens.textMuted), children: selectedSourceLabel ?? `Paying from ${sourceName}` }),
|
|
4378
4239
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: balanceAmountStyle, children: [
|
|
4379
4240
|
"$",
|
|
4380
4241
|
availableBalance.toLocaleString("en-US", { minimumFractionDigits: 2, maximumFractionDigits: 2 })
|
|
@@ -4728,6 +4589,7 @@ function SelectSourceScreen({
|
|
|
4728
4589
|
onChainChange,
|
|
4729
4590
|
onTokenChange,
|
|
4730
4591
|
onConfirm,
|
|
4592
|
+
onBack,
|
|
4731
4593
|
onLogout
|
|
4732
4594
|
}) {
|
|
4733
4595
|
const { tokens } = useSwypeConfig();
|
|
@@ -4746,6 +4608,7 @@ function SelectSourceScreen({
|
|
|
4746
4608
|
ScreenHeader,
|
|
4747
4609
|
{
|
|
4748
4610
|
title: "Select Source",
|
|
4611
|
+
onBack,
|
|
4749
4612
|
right: /* @__PURE__ */ jsxRuntime.jsx(SettingsMenu, { onLogout })
|
|
4750
4613
|
}
|
|
4751
4614
|
),
|
|
@@ -5168,6 +5031,28 @@ var waitHintStyle2 = (color) => ({
|
|
|
5168
5031
|
color,
|
|
5169
5032
|
margin: 0
|
|
5170
5033
|
});
|
|
5034
|
+
|
|
5035
|
+
// src/deeplink.ts
|
|
5036
|
+
var IFRAME_CLEANUP_DELAY_MS = 3e3;
|
|
5037
|
+
var LOCATION_FALLBACK_DELAY_MS = 100;
|
|
5038
|
+
function triggerDeeplink(uri) {
|
|
5039
|
+
try {
|
|
5040
|
+
const iframe = document.createElement("iframe");
|
|
5041
|
+
iframe.style.display = "none";
|
|
5042
|
+
iframe.src = uri;
|
|
5043
|
+
document.body.appendChild(iframe);
|
|
5044
|
+
setTimeout(() => {
|
|
5045
|
+
try {
|
|
5046
|
+
document.body.removeChild(iframe);
|
|
5047
|
+
} catch {
|
|
5048
|
+
}
|
|
5049
|
+
}, IFRAME_CLEANUP_DELAY_MS);
|
|
5050
|
+
} catch {
|
|
5051
|
+
}
|
|
5052
|
+
setTimeout(() => {
|
|
5053
|
+
window.location.href = uri;
|
|
5054
|
+
}, LOCATION_FALLBACK_DELAY_MS);
|
|
5055
|
+
}
|
|
5171
5056
|
function OpenWalletScreen({
|
|
5172
5057
|
walletName,
|
|
5173
5058
|
deeplinkUri,
|
|
@@ -5613,6 +5498,7 @@ function StepRenderer({
|
|
|
5613
5498
|
selectedSource,
|
|
5614
5499
|
selectSourceChoices,
|
|
5615
5500
|
selectSourceRecommended,
|
|
5501
|
+
selectSourceAvailableBalance,
|
|
5616
5502
|
authInput,
|
|
5617
5503
|
otpCode,
|
|
5618
5504
|
selectSourceChainName,
|
|
@@ -5734,17 +5620,23 @@ function StepRenderer({
|
|
|
5734
5620
|
);
|
|
5735
5621
|
}
|
|
5736
5622
|
if (step === "setup") {
|
|
5623
|
+
const selectSourceTokenCount = selectSourceChoices.reduce(
|
|
5624
|
+
(sum, chain) => sum + chain.tokens.length,
|
|
5625
|
+
0
|
|
5626
|
+
);
|
|
5627
|
+
const effectiveTokenCount = tokenCount > 0 ? tokenCount : selectSourceTokenCount;
|
|
5628
|
+
const effectiveSourceLabel = selectedSourceLabel ?? (selectSourceChainName && selectSourceTokenSymbol ? `${selectSourceTokenSymbol} on ${selectSourceChainName}` : void 0);
|
|
5737
5629
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
5738
5630
|
SetupScreen,
|
|
5739
5631
|
{
|
|
5740
|
-
availableBalance: selectedSource ? selectedSource.balance.available.amount : selectedAccount ? selectedAccount.wallets.reduce((sum, w) => sum + w.balance.available.amount, 0) : maxSourceBalance,
|
|
5741
|
-
tokenCount,
|
|
5632
|
+
availableBalance: selectedSource ? selectedSource.balance.available.amount : selectedAccount ? selectedAccount.wallets.reduce((sum, w) => sum + w.balance.available.amount, 0) : selectSourceAvailableBalance > 0 ? selectSourceAvailableBalance : maxSourceBalance,
|
|
5633
|
+
tokenCount: effectiveTokenCount,
|
|
5742
5634
|
sourceName,
|
|
5743
5635
|
onSetupOneTap: handlers.onSetupOneTap,
|
|
5744
5636
|
onBack: () => handlers.onNavigate("deposit"),
|
|
5745
5637
|
onLogout: handlers.onLogout,
|
|
5746
5638
|
onAdvanced: handlers.onSelectToken,
|
|
5747
|
-
selectedSourceLabel,
|
|
5639
|
+
selectedSourceLabel: effectiveSourceLabel,
|
|
5748
5640
|
loading: savingOneTapLimit,
|
|
5749
5641
|
error: state.error
|
|
5750
5642
|
}
|
|
@@ -5792,7 +5684,8 @@ function StepRenderer({
|
|
|
5792
5684
|
onSelectAccount: handlers.onSelectAccount,
|
|
5793
5685
|
onAuthorizeAccount: handlers.onContinueConnection,
|
|
5794
5686
|
onAddProvider: () => handlers.onNavigate("wallet-picker"),
|
|
5795
|
-
onSelectToken: handlers.onSelectToken
|
|
5687
|
+
onSelectToken: handlers.onSelectToken,
|
|
5688
|
+
selectedSourceLabel
|
|
5796
5689
|
}
|
|
5797
5690
|
);
|
|
5798
5691
|
}
|
|
@@ -5824,6 +5717,7 @@ function StepRenderer({
|
|
|
5824
5717
|
);
|
|
5825
5718
|
}
|
|
5826
5719
|
if (step === "select-source") {
|
|
5720
|
+
const cameFromSetup = state.previousStep === "setup";
|
|
5827
5721
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
5828
5722
|
SelectSourceScreen,
|
|
5829
5723
|
{
|
|
@@ -5833,7 +5727,8 @@ function StepRenderer({
|
|
|
5833
5727
|
recommended: selectSourceRecommended,
|
|
5834
5728
|
onChainChange: handlers.onSelectSourceChainChange,
|
|
5835
5729
|
onTokenChange: handlers.onSetSelectSourceTokenSymbol,
|
|
5836
|
-
onConfirm: handlers.onConfirmSelectSource,
|
|
5730
|
+
onConfirm: cameFromSetup ? () => handlers.onNavigate("setup") : handlers.onConfirmSelectSource,
|
|
5731
|
+
onBack: cameFromSetup ? () => handlers.onNavigate("setup") : void 0,
|
|
5837
5732
|
onLogout: handlers.onLogout
|
|
5838
5733
|
}
|
|
5839
5734
|
);
|
|
@@ -5883,12 +5778,29 @@ function StepRenderer({
|
|
|
5883
5778
|
selectedAccountId: state.selectedAccountId,
|
|
5884
5779
|
onSelectAccount: handlers.onSelectAccount,
|
|
5885
5780
|
onAuthorizeAccount: handlers.onContinueConnection,
|
|
5886
|
-
onAddProvider: () => handlers.onNavigate("wallet-picker")
|
|
5781
|
+
onAddProvider: () => handlers.onNavigate("wallet-picker"),
|
|
5782
|
+
selectedSourceLabel
|
|
5887
5783
|
}
|
|
5888
5784
|
);
|
|
5889
5785
|
}
|
|
5890
5786
|
return null;
|
|
5891
5787
|
}
|
|
5788
|
+
|
|
5789
|
+
// src/sentry.ts
|
|
5790
|
+
var _mod;
|
|
5791
|
+
function captureException(error) {
|
|
5792
|
+
if (_mod === null) return;
|
|
5793
|
+
if (_mod) {
|
|
5794
|
+
_mod.captureException(error);
|
|
5795
|
+
return;
|
|
5796
|
+
}
|
|
5797
|
+
import('@sentry/react').then((m) => {
|
|
5798
|
+
_mod = m;
|
|
5799
|
+
m.captureException(error);
|
|
5800
|
+
}).catch(() => {
|
|
5801
|
+
_mod = null;
|
|
5802
|
+
});
|
|
5803
|
+
}
|
|
5892
5804
|
var PaymentErrorBoundary = class extends react.Component {
|
|
5893
5805
|
constructor(props) {
|
|
5894
5806
|
super(props);
|
|
@@ -5957,78 +5869,7 @@ var buttonStyle3 = {
|
|
|
5957
5869
|
fontFamily: "inherit",
|
|
5958
5870
|
cursor: "pointer"
|
|
5959
5871
|
};
|
|
5960
|
-
function
|
|
5961
|
-
const resetKey = react.useRef(0);
|
|
5962
|
-
const handleBoundaryReset = react.useCallback(() => {
|
|
5963
|
-
resetKey.current += 1;
|
|
5964
|
-
}, []);
|
|
5965
|
-
return /* @__PURE__ */ jsxRuntime.jsx(PaymentErrorBoundary, { onReset: handleBoundaryReset, children: /* @__PURE__ */ jsxRuntime.jsx(SwypePaymentInner, { ...props }) }, resetKey.current);
|
|
5966
|
-
}
|
|
5967
|
-
function SwypePaymentInner({
|
|
5968
|
-
destination,
|
|
5969
|
-
onComplete,
|
|
5970
|
-
onError,
|
|
5971
|
-
useWalletConnector: useWalletConnectorProp,
|
|
5972
|
-
idempotencyKey,
|
|
5973
|
-
merchantAuthorization,
|
|
5974
|
-
merchantName,
|
|
5975
|
-
onBack,
|
|
5976
|
-
onDismiss,
|
|
5977
|
-
autoCloseSeconds
|
|
5978
|
-
}) {
|
|
5979
|
-
const { apiBaseUrl, depositAmount } = useSwypeConfig();
|
|
5980
|
-
const { ready, authenticated, user, logout, getAccessToken } = reactAuth.usePrivy();
|
|
5981
|
-
const {
|
|
5982
|
-
sendCode: sendEmailCode,
|
|
5983
|
-
loginWithCode: loginWithEmailCode,
|
|
5984
|
-
state: emailLoginState
|
|
5985
|
-
} = reactAuth.useLoginWithEmail();
|
|
5986
|
-
const {
|
|
5987
|
-
sendCode: sendSmsCode,
|
|
5988
|
-
loginWithCode: loginWithSmsCode,
|
|
5989
|
-
state: smsLoginState
|
|
5990
|
-
} = reactAuth.useLoginWithSms();
|
|
5991
|
-
reactAuth.useLoginWithOAuth();
|
|
5992
|
-
const [state, dispatch] = react.useReducer(
|
|
5993
|
-
paymentReducer,
|
|
5994
|
-
{
|
|
5995
|
-
depositAmount,
|
|
5996
|
-
passkeyPopupNeeded: isSafari() && isInCrossOriginIframe(),
|
|
5997
|
-
activeCredentialId: typeof window === "undefined" ? null : window.localStorage.getItem(ACTIVE_CREDENTIAL_STORAGE_KEY)
|
|
5998
|
-
},
|
|
5999
|
-
createInitialState
|
|
6000
|
-
);
|
|
6001
|
-
const loadingDataRef = react.useRef(false);
|
|
6002
|
-
const pollingTransferIdRef = react.useRef(null);
|
|
6003
|
-
const setupAccountIdRef = react.useRef(null);
|
|
6004
|
-
const mobileSetupFlowRef = react.useRef(false);
|
|
6005
|
-
const handlingMobileReturnRef = react.useRef(false);
|
|
6006
|
-
const processingStartedAtRef = react.useRef(null);
|
|
6007
|
-
const initializedSelectSourceActionRef = react.useRef(null);
|
|
6008
|
-
const preSelectSourceStepRef = react.useRef(null);
|
|
6009
|
-
const pendingTokenAuthRef = react.useRef(null);
|
|
6010
|
-
const pendingTokenSelectionRef = react.useRef(null);
|
|
6011
|
-
const pendingTokenAuthSessionRef = react.useRef(null);
|
|
6012
|
-
const reauthSessionIdRef = react.useRef(null);
|
|
6013
|
-
const reauthTokenRef = react.useRef(null);
|
|
6014
|
-
const checkingPasskeyRef = react.useRef(false);
|
|
6015
|
-
const onCompleteRef = react.useRef(onComplete);
|
|
6016
|
-
onCompleteRef.current = onComplete;
|
|
6017
|
-
const pollingRef = react.useRef(null);
|
|
6018
|
-
const getAccessTokenRef = react.useRef(getAccessToken);
|
|
6019
|
-
getAccessTokenRef.current = getAccessToken;
|
|
6020
|
-
const handleAuthorizedMobileReturnRef = react.useRef(
|
|
6021
|
-
null
|
|
6022
|
-
);
|
|
6023
|
-
const [authInput, setAuthInput] = react.useState("");
|
|
6024
|
-
const [otpCode, setOtpCode] = react.useState("");
|
|
6025
|
-
const [selectSourceChainName, setSelectSourceChainName] = react.useState("");
|
|
6026
|
-
const [selectSourceTokenSymbol, setSelectSourceTokenSymbol] = react.useState("");
|
|
6027
|
-
const [savingOneTapLimit, setSavingOneTapLimit] = react.useState(false);
|
|
6028
|
-
const authExecutor = useAuthorizationExecutor();
|
|
6029
|
-
const polling = useTransferPolling();
|
|
6030
|
-
pollingRef.current = polling;
|
|
6031
|
-
const transferSigning = useTransferSigning();
|
|
5872
|
+
function useDerivedState(state) {
|
|
6032
5873
|
const { sourceType, sourceId } = deriveSourceTypeAndId(state);
|
|
6033
5874
|
const selectedAccount = state.accounts.find((a) => a.id === state.selectedAccountId);
|
|
6034
5875
|
const selectedWallet = selectedAccount?.wallets.find(
|
|
@@ -6078,8 +5919,36 @@ function SwypePaymentInner({
|
|
|
6078
5919
|
}
|
|
6079
5920
|
return count;
|
|
6080
5921
|
}, [state.accounts]);
|
|
6081
|
-
|
|
6082
|
-
|
|
5922
|
+
return {
|
|
5923
|
+
sourceType,
|
|
5924
|
+
sourceId,
|
|
5925
|
+
selectedAccount,
|
|
5926
|
+
selectedWallet,
|
|
5927
|
+
selectedSource,
|
|
5928
|
+
sourceName,
|
|
5929
|
+
sourceAddress,
|
|
5930
|
+
sourceVerified,
|
|
5931
|
+
pendingConnections,
|
|
5932
|
+
depositEligibleAccounts,
|
|
5933
|
+
maxSourceBalance,
|
|
5934
|
+
tokenCount
|
|
5935
|
+
};
|
|
5936
|
+
}
|
|
5937
|
+
function useAuthHandlers(dispatch, verificationTarget) {
|
|
5938
|
+
const {
|
|
5939
|
+
sendCode: sendEmailCode,
|
|
5940
|
+
loginWithCode: loginWithEmailCode,
|
|
5941
|
+
state: emailLoginState
|
|
5942
|
+
} = reactAuth.useLoginWithEmail();
|
|
5943
|
+
const {
|
|
5944
|
+
sendCode: sendSmsCode,
|
|
5945
|
+
loginWithCode: loginWithSmsCode,
|
|
5946
|
+
state: smsLoginState
|
|
5947
|
+
} = reactAuth.useLoginWithSms();
|
|
5948
|
+
const [authInput, setAuthInput] = react.useState("");
|
|
5949
|
+
const [otpCode, setOtpCode] = react.useState("");
|
|
5950
|
+
const activeOtpStatus = verificationTarget?.kind === "email" ? emailLoginState.status : verificationTarget?.kind === "phone" ? smsLoginState.status : "initial";
|
|
5951
|
+
const activeOtpErrorMessage = verificationTarget?.kind === "email" && emailLoginState.status === "error" ? emailLoginState.error?.message ?? "Failed to continue with email." : verificationTarget?.kind === "phone" && smsLoginState.status === "error" ? smsLoginState.error?.message ?? "Failed to continue with phone number." : null;
|
|
6083
5952
|
const handleSendLoginCode = react.useCallback(async () => {
|
|
6084
5953
|
const normalizedIdentifier = normalizeAuthIdentifier(authInput);
|
|
6085
5954
|
if (!normalizedIdentifier) {
|
|
@@ -6101,9 +5970,9 @@ function SwypePaymentInner({
|
|
|
6101
5970
|
error: err instanceof Error ? err.message : "Failed to send verification code"
|
|
6102
5971
|
});
|
|
6103
5972
|
}
|
|
6104
|
-
}, [authInput, sendEmailCode, sendSmsCode]);
|
|
5973
|
+
}, [authInput, sendEmailCode, sendSmsCode, dispatch]);
|
|
6105
5974
|
const handleVerifyLoginCode = react.useCallback(async () => {
|
|
6106
|
-
if (!
|
|
5975
|
+
if (!verificationTarget) return;
|
|
6107
5976
|
const trimmedCode = otpCode.trim();
|
|
6108
5977
|
if (!/^\d{6}$/.test(trimmedCode)) {
|
|
6109
5978
|
dispatch({ type: "SET_ERROR", error: "Enter the 6-digit verification code." });
|
|
@@ -6111,7 +5980,7 @@ function SwypePaymentInner({
|
|
|
6111
5980
|
}
|
|
6112
5981
|
dispatch({ type: "SET_ERROR", error: null });
|
|
6113
5982
|
try {
|
|
6114
|
-
if (
|
|
5983
|
+
if (verificationTarget.kind === "email") {
|
|
6115
5984
|
await loginWithEmailCode({ code: trimmedCode });
|
|
6116
5985
|
} else {
|
|
6117
5986
|
await loginWithSmsCode({ code: trimmedCode });
|
|
@@ -6123,15 +5992,15 @@ function SwypePaymentInner({
|
|
|
6123
5992
|
error: err instanceof Error ? err.message : "Failed to verify code"
|
|
6124
5993
|
});
|
|
6125
5994
|
}
|
|
6126
|
-
}, [
|
|
5995
|
+
}, [verificationTarget, otpCode, loginWithEmailCode, loginWithSmsCode, dispatch]);
|
|
6127
5996
|
const handleResendLoginCode = react.useCallback(async () => {
|
|
6128
|
-
if (!
|
|
5997
|
+
if (!verificationTarget) return;
|
|
6129
5998
|
dispatch({ type: "SET_ERROR", error: null });
|
|
6130
5999
|
try {
|
|
6131
|
-
if (
|
|
6132
|
-
await sendEmailCode({ email:
|
|
6000
|
+
if (verificationTarget.kind === "email") {
|
|
6001
|
+
await sendEmailCode({ email: verificationTarget.value });
|
|
6133
6002
|
} else {
|
|
6134
|
-
await sendSmsCode({ phoneNumber:
|
|
6003
|
+
await sendSmsCode({ phoneNumber: verificationTarget.value });
|
|
6135
6004
|
}
|
|
6136
6005
|
} catch (err) {
|
|
6137
6006
|
captureException(err);
|
|
@@ -6140,7 +6009,68 @@ function SwypePaymentInner({
|
|
|
6140
6009
|
error: err instanceof Error ? err.message : "Failed to resend code"
|
|
6141
6010
|
});
|
|
6142
6011
|
}
|
|
6143
|
-
}, [
|
|
6012
|
+
}, [verificationTarget, sendEmailCode, sendSmsCode, dispatch]);
|
|
6013
|
+
return {
|
|
6014
|
+
authInput,
|
|
6015
|
+
otpCode,
|
|
6016
|
+
activeOtpStatus,
|
|
6017
|
+
activeOtpErrorMessage,
|
|
6018
|
+
setAuthInput,
|
|
6019
|
+
setOtpCode,
|
|
6020
|
+
handleSendLoginCode,
|
|
6021
|
+
handleVerifyLoginCode,
|
|
6022
|
+
handleResendLoginCode
|
|
6023
|
+
};
|
|
6024
|
+
}
|
|
6025
|
+
|
|
6026
|
+
// src/mobileFlow.ts
|
|
6027
|
+
function hasActiveWallet(accounts) {
|
|
6028
|
+
return accounts.some((account) => account.wallets.some((wallet) => wallet.status === "ACTIVE"));
|
|
6029
|
+
}
|
|
6030
|
+
function resolvePostAuthStep(state) {
|
|
6031
|
+
if (!state.hasPasskey) {
|
|
6032
|
+
return { step: "create-passkey", clearPersistedFlow: false };
|
|
6033
|
+
}
|
|
6034
|
+
if (state.persistedMobileFlow) {
|
|
6035
|
+
if (state.persistedMobileFlow.isReauthorization) {
|
|
6036
|
+
return { step: "open-wallet", clearPersistedFlow: false };
|
|
6037
|
+
}
|
|
6038
|
+
if (state.persistedMobileFlow.isSetup && hasActiveWallet(state.accounts)) {
|
|
6039
|
+
return { step: "deposit", clearPersistedFlow: true };
|
|
6040
|
+
}
|
|
6041
|
+
return { step: "open-wallet", clearPersistedFlow: false };
|
|
6042
|
+
}
|
|
6043
|
+
if (state.mobileSetupInProgress && !hasActiveWallet(state.accounts)) {
|
|
6044
|
+
return { step: "open-wallet", clearPersistedFlow: false };
|
|
6045
|
+
}
|
|
6046
|
+
if ((state.accounts.length === 0 || !hasActiveWallet(state.accounts)) && !state.connectingNewAccount) {
|
|
6047
|
+
return { step: "wallet-picker", clearPersistedFlow: false };
|
|
6048
|
+
}
|
|
6049
|
+
return { step: "deposit", clearPersistedFlow: false };
|
|
6050
|
+
}
|
|
6051
|
+
function resolveRestoredMobileFlow(transferStatus, isSetup) {
|
|
6052
|
+
if (transferStatus === "AUTHORIZED") {
|
|
6053
|
+
return isSetup ? { kind: "resume-setup-deposit", step: "deposit", clearPersistedFlow: true } : { kind: "resume-confirm-sign", step: "confirm-sign", clearPersistedFlow: true };
|
|
6054
|
+
}
|
|
6055
|
+
if (transferStatus === "COMPLETED") {
|
|
6056
|
+
return { kind: "resume-success", step: "success", clearPersistedFlow: true };
|
|
6057
|
+
}
|
|
6058
|
+
if (transferStatus === "FAILED") {
|
|
6059
|
+
return { kind: "resume-failed", step: "success", clearPersistedFlow: true };
|
|
6060
|
+
}
|
|
6061
|
+
if (transferStatus === "SENDING" || transferStatus === "SENT") {
|
|
6062
|
+
return { kind: "resume-processing", step: "processing", clearPersistedFlow: true };
|
|
6063
|
+
}
|
|
6064
|
+
if (isSetup) {
|
|
6065
|
+
return { kind: "resume-stale-setup", step: "wallet-picker", clearPersistedFlow: true };
|
|
6066
|
+
}
|
|
6067
|
+
return { kind: "resume-open-wallet", step: "open-wallet", clearPersistedFlow: false };
|
|
6068
|
+
}
|
|
6069
|
+
|
|
6070
|
+
// src/hooks/usePasskeyHandlers.ts
|
|
6071
|
+
function usePasskeyHandlers(dispatch, apiBaseUrl, accounts, knownCredentialIds, mobileSetupFlowRef) {
|
|
6072
|
+
const { user, getAccessToken } = reactAuth.usePrivy();
|
|
6073
|
+
const checkingPasskeyRef = react.useRef(false);
|
|
6144
6074
|
const completePasskeyRegistration = react.useCallback(async (credentialId, publicKey) => {
|
|
6145
6075
|
const token = await getAccessToken();
|
|
6146
6076
|
if (!token) throw new Error("Not authenticated");
|
|
@@ -6149,14 +6079,14 @@ function SwypePaymentInner({
|
|
|
6149
6079
|
window.localStorage.setItem(ACTIVE_CREDENTIAL_STORAGE_KEY, credentialId);
|
|
6150
6080
|
const resolved = resolvePostAuthStep({
|
|
6151
6081
|
hasPasskey: true,
|
|
6152
|
-
accounts
|
|
6082
|
+
accounts,
|
|
6153
6083
|
persistedMobileFlow: loadMobileFlowState(),
|
|
6154
6084
|
mobileSetupInProgress: mobileSetupFlowRef.current,
|
|
6155
6085
|
connectingNewAccount: false
|
|
6156
6086
|
});
|
|
6157
6087
|
if (resolved.clearPersistedFlow) clearMobileFlowState();
|
|
6158
6088
|
dispatch({ type: "NAVIGATE", step: resolved.step });
|
|
6159
|
-
}, [getAccessToken, apiBaseUrl,
|
|
6089
|
+
}, [getAccessToken, apiBaseUrl, accounts, mobileSetupFlowRef, dispatch]);
|
|
6160
6090
|
const handleRegisterPasskey = react.useCallback(async () => {
|
|
6161
6091
|
dispatch({ type: "SET_REGISTERING_PASSKEY", value: true });
|
|
6162
6092
|
dispatch({ type: "SET_ERROR", error: null });
|
|
@@ -6180,7 +6110,7 @@ function SwypePaymentInner({
|
|
|
6180
6110
|
} finally {
|
|
6181
6111
|
dispatch({ type: "SET_REGISTERING_PASSKEY", value: false });
|
|
6182
6112
|
}
|
|
6183
|
-
}, [user, completePasskeyRegistration]);
|
|
6113
|
+
}, [user, completePasskeyRegistration, dispatch]);
|
|
6184
6114
|
const handleCreatePasskeyViaPopup = react.useCallback(async () => {
|
|
6185
6115
|
dispatch({ type: "SET_REGISTERING_PASSKEY", value: true });
|
|
6186
6116
|
dispatch({ type: "SET_ERROR", error: null });
|
|
@@ -6198,7 +6128,7 @@ function SwypePaymentInner({
|
|
|
6198
6128
|
localStorage.setItem(ACTIVE_CREDENTIAL_STORAGE_KEY, credentialId);
|
|
6199
6129
|
const resolved = resolvePostAuthStep({
|
|
6200
6130
|
hasPasskey: true,
|
|
6201
|
-
accounts
|
|
6131
|
+
accounts,
|
|
6202
6132
|
persistedMobileFlow: loadMobileFlowState(),
|
|
6203
6133
|
mobileSetupInProgress: mobileSetupFlowRef.current,
|
|
6204
6134
|
connectingNewAccount: false
|
|
@@ -6214,14 +6144,14 @@ function SwypePaymentInner({
|
|
|
6214
6144
|
} finally {
|
|
6215
6145
|
dispatch({ type: "SET_REGISTERING_PASSKEY", value: false });
|
|
6216
6146
|
}
|
|
6217
|
-
}, [user, getAccessToken, apiBaseUrl,
|
|
6147
|
+
}, [user, getAccessToken, apiBaseUrl, accounts, mobileSetupFlowRef, dispatch]);
|
|
6218
6148
|
const handleVerifyPasskeyViaPopup = react.useCallback(async () => {
|
|
6219
6149
|
dispatch({ type: "SET_VERIFYING_PASSKEY", value: true });
|
|
6220
6150
|
dispatch({ type: "SET_ERROR", error: null });
|
|
6221
6151
|
try {
|
|
6222
6152
|
const token = await getAccessToken();
|
|
6223
6153
|
const matched = await findDevicePasskeyViaPopup({
|
|
6224
|
-
credentialIds:
|
|
6154
|
+
credentialIds: knownCredentialIds,
|
|
6225
6155
|
rpId: resolvePasskeyRpId(),
|
|
6226
6156
|
authToken: token ?? void 0,
|
|
6227
6157
|
apiBaseUrl
|
|
@@ -6235,7 +6165,7 @@ function SwypePaymentInner({
|
|
|
6235
6165
|
}
|
|
6236
6166
|
const resolved = resolvePostAuthStep({
|
|
6237
6167
|
hasPasskey: true,
|
|
6238
|
-
accounts
|
|
6168
|
+
accounts,
|
|
6239
6169
|
persistedMobileFlow: loadMobileFlowState(),
|
|
6240
6170
|
mobileSetupInProgress: mobileSetupFlowRef.current,
|
|
6241
6171
|
connectingNewAccount: false
|
|
@@ -6257,44 +6187,48 @@ function SwypePaymentInner({
|
|
|
6257
6187
|
} finally {
|
|
6258
6188
|
dispatch({ type: "SET_VERIFYING_PASSKEY", value: false });
|
|
6259
6189
|
}
|
|
6260
|
-
}, [
|
|
6190
|
+
}, [knownCredentialIds, getAccessToken, apiBaseUrl, accounts, mobileSetupFlowRef, dispatch]);
|
|
6191
|
+
return {
|
|
6192
|
+
handleRegisterPasskey,
|
|
6193
|
+
handleCreatePasskeyViaPopup,
|
|
6194
|
+
handleVerifyPasskeyViaPopup,
|
|
6195
|
+
checkingPasskeyRef
|
|
6196
|
+
};
|
|
6197
|
+
}
|
|
6198
|
+
function useTransferHandlers(deps) {
|
|
6199
|
+
const {
|
|
6200
|
+
dispatch,
|
|
6201
|
+
getAccessToken,
|
|
6202
|
+
apiBaseUrl,
|
|
6203
|
+
depositAmount,
|
|
6204
|
+
destination,
|
|
6205
|
+
idempotencyKey,
|
|
6206
|
+
merchantAuthorization,
|
|
6207
|
+
onComplete,
|
|
6208
|
+
onError,
|
|
6209
|
+
polling,
|
|
6210
|
+
transferSigning,
|
|
6211
|
+
sourceType,
|
|
6212
|
+
sourceId,
|
|
6213
|
+
sourceTokenAddress,
|
|
6214
|
+
activeCredentialId,
|
|
6215
|
+
selectedAccountId,
|
|
6216
|
+
transfer,
|
|
6217
|
+
accounts
|
|
6218
|
+
} = deps;
|
|
6219
|
+
const processingStartedAtRef = react.useRef(null);
|
|
6220
|
+
const pollingTransferIdRef = react.useRef(null);
|
|
6261
6221
|
const reloadAccounts = react.useCallback(async () => {
|
|
6262
6222
|
const token = await getAccessToken();
|
|
6263
|
-
if (!token || !
|
|
6223
|
+
if (!token || !activeCredentialId) return;
|
|
6264
6224
|
const [accts, prov] = await Promise.all([
|
|
6265
|
-
fetchAccounts(apiBaseUrl, token,
|
|
6225
|
+
fetchAccounts(apiBaseUrl, token, activeCredentialId),
|
|
6266
6226
|
fetchProviders(apiBaseUrl, token)
|
|
6267
6227
|
]);
|
|
6268
6228
|
const parsedAmt = depositAmount != null ? depositAmount : 0;
|
|
6269
|
-
const defaults = resolveDepositSelection(accts, parsedAmt,
|
|
6229
|
+
const defaults = resolveDepositSelection(accts, parsedAmt, selectedAccountId);
|
|
6270
6230
|
dispatch({ type: "ACCOUNTS_RELOADED", accounts: accts, providers: prov, defaults });
|
|
6271
|
-
}, [getAccessToken,
|
|
6272
|
-
const handleAuthorizedMobileReturn = react.useCallback(async (authorizedTransfer, isSetup) => {
|
|
6273
|
-
if (handlingMobileReturnRef.current) return;
|
|
6274
|
-
handlingMobileReturnRef.current = true;
|
|
6275
|
-
polling.stopPolling();
|
|
6276
|
-
if (isSetup) {
|
|
6277
|
-
mobileSetupFlowRef.current = false;
|
|
6278
|
-
clearMobileFlowState();
|
|
6279
|
-
try {
|
|
6280
|
-
await reloadAccounts();
|
|
6281
|
-
loadingDataRef.current = false;
|
|
6282
|
-
dispatch({ type: "MOBILE_SETUP_COMPLETE", transfer: authorizedTransfer });
|
|
6283
|
-
} catch (err) {
|
|
6284
|
-
handlingMobileReturnRef.current = false;
|
|
6285
|
-
dispatch({
|
|
6286
|
-
type: "SET_ERROR",
|
|
6287
|
-
error: err instanceof Error ? err.message : "Wallet authorized, but we could not refresh your account yet."
|
|
6288
|
-
});
|
|
6289
|
-
dispatch({ type: "NAVIGATE", step: "open-wallet" });
|
|
6290
|
-
}
|
|
6291
|
-
return;
|
|
6292
|
-
}
|
|
6293
|
-
mobileSetupFlowRef.current = false;
|
|
6294
|
-
clearMobileFlowState();
|
|
6295
|
-
dispatch({ type: "MOBILE_SIGN_READY", transfer: authorizedTransfer });
|
|
6296
|
-
}, [polling.stopPolling, reloadAccounts]);
|
|
6297
|
-
handleAuthorizedMobileReturnRef.current = handleAuthorizedMobileReturn;
|
|
6231
|
+
}, [getAccessToken, activeCredentialId, selectedAccountId, apiBaseUrl, depositAmount, dispatch]);
|
|
6298
6232
|
const handlePay = react.useCallback(async (payAmount, sourceOverrides) => {
|
|
6299
6233
|
if (isNaN(payAmount) || payAmount < MIN_SEND_AMOUNT_USD) {
|
|
6300
6234
|
dispatch({ type: "SET_ERROR", error: `Minimum amount is $${MIN_SEND_AMOUNT_USD.toFixed(2)}.` });
|
|
@@ -6304,7 +6238,7 @@ function SwypePaymentInner({
|
|
|
6304
6238
|
dispatch({ type: "SET_ERROR", error: "No account or provider selected." });
|
|
6305
6239
|
return;
|
|
6306
6240
|
}
|
|
6307
|
-
if (!
|
|
6241
|
+
if (!activeCredentialId) {
|
|
6308
6242
|
dispatch({ type: "SET_ERROR", error: "Create or verify a passkey on this device before continuing." });
|
|
6309
6243
|
dispatch({ type: "NAVIGATE", step: "create-passkey" });
|
|
6310
6244
|
return;
|
|
@@ -6312,10 +6246,10 @@ function SwypePaymentInner({
|
|
|
6312
6246
|
dispatch({ type: "PAY_STARTED", isSetupRedirect: false });
|
|
6313
6247
|
processingStartedAtRef.current = Date.now();
|
|
6314
6248
|
try {
|
|
6315
|
-
if (
|
|
6316
|
-
const signedTransfer2 = await transferSigning.signTransfer(
|
|
6249
|
+
if (transfer?.status === "AUTHORIZED") {
|
|
6250
|
+
const signedTransfer2 = await transferSigning.signTransfer(transfer.id);
|
|
6317
6251
|
dispatch({ type: "TRANSFER_SIGNED", transfer: signedTransfer2 });
|
|
6318
|
-
polling.startPolling(
|
|
6252
|
+
polling.startPolling(transfer.id);
|
|
6319
6253
|
return;
|
|
6320
6254
|
}
|
|
6321
6255
|
const token = await getAccessToken();
|
|
@@ -6323,7 +6257,7 @@ function SwypePaymentInner({
|
|
|
6323
6257
|
let effectiveSourceType = sourceOverrides?.sourceType ?? sourceType;
|
|
6324
6258
|
let effectiveSourceId = sourceOverrides?.sourceId ?? sourceId;
|
|
6325
6259
|
if (effectiveSourceType === "accountId") {
|
|
6326
|
-
const acct =
|
|
6260
|
+
const acct = accounts.find((a) => a.id === effectiveSourceId);
|
|
6327
6261
|
const preferredWallet = acct ? getPreferredDepositWallet(acct, payAmount) : null;
|
|
6328
6262
|
if (preferredWallet?.status === "ACTIVE") {
|
|
6329
6263
|
effectiveSourceType = "walletId";
|
|
@@ -6332,10 +6266,11 @@ function SwypePaymentInner({
|
|
|
6332
6266
|
}
|
|
6333
6267
|
const t = await createTransfer(apiBaseUrl, token, {
|
|
6334
6268
|
id: idempotencyKey,
|
|
6335
|
-
credentialId:
|
|
6269
|
+
credentialId: activeCredentialId,
|
|
6336
6270
|
merchantAuthorization,
|
|
6337
6271
|
sourceType: effectiveSourceType,
|
|
6338
6272
|
sourceId: effectiveSourceId,
|
|
6273
|
+
sourceTokenAddress,
|
|
6339
6274
|
destination,
|
|
6340
6275
|
amount: payAmount
|
|
6341
6276
|
});
|
|
@@ -6355,11 +6290,7 @@ function SwypePaymentInner({
|
|
|
6355
6290
|
} catch (err) {
|
|
6356
6291
|
captureException(err);
|
|
6357
6292
|
const msg = err instanceof Error ? err.message : "Transfer failed";
|
|
6358
|
-
dispatch({
|
|
6359
|
-
type: "PAY_ERROR",
|
|
6360
|
-
error: msg,
|
|
6361
|
-
fallbackStep: "deposit"
|
|
6362
|
-
});
|
|
6293
|
+
dispatch({ type: "PAY_ERROR", error: msg, fallbackStep: "deposit" });
|
|
6363
6294
|
onError?.(msg);
|
|
6364
6295
|
} finally {
|
|
6365
6296
|
dispatch({ type: "PAY_ENDED" });
|
|
@@ -6367,9 +6298,10 @@ function SwypePaymentInner({
|
|
|
6367
6298
|
}, [
|
|
6368
6299
|
sourceId,
|
|
6369
6300
|
sourceType,
|
|
6370
|
-
|
|
6371
|
-
|
|
6372
|
-
|
|
6301
|
+
sourceTokenAddress,
|
|
6302
|
+
activeCredentialId,
|
|
6303
|
+
transfer,
|
|
6304
|
+
accounts,
|
|
6373
6305
|
destination,
|
|
6374
6306
|
apiBaseUrl,
|
|
6375
6307
|
getAccessToken,
|
|
@@ -6378,51 +6310,222 @@ function SwypePaymentInner({
|
|
|
6378
6310
|
onError,
|
|
6379
6311
|
onComplete,
|
|
6380
6312
|
idempotencyKey,
|
|
6381
|
-
merchantAuthorization
|
|
6313
|
+
merchantAuthorization,
|
|
6314
|
+
dispatch
|
|
6382
6315
|
]);
|
|
6383
|
-
const
|
|
6384
|
-
|
|
6385
|
-
|
|
6316
|
+
const handleConfirmSign = react.useCallback(async () => {
|
|
6317
|
+
const t = transfer ?? polling.transfer;
|
|
6318
|
+
if (!t) return;
|
|
6319
|
+
try {
|
|
6320
|
+
const signedTransfer = await transferSigning.signTransfer(t.id);
|
|
6321
|
+
clearMobileFlowState();
|
|
6322
|
+
dispatch({ type: "CONFIRM_SIGN_SUCCESS", transfer: signedTransfer });
|
|
6323
|
+
polling.startPolling(t.id);
|
|
6324
|
+
} catch (err) {
|
|
6325
|
+
captureException(err);
|
|
6326
|
+
const msg = err instanceof Error ? err.message : "Failed to sign transfer";
|
|
6327
|
+
dispatch({ type: "SET_ERROR", error: msg });
|
|
6328
|
+
onError?.(msg);
|
|
6329
|
+
}
|
|
6330
|
+
}, [transfer, polling.transfer, polling.startPolling, transferSigning, onError, dispatch]);
|
|
6331
|
+
return {
|
|
6332
|
+
reloadAccounts,
|
|
6333
|
+
handlePay,
|
|
6334
|
+
handleConfirmSign,
|
|
6335
|
+
processingStartedAtRef,
|
|
6336
|
+
pollingTransferIdRef
|
|
6337
|
+
};
|
|
6338
|
+
}
|
|
6339
|
+
function useSourceSelectionHandlers(dispatch, authExecutor) {
|
|
6340
|
+
const [selectSourceChainName, setSelectSourceChainName] = react.useState("");
|
|
6341
|
+
const [selectSourceTokenSymbol, setSelectSourceTokenSymbol] = react.useState("");
|
|
6342
|
+
const initializedSelectSourceActionRef = react.useRef(null);
|
|
6343
|
+
const preSelectSourceStepRef = react.useRef(null);
|
|
6344
|
+
const pendingSelectSourceAction = authExecutor.pendingSelectSource;
|
|
6345
|
+
const selectSourceChoices = react.useMemo(() => {
|
|
6346
|
+
if (!pendingSelectSourceAction) return [];
|
|
6347
|
+
const options = pendingSelectSourceAction.metadata?.options ?? [];
|
|
6348
|
+
return buildSelectSourceChoices(options);
|
|
6349
|
+
}, [pendingSelectSourceAction]);
|
|
6350
|
+
const selectSourceRecommended = react.useMemo(() => {
|
|
6351
|
+
if (!pendingSelectSourceAction) return null;
|
|
6352
|
+
return pendingSelectSourceAction.metadata?.recommended ?? null;
|
|
6353
|
+
}, [pendingSelectSourceAction]);
|
|
6354
|
+
const selectSourceAvailableBalance = react.useMemo(() => {
|
|
6355
|
+
if (!pendingSelectSourceAction) return 0;
|
|
6356
|
+
const options = pendingSelectSourceAction.metadata?.options ?? [];
|
|
6357
|
+
const recommended = selectSourceRecommended;
|
|
6358
|
+
if (recommended) {
|
|
6359
|
+
const match = options.find(
|
|
6360
|
+
(opt) => opt.chainName === recommended.chainName && opt.tokenSymbol === recommended.tokenSymbol
|
|
6361
|
+
);
|
|
6362
|
+
if (match) return Number(match.rawBalance) / Math.pow(10, match.decimals);
|
|
6363
|
+
}
|
|
6364
|
+
let max = 0;
|
|
6365
|
+
for (const opt of options) {
|
|
6366
|
+
const bal = Number(opt.rawBalance) / Math.pow(10, opt.decimals);
|
|
6367
|
+
if (bal > max) max = bal;
|
|
6368
|
+
}
|
|
6369
|
+
return max;
|
|
6370
|
+
}, [pendingSelectSourceAction, selectSourceRecommended]);
|
|
6371
|
+
const handleSelectSourceChainChange = react.useCallback(
|
|
6372
|
+
(chainName) => {
|
|
6373
|
+
setSelectSourceChainName(chainName);
|
|
6374
|
+
const chain = selectSourceChoices.find((c) => c.chainName === chainName);
|
|
6375
|
+
if (!chain || chain.tokens.length === 0) return;
|
|
6376
|
+
const recommendedToken = selectSourceRecommended?.chainName === chainName ? selectSourceRecommended.tokenSymbol : null;
|
|
6377
|
+
const hasRecommended = !!recommendedToken && chain.tokens.some((t) => t.tokenSymbol === recommendedToken);
|
|
6378
|
+
setSelectSourceTokenSymbol(
|
|
6379
|
+
hasRecommended ? recommendedToken : chain.tokens[0].tokenSymbol
|
|
6380
|
+
);
|
|
6381
|
+
},
|
|
6382
|
+
[selectSourceChoices, selectSourceRecommended]
|
|
6383
|
+
);
|
|
6384
|
+
const handleConfirmSelectSource = react.useCallback(() => {
|
|
6385
|
+
authExecutor.resolveSelectSource({
|
|
6386
|
+
chainName: selectSourceChainName,
|
|
6387
|
+
tokenSymbol: selectSourceTokenSymbol
|
|
6388
|
+
});
|
|
6389
|
+
}, [authExecutor, selectSourceChainName, selectSourceTokenSymbol]);
|
|
6390
|
+
return {
|
|
6391
|
+
selectSourceChainName,
|
|
6392
|
+
selectSourceTokenSymbol,
|
|
6393
|
+
setSelectSourceChainName,
|
|
6394
|
+
setSelectSourceTokenSymbol,
|
|
6395
|
+
selectSourceChoices,
|
|
6396
|
+
selectSourceRecommended,
|
|
6397
|
+
selectSourceAvailableBalance,
|
|
6398
|
+
handleSelectSourceChainChange,
|
|
6399
|
+
handleConfirmSelectSource,
|
|
6400
|
+
pendingSelectSourceAction,
|
|
6401
|
+
initializedSelectSourceActionRef,
|
|
6402
|
+
preSelectSourceStepRef
|
|
6403
|
+
};
|
|
6404
|
+
}
|
|
6405
|
+
function useMobileFlowHandlers(dispatch, polling, reloadAccounts, pollingTransferIdRef, stateTransfer, refs) {
|
|
6406
|
+
const {
|
|
6407
|
+
mobileSetupFlowRef,
|
|
6408
|
+
handlingMobileReturnRef,
|
|
6409
|
+
loadingDataRef
|
|
6410
|
+
} = refs;
|
|
6411
|
+
const handleAuthorizedMobileReturn = react.useCallback(async (authorizedTransfer, isSetup) => {
|
|
6412
|
+
if (handlingMobileReturnRef.current) return;
|
|
6413
|
+
handlingMobileReturnRef.current = true;
|
|
6414
|
+
polling.stopPolling();
|
|
6415
|
+
if (isSetup) {
|
|
6416
|
+
mobileSetupFlowRef.current = false;
|
|
6417
|
+
clearMobileFlowState();
|
|
6418
|
+
try {
|
|
6419
|
+
await reloadAccounts();
|
|
6420
|
+
loadingDataRef.current = false;
|
|
6421
|
+
dispatch({ type: "MOBILE_SETUP_COMPLETE", transfer: authorizedTransfer });
|
|
6422
|
+
} catch (err) {
|
|
6423
|
+
handlingMobileReturnRef.current = false;
|
|
6424
|
+
dispatch({
|
|
6425
|
+
type: "SET_ERROR",
|
|
6426
|
+
error: err instanceof Error ? err.message : "Wallet authorized, but we could not refresh your account yet."
|
|
6427
|
+
});
|
|
6428
|
+
dispatch({ type: "NAVIGATE", step: "open-wallet" });
|
|
6429
|
+
}
|
|
6430
|
+
return;
|
|
6431
|
+
}
|
|
6432
|
+
mobileSetupFlowRef.current = false;
|
|
6433
|
+
clearMobileFlowState();
|
|
6434
|
+
dispatch({ type: "MOBILE_SIGN_READY", transfer: authorizedTransfer });
|
|
6435
|
+
}, [polling.stopPolling, reloadAccounts, dispatch]);
|
|
6436
|
+
const handleRetryMobileStatus = react.useCallback(() => {
|
|
6437
|
+
dispatch({ type: "SET_ERROR", error: null });
|
|
6438
|
+
handlingMobileReturnRef.current = false;
|
|
6439
|
+
const currentTransfer = polling.transfer ?? stateTransfer;
|
|
6440
|
+
if (currentTransfer?.status === "AUTHORIZED") {
|
|
6441
|
+
void handleAuthorizedMobileReturn(currentTransfer, mobileSetupFlowRef.current);
|
|
6386
6442
|
return;
|
|
6387
6443
|
}
|
|
6388
|
-
|
|
6444
|
+
const transferIdToResume = pollingTransferIdRef.current ?? currentTransfer?.id;
|
|
6445
|
+
if (transferIdToResume) {
|
|
6446
|
+
polling.startPolling(transferIdToResume);
|
|
6447
|
+
}
|
|
6448
|
+
}, [handleAuthorizedMobileReturn, polling, stateTransfer, pollingTransferIdRef, dispatch]);
|
|
6449
|
+
return {
|
|
6450
|
+
handleAuthorizedMobileReturn,
|
|
6451
|
+
handleRetryMobileStatus
|
|
6452
|
+
};
|
|
6453
|
+
}
|
|
6454
|
+
|
|
6455
|
+
// src/walletFlow.ts
|
|
6456
|
+
var MOBILE_USER_AGENT_PATTERN = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i;
|
|
6457
|
+
function isMobileUserAgent(userAgent) {
|
|
6458
|
+
if (!userAgent) {
|
|
6459
|
+
return false;
|
|
6460
|
+
}
|
|
6461
|
+
return MOBILE_USER_AGENT_PATTERN.test(userAgent);
|
|
6462
|
+
}
|
|
6463
|
+
function shouldUseWalletConnector(options) {
|
|
6464
|
+
return options.useWalletConnector ?? !isMobileUserAgent(options.userAgent);
|
|
6465
|
+
}
|
|
6466
|
+
|
|
6467
|
+
// src/hooks/useProviderHandlers.ts
|
|
6468
|
+
function useProviderHandlers(deps) {
|
|
6469
|
+
const {
|
|
6470
|
+
dispatch,
|
|
6471
|
+
getAccessToken,
|
|
6472
|
+
apiBaseUrl,
|
|
6473
|
+
depositAmount,
|
|
6474
|
+
useWalletConnectorProp,
|
|
6475
|
+
activeCredentialId,
|
|
6476
|
+
selectedAccountId,
|
|
6477
|
+
accounts,
|
|
6478
|
+
providers,
|
|
6479
|
+
authExecutor,
|
|
6480
|
+
reloadAccounts,
|
|
6481
|
+
onError,
|
|
6482
|
+
mobileSetupFlowRef,
|
|
6483
|
+
handlingMobileReturnRef,
|
|
6484
|
+
setupAccountIdRef,
|
|
6485
|
+
reauthSessionIdRef,
|
|
6486
|
+
reauthTokenRef
|
|
6487
|
+
} = deps;
|
|
6488
|
+
const handleSelectProvider = react.useCallback(async (providerId) => {
|
|
6489
|
+
dispatch({ type: "SELECT_PROVIDER", providerId });
|
|
6490
|
+
if (!activeCredentialId) {
|
|
6389
6491
|
dispatch({ type: "SET_ERROR", error: "Create or verify a passkey on this device before continuing." });
|
|
6390
6492
|
dispatch({ type: "NAVIGATE", step: "create-passkey" });
|
|
6391
6493
|
return;
|
|
6392
6494
|
}
|
|
6393
|
-
const
|
|
6394
|
-
const
|
|
6395
|
-
|
|
6396
|
-
|
|
6495
|
+
const provider = providers.find((p) => p.id === providerId);
|
|
6496
|
+
const providerName = provider?.name ?? "Wallet";
|
|
6497
|
+
const isMobile = !shouldUseWalletConnector({
|
|
6498
|
+
useWalletConnector: useWalletConnectorProp,
|
|
6499
|
+
userAgent: typeof navigator === "undefined" ? void 0 : navigator.userAgent
|
|
6500
|
+
});
|
|
6501
|
+
if (isMobile) {
|
|
6502
|
+
dispatch({ type: "PAY_STARTED", isSetupRedirect: true });
|
|
6503
|
+
} else {
|
|
6504
|
+
dispatch({ type: "PAY_STARTED", isSetupRedirect: false });
|
|
6505
|
+
dispatch({ type: "NAVIGATE", step: "setup-status" });
|
|
6397
6506
|
}
|
|
6398
|
-
dispatch({ type: "SET_ERROR", error: null });
|
|
6399
|
-
dispatch({ type: "SET_INCREASING_LIMIT", value: true });
|
|
6400
6507
|
try {
|
|
6401
6508
|
const token = await getAccessToken();
|
|
6402
6509
|
if (!token) throw new Error("Not authenticated");
|
|
6403
|
-
const
|
|
6404
|
-
|
|
6405
|
-
|
|
6406
|
-
|
|
6407
|
-
|
|
6408
|
-
|
|
6409
|
-
const isMobile = !shouldUseWalletConnector({
|
|
6410
|
-
useWalletConnector: useWalletConnectorProp,
|
|
6411
|
-
userAgent: typeof navigator === "undefined" ? void 0 : navigator.userAgent
|
|
6510
|
+
const accountId = crypto.randomUUID();
|
|
6511
|
+
const account = await createAccount(apiBaseUrl, token, {
|
|
6512
|
+
id: accountId,
|
|
6513
|
+
name: providerName,
|
|
6514
|
+
credentialId: activeCredentialId,
|
|
6515
|
+
providerId
|
|
6412
6516
|
});
|
|
6517
|
+
const session = account.authorizationSessions?.[0];
|
|
6518
|
+
if (!session) throw new Error("No authorization session returned.");
|
|
6413
6519
|
if (isMobile) {
|
|
6414
6520
|
handlingMobileReturnRef.current = false;
|
|
6415
6521
|
mobileSetupFlowRef.current = true;
|
|
6416
|
-
setupAccountIdRef.current =
|
|
6417
|
-
reauthSessionIdRef.current = session.id;
|
|
6418
|
-
reauthTokenRef.current = null;
|
|
6522
|
+
setupAccountIdRef.current = account.id;
|
|
6419
6523
|
persistMobileFlowState({
|
|
6420
|
-
accountId:
|
|
6524
|
+
accountId: account.id,
|
|
6421
6525
|
sessionId: session.id,
|
|
6422
6526
|
deeplinkUri: session.uri,
|
|
6423
|
-
providerId
|
|
6424
|
-
isSetup: true
|
|
6425
|
-
isReauthorization: true
|
|
6527
|
+
providerId,
|
|
6528
|
+
isSetup: true
|
|
6426
6529
|
});
|
|
6427
6530
|
dispatch({ type: "MOBILE_DEEPLINK_READY", deeplinkUri: session.uri });
|
|
6428
6531
|
triggerDeeplink(session.uri);
|
|
@@ -6433,57 +6536,75 @@ function SwypePaymentInner({
|
|
|
6433
6536
|
}
|
|
6434
6537
|
} catch (err) {
|
|
6435
6538
|
captureException(err);
|
|
6436
|
-
const msg = err instanceof Error ? err.message : "Failed to
|
|
6437
|
-
dispatch({ type: "
|
|
6539
|
+
const msg = err instanceof Error ? err.message : "Failed to set up wallet";
|
|
6540
|
+
dispatch({ type: "PAY_ERROR", error: msg, fallbackStep: "wallet-picker" });
|
|
6438
6541
|
onError?.(msg);
|
|
6439
6542
|
} finally {
|
|
6440
|
-
dispatch({ type: "
|
|
6543
|
+
dispatch({ type: "PAY_ENDED" });
|
|
6441
6544
|
}
|
|
6442
6545
|
}, [
|
|
6443
|
-
|
|
6444
|
-
|
|
6445
|
-
state.accounts,
|
|
6446
|
-
state.providers,
|
|
6546
|
+
activeCredentialId,
|
|
6547
|
+
providers,
|
|
6447
6548
|
apiBaseUrl,
|
|
6448
6549
|
getAccessToken,
|
|
6449
6550
|
authExecutor,
|
|
6450
6551
|
useWalletConnectorProp,
|
|
6451
6552
|
reloadAccounts,
|
|
6452
|
-
onError
|
|
6553
|
+
onError,
|
|
6554
|
+
dispatch,
|
|
6555
|
+
mobileSetupFlowRef,
|
|
6556
|
+
handlingMobileReturnRef,
|
|
6557
|
+
setupAccountIdRef
|
|
6453
6558
|
]);
|
|
6454
|
-
const
|
|
6455
|
-
|
|
6456
|
-
|
|
6457
|
-
|
|
6458
|
-
|
|
6459
|
-
|
|
6460
|
-
|
|
6461
|
-
|
|
6559
|
+
const handleContinueConnection = react.useCallback(
|
|
6560
|
+
(accountId) => {
|
|
6561
|
+
const acct = accounts.find((a) => a.id === accountId);
|
|
6562
|
+
if (!acct) return;
|
|
6563
|
+
const matchedProvider = providers.find((p) => p.name === acct.name);
|
|
6564
|
+
if (matchedProvider) {
|
|
6565
|
+
handleSelectProvider(matchedProvider.id);
|
|
6566
|
+
}
|
|
6567
|
+
},
|
|
6568
|
+
[accounts, providers, handleSelectProvider]
|
|
6569
|
+
);
|
|
6570
|
+
const handleSelectAccount = react.useCallback(
|
|
6571
|
+
(accountId) => {
|
|
6572
|
+
const acct = accounts.find((a) => a.id === accountId);
|
|
6573
|
+
if (!acct) return;
|
|
6574
|
+
const activeWallet = getPreferredDepositWallet(acct, depositAmount ?? 0);
|
|
6575
|
+
dispatch({
|
|
6576
|
+
type: "SELECT_ACCOUNT",
|
|
6577
|
+
accountId,
|
|
6578
|
+
walletId: activeWallet?.id ?? null
|
|
6579
|
+
});
|
|
6580
|
+
},
|
|
6581
|
+
[accounts, depositAmount, dispatch]
|
|
6582
|
+
);
|
|
6583
|
+
const handleIncreaseLimit = react.useCallback(async () => {
|
|
6584
|
+
if (!selectedAccountId) {
|
|
6462
6585
|
dispatch({ type: "SET_ERROR", error: "No account selected." });
|
|
6463
6586
|
return;
|
|
6464
6587
|
}
|
|
6465
|
-
if (!
|
|
6588
|
+
if (!activeCredentialId) {
|
|
6466
6589
|
dispatch({ type: "SET_ERROR", error: "Create or verify a passkey on this device before continuing." });
|
|
6467
6590
|
dispatch({ type: "NAVIGATE", step: "create-passkey" });
|
|
6468
6591
|
return;
|
|
6469
6592
|
}
|
|
6470
|
-
const acct =
|
|
6471
|
-
const matchedProvider = acct ?
|
|
6593
|
+
const acct = accounts.find((a) => a.id === selectedAccountId);
|
|
6594
|
+
const matchedProvider = acct ? providers.find((p) => p.name === acct.name) : void 0;
|
|
6472
6595
|
if (matchedProvider) {
|
|
6473
6596
|
dispatch({ type: "SELECT_PROVIDER", providerId: matchedProvider.id });
|
|
6474
6597
|
}
|
|
6475
6598
|
dispatch({ type: "SET_ERROR", error: null });
|
|
6476
6599
|
dispatch({ type: "SET_INCREASING_LIMIT", value: true });
|
|
6477
|
-
pendingTokenAuthRef.current = { tokenAddress, chainId, tokenSymbol, walletId: _walletId };
|
|
6478
6600
|
try {
|
|
6479
6601
|
const token = await getAccessToken();
|
|
6480
6602
|
if (!token) throw new Error("Not authenticated");
|
|
6481
6603
|
const session = await createAccountAuthorizationSession(
|
|
6482
6604
|
apiBaseUrl,
|
|
6483
6605
|
token,
|
|
6484
|
-
|
|
6485
|
-
|
|
6486
|
-
{ tokenAddress, chainId }
|
|
6606
|
+
selectedAccountId,
|
|
6607
|
+
activeCredentialId
|
|
6487
6608
|
);
|
|
6488
6609
|
const isMobile = !shouldUseWalletConnector({
|
|
6489
6610
|
useWalletConnector: useWalletConnectorProp,
|
|
@@ -6492,205 +6613,187 @@ function SwypePaymentInner({
|
|
|
6492
6613
|
if (isMobile) {
|
|
6493
6614
|
handlingMobileReturnRef.current = false;
|
|
6494
6615
|
mobileSetupFlowRef.current = true;
|
|
6495
|
-
setupAccountIdRef.current =
|
|
6616
|
+
setupAccountIdRef.current = selectedAccountId;
|
|
6496
6617
|
reauthSessionIdRef.current = session.id;
|
|
6497
|
-
reauthTokenRef.current =
|
|
6618
|
+
reauthTokenRef.current = null;
|
|
6498
6619
|
persistMobileFlowState({
|
|
6499
|
-
accountId:
|
|
6620
|
+
accountId: selectedAccountId,
|
|
6500
6621
|
sessionId: session.id,
|
|
6501
6622
|
deeplinkUri: session.uri,
|
|
6502
6623
|
providerId: matchedProvider?.id ?? null,
|
|
6503
6624
|
isSetup: true,
|
|
6504
|
-
isReauthorization: true
|
|
6505
|
-
reauthorizationToken: { walletId: _walletId, tokenSymbol }
|
|
6625
|
+
isReauthorization: true
|
|
6506
6626
|
});
|
|
6507
6627
|
dispatch({ type: "MOBILE_DEEPLINK_READY", deeplinkUri: session.uri });
|
|
6508
6628
|
triggerDeeplink(session.uri);
|
|
6509
6629
|
} else {
|
|
6510
|
-
|
|
6511
|
-
|
|
6512
|
-
|
|
6513
|
-
|
|
6514
|
-
tokenAddress,
|
|
6515
|
-
chainId
|
|
6516
|
-
};
|
|
6517
|
-
dispatch({ type: "SELECT_TOKEN", walletId: _walletId, tokenSymbol });
|
|
6518
|
-
dispatch({ type: "NAVIGATE", step: "setup" });
|
|
6630
|
+
dispatch({ type: "NAVIGATE", step: "setup-status" });
|
|
6631
|
+
await authExecutor.executeSessionById(session.id);
|
|
6632
|
+
await reloadAccounts();
|
|
6633
|
+
dispatch({ type: "NAVIGATE", step: "deposit" });
|
|
6519
6634
|
}
|
|
6520
6635
|
} catch (err) {
|
|
6521
6636
|
captureException(err);
|
|
6522
|
-
const msg = err instanceof Error ? err.message : "Failed to
|
|
6637
|
+
const msg = err instanceof Error ? err.message : "Failed to increase limit";
|
|
6523
6638
|
dispatch({ type: "SET_ERROR", error: msg });
|
|
6524
6639
|
onError?.(msg);
|
|
6525
6640
|
} finally {
|
|
6526
|
-
pendingTokenAuthRef.current = null;
|
|
6527
6641
|
dispatch({ type: "SET_INCREASING_LIMIT", value: false });
|
|
6528
6642
|
}
|
|
6529
6643
|
}, [
|
|
6530
|
-
|
|
6531
|
-
|
|
6532
|
-
|
|
6533
|
-
|
|
6644
|
+
selectedAccountId,
|
|
6645
|
+
activeCredentialId,
|
|
6646
|
+
accounts,
|
|
6647
|
+
providers,
|
|
6534
6648
|
apiBaseUrl,
|
|
6535
6649
|
getAccessToken,
|
|
6536
6650
|
authExecutor,
|
|
6537
6651
|
useWalletConnectorProp,
|
|
6538
6652
|
reloadAccounts,
|
|
6539
|
-
onError
|
|
6653
|
+
onError,
|
|
6654
|
+
dispatch,
|
|
6655
|
+
mobileSetupFlowRef,
|
|
6656
|
+
handlingMobileReturnRef,
|
|
6657
|
+
setupAccountIdRef,
|
|
6658
|
+
reauthSessionIdRef,
|
|
6659
|
+
reauthTokenRef
|
|
6540
6660
|
]);
|
|
6541
|
-
const
|
|
6542
|
-
|
|
6543
|
-
|
|
6544
|
-
|
|
6545
|
-
|
|
6546
|
-
clearMobileFlowState();
|
|
6547
|
-
dispatch({ type: "CONFIRM_SIGN_SUCCESS", transfer: signedTransfer });
|
|
6548
|
-
polling.startPolling(t.id);
|
|
6549
|
-
} catch (err) {
|
|
6550
|
-
captureException(err);
|
|
6551
|
-
const msg = err instanceof Error ? err.message : "Failed to sign transfer";
|
|
6552
|
-
dispatch({ type: "SET_ERROR", error: msg });
|
|
6553
|
-
onError?.(msg);
|
|
6661
|
+
const handleNavigateToTokenPicker = react.useCallback(() => {
|
|
6662
|
+
if (authExecutor.pendingSelectSource) {
|
|
6663
|
+
dispatch({ type: "NAVIGATE", step: "select-source" });
|
|
6664
|
+
} else {
|
|
6665
|
+
dispatch({ type: "NAVIGATE", step: "token-picker" });
|
|
6554
6666
|
}
|
|
6555
|
-
}, [
|
|
6556
|
-
const
|
|
6557
|
-
dispatch({ type: "
|
|
6558
|
-
|
|
6559
|
-
|
|
6560
|
-
if (
|
|
6561
|
-
|
|
6667
|
+
}, [dispatch, authExecutor.pendingSelectSource]);
|
|
6668
|
+
const handleSelectAuthorizedToken = react.useCallback((walletId, tokenSymbol) => {
|
|
6669
|
+
dispatch({ type: "SELECT_TOKEN", walletId, tokenSymbol });
|
|
6670
|
+
}, [dispatch]);
|
|
6671
|
+
const handleAuthorizeToken = react.useCallback(async (_walletId, tokenAddress, chainId, tokenSymbol) => {
|
|
6672
|
+
if (!selectedAccountId) {
|
|
6673
|
+
dispatch({ type: "SET_ERROR", error: "No account selected." });
|
|
6562
6674
|
return;
|
|
6563
6675
|
}
|
|
6564
|
-
|
|
6565
|
-
if (transferIdToResume) {
|
|
6566
|
-
polling.startPolling(transferIdToResume);
|
|
6567
|
-
}
|
|
6568
|
-
}, [handleAuthorizedMobileReturn, polling, state.transfer]);
|
|
6569
|
-
const handleSelectProvider = react.useCallback(async (providerId) => {
|
|
6570
|
-
dispatch({ type: "SELECT_PROVIDER", providerId });
|
|
6571
|
-
if (!state.activeCredentialId) {
|
|
6676
|
+
if (!activeCredentialId) {
|
|
6572
6677
|
dispatch({ type: "SET_ERROR", error: "Create or verify a passkey on this device before continuing." });
|
|
6573
6678
|
dispatch({ type: "NAVIGATE", step: "create-passkey" });
|
|
6574
6679
|
return;
|
|
6575
6680
|
}
|
|
6576
|
-
const
|
|
6577
|
-
const
|
|
6578
|
-
|
|
6579
|
-
|
|
6580
|
-
userAgent: typeof navigator === "undefined" ? void 0 : navigator.userAgent
|
|
6581
|
-
});
|
|
6582
|
-
if (isMobile) {
|
|
6583
|
-
dispatch({ type: "PAY_STARTED", isSetupRedirect: true });
|
|
6584
|
-
} else {
|
|
6585
|
-
dispatch({ type: "PAY_STARTED", isSetupRedirect: false });
|
|
6586
|
-
dispatch({ type: "NAVIGATE", step: "setup-status" });
|
|
6681
|
+
const acct = accounts.find((a) => a.id === selectedAccountId);
|
|
6682
|
+
const matchedProvider = acct ? providers.find((p) => p.name === acct.name) : void 0;
|
|
6683
|
+
if (matchedProvider) {
|
|
6684
|
+
dispatch({ type: "SELECT_PROVIDER", providerId: matchedProvider.id });
|
|
6587
6685
|
}
|
|
6686
|
+
dispatch({ type: "SET_ERROR", error: null });
|
|
6687
|
+
dispatch({ type: "SET_INCREASING_LIMIT", value: true });
|
|
6588
6688
|
try {
|
|
6589
6689
|
const token = await getAccessToken();
|
|
6590
6690
|
if (!token) throw new Error("Not authenticated");
|
|
6591
|
-
const
|
|
6592
|
-
|
|
6593
|
-
|
|
6594
|
-
|
|
6595
|
-
|
|
6596
|
-
|
|
6691
|
+
const session = await createAccountAuthorizationSession(
|
|
6692
|
+
apiBaseUrl,
|
|
6693
|
+
token,
|
|
6694
|
+
selectedAccountId,
|
|
6695
|
+
activeCredentialId,
|
|
6696
|
+
{ tokenAddress, chainId }
|
|
6697
|
+
);
|
|
6698
|
+
const isMobile = !shouldUseWalletConnector({
|
|
6699
|
+
useWalletConnector: useWalletConnectorProp,
|
|
6700
|
+
userAgent: typeof navigator === "undefined" ? void 0 : navigator.userAgent
|
|
6597
6701
|
});
|
|
6598
|
-
const session = account.authorizationSessions?.[0];
|
|
6599
|
-
if (!session) throw new Error("No authorization session returned.");
|
|
6600
6702
|
if (isMobile) {
|
|
6601
6703
|
handlingMobileReturnRef.current = false;
|
|
6602
6704
|
mobileSetupFlowRef.current = true;
|
|
6603
|
-
setupAccountIdRef.current =
|
|
6705
|
+
setupAccountIdRef.current = selectedAccountId;
|
|
6706
|
+
reauthSessionIdRef.current = session.id;
|
|
6707
|
+
reauthTokenRef.current = { walletId: _walletId, tokenSymbol };
|
|
6604
6708
|
persistMobileFlowState({
|
|
6605
|
-
accountId:
|
|
6709
|
+
accountId: selectedAccountId,
|
|
6606
6710
|
sessionId: session.id,
|
|
6607
6711
|
deeplinkUri: session.uri,
|
|
6608
|
-
providerId,
|
|
6609
|
-
isSetup: true
|
|
6712
|
+
providerId: matchedProvider?.id ?? null,
|
|
6713
|
+
isSetup: true,
|
|
6714
|
+
isReauthorization: true,
|
|
6715
|
+
reauthorizationToken: { walletId: _walletId, tokenSymbol }
|
|
6610
6716
|
});
|
|
6611
6717
|
dispatch({ type: "MOBILE_DEEPLINK_READY", deeplinkUri: session.uri });
|
|
6612
6718
|
triggerDeeplink(session.uri);
|
|
6613
6719
|
} else {
|
|
6720
|
+
dispatch({ type: "NAVIGATE", step: "setup-status" });
|
|
6614
6721
|
await authExecutor.executeSessionById(session.id);
|
|
6615
6722
|
await reloadAccounts();
|
|
6616
|
-
dispatch({ type: "
|
|
6723
|
+
dispatch({ type: "SELECT_TOKEN", walletId: _walletId, tokenSymbol });
|
|
6617
6724
|
}
|
|
6618
6725
|
} catch (err) {
|
|
6619
6726
|
captureException(err);
|
|
6620
|
-
const msg = err instanceof Error ? err.message : "Failed to
|
|
6621
|
-
dispatch({ type: "
|
|
6727
|
+
const msg = err instanceof Error ? err.message : "Failed to authorize token";
|
|
6728
|
+
dispatch({ type: "SET_ERROR", error: msg });
|
|
6622
6729
|
onError?.(msg);
|
|
6623
6730
|
} finally {
|
|
6624
|
-
dispatch({ type: "
|
|
6731
|
+
dispatch({ type: "SET_INCREASING_LIMIT", value: false });
|
|
6625
6732
|
}
|
|
6626
6733
|
}, [
|
|
6627
|
-
|
|
6628
|
-
|
|
6734
|
+
selectedAccountId,
|
|
6735
|
+
activeCredentialId,
|
|
6736
|
+
accounts,
|
|
6737
|
+
providers,
|
|
6629
6738
|
apiBaseUrl,
|
|
6630
6739
|
getAccessToken,
|
|
6631
6740
|
authExecutor,
|
|
6632
6741
|
useWalletConnectorProp,
|
|
6633
6742
|
reloadAccounts,
|
|
6634
|
-
onError
|
|
6743
|
+
onError,
|
|
6744
|
+
dispatch,
|
|
6745
|
+
mobileSetupFlowRef,
|
|
6746
|
+
handlingMobileReturnRef,
|
|
6747
|
+
setupAccountIdRef,
|
|
6748
|
+
reauthSessionIdRef,
|
|
6749
|
+
reauthTokenRef
|
|
6635
6750
|
]);
|
|
6636
|
-
|
|
6637
|
-
|
|
6638
|
-
|
|
6639
|
-
|
|
6640
|
-
|
|
6641
|
-
|
|
6642
|
-
|
|
6643
|
-
|
|
6644
|
-
|
|
6645
|
-
|
|
6646
|
-
|
|
6647
|
-
const
|
|
6648
|
-
|
|
6649
|
-
|
|
6650
|
-
|
|
6651
|
-
|
|
6652
|
-
|
|
6653
|
-
|
|
6654
|
-
|
|
6655
|
-
|
|
6656
|
-
|
|
6657
|
-
},
|
|
6658
|
-
[state.accounts, depositAmount]
|
|
6659
|
-
);
|
|
6751
|
+
return {
|
|
6752
|
+
handleSelectProvider,
|
|
6753
|
+
handleContinueConnection,
|
|
6754
|
+
handleSelectAccount,
|
|
6755
|
+
handleIncreaseLimit,
|
|
6756
|
+
handleNavigateToTokenPicker,
|
|
6757
|
+
handleSelectAuthorizedToken,
|
|
6758
|
+
handleAuthorizeToken
|
|
6759
|
+
};
|
|
6760
|
+
}
|
|
6761
|
+
function useOneTapSetupHandlers(deps) {
|
|
6762
|
+
const {
|
|
6763
|
+
dispatch,
|
|
6764
|
+
getAccessToken,
|
|
6765
|
+
apiBaseUrl,
|
|
6766
|
+
authExecutor,
|
|
6767
|
+
selectSourceChainName,
|
|
6768
|
+
selectSourceTokenSymbol
|
|
6769
|
+
} = deps;
|
|
6770
|
+
const [savingOneTapLimit, setSavingOneTapLimit] = react.useState(false);
|
|
6771
|
+
const oneTapLimitSavedDuringSetupRef = react.useRef(false);
|
|
6660
6772
|
const handleSetupOneTap = react.useCallback(async (limit) => {
|
|
6661
6773
|
setSavingOneTapLimit(true);
|
|
6662
6774
|
try {
|
|
6663
6775
|
const token = await getAccessToken();
|
|
6664
6776
|
if (!token) throw new Error("Not authenticated");
|
|
6665
6777
|
await updateUserConfig(apiBaseUrl, token, { defaultAllowance: limit });
|
|
6666
|
-
if (authExecutor.
|
|
6667
|
-
authExecutor.
|
|
6668
|
-
|
|
6669
|
-
|
|
6670
|
-
|
|
6671
|
-
|
|
6672
|
-
|
|
6673
|
-
|
|
6674
|
-
|
|
6675
|
-
|
|
6676
|
-
|
|
6677
|
-
|
|
6678
|
-
|
|
6679
|
-
try {
|
|
6680
|
-
await authExecutor.executeSessionById(pending.sessionId);
|
|
6681
|
-
await reloadAccounts();
|
|
6682
|
-
dispatch({ type: "SELECT_TOKEN", walletId: pending.walletId, tokenSymbol: pending.tokenSymbol });
|
|
6683
|
-
} catch (authErr) {
|
|
6684
|
-
captureException(authErr);
|
|
6685
|
-
dispatch({
|
|
6686
|
-
type: "SET_ERROR",
|
|
6687
|
-
error: authErr instanceof Error ? authErr.message : "Failed to authorize token"
|
|
6688
|
-
});
|
|
6689
|
-
dispatch({ type: "NAVIGATE", step: "deposit" });
|
|
6690
|
-
} finally {
|
|
6691
|
-
pendingTokenAuthRef.current = null;
|
|
6692
|
-
dispatch({ type: "SET_INCREASING_LIMIT", value: false });
|
|
6778
|
+
if (authExecutor.pendingSelectSource) {
|
|
6779
|
+
const action = authExecutor.pendingSelectSource;
|
|
6780
|
+
const recommended = action.metadata?.recommended;
|
|
6781
|
+
let chainName;
|
|
6782
|
+
let tokenSymbol;
|
|
6783
|
+
if (selectSourceChainName && selectSourceTokenSymbol) {
|
|
6784
|
+
chainName = selectSourceChainName;
|
|
6785
|
+
tokenSymbol = selectSourceTokenSymbol;
|
|
6786
|
+
} else {
|
|
6787
|
+
const options = action.metadata?.options ?? [];
|
|
6788
|
+
const choices = buildSelectSourceChoices(options);
|
|
6789
|
+
chainName = recommended?.chainName ?? choices[0]?.chainName ?? "Base";
|
|
6790
|
+
tokenSymbol = recommended?.tokenSymbol ?? choices[0]?.tokens[0]?.tokenSymbol ?? "USDC";
|
|
6693
6791
|
}
|
|
6792
|
+
oneTapLimitSavedDuringSetupRef.current = true;
|
|
6793
|
+
authExecutor.resolveSelectSource({ chainName, tokenSymbol });
|
|
6794
|
+
dispatch({ type: "NAVIGATE", step: "setup-status" });
|
|
6795
|
+
} else if (authExecutor.pendingOneTapSetup) {
|
|
6796
|
+
authExecutor.resolveOneTapSetup();
|
|
6694
6797
|
} else {
|
|
6695
6798
|
dispatch({ type: "NAVIGATE", step: "deposit" });
|
|
6696
6799
|
}
|
|
@@ -6703,76 +6806,118 @@ function SwypePaymentInner({
|
|
|
6703
6806
|
} finally {
|
|
6704
6807
|
setSavingOneTapLimit(false);
|
|
6705
6808
|
}
|
|
6706
|
-
}, [getAccessToken, apiBaseUrl, authExecutor,
|
|
6707
|
-
|
|
6708
|
-
|
|
6709
|
-
|
|
6710
|
-
|
|
6711
|
-
|
|
6712
|
-
|
|
6713
|
-
|
|
6714
|
-
|
|
6715
|
-
|
|
6716
|
-
|
|
6717
|
-
|
|
6718
|
-
|
|
6719
|
-
|
|
6720
|
-
|
|
6721
|
-
|
|
6722
|
-
|
|
6723
|
-
|
|
6724
|
-
|
|
6725
|
-
|
|
6726
|
-
|
|
6727
|
-
|
|
6728
|
-
|
|
6729
|
-
|
|
6730
|
-
|
|
6731
|
-
|
|
6732
|
-
|
|
6733
|
-
|
|
6734
|
-
|
|
6735
|
-
|
|
6736
|
-
|
|
6737
|
-
|
|
6738
|
-
|
|
6739
|
-
|
|
6740
|
-
|
|
6741
|
-
|
|
6742
|
-
|
|
6743
|
-
|
|
6744
|
-
|
|
6745
|
-
|
|
6746
|
-
|
|
6747
|
-
|
|
6748
|
-
|
|
6749
|
-
|
|
6750
|
-
|
|
6751
|
-
|
|
6752
|
-
|
|
6753
|
-
|
|
6754
|
-
|
|
6755
|
-
|
|
6756
|
-
|
|
6757
|
-
|
|
6758
|
-
|
|
6759
|
-
|
|
6760
|
-
|
|
6761
|
-
|
|
6762
|
-
|
|
6763
|
-
|
|
6764
|
-
|
|
6765
|
-
|
|
6766
|
-
|
|
6809
|
+
}, [getAccessToken, apiBaseUrl, authExecutor, dispatch, selectSourceChainName, selectSourceTokenSymbol]);
|
|
6810
|
+
return {
|
|
6811
|
+
handleSetupOneTap,
|
|
6812
|
+
savingOneTapLimit,
|
|
6813
|
+
oneTapLimitSavedDuringSetupRef
|
|
6814
|
+
};
|
|
6815
|
+
}
|
|
6816
|
+
|
|
6817
|
+
// src/dataLoading.ts
|
|
6818
|
+
function resolveDataLoadAction({
|
|
6819
|
+
authenticated,
|
|
6820
|
+
step,
|
|
6821
|
+
accountsCount,
|
|
6822
|
+
hasActiveCredential,
|
|
6823
|
+
loading
|
|
6824
|
+
}) {
|
|
6825
|
+
if (!authenticated || step === "login" || step === "otp-verify" || accountsCount > 0 || !hasActiveCredential) {
|
|
6826
|
+
return "reset";
|
|
6827
|
+
}
|
|
6828
|
+
if (loading) {
|
|
6829
|
+
return "wait";
|
|
6830
|
+
}
|
|
6831
|
+
return "load";
|
|
6832
|
+
}
|
|
6833
|
+
|
|
6834
|
+
// src/processingStatus.ts
|
|
6835
|
+
var PROCESSING_TIMEOUT_MS = 18e4;
|
|
6836
|
+
function resolvePreferredTransfer(polledTransfer, localTransfer) {
|
|
6837
|
+
return polledTransfer ?? localTransfer;
|
|
6838
|
+
}
|
|
6839
|
+
function getTransferStatus(polledTransfer, localTransfer) {
|
|
6840
|
+
const transfer = resolvePreferredTransfer(polledTransfer, localTransfer);
|
|
6841
|
+
return transfer?.status ?? "UNKNOWN";
|
|
6842
|
+
}
|
|
6843
|
+
function hasProcessingTimedOut(processingStartedAtMs, nowMs) {
|
|
6844
|
+
if (!processingStartedAtMs) return false;
|
|
6845
|
+
return nowMs - processingStartedAtMs >= PROCESSING_TIMEOUT_MS;
|
|
6846
|
+
}
|
|
6847
|
+
var STATUS_DISPLAY_LABELS = {
|
|
6848
|
+
CREATED: "created",
|
|
6849
|
+
AUTHORIZED: "authorized",
|
|
6850
|
+
SENDING: "sending",
|
|
6851
|
+
SENT: "confirming delivery",
|
|
6852
|
+
COMPLETED: "completed",
|
|
6853
|
+
FAILED: "failed"
|
|
6854
|
+
};
|
|
6855
|
+
function getStatusDisplayLabel(status) {
|
|
6856
|
+
return STATUS_DISPLAY_LABELS[status] ?? status;
|
|
6857
|
+
}
|
|
6858
|
+
function buildProcessingTimeoutMessage(status) {
|
|
6859
|
+
const label = getStatusDisplayLabel(status);
|
|
6860
|
+
return `Payment is taking longer than expected (status: ${label}). Please try again.`;
|
|
6861
|
+
}
|
|
6862
|
+
|
|
6863
|
+
// src/hooks/usePaymentEffects.ts
|
|
6864
|
+
function usePaymentEffects(deps) {
|
|
6865
|
+
const {
|
|
6866
|
+
state,
|
|
6867
|
+
dispatch,
|
|
6868
|
+
ready,
|
|
6869
|
+
authenticated,
|
|
6870
|
+
apiBaseUrl,
|
|
6871
|
+
depositAmount,
|
|
6872
|
+
useWalletConnectorProp,
|
|
6873
|
+
onComplete,
|
|
6874
|
+
onError,
|
|
6875
|
+
polling,
|
|
6876
|
+
authExecutor,
|
|
6877
|
+
reloadAccounts,
|
|
6878
|
+
activeOtpStatus,
|
|
6879
|
+
activeOtpErrorMessage,
|
|
6880
|
+
otpCode,
|
|
6881
|
+
handleVerifyLoginCode,
|
|
6882
|
+
setAuthInput,
|
|
6883
|
+
setOtpCode,
|
|
6884
|
+
mobileSetupFlowRef,
|
|
6885
|
+
handlingMobileReturnRef,
|
|
6886
|
+
setupAccountIdRef,
|
|
6887
|
+
reauthSessionIdRef,
|
|
6888
|
+
reauthTokenRef,
|
|
6889
|
+
loadingDataRef,
|
|
6890
|
+
pollingTransferIdRef,
|
|
6891
|
+
processingStartedAtRef,
|
|
6892
|
+
checkingPasskeyRef,
|
|
6893
|
+
pendingSelectSourceAction,
|
|
6894
|
+
selectSourceChoices,
|
|
6895
|
+
selectSourceRecommended,
|
|
6896
|
+
setSelectSourceChainName,
|
|
6897
|
+
setSelectSourceTokenSymbol,
|
|
6898
|
+
initializedSelectSourceActionRef,
|
|
6899
|
+
preSelectSourceStepRef,
|
|
6900
|
+
oneTapLimitSavedDuringSetupRef,
|
|
6901
|
+
handleAuthorizedMobileReturn
|
|
6902
|
+
} = deps;
|
|
6903
|
+
const { getAccessToken } = reactAuth.usePrivy();
|
|
6904
|
+
const onCompleteRef = react.useRef(onComplete);
|
|
6905
|
+
onCompleteRef.current = onComplete;
|
|
6906
|
+
const getAccessTokenRef = react.useRef(getAccessToken);
|
|
6907
|
+
getAccessTokenRef.current = getAccessToken;
|
|
6908
|
+
const pollingRef = react.useRef(polling);
|
|
6909
|
+
pollingRef.current = polling;
|
|
6910
|
+
const handleAuthorizedMobileReturnRef = react.useRef(handleAuthorizedMobileReturn);
|
|
6911
|
+
handleAuthorizedMobileReturnRef.current = handleAuthorizedMobileReturn;
|
|
6767
6912
|
react.useEffect(() => {
|
|
6768
6913
|
if (depositAmount != null) {
|
|
6769
6914
|
dispatch({ type: "SYNC_AMOUNT", amount: depositAmount.toString() });
|
|
6770
6915
|
}
|
|
6771
|
-
}, [depositAmount]);
|
|
6916
|
+
}, [depositAmount, dispatch]);
|
|
6772
6917
|
react.useEffect(() => {
|
|
6773
6918
|
if (authenticated || state.step !== "otp-verify") return;
|
|
6774
6919
|
if (activeOtpErrorMessage) dispatch({ type: "SET_ERROR", error: activeOtpErrorMessage });
|
|
6775
|
-
}, [activeOtpErrorMessage, authenticated, state.step]);
|
|
6920
|
+
}, [activeOtpErrorMessage, authenticated, state.step, dispatch]);
|
|
6776
6921
|
react.useEffect(() => {
|
|
6777
6922
|
if (state.step === "otp-verify" && /^\d{6}$/.test(otpCode.trim()) && activeOtpStatus === "awaiting-code-input") {
|
|
6778
6923
|
handleVerifyLoginCode();
|
|
@@ -6999,7 +7144,7 @@ function SwypePaymentInner({
|
|
|
6999
7144
|
const load = async () => {
|
|
7000
7145
|
dispatch({ type: "DATA_LOAD_START" });
|
|
7001
7146
|
try {
|
|
7002
|
-
const token = await
|
|
7147
|
+
const token = await getAccessTokenRef.current();
|
|
7003
7148
|
if (!token) throw new Error("Not authenticated");
|
|
7004
7149
|
const [prov, accts, chn] = await Promise.all([
|
|
7005
7150
|
fetchProviders(apiBaseUrl, token),
|
|
@@ -7053,7 +7198,6 @@ function SwypePaymentInner({
|
|
|
7053
7198
|
state.step,
|
|
7054
7199
|
state.accounts.length,
|
|
7055
7200
|
apiBaseUrl,
|
|
7056
|
-
getAccessToken,
|
|
7057
7201
|
state.activeCredentialId,
|
|
7058
7202
|
state.selectedAccountId,
|
|
7059
7203
|
depositAmount
|
|
@@ -7068,7 +7212,7 @@ function SwypePaymentInner({
|
|
|
7068
7212
|
clearMobileFlowState();
|
|
7069
7213
|
dispatch({ type: "TRANSFER_FAILED", transfer: polling.transfer, error: "Transfer failed." });
|
|
7070
7214
|
}
|
|
7071
|
-
}, [polling.transfer, onComplete]);
|
|
7215
|
+
}, [polling.transfer, onComplete, dispatch]);
|
|
7072
7216
|
react.useEffect(() => {
|
|
7073
7217
|
if (state.step !== "processing") {
|
|
7074
7218
|
processingStartedAtRef.current = null;
|
|
@@ -7094,7 +7238,7 @@ function SwypePaymentInner({
|
|
|
7094
7238
|
}
|
|
7095
7239
|
const timeoutId = window.setTimeout(handleTimeout, remainingMs);
|
|
7096
7240
|
return () => window.clearTimeout(timeoutId);
|
|
7097
|
-
}, [state.step, polling.transfer, state.transfer, polling.stopPolling, onError]);
|
|
7241
|
+
}, [state.step, polling.transfer, state.transfer, polling.stopPolling, onError, dispatch, processingStartedAtRef]);
|
|
7098
7242
|
react.useEffect(() => {
|
|
7099
7243
|
if (!state.mobileFlow) {
|
|
7100
7244
|
handlingMobileReturnRef.current = false;
|
|
@@ -7104,7 +7248,7 @@ function SwypePaymentInner({
|
|
|
7104
7248
|
const polledTransfer = polling.transfer;
|
|
7105
7249
|
if (!polledTransfer || polledTransfer.status !== "AUTHORIZED") return;
|
|
7106
7250
|
void handleAuthorizedMobileReturn(polledTransfer, mobileSetupFlowRef.current);
|
|
7107
|
-
}, [state.mobileFlow, polling.transfer, handleAuthorizedMobileReturn]);
|
|
7251
|
+
}, [state.mobileFlow, polling.transfer, handleAuthorizedMobileReturn, handlingMobileReturnRef, mobileSetupFlowRef]);
|
|
7108
7252
|
react.useEffect(() => {
|
|
7109
7253
|
if (!state.mobileFlow || !mobileSetupFlowRef.current) return;
|
|
7110
7254
|
if (state.step !== "open-wallet") return;
|
|
@@ -7175,7 +7319,18 @@ function SwypePaymentInner({
|
|
|
7175
7319
|
window.clearInterval(intervalId);
|
|
7176
7320
|
document.removeEventListener("visibilitychange", handleVisibility);
|
|
7177
7321
|
};
|
|
7178
|
-
}, [
|
|
7322
|
+
}, [
|
|
7323
|
+
state.mobileFlow,
|
|
7324
|
+
state.step,
|
|
7325
|
+
state.activeCredentialId,
|
|
7326
|
+
apiBaseUrl,
|
|
7327
|
+
reloadAccounts,
|
|
7328
|
+
dispatch,
|
|
7329
|
+
mobileSetupFlowRef,
|
|
7330
|
+
setupAccountIdRef,
|
|
7331
|
+
reauthSessionIdRef,
|
|
7332
|
+
reauthTokenRef
|
|
7333
|
+
]);
|
|
7179
7334
|
react.useEffect(() => {
|
|
7180
7335
|
if (!state.mobileFlow) return;
|
|
7181
7336
|
if (handlingMobileReturnRef.current) return;
|
|
@@ -7189,7 +7344,14 @@ function SwypePaymentInner({
|
|
|
7189
7344
|
};
|
|
7190
7345
|
document.addEventListener("visibilitychange", handleVisibility);
|
|
7191
7346
|
return () => document.removeEventListener("visibilitychange", handleVisibility);
|
|
7192
|
-
}, [
|
|
7347
|
+
}, [
|
|
7348
|
+
state.mobileFlow,
|
|
7349
|
+
state.transfer?.id,
|
|
7350
|
+
polling.isPolling,
|
|
7351
|
+
polling.startPolling,
|
|
7352
|
+
handlingMobileReturnRef,
|
|
7353
|
+
pollingTransferIdRef
|
|
7354
|
+
]);
|
|
7193
7355
|
react.useEffect(() => {
|
|
7194
7356
|
if (!pendingSelectSourceAction) {
|
|
7195
7357
|
initializedSelectSourceActionRef.current = null;
|
|
@@ -7198,20 +7360,6 @@ function SwypePaymentInner({
|
|
|
7198
7360
|
return;
|
|
7199
7361
|
}
|
|
7200
7362
|
if (initializedSelectSourceActionRef.current === pendingSelectSourceAction.id) return;
|
|
7201
|
-
const options = pendingSelectSourceAction.metadata?.options ?? [];
|
|
7202
|
-
if (pendingTokenAuthRef.current) {
|
|
7203
|
-
const { tokenAddress, chainId } = pendingTokenAuthRef.current;
|
|
7204
|
-
const chainIdHex = `0x${chainId.toString(16)}`;
|
|
7205
|
-
const match = options.find(
|
|
7206
|
-
(opt) => opt.tokenAddress.toLowerCase() === tokenAddress.toLowerCase() && opt.chainId.toLowerCase() === chainIdHex.toLowerCase()
|
|
7207
|
-
);
|
|
7208
|
-
if (match) {
|
|
7209
|
-
setSelectSourceChainName(match.chainName);
|
|
7210
|
-
setSelectSourceTokenSymbol(match.tokenSymbol);
|
|
7211
|
-
initializedSelectSourceActionRef.current = pendingSelectSourceAction.id;
|
|
7212
|
-
return;
|
|
7213
|
-
}
|
|
7214
|
-
}
|
|
7215
7363
|
const hasRecommended = !!selectSourceRecommended && selectSourceChoices.some(
|
|
7216
7364
|
(chain) => chain.chainName === selectSourceRecommended.chainName && chain.tokens.some((t) => t.tokenSymbol === selectSourceRecommended.tokenSymbol)
|
|
7217
7365
|
);
|
|
@@ -7226,7 +7374,14 @@ function SwypePaymentInner({
|
|
|
7226
7374
|
setSelectSourceTokenSymbol("USDC");
|
|
7227
7375
|
}
|
|
7228
7376
|
initializedSelectSourceActionRef.current = pendingSelectSourceAction.id;
|
|
7229
|
-
}, [
|
|
7377
|
+
}, [
|
|
7378
|
+
pendingSelectSourceAction,
|
|
7379
|
+
selectSourceChoices,
|
|
7380
|
+
selectSourceRecommended,
|
|
7381
|
+
setSelectSourceChainName,
|
|
7382
|
+
setSelectSourceTokenSymbol,
|
|
7383
|
+
initializedSelectSourceActionRef
|
|
7384
|
+
]);
|
|
7230
7385
|
react.useEffect(() => {
|
|
7231
7386
|
if (pendingSelectSourceAction && (state.step === "processing" || state.step === "open-wallet" || state.step === "setup-status")) {
|
|
7232
7387
|
const isDesktop = shouldUseWalletConnector({
|
|
@@ -7234,24 +7389,8 @@ function SwypePaymentInner({
|
|
|
7234
7389
|
userAgent: typeof navigator === "undefined" ? void 0 : navigator.userAgent
|
|
7235
7390
|
});
|
|
7236
7391
|
if (isDesktop && state.step === "setup-status") {
|
|
7237
|
-
|
|
7238
|
-
|
|
7239
|
-
let chainName;
|
|
7240
|
-
let tokenSymbol;
|
|
7241
|
-
if (pendingTokenAuthRef.current) {
|
|
7242
|
-
const { tokenAddress, chainId } = pendingTokenAuthRef.current;
|
|
7243
|
-
const chainIdHex = `0x${chainId.toString(16)}`;
|
|
7244
|
-
const match = options.find(
|
|
7245
|
-
(opt) => opt.tokenAddress.toLowerCase() === tokenAddress.toLowerCase() && opt.chainId.toLowerCase() === chainIdHex.toLowerCase()
|
|
7246
|
-
);
|
|
7247
|
-
chainName = match?.chainName ?? recommended?.chainName ?? "Base";
|
|
7248
|
-
tokenSymbol = match?.tokenSymbol ?? recommended?.tokenSymbol ?? "USDC";
|
|
7249
|
-
} else {
|
|
7250
|
-
const choices = buildSelectSourceChoices(options);
|
|
7251
|
-
chainName = recommended?.chainName ?? choices[0]?.chainName ?? "Base";
|
|
7252
|
-
tokenSymbol = recommended?.tokenSymbol ?? choices[0]?.tokens[0]?.tokenSymbol ?? "USDC";
|
|
7253
|
-
}
|
|
7254
|
-
authExecutor.resolveSelectSource({ chainName, tokenSymbol });
|
|
7392
|
+
preSelectSourceStepRef.current = state.step;
|
|
7393
|
+
dispatch({ type: "NAVIGATE", step: "setup" });
|
|
7255
7394
|
return;
|
|
7256
7395
|
}
|
|
7257
7396
|
preSelectSourceStepRef.current = state.step;
|
|
@@ -7260,75 +7399,243 @@ function SwypePaymentInner({
|
|
|
7260
7399
|
dispatch({ type: "NAVIGATE", step: preSelectSourceStepRef.current ?? "processing" });
|
|
7261
7400
|
preSelectSourceStepRef.current = null;
|
|
7262
7401
|
}
|
|
7263
|
-
}, [pendingSelectSourceAction, state.step,
|
|
7402
|
+
}, [pendingSelectSourceAction, state.step, useWalletConnectorProp, dispatch, preSelectSourceStepRef, authExecutor]);
|
|
7264
7403
|
const pendingOneTapSetupAction = authExecutor.pendingOneTapSetup;
|
|
7265
7404
|
const preOneTapSetupStepRef = react.useRef(null);
|
|
7266
7405
|
react.useEffect(() => {
|
|
7267
7406
|
if (pendingOneTapSetupAction && state.step === "setup-status") {
|
|
7268
|
-
|
|
7269
|
-
|
|
7270
|
-
|
|
7271
|
-
}
|
|
7407
|
+
if (oneTapLimitSavedDuringSetupRef.current) {
|
|
7408
|
+
oneTapLimitSavedDuringSetupRef.current = false;
|
|
7409
|
+
authExecutor.resolveOneTapSetup();
|
|
7410
|
+
} else {
|
|
7411
|
+
preOneTapSetupStepRef.current = state.step;
|
|
7412
|
+
reloadAccounts().then(() => {
|
|
7413
|
+
dispatch({ type: "NAVIGATE", step: "setup" });
|
|
7414
|
+
});
|
|
7415
|
+
}
|
|
7272
7416
|
} else if (!pendingOneTapSetupAction && state.step === "setup" && preOneTapSetupStepRef.current) {
|
|
7273
7417
|
dispatch({ type: "NAVIGATE", step: preOneTapSetupStepRef.current });
|
|
7274
7418
|
preOneTapSetupStepRef.current = null;
|
|
7275
7419
|
}
|
|
7276
|
-
}, [pendingOneTapSetupAction, state.step, reloadAccounts]);
|
|
7420
|
+
}, [pendingOneTapSetupAction, state.step, reloadAccounts, authExecutor, dispatch, oneTapLimitSavedDuringSetupRef]);
|
|
7421
|
+
}
|
|
7422
|
+
function SwypePayment(props) {
|
|
7423
|
+
const resetKey = react.useRef(0);
|
|
7424
|
+
const handleBoundaryReset = react.useCallback(() => {
|
|
7425
|
+
resetKey.current += 1;
|
|
7426
|
+
}, []);
|
|
7427
|
+
return /* @__PURE__ */ jsxRuntime.jsx(PaymentErrorBoundary, { onReset: handleBoundaryReset, children: /* @__PURE__ */ jsxRuntime.jsx(SwypePaymentInner, { ...props }) }, resetKey.current);
|
|
7428
|
+
}
|
|
7429
|
+
function SwypePaymentInner({
|
|
7430
|
+
destination,
|
|
7431
|
+
onComplete,
|
|
7432
|
+
onError,
|
|
7433
|
+
useWalletConnector: useWalletConnectorProp,
|
|
7434
|
+
idempotencyKey,
|
|
7435
|
+
merchantAuthorization,
|
|
7436
|
+
merchantName,
|
|
7437
|
+
onBack,
|
|
7438
|
+
onDismiss,
|
|
7439
|
+
autoCloseSeconds
|
|
7440
|
+
}) {
|
|
7441
|
+
const { apiBaseUrl, depositAmount } = useSwypeConfig();
|
|
7442
|
+
const { ready, authenticated, logout, getAccessToken } = reactAuth.usePrivy();
|
|
7443
|
+
reactAuth.useLoginWithOAuth();
|
|
7444
|
+
const [state, dispatch] = react.useReducer(
|
|
7445
|
+
paymentReducer,
|
|
7446
|
+
{
|
|
7447
|
+
depositAmount,
|
|
7448
|
+
passkeyPopupNeeded: isSafari() && isInCrossOriginIframe(),
|
|
7449
|
+
activeCredentialId: typeof window === "undefined" ? null : window.localStorage.getItem(ACTIVE_CREDENTIAL_STORAGE_KEY)
|
|
7450
|
+
},
|
|
7451
|
+
createInitialState
|
|
7452
|
+
);
|
|
7453
|
+
const authExecutor = useAuthorizationExecutor();
|
|
7454
|
+
const polling = useTransferPolling();
|
|
7455
|
+
const transferSigning = useTransferSigning();
|
|
7456
|
+
const mobileFlowRefs = {
|
|
7457
|
+
mobileSetupFlowRef: react.useRef(false),
|
|
7458
|
+
handlingMobileReturnRef: react.useRef(false),
|
|
7459
|
+
setupAccountIdRef: react.useRef(null),
|
|
7460
|
+
reauthSessionIdRef: react.useRef(null),
|
|
7461
|
+
reauthTokenRef: react.useRef(null),
|
|
7462
|
+
loadingDataRef: react.useRef(false)
|
|
7463
|
+
};
|
|
7464
|
+
const derived = useDerivedState(state);
|
|
7465
|
+
const auth = useAuthHandlers(dispatch, state.verificationTarget);
|
|
7466
|
+
const passkey = usePasskeyHandlers(
|
|
7467
|
+
dispatch,
|
|
7468
|
+
apiBaseUrl,
|
|
7469
|
+
state.accounts,
|
|
7470
|
+
state.knownCredentialIds,
|
|
7471
|
+
mobileFlowRefs.mobileSetupFlowRef
|
|
7472
|
+
);
|
|
7473
|
+
const transfer = useTransferHandlers({
|
|
7474
|
+
dispatch,
|
|
7475
|
+
getAccessToken,
|
|
7476
|
+
apiBaseUrl,
|
|
7477
|
+
depositAmount,
|
|
7478
|
+
destination,
|
|
7479
|
+
idempotencyKey,
|
|
7480
|
+
merchantAuthorization,
|
|
7481
|
+
onComplete,
|
|
7482
|
+
onError,
|
|
7483
|
+
polling,
|
|
7484
|
+
transferSigning,
|
|
7485
|
+
sourceType: derived.sourceType,
|
|
7486
|
+
sourceId: derived.sourceId,
|
|
7487
|
+
sourceTokenAddress: derived.selectedSource?.address,
|
|
7488
|
+
activeCredentialId: state.activeCredentialId,
|
|
7489
|
+
selectedAccountId: state.selectedAccountId,
|
|
7490
|
+
transfer: state.transfer,
|
|
7491
|
+
accounts: state.accounts
|
|
7492
|
+
});
|
|
7493
|
+
const mobileFlow = useMobileFlowHandlers(
|
|
7494
|
+
dispatch,
|
|
7495
|
+
polling,
|
|
7496
|
+
transfer.reloadAccounts,
|
|
7497
|
+
transfer.pollingTransferIdRef,
|
|
7498
|
+
state.transfer,
|
|
7499
|
+
mobileFlowRefs
|
|
7500
|
+
);
|
|
7501
|
+
const sourceSelection = useSourceSelectionHandlers(dispatch, authExecutor);
|
|
7502
|
+
const provider = useProviderHandlers({
|
|
7503
|
+
dispatch,
|
|
7504
|
+
getAccessToken,
|
|
7505
|
+
apiBaseUrl,
|
|
7506
|
+
depositAmount,
|
|
7507
|
+
useWalletConnectorProp,
|
|
7508
|
+
activeCredentialId: state.activeCredentialId,
|
|
7509
|
+
selectedAccountId: state.selectedAccountId,
|
|
7510
|
+
accounts: state.accounts,
|
|
7511
|
+
providers: state.providers,
|
|
7512
|
+
authExecutor,
|
|
7513
|
+
reloadAccounts: transfer.reloadAccounts,
|
|
7514
|
+
onError,
|
|
7515
|
+
mobileSetupFlowRef: mobileFlowRefs.mobileSetupFlowRef,
|
|
7516
|
+
handlingMobileReturnRef: mobileFlowRefs.handlingMobileReturnRef,
|
|
7517
|
+
setupAccountIdRef: mobileFlowRefs.setupAccountIdRef,
|
|
7518
|
+
reauthSessionIdRef: mobileFlowRefs.reauthSessionIdRef,
|
|
7519
|
+
reauthTokenRef: mobileFlowRefs.reauthTokenRef
|
|
7520
|
+
});
|
|
7521
|
+
const oneTapSetup = useOneTapSetupHandlers({
|
|
7522
|
+
dispatch,
|
|
7523
|
+
getAccessToken,
|
|
7524
|
+
apiBaseUrl,
|
|
7525
|
+
authExecutor,
|
|
7526
|
+
selectSourceChainName: sourceSelection.selectSourceChainName,
|
|
7527
|
+
selectSourceTokenSymbol: sourceSelection.selectSourceTokenSymbol
|
|
7528
|
+
});
|
|
7529
|
+
const handleNewPayment = react.useCallback(() => {
|
|
7530
|
+
clearMobileFlowState();
|
|
7531
|
+
transfer.processingStartedAtRef.current = null;
|
|
7532
|
+
transfer.pollingTransferIdRef.current = null;
|
|
7533
|
+
sourceSelection.preSelectSourceStepRef.current = null;
|
|
7534
|
+
oneTapSetup.oneTapLimitSavedDuringSetupRef.current = false;
|
|
7535
|
+
dispatch({
|
|
7536
|
+
type: "NEW_PAYMENT",
|
|
7537
|
+
depositAmount,
|
|
7538
|
+
firstAccountId: state.accounts.length > 0 ? state.accounts[0].id : null
|
|
7539
|
+
});
|
|
7540
|
+
}, [depositAmount, state.accounts, transfer, sourceSelection, provider, oneTapSetup]);
|
|
7541
|
+
const handleLogout = react.useCallback(async () => {
|
|
7542
|
+
try {
|
|
7543
|
+
await logout();
|
|
7544
|
+
} catch {
|
|
7545
|
+
}
|
|
7546
|
+
clearMobileFlowState();
|
|
7547
|
+
if (typeof window !== "undefined") {
|
|
7548
|
+
window.localStorage.removeItem(ACTIVE_CREDENTIAL_STORAGE_KEY);
|
|
7549
|
+
}
|
|
7550
|
+
polling.stopPolling();
|
|
7551
|
+
sourceSelection.preSelectSourceStepRef.current = null;
|
|
7552
|
+
passkey.checkingPasskeyRef.current = false;
|
|
7553
|
+
oneTapSetup.oneTapLimitSavedDuringSetupRef.current = false;
|
|
7554
|
+
auth.setAuthInput("");
|
|
7555
|
+
auth.setOtpCode("");
|
|
7556
|
+
dispatch({ type: "LOGOUT", depositAmount });
|
|
7557
|
+
}, [logout, polling, depositAmount, auth, sourceSelection, provider, passkey, oneTapSetup]);
|
|
7558
|
+
usePaymentEffects({
|
|
7559
|
+
state,
|
|
7560
|
+
dispatch,
|
|
7561
|
+
ready,
|
|
7562
|
+
authenticated,
|
|
7563
|
+
apiBaseUrl,
|
|
7564
|
+
depositAmount,
|
|
7565
|
+
useWalletConnectorProp,
|
|
7566
|
+
onComplete,
|
|
7567
|
+
onError,
|
|
7568
|
+
polling,
|
|
7569
|
+
authExecutor,
|
|
7570
|
+
reloadAccounts: transfer.reloadAccounts,
|
|
7571
|
+
activeOtpStatus: auth.activeOtpStatus,
|
|
7572
|
+
activeOtpErrorMessage: auth.activeOtpErrorMessage,
|
|
7573
|
+
otpCode: auth.otpCode,
|
|
7574
|
+
handleVerifyLoginCode: auth.handleVerifyLoginCode,
|
|
7575
|
+
setAuthInput: auth.setAuthInput,
|
|
7576
|
+
setOtpCode: auth.setOtpCode,
|
|
7577
|
+
mobileSetupFlowRef: mobileFlowRefs.mobileSetupFlowRef,
|
|
7578
|
+
handlingMobileReturnRef: mobileFlowRefs.handlingMobileReturnRef,
|
|
7579
|
+
setupAccountIdRef: mobileFlowRefs.setupAccountIdRef,
|
|
7580
|
+
reauthSessionIdRef: mobileFlowRefs.reauthSessionIdRef,
|
|
7581
|
+
reauthTokenRef: mobileFlowRefs.reauthTokenRef,
|
|
7582
|
+
loadingDataRef: mobileFlowRefs.loadingDataRef,
|
|
7583
|
+
pollingTransferIdRef: transfer.pollingTransferIdRef,
|
|
7584
|
+
processingStartedAtRef: transfer.processingStartedAtRef,
|
|
7585
|
+
checkingPasskeyRef: passkey.checkingPasskeyRef,
|
|
7586
|
+
pendingSelectSourceAction: sourceSelection.pendingSelectSourceAction,
|
|
7587
|
+
selectSourceChoices: sourceSelection.selectSourceChoices,
|
|
7588
|
+
selectSourceRecommended: sourceSelection.selectSourceRecommended,
|
|
7589
|
+
setSelectSourceChainName: sourceSelection.setSelectSourceChainName,
|
|
7590
|
+
setSelectSourceTokenSymbol: sourceSelection.setSelectSourceTokenSymbol,
|
|
7591
|
+
initializedSelectSourceActionRef: sourceSelection.initializedSelectSourceActionRef,
|
|
7592
|
+
preSelectSourceStepRef: sourceSelection.preSelectSourceStepRef,
|
|
7593
|
+
oneTapLimitSavedDuringSetupRef: oneTapSetup.oneTapLimitSavedDuringSetupRef,
|
|
7594
|
+
handleAuthorizedMobileReturn: mobileFlow.handleAuthorizedMobileReturn
|
|
7595
|
+
});
|
|
7277
7596
|
const handlers = react.useMemo(() => ({
|
|
7278
|
-
onSendLoginCode: handleSendLoginCode,
|
|
7279
|
-
onVerifyLoginCode: handleVerifyLoginCode,
|
|
7280
|
-
onResendLoginCode: handleResendLoginCode,
|
|
7597
|
+
onSendLoginCode: auth.handleSendLoginCode,
|
|
7598
|
+
onVerifyLoginCode: auth.handleVerifyLoginCode,
|
|
7599
|
+
onResendLoginCode: auth.handleResendLoginCode,
|
|
7281
7600
|
onBackFromOtp: () => {
|
|
7282
|
-
setOtpCode("");
|
|
7601
|
+
auth.setOtpCode("");
|
|
7283
7602
|
dispatch({ type: "BACK_TO_LOGIN" });
|
|
7284
7603
|
},
|
|
7285
|
-
onRegisterPasskey: handleRegisterPasskey,
|
|
7286
|
-
onCreatePasskeyViaPopup: handleCreatePasskeyViaPopup,
|
|
7287
|
-
onVerifyPasskeyViaPopup: handleVerifyPasskeyViaPopup,
|
|
7288
|
-
onSelectProvider: handleSelectProvider,
|
|
7289
|
-
onContinueConnection: handleContinueConnection,
|
|
7290
|
-
onSelectAccount: handleSelectAccount,
|
|
7291
|
-
onPay: handlePay,
|
|
7292
|
-
onIncreaseLimit: handleIncreaseLimit,
|
|
7293
|
-
onConfirmSign: handleConfirmSign,
|
|
7294
|
-
onRetryMobileStatus: handleRetryMobileStatus,
|
|
7604
|
+
onRegisterPasskey: passkey.handleRegisterPasskey,
|
|
7605
|
+
onCreatePasskeyViaPopup: passkey.handleCreatePasskeyViaPopup,
|
|
7606
|
+
onVerifyPasskeyViaPopup: passkey.handleVerifyPasskeyViaPopup,
|
|
7607
|
+
onSelectProvider: provider.handleSelectProvider,
|
|
7608
|
+
onContinueConnection: provider.handleContinueConnection,
|
|
7609
|
+
onSelectAccount: provider.handleSelectAccount,
|
|
7610
|
+
onPay: transfer.handlePay,
|
|
7611
|
+
onIncreaseLimit: provider.handleIncreaseLimit,
|
|
7612
|
+
onConfirmSign: transfer.handleConfirmSign,
|
|
7613
|
+
onRetryMobileStatus: mobileFlow.handleRetryMobileStatus,
|
|
7295
7614
|
onLogout: handleLogout,
|
|
7296
7615
|
onNewPayment: handleNewPayment,
|
|
7297
7616
|
onNavigate: (step) => dispatch({ type: "NAVIGATE", step }),
|
|
7298
|
-
onSetAuthInput: setAuthInput,
|
|
7617
|
+
onSetAuthInput: auth.setAuthInput,
|
|
7299
7618
|
onSetOtpCode: (code) => {
|
|
7300
|
-
setOtpCode(code);
|
|
7619
|
+
auth.setOtpCode(code);
|
|
7301
7620
|
dispatch({ type: "SET_ERROR", error: null });
|
|
7302
7621
|
},
|
|
7303
|
-
onSelectSourceChainChange: handleSelectSourceChainChange,
|
|
7304
|
-
onSetSelectSourceTokenSymbol: setSelectSourceTokenSymbol,
|
|
7305
|
-
onConfirmSelectSource: handleConfirmSelectSource,
|
|
7306
|
-
onSetupOneTap: handleSetupOneTap,
|
|
7307
|
-
onSelectToken: handleNavigateToTokenPicker,
|
|
7308
|
-
onSelectAuthorizedToken: handleSelectAuthorizedToken,
|
|
7309
|
-
onAuthorizeToken: handleAuthorizeToken
|
|
7622
|
+
onSelectSourceChainChange: sourceSelection.handleSelectSourceChainChange,
|
|
7623
|
+
onSetSelectSourceTokenSymbol: sourceSelection.setSelectSourceTokenSymbol,
|
|
7624
|
+
onConfirmSelectSource: sourceSelection.handleConfirmSelectSource,
|
|
7625
|
+
onSetupOneTap: oneTapSetup.handleSetupOneTap,
|
|
7626
|
+
onSelectToken: provider.handleNavigateToTokenPicker,
|
|
7627
|
+
onSelectAuthorizedToken: provider.handleSelectAuthorizedToken,
|
|
7628
|
+
onAuthorizeToken: provider.handleAuthorizeToken
|
|
7310
7629
|
}), [
|
|
7311
|
-
|
|
7312
|
-
|
|
7313
|
-
|
|
7314
|
-
|
|
7315
|
-
|
|
7316
|
-
|
|
7317
|
-
|
|
7318
|
-
handleContinueConnection,
|
|
7319
|
-
handleSelectAccount,
|
|
7320
|
-
handlePay,
|
|
7321
|
-
handleIncreaseLimit,
|
|
7322
|
-
handleConfirmSign,
|
|
7323
|
-
handleRetryMobileStatus,
|
|
7630
|
+
auth,
|
|
7631
|
+
passkey,
|
|
7632
|
+
provider,
|
|
7633
|
+
transfer,
|
|
7634
|
+
mobileFlow,
|
|
7635
|
+
sourceSelection,
|
|
7636
|
+
oneTapSetup,
|
|
7324
7637
|
handleLogout,
|
|
7325
|
-
handleNewPayment
|
|
7326
|
-
handleSelectSourceChainChange,
|
|
7327
|
-
handleConfirmSelectSource,
|
|
7328
|
-
handleSetupOneTap,
|
|
7329
|
-
handleNavigateToTokenPicker,
|
|
7330
|
-
handleSelectAuthorizedToken,
|
|
7331
|
-
handleAuthorizeToken
|
|
7638
|
+
handleNewPayment
|
|
7332
7639
|
]);
|
|
7333
7640
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
7334
7641
|
StepRenderer,
|
|
@@ -7336,28 +7643,29 @@ function SwypePaymentInner({
|
|
|
7336
7643
|
state,
|
|
7337
7644
|
ready,
|
|
7338
7645
|
authenticated,
|
|
7339
|
-
activeOtpStatus,
|
|
7646
|
+
activeOtpStatus: auth.activeOtpStatus,
|
|
7340
7647
|
pollingTransfer: polling.transfer,
|
|
7341
7648
|
pollingError: polling.error,
|
|
7342
7649
|
authExecutorError: authExecutor.error,
|
|
7343
7650
|
transferSigningSigning: transferSigning.signing,
|
|
7344
7651
|
transferSigningError: transferSigning.error,
|
|
7345
|
-
pendingConnections,
|
|
7346
|
-
depositEligibleAccounts,
|
|
7347
|
-
sourceName,
|
|
7348
|
-
sourceAddress,
|
|
7349
|
-
sourceVerified,
|
|
7350
|
-
maxSourceBalance,
|
|
7351
|
-
tokenCount,
|
|
7352
|
-
selectedAccount,
|
|
7353
|
-
selectedSource,
|
|
7354
|
-
selectSourceChoices,
|
|
7355
|
-
selectSourceRecommended,
|
|
7356
|
-
|
|
7357
|
-
|
|
7358
|
-
|
|
7359
|
-
|
|
7360
|
-
|
|
7652
|
+
pendingConnections: derived.pendingConnections,
|
|
7653
|
+
depositEligibleAccounts: derived.depositEligibleAccounts,
|
|
7654
|
+
sourceName: derived.sourceName,
|
|
7655
|
+
sourceAddress: derived.sourceAddress,
|
|
7656
|
+
sourceVerified: derived.sourceVerified,
|
|
7657
|
+
maxSourceBalance: derived.maxSourceBalance,
|
|
7658
|
+
tokenCount: derived.tokenCount,
|
|
7659
|
+
selectedAccount: derived.selectedAccount,
|
|
7660
|
+
selectedSource: derived.selectedSource,
|
|
7661
|
+
selectSourceChoices: sourceSelection.selectSourceChoices,
|
|
7662
|
+
selectSourceRecommended: sourceSelection.selectSourceRecommended,
|
|
7663
|
+
selectSourceAvailableBalance: sourceSelection.selectSourceAvailableBalance,
|
|
7664
|
+
authInput: auth.authInput,
|
|
7665
|
+
otpCode: auth.otpCode,
|
|
7666
|
+
selectSourceChainName: sourceSelection.selectSourceChainName,
|
|
7667
|
+
selectSourceTokenSymbol: sourceSelection.selectSourceTokenSymbol,
|
|
7668
|
+
savingOneTapLimit: oneTapSetup.savingOneTapLimit,
|
|
7361
7669
|
merchantName,
|
|
7362
7670
|
onBack,
|
|
7363
7671
|
onDismiss,
|