@swype-org/react-sdk 0.1.133 → 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 +1250 -991
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -4
- package/dist/index.d.ts +2 -4
- package/dist/index.js +1251 -992
- 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);
|
|
@@ -4252,8 +4115,7 @@ function DepositScreen({
|
|
|
4252
4115
|
onAuthorizeAccount,
|
|
4253
4116
|
onAddProvider,
|
|
4254
4117
|
onSelectToken,
|
|
4255
|
-
|
|
4256
|
-
onStartSetup
|
|
4118
|
+
selectedSourceLabel
|
|
4257
4119
|
}) {
|
|
4258
4120
|
const { tokens } = useSwypeConfig();
|
|
4259
4121
|
const amount = initialAmount;
|
|
@@ -4261,29 +4123,6 @@ function DepositScreen({
|
|
|
4261
4123
|
const exceedsLimit = amount > remainingLimit && !isLowBalance;
|
|
4262
4124
|
const canDeposit = amount >= MIN_DEPOSIT && !exceedsLimit && !isLowBalance && !processing;
|
|
4263
4125
|
const headerTitle = merchantName ? `Deposit to ${merchantName}` : "Deposit";
|
|
4264
|
-
if (pendingSetup) {
|
|
4265
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
4266
|
-
ScreenLayout,
|
|
4267
|
-
{
|
|
4268
|
-
footer: /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
4269
|
-
/* @__PURE__ */ jsxRuntime.jsx(PrimaryButton, { onClick: onStartSetup, children: "Set up One-Tap" }),
|
|
4270
|
-
/* @__PURE__ */ jsxRuntime.jsx("p", { style: setupHintStyle(tokens.textSecondary), children: "Choose your source and set your One-Tap limit to deposit instantly." }),
|
|
4271
|
-
/* @__PURE__ */ jsxRuntime.jsx(PoweredByFooter, {})
|
|
4272
|
-
] }),
|
|
4273
|
-
children: [
|
|
4274
|
-
/* @__PURE__ */ jsxRuntime.jsx(ScreenHeader, { title: headerTitle, right: /* @__PURE__ */ jsxRuntime.jsx(SettingsMenu, { onLogout }) }),
|
|
4275
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: setupContentStyle, children: [
|
|
4276
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { style: amountDisplayStyle, children: /* @__PURE__ */ jsxRuntime.jsxs("span", { style: amountStyle(tokens), children: [
|
|
4277
|
-
"$",
|
|
4278
|
-
amount.toFixed(2)
|
|
4279
|
-
] }) }),
|
|
4280
|
-
/* @__PURE__ */ jsxRuntime.jsx("p", { style: setupDescStyle(tokens.textSecondary), children: "Set up your payment source to deposit with One-Tap \u2014 no approvals needed after setup." })
|
|
4281
|
-
] }),
|
|
4282
|
-
error && /* @__PURE__ */ jsxRuntime.jsx("div", { style: errorBannerStyle5(tokens), children: error })
|
|
4283
|
-
]
|
|
4284
|
-
}
|
|
4285
|
-
);
|
|
4286
|
-
}
|
|
4287
4126
|
if (isLowBalance) {
|
|
4288
4127
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
4289
4128
|
ScreenLayout,
|
|
@@ -4321,7 +4160,7 @@ function DepositScreen({
|
|
|
4321
4160
|
/* @__PURE__ */ jsxRuntime.jsx("text", { x: "12", y: "16", textAnchor: "middle", fontSize: "12", fill: "#fff", fontWeight: "700", children: "$" })
|
|
4322
4161
|
] }) }),
|
|
4323
4162
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4324
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { style: balanceLabelStyle2(tokens.textMuted), children: "Available" }),
|
|
4163
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { style: balanceLabelStyle2(tokens.textMuted), children: selectedSourceLabel ?? "Available" }),
|
|
4325
4164
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: { ...balanceAmountStyle, color: tokens.warning }, children: [
|
|
4326
4165
|
"$",
|
|
4327
4166
|
availableBalance.toFixed(2)
|
|
@@ -4396,10 +4235,7 @@ function DepositScreen({
|
|
|
4396
4235
|
/* @__PURE__ */ jsxRuntime.jsx("text", { x: "12", y: "16", textAnchor: "middle", fontSize: "12", fill: "#fff", fontWeight: "700", children: "$" })
|
|
4397
4236
|
] }) }),
|
|
4398
4237
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4399
|
-
/* @__PURE__ */ jsxRuntime.
|
|
4400
|
-
"Paying from ",
|
|
4401
|
-
sourceName
|
|
4402
|
-
] }),
|
|
4238
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { style: balanceLabelStyle2(tokens.textMuted), children: selectedSourceLabel ?? `Paying from ${sourceName}` }),
|
|
4403
4239
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: balanceAmountStyle, children: [
|
|
4404
4240
|
"$",
|
|
4405
4241
|
availableBalance.toLocaleString("en-US", { minimumFractionDigits: 2, maximumFractionDigits: 2 })
|
|
@@ -4546,29 +4382,6 @@ var switchHintStyle = (color) => ({
|
|
|
4546
4382
|
var outlineBtnWrapStyle = {
|
|
4547
4383
|
marginBottom: 8
|
|
4548
4384
|
};
|
|
4549
|
-
var setupContentStyle = {
|
|
4550
|
-
flex: 1,
|
|
4551
|
-
display: "flex",
|
|
4552
|
-
flexDirection: "column",
|
|
4553
|
-
alignItems: "center",
|
|
4554
|
-
justifyContent: "center",
|
|
4555
|
-
textAlign: "center",
|
|
4556
|
-
padding: "0 24px"
|
|
4557
|
-
};
|
|
4558
|
-
var setupDescStyle = (color) => ({
|
|
4559
|
-
fontSize: "0.88rem",
|
|
4560
|
-
color,
|
|
4561
|
-
margin: "8px 0 0",
|
|
4562
|
-
lineHeight: 1.6,
|
|
4563
|
-
maxWidth: 300
|
|
4564
|
-
});
|
|
4565
|
-
var setupHintStyle = (color) => ({
|
|
4566
|
-
textAlign: "center",
|
|
4567
|
-
fontSize: "0.78rem",
|
|
4568
|
-
color,
|
|
4569
|
-
margin: "12px 0 2px",
|
|
4570
|
-
lineHeight: 1.5
|
|
4571
|
-
});
|
|
4572
4385
|
function SuccessScreen({
|
|
4573
4386
|
amount,
|
|
4574
4387
|
currency,
|
|
@@ -5218,6 +5031,28 @@ var waitHintStyle2 = (color) => ({
|
|
|
5218
5031
|
color,
|
|
5219
5032
|
margin: 0
|
|
5220
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
|
+
}
|
|
5221
5056
|
function OpenWalletScreen({
|
|
5222
5057
|
walletName,
|
|
5223
5058
|
deeplinkUri,
|
|
@@ -5663,12 +5498,12 @@ function StepRenderer({
|
|
|
5663
5498
|
selectedSource,
|
|
5664
5499
|
selectSourceChoices,
|
|
5665
5500
|
selectSourceRecommended,
|
|
5501
|
+
selectSourceAvailableBalance,
|
|
5666
5502
|
authInput,
|
|
5667
5503
|
otpCode,
|
|
5668
5504
|
selectSourceChainName,
|
|
5669
5505
|
selectSourceTokenSymbol,
|
|
5670
5506
|
savingOneTapLimit,
|
|
5671
|
-
pendingSetup,
|
|
5672
5507
|
merchantName,
|
|
5673
5508
|
onBack,
|
|
5674
5509
|
onDismiss,
|
|
@@ -5785,19 +5620,23 @@ function StepRenderer({
|
|
|
5785
5620
|
);
|
|
5786
5621
|
}
|
|
5787
5622
|
if (step === "setup") {
|
|
5788
|
-
const
|
|
5789
|
-
|
|
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);
|
|
5790
5629
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
5791
5630
|
SetupScreen,
|
|
5792
5631
|
{
|
|
5793
|
-
availableBalance: selectedSource ? selectedSource.balance.available.amount : selectedAccount ? selectedAccount.wallets.reduce((sum, w) => sum + w.balance.available.amount, 0) : maxSourceBalance,
|
|
5794
|
-
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,
|
|
5795
5634
|
sourceName,
|
|
5796
5635
|
onSetupOneTap: handlers.onSetupOneTap,
|
|
5797
5636
|
onBack: () => handlers.onNavigate("deposit"),
|
|
5798
5637
|
onLogout: handlers.onLogout,
|
|
5799
|
-
onAdvanced:
|
|
5800
|
-
selectedSourceLabel:
|
|
5638
|
+
onAdvanced: handlers.onSelectToken,
|
|
5639
|
+
selectedSourceLabel: effectiveSourceLabel,
|
|
5801
5640
|
loading: savingOneTapLimit,
|
|
5802
5641
|
error: state.error
|
|
5803
5642
|
}
|
|
@@ -5846,8 +5685,7 @@ function StepRenderer({
|
|
|
5846
5685
|
onAuthorizeAccount: handlers.onContinueConnection,
|
|
5847
5686
|
onAddProvider: () => handlers.onNavigate("wallet-picker"),
|
|
5848
5687
|
onSelectToken: handlers.onSelectToken,
|
|
5849
|
-
|
|
5850
|
-
onStartSetup: () => handlers.onNavigate("setup")
|
|
5688
|
+
selectedSourceLabel
|
|
5851
5689
|
}
|
|
5852
5690
|
);
|
|
5853
5691
|
}
|
|
@@ -5879,7 +5717,7 @@ function StepRenderer({
|
|
|
5879
5717
|
);
|
|
5880
5718
|
}
|
|
5881
5719
|
if (step === "select-source") {
|
|
5882
|
-
const
|
|
5720
|
+
const cameFromSetup = state.previousStep === "setup";
|
|
5883
5721
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
5884
5722
|
SelectSourceScreen,
|
|
5885
5723
|
{
|
|
@@ -5889,8 +5727,8 @@ function StepRenderer({
|
|
|
5889
5727
|
recommended: selectSourceRecommended,
|
|
5890
5728
|
onChainChange: handlers.onSelectSourceChainChange,
|
|
5891
5729
|
onTokenChange: handlers.onSetSelectSourceTokenSymbol,
|
|
5892
|
-
onConfirm:
|
|
5893
|
-
onBack:
|
|
5730
|
+
onConfirm: cameFromSetup ? () => handlers.onNavigate("setup") : handlers.onConfirmSelectSource,
|
|
5731
|
+
onBack: cameFromSetup ? () => handlers.onNavigate("setup") : void 0,
|
|
5894
5732
|
onLogout: handlers.onLogout
|
|
5895
5733
|
}
|
|
5896
5734
|
);
|
|
@@ -5940,21 +5778,38 @@ function StepRenderer({
|
|
|
5940
5778
|
selectedAccountId: state.selectedAccountId,
|
|
5941
5779
|
onSelectAccount: handlers.onSelectAccount,
|
|
5942
5780
|
onAuthorizeAccount: handlers.onContinueConnection,
|
|
5943
|
-
onAddProvider: () => handlers.onNavigate("wallet-picker")
|
|
5781
|
+
onAddProvider: () => handlers.onNavigate("wallet-picker"),
|
|
5782
|
+
selectedSourceLabel
|
|
5944
5783
|
}
|
|
5945
5784
|
);
|
|
5946
5785
|
}
|
|
5947
5786
|
return null;
|
|
5948
5787
|
}
|
|
5949
|
-
|
|
5950
|
-
|
|
5951
|
-
|
|
5952
|
-
|
|
5953
|
-
|
|
5954
|
-
|
|
5955
|
-
|
|
5956
|
-
|
|
5957
|
-
|
|
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
|
+
}
|
|
5804
|
+
var PaymentErrorBoundary = class extends react.Component {
|
|
5805
|
+
constructor(props) {
|
|
5806
|
+
super(props);
|
|
5807
|
+
this.state = { hasError: false };
|
|
5808
|
+
}
|
|
5809
|
+
static getDerivedStateFromError() {
|
|
5810
|
+
return { hasError: true };
|
|
5811
|
+
}
|
|
5812
|
+
componentDidCatch(error, _info) {
|
|
5958
5813
|
captureException(error);
|
|
5959
5814
|
}
|
|
5960
5815
|
handleReset = () => {
|
|
@@ -6014,78 +5869,7 @@ var buttonStyle3 = {
|
|
|
6014
5869
|
fontFamily: "inherit",
|
|
6015
5870
|
cursor: "pointer"
|
|
6016
5871
|
};
|
|
6017
|
-
function
|
|
6018
|
-
const resetKey = react.useRef(0);
|
|
6019
|
-
const handleBoundaryReset = react.useCallback(() => {
|
|
6020
|
-
resetKey.current += 1;
|
|
6021
|
-
}, []);
|
|
6022
|
-
return /* @__PURE__ */ jsxRuntime.jsx(PaymentErrorBoundary, { onReset: handleBoundaryReset, children: /* @__PURE__ */ jsxRuntime.jsx(SwypePaymentInner, { ...props }) }, resetKey.current);
|
|
6023
|
-
}
|
|
6024
|
-
function SwypePaymentInner({
|
|
6025
|
-
destination,
|
|
6026
|
-
onComplete,
|
|
6027
|
-
onError,
|
|
6028
|
-
useWalletConnector: useWalletConnectorProp,
|
|
6029
|
-
idempotencyKey,
|
|
6030
|
-
merchantAuthorization,
|
|
6031
|
-
merchantName,
|
|
6032
|
-
onBack,
|
|
6033
|
-
onDismiss,
|
|
6034
|
-
autoCloseSeconds
|
|
6035
|
-
}) {
|
|
6036
|
-
const { apiBaseUrl, depositAmount } = useSwypeConfig();
|
|
6037
|
-
const { ready, authenticated, user, logout, getAccessToken } = reactAuth.usePrivy();
|
|
6038
|
-
const {
|
|
6039
|
-
sendCode: sendEmailCode,
|
|
6040
|
-
loginWithCode: loginWithEmailCode,
|
|
6041
|
-
state: emailLoginState
|
|
6042
|
-
} = reactAuth.useLoginWithEmail();
|
|
6043
|
-
const {
|
|
6044
|
-
sendCode: sendSmsCode,
|
|
6045
|
-
loginWithCode: loginWithSmsCode,
|
|
6046
|
-
state: smsLoginState
|
|
6047
|
-
} = reactAuth.useLoginWithSms();
|
|
6048
|
-
reactAuth.useLoginWithOAuth();
|
|
6049
|
-
const [state, dispatch] = react.useReducer(
|
|
6050
|
-
paymentReducer,
|
|
6051
|
-
{
|
|
6052
|
-
depositAmount,
|
|
6053
|
-
passkeyPopupNeeded: isSafari() && isInCrossOriginIframe(),
|
|
6054
|
-
activeCredentialId: typeof window === "undefined" ? null : window.localStorage.getItem(ACTIVE_CREDENTIAL_STORAGE_KEY)
|
|
6055
|
-
},
|
|
6056
|
-
createInitialState
|
|
6057
|
-
);
|
|
6058
|
-
const loadingDataRef = react.useRef(false);
|
|
6059
|
-
const pollingTransferIdRef = react.useRef(null);
|
|
6060
|
-
const setupAccountIdRef = react.useRef(null);
|
|
6061
|
-
const mobileSetupFlowRef = react.useRef(false);
|
|
6062
|
-
const handlingMobileReturnRef = react.useRef(false);
|
|
6063
|
-
const processingStartedAtRef = react.useRef(null);
|
|
6064
|
-
const initializedSelectSourceActionRef = react.useRef(null);
|
|
6065
|
-
const preSelectSourceStepRef = react.useRef(null);
|
|
6066
|
-
const pendingTokenAuthRef = react.useRef(null);
|
|
6067
|
-
const pendingTokenSelectionRef = react.useRef(null);
|
|
6068
|
-
const pendingTokenAuthSessionRef = react.useRef(null);
|
|
6069
|
-
const reauthSessionIdRef = react.useRef(null);
|
|
6070
|
-
const reauthTokenRef = react.useRef(null);
|
|
6071
|
-
const checkingPasskeyRef = react.useRef(false);
|
|
6072
|
-
const onCompleteRef = react.useRef(onComplete);
|
|
6073
|
-
onCompleteRef.current = onComplete;
|
|
6074
|
-
const pollingRef = react.useRef(null);
|
|
6075
|
-
const getAccessTokenRef = react.useRef(getAccessToken);
|
|
6076
|
-
getAccessTokenRef.current = getAccessToken;
|
|
6077
|
-
const handleAuthorizedMobileReturnRef = react.useRef(
|
|
6078
|
-
null
|
|
6079
|
-
);
|
|
6080
|
-
const [authInput, setAuthInput] = react.useState("");
|
|
6081
|
-
const [otpCode, setOtpCode] = react.useState("");
|
|
6082
|
-
const [selectSourceChainName, setSelectSourceChainName] = react.useState("");
|
|
6083
|
-
const [selectSourceTokenSymbol, setSelectSourceTokenSymbol] = react.useState("");
|
|
6084
|
-
const [savingOneTapLimit, setSavingOneTapLimit] = react.useState(false);
|
|
6085
|
-
const authExecutor = useAuthorizationExecutor();
|
|
6086
|
-
const polling = useTransferPolling();
|
|
6087
|
-
pollingRef.current = polling;
|
|
6088
|
-
const transferSigning = useTransferSigning();
|
|
5872
|
+
function useDerivedState(state) {
|
|
6089
5873
|
const { sourceType, sourceId } = deriveSourceTypeAndId(state);
|
|
6090
5874
|
const selectedAccount = state.accounts.find((a) => a.id === state.selectedAccountId);
|
|
6091
5875
|
const selectedWallet = selectedAccount?.wallets.find(
|
|
@@ -6135,8 +5919,36 @@ function SwypePaymentInner({
|
|
|
6135
5919
|
}
|
|
6136
5920
|
return count;
|
|
6137
5921
|
}, [state.accounts]);
|
|
6138
|
-
|
|
6139
|
-
|
|
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;
|
|
6140
5952
|
const handleSendLoginCode = react.useCallback(async () => {
|
|
6141
5953
|
const normalizedIdentifier = normalizeAuthIdentifier(authInput);
|
|
6142
5954
|
if (!normalizedIdentifier) {
|
|
@@ -6158,9 +5970,9 @@ function SwypePaymentInner({
|
|
|
6158
5970
|
error: err instanceof Error ? err.message : "Failed to send verification code"
|
|
6159
5971
|
});
|
|
6160
5972
|
}
|
|
6161
|
-
}, [authInput, sendEmailCode, sendSmsCode]);
|
|
5973
|
+
}, [authInput, sendEmailCode, sendSmsCode, dispatch]);
|
|
6162
5974
|
const handleVerifyLoginCode = react.useCallback(async () => {
|
|
6163
|
-
if (!
|
|
5975
|
+
if (!verificationTarget) return;
|
|
6164
5976
|
const trimmedCode = otpCode.trim();
|
|
6165
5977
|
if (!/^\d{6}$/.test(trimmedCode)) {
|
|
6166
5978
|
dispatch({ type: "SET_ERROR", error: "Enter the 6-digit verification code." });
|
|
@@ -6168,7 +5980,7 @@ function SwypePaymentInner({
|
|
|
6168
5980
|
}
|
|
6169
5981
|
dispatch({ type: "SET_ERROR", error: null });
|
|
6170
5982
|
try {
|
|
6171
|
-
if (
|
|
5983
|
+
if (verificationTarget.kind === "email") {
|
|
6172
5984
|
await loginWithEmailCode({ code: trimmedCode });
|
|
6173
5985
|
} else {
|
|
6174
5986
|
await loginWithSmsCode({ code: trimmedCode });
|
|
@@ -6180,15 +5992,15 @@ function SwypePaymentInner({
|
|
|
6180
5992
|
error: err instanceof Error ? err.message : "Failed to verify code"
|
|
6181
5993
|
});
|
|
6182
5994
|
}
|
|
6183
|
-
}, [
|
|
5995
|
+
}, [verificationTarget, otpCode, loginWithEmailCode, loginWithSmsCode, dispatch]);
|
|
6184
5996
|
const handleResendLoginCode = react.useCallback(async () => {
|
|
6185
|
-
if (!
|
|
5997
|
+
if (!verificationTarget) return;
|
|
6186
5998
|
dispatch({ type: "SET_ERROR", error: null });
|
|
6187
5999
|
try {
|
|
6188
|
-
if (
|
|
6189
|
-
await sendEmailCode({ email:
|
|
6000
|
+
if (verificationTarget.kind === "email") {
|
|
6001
|
+
await sendEmailCode({ email: verificationTarget.value });
|
|
6190
6002
|
} else {
|
|
6191
|
-
await sendSmsCode({ phoneNumber:
|
|
6003
|
+
await sendSmsCode({ phoneNumber: verificationTarget.value });
|
|
6192
6004
|
}
|
|
6193
6005
|
} catch (err) {
|
|
6194
6006
|
captureException(err);
|
|
@@ -6197,7 +6009,68 @@ function SwypePaymentInner({
|
|
|
6197
6009
|
error: err instanceof Error ? err.message : "Failed to resend code"
|
|
6198
6010
|
});
|
|
6199
6011
|
}
|
|
6200
|
-
}, [
|
|
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);
|
|
6201
6074
|
const completePasskeyRegistration = react.useCallback(async (credentialId, publicKey) => {
|
|
6202
6075
|
const token = await getAccessToken();
|
|
6203
6076
|
if (!token) throw new Error("Not authenticated");
|
|
@@ -6206,14 +6079,14 @@ function SwypePaymentInner({
|
|
|
6206
6079
|
window.localStorage.setItem(ACTIVE_CREDENTIAL_STORAGE_KEY, credentialId);
|
|
6207
6080
|
const resolved = resolvePostAuthStep({
|
|
6208
6081
|
hasPasskey: true,
|
|
6209
|
-
accounts
|
|
6082
|
+
accounts,
|
|
6210
6083
|
persistedMobileFlow: loadMobileFlowState(),
|
|
6211
6084
|
mobileSetupInProgress: mobileSetupFlowRef.current,
|
|
6212
6085
|
connectingNewAccount: false
|
|
6213
6086
|
});
|
|
6214
6087
|
if (resolved.clearPersistedFlow) clearMobileFlowState();
|
|
6215
6088
|
dispatch({ type: "NAVIGATE", step: resolved.step });
|
|
6216
|
-
}, [getAccessToken, apiBaseUrl,
|
|
6089
|
+
}, [getAccessToken, apiBaseUrl, accounts, mobileSetupFlowRef, dispatch]);
|
|
6217
6090
|
const handleRegisterPasskey = react.useCallback(async () => {
|
|
6218
6091
|
dispatch({ type: "SET_REGISTERING_PASSKEY", value: true });
|
|
6219
6092
|
dispatch({ type: "SET_ERROR", error: null });
|
|
@@ -6237,7 +6110,7 @@ function SwypePaymentInner({
|
|
|
6237
6110
|
} finally {
|
|
6238
6111
|
dispatch({ type: "SET_REGISTERING_PASSKEY", value: false });
|
|
6239
6112
|
}
|
|
6240
|
-
}, [user, completePasskeyRegistration]);
|
|
6113
|
+
}, [user, completePasskeyRegistration, dispatch]);
|
|
6241
6114
|
const handleCreatePasskeyViaPopup = react.useCallback(async () => {
|
|
6242
6115
|
dispatch({ type: "SET_REGISTERING_PASSKEY", value: true });
|
|
6243
6116
|
dispatch({ type: "SET_ERROR", error: null });
|
|
@@ -6255,7 +6128,7 @@ function SwypePaymentInner({
|
|
|
6255
6128
|
localStorage.setItem(ACTIVE_CREDENTIAL_STORAGE_KEY, credentialId);
|
|
6256
6129
|
const resolved = resolvePostAuthStep({
|
|
6257
6130
|
hasPasskey: true,
|
|
6258
|
-
accounts
|
|
6131
|
+
accounts,
|
|
6259
6132
|
persistedMobileFlow: loadMobileFlowState(),
|
|
6260
6133
|
mobileSetupInProgress: mobileSetupFlowRef.current,
|
|
6261
6134
|
connectingNewAccount: false
|
|
@@ -6271,14 +6144,14 @@ function SwypePaymentInner({
|
|
|
6271
6144
|
} finally {
|
|
6272
6145
|
dispatch({ type: "SET_REGISTERING_PASSKEY", value: false });
|
|
6273
6146
|
}
|
|
6274
|
-
}, [user, getAccessToken, apiBaseUrl,
|
|
6147
|
+
}, [user, getAccessToken, apiBaseUrl, accounts, mobileSetupFlowRef, dispatch]);
|
|
6275
6148
|
const handleVerifyPasskeyViaPopup = react.useCallback(async () => {
|
|
6276
6149
|
dispatch({ type: "SET_VERIFYING_PASSKEY", value: true });
|
|
6277
6150
|
dispatch({ type: "SET_ERROR", error: null });
|
|
6278
6151
|
try {
|
|
6279
6152
|
const token = await getAccessToken();
|
|
6280
6153
|
const matched = await findDevicePasskeyViaPopup({
|
|
6281
|
-
credentialIds:
|
|
6154
|
+
credentialIds: knownCredentialIds,
|
|
6282
6155
|
rpId: resolvePasskeyRpId(),
|
|
6283
6156
|
authToken: token ?? void 0,
|
|
6284
6157
|
apiBaseUrl
|
|
@@ -6292,7 +6165,7 @@ function SwypePaymentInner({
|
|
|
6292
6165
|
}
|
|
6293
6166
|
const resolved = resolvePostAuthStep({
|
|
6294
6167
|
hasPasskey: true,
|
|
6295
|
-
accounts
|
|
6168
|
+
accounts,
|
|
6296
6169
|
persistedMobileFlow: loadMobileFlowState(),
|
|
6297
6170
|
mobileSetupInProgress: mobileSetupFlowRef.current,
|
|
6298
6171
|
connectingNewAccount: false
|
|
@@ -6314,44 +6187,48 @@ function SwypePaymentInner({
|
|
|
6314
6187
|
} finally {
|
|
6315
6188
|
dispatch({ type: "SET_VERIFYING_PASSKEY", value: false });
|
|
6316
6189
|
}
|
|
6317
|
-
}, [
|
|
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);
|
|
6318
6221
|
const reloadAccounts = react.useCallback(async () => {
|
|
6319
6222
|
const token = await getAccessToken();
|
|
6320
|
-
if (!token || !
|
|
6223
|
+
if (!token || !activeCredentialId) return;
|
|
6321
6224
|
const [accts, prov] = await Promise.all([
|
|
6322
|
-
fetchAccounts(apiBaseUrl, token,
|
|
6225
|
+
fetchAccounts(apiBaseUrl, token, activeCredentialId),
|
|
6323
6226
|
fetchProviders(apiBaseUrl, token)
|
|
6324
6227
|
]);
|
|
6325
6228
|
const parsedAmt = depositAmount != null ? depositAmount : 0;
|
|
6326
|
-
const defaults = resolveDepositSelection(accts, parsedAmt,
|
|
6229
|
+
const defaults = resolveDepositSelection(accts, parsedAmt, selectedAccountId);
|
|
6327
6230
|
dispatch({ type: "ACCOUNTS_RELOADED", accounts: accts, providers: prov, defaults });
|
|
6328
|
-
}, [getAccessToken,
|
|
6329
|
-
const handleAuthorizedMobileReturn = react.useCallback(async (authorizedTransfer, isSetup) => {
|
|
6330
|
-
if (handlingMobileReturnRef.current) return;
|
|
6331
|
-
handlingMobileReturnRef.current = true;
|
|
6332
|
-
polling.stopPolling();
|
|
6333
|
-
if (isSetup) {
|
|
6334
|
-
mobileSetupFlowRef.current = false;
|
|
6335
|
-
clearMobileFlowState();
|
|
6336
|
-
try {
|
|
6337
|
-
await reloadAccounts();
|
|
6338
|
-
loadingDataRef.current = false;
|
|
6339
|
-
dispatch({ type: "MOBILE_SETUP_COMPLETE", transfer: authorizedTransfer });
|
|
6340
|
-
} catch (err) {
|
|
6341
|
-
handlingMobileReturnRef.current = false;
|
|
6342
|
-
dispatch({
|
|
6343
|
-
type: "SET_ERROR",
|
|
6344
|
-
error: err instanceof Error ? err.message : "Wallet authorized, but we could not refresh your account yet."
|
|
6345
|
-
});
|
|
6346
|
-
dispatch({ type: "NAVIGATE", step: "open-wallet" });
|
|
6347
|
-
}
|
|
6348
|
-
return;
|
|
6349
|
-
}
|
|
6350
|
-
mobileSetupFlowRef.current = false;
|
|
6351
|
-
clearMobileFlowState();
|
|
6352
|
-
dispatch({ type: "MOBILE_SIGN_READY", transfer: authorizedTransfer });
|
|
6353
|
-
}, [polling.stopPolling, reloadAccounts]);
|
|
6354
|
-
handleAuthorizedMobileReturnRef.current = handleAuthorizedMobileReturn;
|
|
6231
|
+
}, [getAccessToken, activeCredentialId, selectedAccountId, apiBaseUrl, depositAmount, dispatch]);
|
|
6355
6232
|
const handlePay = react.useCallback(async (payAmount, sourceOverrides) => {
|
|
6356
6233
|
if (isNaN(payAmount) || payAmount < MIN_SEND_AMOUNT_USD) {
|
|
6357
6234
|
dispatch({ type: "SET_ERROR", error: `Minimum amount is $${MIN_SEND_AMOUNT_USD.toFixed(2)}.` });
|
|
@@ -6361,7 +6238,7 @@ function SwypePaymentInner({
|
|
|
6361
6238
|
dispatch({ type: "SET_ERROR", error: "No account or provider selected." });
|
|
6362
6239
|
return;
|
|
6363
6240
|
}
|
|
6364
|
-
if (!
|
|
6241
|
+
if (!activeCredentialId) {
|
|
6365
6242
|
dispatch({ type: "SET_ERROR", error: "Create or verify a passkey on this device before continuing." });
|
|
6366
6243
|
dispatch({ type: "NAVIGATE", step: "create-passkey" });
|
|
6367
6244
|
return;
|
|
@@ -6369,10 +6246,10 @@ function SwypePaymentInner({
|
|
|
6369
6246
|
dispatch({ type: "PAY_STARTED", isSetupRedirect: false });
|
|
6370
6247
|
processingStartedAtRef.current = Date.now();
|
|
6371
6248
|
try {
|
|
6372
|
-
if (
|
|
6373
|
-
const signedTransfer2 = await transferSigning.signTransfer(
|
|
6249
|
+
if (transfer?.status === "AUTHORIZED") {
|
|
6250
|
+
const signedTransfer2 = await transferSigning.signTransfer(transfer.id);
|
|
6374
6251
|
dispatch({ type: "TRANSFER_SIGNED", transfer: signedTransfer2 });
|
|
6375
|
-
polling.startPolling(
|
|
6252
|
+
polling.startPolling(transfer.id);
|
|
6376
6253
|
return;
|
|
6377
6254
|
}
|
|
6378
6255
|
const token = await getAccessToken();
|
|
@@ -6380,7 +6257,7 @@ function SwypePaymentInner({
|
|
|
6380
6257
|
let effectiveSourceType = sourceOverrides?.sourceType ?? sourceType;
|
|
6381
6258
|
let effectiveSourceId = sourceOverrides?.sourceId ?? sourceId;
|
|
6382
6259
|
if (effectiveSourceType === "accountId") {
|
|
6383
|
-
const acct =
|
|
6260
|
+
const acct = accounts.find((a) => a.id === effectiveSourceId);
|
|
6384
6261
|
const preferredWallet = acct ? getPreferredDepositWallet(acct, payAmount) : null;
|
|
6385
6262
|
if (preferredWallet?.status === "ACTIVE") {
|
|
6386
6263
|
effectiveSourceType = "walletId";
|
|
@@ -6389,10 +6266,11 @@ function SwypePaymentInner({
|
|
|
6389
6266
|
}
|
|
6390
6267
|
const t = await createTransfer(apiBaseUrl, token, {
|
|
6391
6268
|
id: idempotencyKey,
|
|
6392
|
-
credentialId:
|
|
6269
|
+
credentialId: activeCredentialId,
|
|
6393
6270
|
merchantAuthorization,
|
|
6394
6271
|
sourceType: effectiveSourceType,
|
|
6395
6272
|
sourceId: effectiveSourceId,
|
|
6273
|
+
sourceTokenAddress,
|
|
6396
6274
|
destination,
|
|
6397
6275
|
amount: payAmount
|
|
6398
6276
|
});
|
|
@@ -6412,11 +6290,7 @@ function SwypePaymentInner({
|
|
|
6412
6290
|
} catch (err) {
|
|
6413
6291
|
captureException(err);
|
|
6414
6292
|
const msg = err instanceof Error ? err.message : "Transfer failed";
|
|
6415
|
-
dispatch({
|
|
6416
|
-
type: "PAY_ERROR",
|
|
6417
|
-
error: msg,
|
|
6418
|
-
fallbackStep: "deposit"
|
|
6419
|
-
});
|
|
6293
|
+
dispatch({ type: "PAY_ERROR", error: msg, fallbackStep: "deposit" });
|
|
6420
6294
|
onError?.(msg);
|
|
6421
6295
|
} finally {
|
|
6422
6296
|
dispatch({ type: "PAY_ENDED" });
|
|
@@ -6424,9 +6298,10 @@ function SwypePaymentInner({
|
|
|
6424
6298
|
}, [
|
|
6425
6299
|
sourceId,
|
|
6426
6300
|
sourceType,
|
|
6427
|
-
|
|
6428
|
-
|
|
6429
|
-
|
|
6301
|
+
sourceTokenAddress,
|
|
6302
|
+
activeCredentialId,
|
|
6303
|
+
transfer,
|
|
6304
|
+
accounts,
|
|
6430
6305
|
destination,
|
|
6431
6306
|
apiBaseUrl,
|
|
6432
6307
|
getAccessToken,
|
|
@@ -6435,185 +6310,133 @@ function SwypePaymentInner({
|
|
|
6435
6310
|
onError,
|
|
6436
6311
|
onComplete,
|
|
6437
6312
|
idempotencyKey,
|
|
6438
|
-
merchantAuthorization
|
|
6313
|
+
merchantAuthorization,
|
|
6314
|
+
dispatch
|
|
6439
6315
|
]);
|
|
6440
|
-
const
|
|
6441
|
-
|
|
6442
|
-
|
|
6443
|
-
return;
|
|
6444
|
-
}
|
|
6445
|
-
if (!state.activeCredentialId) {
|
|
6446
|
-
dispatch({ type: "SET_ERROR", error: "Create or verify a passkey on this device before continuing." });
|
|
6447
|
-
dispatch({ type: "NAVIGATE", step: "create-passkey" });
|
|
6448
|
-
return;
|
|
6449
|
-
}
|
|
6450
|
-
const acct = state.accounts.find((a) => a.id === state.selectedAccountId);
|
|
6451
|
-
const matchedProvider = acct ? state.providers.find((p) => p.name === acct.name) : void 0;
|
|
6452
|
-
if (matchedProvider) {
|
|
6453
|
-
dispatch({ type: "SELECT_PROVIDER", providerId: matchedProvider.id });
|
|
6454
|
-
}
|
|
6455
|
-
dispatch({ type: "SET_ERROR", error: null });
|
|
6456
|
-
dispatch({ type: "SET_INCREASING_LIMIT", value: true });
|
|
6316
|
+
const handleConfirmSign = react.useCallback(async () => {
|
|
6317
|
+
const t = transfer ?? polling.transfer;
|
|
6318
|
+
if (!t) return;
|
|
6457
6319
|
try {
|
|
6458
|
-
const
|
|
6459
|
-
|
|
6460
|
-
|
|
6461
|
-
|
|
6462
|
-
token,
|
|
6463
|
-
state.selectedAccountId,
|
|
6464
|
-
state.activeCredentialId
|
|
6465
|
-
);
|
|
6466
|
-
const isMobile = !shouldUseWalletConnector({
|
|
6467
|
-
useWalletConnector: useWalletConnectorProp,
|
|
6468
|
-
userAgent: typeof navigator === "undefined" ? void 0 : navigator.userAgent
|
|
6469
|
-
});
|
|
6470
|
-
if (isMobile) {
|
|
6471
|
-
handlingMobileReturnRef.current = false;
|
|
6472
|
-
mobileSetupFlowRef.current = true;
|
|
6473
|
-
setupAccountIdRef.current = state.selectedAccountId;
|
|
6474
|
-
reauthSessionIdRef.current = session.id;
|
|
6475
|
-
reauthTokenRef.current = null;
|
|
6476
|
-
persistMobileFlowState({
|
|
6477
|
-
accountId: state.selectedAccountId,
|
|
6478
|
-
sessionId: session.id,
|
|
6479
|
-
deeplinkUri: session.uri,
|
|
6480
|
-
providerId: matchedProvider?.id ?? null,
|
|
6481
|
-
isSetup: true,
|
|
6482
|
-
isReauthorization: true
|
|
6483
|
-
});
|
|
6484
|
-
dispatch({ type: "MOBILE_DEEPLINK_READY", deeplinkUri: session.uri });
|
|
6485
|
-
triggerDeeplink(session.uri);
|
|
6486
|
-
} else {
|
|
6487
|
-
await authExecutor.executeSessionById(session.id);
|
|
6488
|
-
await reloadAccounts();
|
|
6489
|
-
dispatch({ type: "NAVIGATE", step: "deposit" });
|
|
6490
|
-
}
|
|
6320
|
+
const signedTransfer = await transferSigning.signTransfer(t.id);
|
|
6321
|
+
clearMobileFlowState();
|
|
6322
|
+
dispatch({ type: "CONFIRM_SIGN_SUCCESS", transfer: signedTransfer });
|
|
6323
|
+
polling.startPolling(t.id);
|
|
6491
6324
|
} catch (err) {
|
|
6492
6325
|
captureException(err);
|
|
6493
|
-
const msg = err instanceof Error ? err.message : "Failed to
|
|
6326
|
+
const msg = err instanceof Error ? err.message : "Failed to sign transfer";
|
|
6494
6327
|
dispatch({ type: "SET_ERROR", error: msg });
|
|
6495
6328
|
onError?.(msg);
|
|
6496
|
-
} finally {
|
|
6497
|
-
dispatch({ type: "SET_INCREASING_LIMIT", value: false });
|
|
6498
6329
|
}
|
|
6499
|
-
}, [
|
|
6500
|
-
|
|
6501
|
-
state.activeCredentialId,
|
|
6502
|
-
state.accounts,
|
|
6503
|
-
state.providers,
|
|
6504
|
-
apiBaseUrl,
|
|
6505
|
-
getAccessToken,
|
|
6506
|
-
authExecutor,
|
|
6507
|
-
useWalletConnectorProp,
|
|
6330
|
+
}, [transfer, polling.transfer, polling.startPolling, transferSigning, onError, dispatch]);
|
|
6331
|
+
return {
|
|
6508
6332
|
reloadAccounts,
|
|
6509
|
-
|
|
6510
|
-
|
|
6511
|
-
|
|
6512
|
-
|
|
6513
|
-
}
|
|
6514
|
-
|
|
6515
|
-
|
|
6516
|
-
|
|
6517
|
-
const
|
|
6518
|
-
|
|
6519
|
-
|
|
6520
|
-
|
|
6521
|
-
|
|
6522
|
-
if (!
|
|
6523
|
-
|
|
6524
|
-
|
|
6525
|
-
|
|
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);
|
|
6526
6363
|
}
|
|
6527
|
-
|
|
6528
|
-
|
|
6529
|
-
|
|
6530
|
-
|
|
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;
|
|
6531
6368
|
}
|
|
6532
|
-
|
|
6533
|
-
|
|
6534
|
-
|
|
6535
|
-
|
|
6536
|
-
|
|
6537
|
-
|
|
6538
|
-
|
|
6539
|
-
|
|
6540
|
-
|
|
6541
|
-
|
|
6542
|
-
|
|
6543
|
-
{ tokenAddress, chainId }
|
|
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
|
|
6544
6380
|
);
|
|
6545
|
-
|
|
6546
|
-
|
|
6547
|
-
|
|
6548
|
-
|
|
6549
|
-
|
|
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) {
|
|
6550
6423
|
handlingMobileReturnRef.current = false;
|
|
6551
|
-
|
|
6552
|
-
|
|
6553
|
-
|
|
6554
|
-
reauthTokenRef.current = { walletId: _walletId, tokenSymbol };
|
|
6555
|
-
persistMobileFlowState({
|
|
6556
|
-
accountId: state.selectedAccountId,
|
|
6557
|
-
sessionId: session.id,
|
|
6558
|
-
deeplinkUri: session.uri,
|
|
6559
|
-
providerId: matchedProvider?.id ?? null,
|
|
6560
|
-
isSetup: true,
|
|
6561
|
-
isReauthorization: true,
|
|
6562
|
-
reauthorizationToken: { walletId: _walletId, tokenSymbol }
|
|
6424
|
+
dispatch({
|
|
6425
|
+
type: "SET_ERROR",
|
|
6426
|
+
error: err instanceof Error ? err.message : "Wallet authorized, but we could not refresh your account yet."
|
|
6563
6427
|
});
|
|
6564
|
-
dispatch({ type: "
|
|
6565
|
-
triggerDeeplink(session.uri);
|
|
6566
|
-
} else {
|
|
6567
|
-
pendingTokenAuthSessionRef.current = {
|
|
6568
|
-
sessionId: session.id,
|
|
6569
|
-
walletId: _walletId,
|
|
6570
|
-
tokenSymbol,
|
|
6571
|
-
tokenAddress,
|
|
6572
|
-
chainId
|
|
6573
|
-
};
|
|
6574
|
-
dispatch({ type: "SELECT_TOKEN", walletId: _walletId, tokenSymbol });
|
|
6575
|
-
dispatch({ type: "NAVIGATE", step: "setup" });
|
|
6428
|
+
dispatch({ type: "NAVIGATE", step: "open-wallet" });
|
|
6576
6429
|
}
|
|
6577
|
-
|
|
6578
|
-
captureException(err);
|
|
6579
|
-
const msg = err instanceof Error ? err.message : "Failed to authorize token";
|
|
6580
|
-
dispatch({ type: "SET_ERROR", error: msg });
|
|
6581
|
-
onError?.(msg);
|
|
6582
|
-
} finally {
|
|
6583
|
-
pendingTokenAuthRef.current = null;
|
|
6584
|
-
dispatch({ type: "SET_INCREASING_LIMIT", value: false });
|
|
6585
|
-
}
|
|
6586
|
-
}, [
|
|
6587
|
-
state.selectedAccountId,
|
|
6588
|
-
state.activeCredentialId,
|
|
6589
|
-
state.accounts,
|
|
6590
|
-
state.providers,
|
|
6591
|
-
apiBaseUrl,
|
|
6592
|
-
getAccessToken,
|
|
6593
|
-
authExecutor,
|
|
6594
|
-
useWalletConnectorProp,
|
|
6595
|
-
reloadAccounts,
|
|
6596
|
-
onError
|
|
6597
|
-
]);
|
|
6598
|
-
const handleConfirmSign = react.useCallback(async () => {
|
|
6599
|
-
const t = state.transfer ?? polling.transfer;
|
|
6600
|
-
if (!t) return;
|
|
6601
|
-
try {
|
|
6602
|
-
const signedTransfer = await transferSigning.signTransfer(t.id);
|
|
6603
|
-
clearMobileFlowState();
|
|
6604
|
-
dispatch({ type: "CONFIRM_SIGN_SUCCESS", transfer: signedTransfer });
|
|
6605
|
-
polling.startPolling(t.id);
|
|
6606
|
-
} catch (err) {
|
|
6607
|
-
captureException(err);
|
|
6608
|
-
const msg = err instanceof Error ? err.message : "Failed to sign transfer";
|
|
6609
|
-
dispatch({ type: "SET_ERROR", error: msg });
|
|
6610
|
-
onError?.(msg);
|
|
6430
|
+
return;
|
|
6611
6431
|
}
|
|
6612
|
-
|
|
6432
|
+
mobileSetupFlowRef.current = false;
|
|
6433
|
+
clearMobileFlowState();
|
|
6434
|
+
dispatch({ type: "MOBILE_SIGN_READY", transfer: authorizedTransfer });
|
|
6435
|
+
}, [polling.stopPolling, reloadAccounts, dispatch]);
|
|
6613
6436
|
const handleRetryMobileStatus = react.useCallback(() => {
|
|
6614
6437
|
dispatch({ type: "SET_ERROR", error: null });
|
|
6615
6438
|
handlingMobileReturnRef.current = false;
|
|
6616
|
-
const currentTransfer = polling.transfer ??
|
|
6439
|
+
const currentTransfer = polling.transfer ?? stateTransfer;
|
|
6617
6440
|
if (currentTransfer?.status === "AUTHORIZED") {
|
|
6618
6441
|
void handleAuthorizedMobileReturn(currentTransfer, mobileSetupFlowRef.current);
|
|
6619
6442
|
return;
|
|
@@ -6622,15 +6445,54 @@ function SwypePaymentInner({
|
|
|
6622
6445
|
if (transferIdToResume) {
|
|
6623
6446
|
polling.startPolling(transferIdToResume);
|
|
6624
6447
|
}
|
|
6625
|
-
}, [handleAuthorizedMobileReturn, polling,
|
|
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;
|
|
6626
6488
|
const handleSelectProvider = react.useCallback(async (providerId) => {
|
|
6627
6489
|
dispatch({ type: "SELECT_PROVIDER", providerId });
|
|
6628
|
-
if (!
|
|
6490
|
+
if (!activeCredentialId) {
|
|
6629
6491
|
dispatch({ type: "SET_ERROR", error: "Create or verify a passkey on this device before continuing." });
|
|
6630
6492
|
dispatch({ type: "NAVIGATE", step: "create-passkey" });
|
|
6631
6493
|
return;
|
|
6632
6494
|
}
|
|
6633
|
-
const provider =
|
|
6495
|
+
const provider = providers.find((p) => p.id === providerId);
|
|
6634
6496
|
const providerName = provider?.name ?? "Wallet";
|
|
6635
6497
|
const isMobile = !shouldUseWalletConnector({
|
|
6636
6498
|
useWalletConnector: useWalletConnectorProp,
|
|
@@ -6649,7 +6511,7 @@ function SwypePaymentInner({
|
|
|
6649
6511
|
const account = await createAccount(apiBaseUrl, token, {
|
|
6650
6512
|
id: accountId,
|
|
6651
6513
|
name: providerName,
|
|
6652
|
-
credentialId:
|
|
6514
|
+
credentialId: activeCredentialId,
|
|
6653
6515
|
providerId
|
|
6654
6516
|
});
|
|
6655
6517
|
const session = account.authorizationSessions?.[0];
|
|
@@ -6681,29 +6543,33 @@ function SwypePaymentInner({
|
|
|
6681
6543
|
dispatch({ type: "PAY_ENDED" });
|
|
6682
6544
|
}
|
|
6683
6545
|
}, [
|
|
6684
|
-
|
|
6685
|
-
|
|
6546
|
+
activeCredentialId,
|
|
6547
|
+
providers,
|
|
6686
6548
|
apiBaseUrl,
|
|
6687
6549
|
getAccessToken,
|
|
6688
6550
|
authExecutor,
|
|
6689
6551
|
useWalletConnectorProp,
|
|
6690
6552
|
reloadAccounts,
|
|
6691
|
-
onError
|
|
6553
|
+
onError,
|
|
6554
|
+
dispatch,
|
|
6555
|
+
mobileSetupFlowRef,
|
|
6556
|
+
handlingMobileReturnRef,
|
|
6557
|
+
setupAccountIdRef
|
|
6692
6558
|
]);
|
|
6693
6559
|
const handleContinueConnection = react.useCallback(
|
|
6694
6560
|
(accountId) => {
|
|
6695
|
-
const acct =
|
|
6561
|
+
const acct = accounts.find((a) => a.id === accountId);
|
|
6696
6562
|
if (!acct) return;
|
|
6697
|
-
const matchedProvider =
|
|
6563
|
+
const matchedProvider = providers.find((p) => p.name === acct.name);
|
|
6698
6564
|
if (matchedProvider) {
|
|
6699
6565
|
handleSelectProvider(matchedProvider.id);
|
|
6700
6566
|
}
|
|
6701
6567
|
},
|
|
6702
|
-
[
|
|
6568
|
+
[accounts, providers, handleSelectProvider]
|
|
6703
6569
|
);
|
|
6704
6570
|
const handleSelectAccount = react.useCallback(
|
|
6705
6571
|
(accountId) => {
|
|
6706
|
-
const acct =
|
|
6572
|
+
const acct = accounts.find((a) => a.id === accountId);
|
|
6707
6573
|
if (!acct) return;
|
|
6708
6574
|
const activeWallet = getPreferredDepositWallet(acct, depositAmount ?? 0);
|
|
6709
6575
|
dispatch({
|
|
@@ -6712,8 +6578,197 @@ function SwypePaymentInner({
|
|
|
6712
6578
|
walletId: activeWallet?.id ?? null
|
|
6713
6579
|
});
|
|
6714
6580
|
},
|
|
6715
|
-
[
|
|
6581
|
+
[accounts, depositAmount, dispatch]
|
|
6716
6582
|
);
|
|
6583
|
+
const handleIncreaseLimit = react.useCallback(async () => {
|
|
6584
|
+
if (!selectedAccountId) {
|
|
6585
|
+
dispatch({ type: "SET_ERROR", error: "No account selected." });
|
|
6586
|
+
return;
|
|
6587
|
+
}
|
|
6588
|
+
if (!activeCredentialId) {
|
|
6589
|
+
dispatch({ type: "SET_ERROR", error: "Create or verify a passkey on this device before continuing." });
|
|
6590
|
+
dispatch({ type: "NAVIGATE", step: "create-passkey" });
|
|
6591
|
+
return;
|
|
6592
|
+
}
|
|
6593
|
+
const acct = accounts.find((a) => a.id === selectedAccountId);
|
|
6594
|
+
const matchedProvider = acct ? providers.find((p) => p.name === acct.name) : void 0;
|
|
6595
|
+
if (matchedProvider) {
|
|
6596
|
+
dispatch({ type: "SELECT_PROVIDER", providerId: matchedProvider.id });
|
|
6597
|
+
}
|
|
6598
|
+
dispatch({ type: "SET_ERROR", error: null });
|
|
6599
|
+
dispatch({ type: "SET_INCREASING_LIMIT", value: true });
|
|
6600
|
+
try {
|
|
6601
|
+
const token = await getAccessToken();
|
|
6602
|
+
if (!token) throw new Error("Not authenticated");
|
|
6603
|
+
const session = await createAccountAuthorizationSession(
|
|
6604
|
+
apiBaseUrl,
|
|
6605
|
+
token,
|
|
6606
|
+
selectedAccountId,
|
|
6607
|
+
activeCredentialId
|
|
6608
|
+
);
|
|
6609
|
+
const isMobile = !shouldUseWalletConnector({
|
|
6610
|
+
useWalletConnector: useWalletConnectorProp,
|
|
6611
|
+
userAgent: typeof navigator === "undefined" ? void 0 : navigator.userAgent
|
|
6612
|
+
});
|
|
6613
|
+
if (isMobile) {
|
|
6614
|
+
handlingMobileReturnRef.current = false;
|
|
6615
|
+
mobileSetupFlowRef.current = true;
|
|
6616
|
+
setupAccountIdRef.current = selectedAccountId;
|
|
6617
|
+
reauthSessionIdRef.current = session.id;
|
|
6618
|
+
reauthTokenRef.current = null;
|
|
6619
|
+
persistMobileFlowState({
|
|
6620
|
+
accountId: selectedAccountId,
|
|
6621
|
+
sessionId: session.id,
|
|
6622
|
+
deeplinkUri: session.uri,
|
|
6623
|
+
providerId: matchedProvider?.id ?? null,
|
|
6624
|
+
isSetup: true,
|
|
6625
|
+
isReauthorization: true
|
|
6626
|
+
});
|
|
6627
|
+
dispatch({ type: "MOBILE_DEEPLINK_READY", deeplinkUri: session.uri });
|
|
6628
|
+
triggerDeeplink(session.uri);
|
|
6629
|
+
} else {
|
|
6630
|
+
dispatch({ type: "NAVIGATE", step: "setup-status" });
|
|
6631
|
+
await authExecutor.executeSessionById(session.id);
|
|
6632
|
+
await reloadAccounts();
|
|
6633
|
+
dispatch({ type: "NAVIGATE", step: "deposit" });
|
|
6634
|
+
}
|
|
6635
|
+
} catch (err) {
|
|
6636
|
+
captureException(err);
|
|
6637
|
+
const msg = err instanceof Error ? err.message : "Failed to increase limit";
|
|
6638
|
+
dispatch({ type: "SET_ERROR", error: msg });
|
|
6639
|
+
onError?.(msg);
|
|
6640
|
+
} finally {
|
|
6641
|
+
dispatch({ type: "SET_INCREASING_LIMIT", value: false });
|
|
6642
|
+
}
|
|
6643
|
+
}, [
|
|
6644
|
+
selectedAccountId,
|
|
6645
|
+
activeCredentialId,
|
|
6646
|
+
accounts,
|
|
6647
|
+
providers,
|
|
6648
|
+
apiBaseUrl,
|
|
6649
|
+
getAccessToken,
|
|
6650
|
+
authExecutor,
|
|
6651
|
+
useWalletConnectorProp,
|
|
6652
|
+
reloadAccounts,
|
|
6653
|
+
onError,
|
|
6654
|
+
dispatch,
|
|
6655
|
+
mobileSetupFlowRef,
|
|
6656
|
+
handlingMobileReturnRef,
|
|
6657
|
+
setupAccountIdRef,
|
|
6658
|
+
reauthSessionIdRef,
|
|
6659
|
+
reauthTokenRef
|
|
6660
|
+
]);
|
|
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" });
|
|
6666
|
+
}
|
|
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." });
|
|
6674
|
+
return;
|
|
6675
|
+
}
|
|
6676
|
+
if (!activeCredentialId) {
|
|
6677
|
+
dispatch({ type: "SET_ERROR", error: "Create or verify a passkey on this device before continuing." });
|
|
6678
|
+
dispatch({ type: "NAVIGATE", step: "create-passkey" });
|
|
6679
|
+
return;
|
|
6680
|
+
}
|
|
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 });
|
|
6685
|
+
}
|
|
6686
|
+
dispatch({ type: "SET_ERROR", error: null });
|
|
6687
|
+
dispatch({ type: "SET_INCREASING_LIMIT", value: true });
|
|
6688
|
+
try {
|
|
6689
|
+
const token = await getAccessToken();
|
|
6690
|
+
if (!token) throw new Error("Not authenticated");
|
|
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
|
|
6701
|
+
});
|
|
6702
|
+
if (isMobile) {
|
|
6703
|
+
handlingMobileReturnRef.current = false;
|
|
6704
|
+
mobileSetupFlowRef.current = true;
|
|
6705
|
+
setupAccountIdRef.current = selectedAccountId;
|
|
6706
|
+
reauthSessionIdRef.current = session.id;
|
|
6707
|
+
reauthTokenRef.current = { walletId: _walletId, tokenSymbol };
|
|
6708
|
+
persistMobileFlowState({
|
|
6709
|
+
accountId: selectedAccountId,
|
|
6710
|
+
sessionId: session.id,
|
|
6711
|
+
deeplinkUri: session.uri,
|
|
6712
|
+
providerId: matchedProvider?.id ?? null,
|
|
6713
|
+
isSetup: true,
|
|
6714
|
+
isReauthorization: true,
|
|
6715
|
+
reauthorizationToken: { walletId: _walletId, tokenSymbol }
|
|
6716
|
+
});
|
|
6717
|
+
dispatch({ type: "MOBILE_DEEPLINK_READY", deeplinkUri: session.uri });
|
|
6718
|
+
triggerDeeplink(session.uri);
|
|
6719
|
+
} else {
|
|
6720
|
+
dispatch({ type: "NAVIGATE", step: "setup-status" });
|
|
6721
|
+
await authExecutor.executeSessionById(session.id);
|
|
6722
|
+
await reloadAccounts();
|
|
6723
|
+
dispatch({ type: "SELECT_TOKEN", walletId: _walletId, tokenSymbol });
|
|
6724
|
+
}
|
|
6725
|
+
} catch (err) {
|
|
6726
|
+
captureException(err);
|
|
6727
|
+
const msg = err instanceof Error ? err.message : "Failed to authorize token";
|
|
6728
|
+
dispatch({ type: "SET_ERROR", error: msg });
|
|
6729
|
+
onError?.(msg);
|
|
6730
|
+
} finally {
|
|
6731
|
+
dispatch({ type: "SET_INCREASING_LIMIT", value: false });
|
|
6732
|
+
}
|
|
6733
|
+
}, [
|
|
6734
|
+
selectedAccountId,
|
|
6735
|
+
activeCredentialId,
|
|
6736
|
+
accounts,
|
|
6737
|
+
providers,
|
|
6738
|
+
apiBaseUrl,
|
|
6739
|
+
getAccessToken,
|
|
6740
|
+
authExecutor,
|
|
6741
|
+
useWalletConnectorProp,
|
|
6742
|
+
reloadAccounts,
|
|
6743
|
+
onError,
|
|
6744
|
+
dispatch,
|
|
6745
|
+
mobileSetupFlowRef,
|
|
6746
|
+
handlingMobileReturnRef,
|
|
6747
|
+
setupAccountIdRef,
|
|
6748
|
+
reauthSessionIdRef,
|
|
6749
|
+
reauthTokenRef
|
|
6750
|
+
]);
|
|
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);
|
|
6717
6772
|
const handleSetupOneTap = react.useCallback(async (limit) => {
|
|
6718
6773
|
setSavingOneTapLimit(true);
|
|
6719
6774
|
try {
|
|
@@ -6721,39 +6776,24 @@ function SwypePaymentInner({
|
|
|
6721
6776
|
if (!token) throw new Error("Not authenticated");
|
|
6722
6777
|
await updateUserConfig(apiBaseUrl, token, { defaultAllowance: limit });
|
|
6723
6778
|
if (authExecutor.pendingSelectSource) {
|
|
6724
|
-
authExecutor.
|
|
6725
|
-
|
|
6726
|
-
|
|
6727
|
-
|
|
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";
|
|
6791
|
+
}
|
|
6792
|
+
oneTapLimitSavedDuringSetupRef.current = true;
|
|
6793
|
+
authExecutor.resolveSelectSource({ chainName, tokenSymbol });
|
|
6728
6794
|
dispatch({ type: "NAVIGATE", step: "setup-status" });
|
|
6729
6795
|
} else if (authExecutor.pendingOneTapSetup) {
|
|
6730
6796
|
authExecutor.resolveOneTapSetup();
|
|
6731
|
-
} else if (pendingTokenAuthSessionRef.current) {
|
|
6732
|
-
const pending = pendingTokenAuthSessionRef.current;
|
|
6733
|
-
pendingTokenAuthSessionRef.current = null;
|
|
6734
|
-
pendingTokenAuthRef.current = {
|
|
6735
|
-
tokenAddress: pending.tokenAddress,
|
|
6736
|
-
chainId: pending.chainId,
|
|
6737
|
-
tokenSymbol: pending.tokenSymbol,
|
|
6738
|
-
walletId: pending.walletId
|
|
6739
|
-
};
|
|
6740
|
-
dispatch({ type: "SET_INCREASING_LIMIT", value: true });
|
|
6741
|
-
dispatch({ type: "NAVIGATE", step: "setup-status" });
|
|
6742
|
-
try {
|
|
6743
|
-
await authExecutor.executeSessionById(pending.sessionId);
|
|
6744
|
-
await reloadAccounts();
|
|
6745
|
-
dispatch({ type: "SELECT_TOKEN", walletId: pending.walletId, tokenSymbol: pending.tokenSymbol });
|
|
6746
|
-
} catch (authErr) {
|
|
6747
|
-
captureException(authErr);
|
|
6748
|
-
dispatch({
|
|
6749
|
-
type: "SET_ERROR",
|
|
6750
|
-
error: authErr instanceof Error ? authErr.message : "Failed to authorize token"
|
|
6751
|
-
});
|
|
6752
|
-
dispatch({ type: "NAVIGATE", step: "deposit" });
|
|
6753
|
-
} finally {
|
|
6754
|
-
pendingTokenAuthRef.current = null;
|
|
6755
|
-
dispatch({ type: "SET_INCREASING_LIMIT", value: false });
|
|
6756
|
-
}
|
|
6757
6797
|
} else {
|
|
6758
6798
|
dispatch({ type: "NAVIGATE", step: "deposit" });
|
|
6759
6799
|
}
|
|
@@ -6766,76 +6806,118 @@ function SwypePaymentInner({
|
|
|
6766
6806
|
} finally {
|
|
6767
6807
|
setSavingOneTapLimit(false);
|
|
6768
6808
|
}
|
|
6769
|
-
}, [getAccessToken, apiBaseUrl, authExecutor,
|
|
6770
|
-
|
|
6771
|
-
|
|
6772
|
-
|
|
6773
|
-
|
|
6774
|
-
|
|
6775
|
-
|
|
6776
|
-
|
|
6777
|
-
|
|
6778
|
-
|
|
6779
|
-
|
|
6780
|
-
|
|
6781
|
-
|
|
6782
|
-
|
|
6783
|
-
|
|
6784
|
-
|
|
6785
|
-
|
|
6786
|
-
|
|
6787
|
-
|
|
6788
|
-
|
|
6789
|
-
|
|
6790
|
-
|
|
6791
|
-
|
|
6792
|
-
|
|
6793
|
-
|
|
6794
|
-
|
|
6795
|
-
|
|
6796
|
-
|
|
6797
|
-
|
|
6798
|
-
|
|
6799
|
-
|
|
6800
|
-
|
|
6801
|
-
|
|
6802
|
-
|
|
6803
|
-
|
|
6804
|
-
|
|
6805
|
-
|
|
6806
|
-
|
|
6807
|
-
|
|
6808
|
-
|
|
6809
|
-
|
|
6810
|
-
|
|
6811
|
-
|
|
6812
|
-
|
|
6813
|
-
|
|
6814
|
-
|
|
6815
|
-
|
|
6816
|
-
|
|
6817
|
-
|
|
6818
|
-
|
|
6819
|
-
|
|
6820
|
-
|
|
6821
|
-
|
|
6822
|
-
|
|
6823
|
-
|
|
6824
|
-
|
|
6825
|
-
|
|
6826
|
-
|
|
6827
|
-
|
|
6828
|
-
|
|
6829
|
-
|
|
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;
|
|
6830
6912
|
react.useEffect(() => {
|
|
6831
6913
|
if (depositAmount != null) {
|
|
6832
6914
|
dispatch({ type: "SYNC_AMOUNT", amount: depositAmount.toString() });
|
|
6833
6915
|
}
|
|
6834
|
-
}, [depositAmount]);
|
|
6916
|
+
}, [depositAmount, dispatch]);
|
|
6835
6917
|
react.useEffect(() => {
|
|
6836
6918
|
if (authenticated || state.step !== "otp-verify") return;
|
|
6837
6919
|
if (activeOtpErrorMessage) dispatch({ type: "SET_ERROR", error: activeOtpErrorMessage });
|
|
6838
|
-
}, [activeOtpErrorMessage, authenticated, state.step]);
|
|
6920
|
+
}, [activeOtpErrorMessage, authenticated, state.step, dispatch]);
|
|
6839
6921
|
react.useEffect(() => {
|
|
6840
6922
|
if (state.step === "otp-verify" && /^\d{6}$/.test(otpCode.trim()) && activeOtpStatus === "awaiting-code-input") {
|
|
6841
6923
|
handleVerifyLoginCode();
|
|
@@ -7062,7 +7144,7 @@ function SwypePaymentInner({
|
|
|
7062
7144
|
const load = async () => {
|
|
7063
7145
|
dispatch({ type: "DATA_LOAD_START" });
|
|
7064
7146
|
try {
|
|
7065
|
-
const token = await
|
|
7147
|
+
const token = await getAccessTokenRef.current();
|
|
7066
7148
|
if (!token) throw new Error("Not authenticated");
|
|
7067
7149
|
const [prov, accts, chn] = await Promise.all([
|
|
7068
7150
|
fetchProviders(apiBaseUrl, token),
|
|
@@ -7116,7 +7198,6 @@ function SwypePaymentInner({
|
|
|
7116
7198
|
state.step,
|
|
7117
7199
|
state.accounts.length,
|
|
7118
7200
|
apiBaseUrl,
|
|
7119
|
-
getAccessToken,
|
|
7120
7201
|
state.activeCredentialId,
|
|
7121
7202
|
state.selectedAccountId,
|
|
7122
7203
|
depositAmount
|
|
@@ -7131,7 +7212,7 @@ function SwypePaymentInner({
|
|
|
7131
7212
|
clearMobileFlowState();
|
|
7132
7213
|
dispatch({ type: "TRANSFER_FAILED", transfer: polling.transfer, error: "Transfer failed." });
|
|
7133
7214
|
}
|
|
7134
|
-
}, [polling.transfer, onComplete]);
|
|
7215
|
+
}, [polling.transfer, onComplete, dispatch]);
|
|
7135
7216
|
react.useEffect(() => {
|
|
7136
7217
|
if (state.step !== "processing") {
|
|
7137
7218
|
processingStartedAtRef.current = null;
|
|
@@ -7157,7 +7238,7 @@ function SwypePaymentInner({
|
|
|
7157
7238
|
}
|
|
7158
7239
|
const timeoutId = window.setTimeout(handleTimeout, remainingMs);
|
|
7159
7240
|
return () => window.clearTimeout(timeoutId);
|
|
7160
|
-
}, [state.step, polling.transfer, state.transfer, polling.stopPolling, onError]);
|
|
7241
|
+
}, [state.step, polling.transfer, state.transfer, polling.stopPolling, onError, dispatch, processingStartedAtRef]);
|
|
7161
7242
|
react.useEffect(() => {
|
|
7162
7243
|
if (!state.mobileFlow) {
|
|
7163
7244
|
handlingMobileReturnRef.current = false;
|
|
@@ -7167,7 +7248,7 @@ function SwypePaymentInner({
|
|
|
7167
7248
|
const polledTransfer = polling.transfer;
|
|
7168
7249
|
if (!polledTransfer || polledTransfer.status !== "AUTHORIZED") return;
|
|
7169
7250
|
void handleAuthorizedMobileReturn(polledTransfer, mobileSetupFlowRef.current);
|
|
7170
|
-
}, [state.mobileFlow, polling.transfer, handleAuthorizedMobileReturn]);
|
|
7251
|
+
}, [state.mobileFlow, polling.transfer, handleAuthorizedMobileReturn, handlingMobileReturnRef, mobileSetupFlowRef]);
|
|
7171
7252
|
react.useEffect(() => {
|
|
7172
7253
|
if (!state.mobileFlow || !mobileSetupFlowRef.current) return;
|
|
7173
7254
|
if (state.step !== "open-wallet") return;
|
|
@@ -7238,7 +7319,18 @@ function SwypePaymentInner({
|
|
|
7238
7319
|
window.clearInterval(intervalId);
|
|
7239
7320
|
document.removeEventListener("visibilitychange", handleVisibility);
|
|
7240
7321
|
};
|
|
7241
|
-
}, [
|
|
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
|
+
]);
|
|
7242
7334
|
react.useEffect(() => {
|
|
7243
7335
|
if (!state.mobileFlow) return;
|
|
7244
7336
|
if (handlingMobileReturnRef.current) return;
|
|
@@ -7252,7 +7344,14 @@ function SwypePaymentInner({
|
|
|
7252
7344
|
};
|
|
7253
7345
|
document.addEventListener("visibilitychange", handleVisibility);
|
|
7254
7346
|
return () => document.removeEventListener("visibilitychange", handleVisibility);
|
|
7255
|
-
}, [
|
|
7347
|
+
}, [
|
|
7348
|
+
state.mobileFlow,
|
|
7349
|
+
state.transfer?.id,
|
|
7350
|
+
polling.isPolling,
|
|
7351
|
+
polling.startPolling,
|
|
7352
|
+
handlingMobileReturnRef,
|
|
7353
|
+
pollingTransferIdRef
|
|
7354
|
+
]);
|
|
7256
7355
|
react.useEffect(() => {
|
|
7257
7356
|
if (!pendingSelectSourceAction) {
|
|
7258
7357
|
initializedSelectSourceActionRef.current = null;
|
|
@@ -7261,20 +7360,6 @@ function SwypePaymentInner({
|
|
|
7261
7360
|
return;
|
|
7262
7361
|
}
|
|
7263
7362
|
if (initializedSelectSourceActionRef.current === pendingSelectSourceAction.id) return;
|
|
7264
|
-
const options = pendingSelectSourceAction.metadata?.options ?? [];
|
|
7265
|
-
if (pendingTokenAuthRef.current) {
|
|
7266
|
-
const { tokenAddress, chainId } = pendingTokenAuthRef.current;
|
|
7267
|
-
const chainIdHex = `0x${chainId.toString(16)}`;
|
|
7268
|
-
const match = options.find(
|
|
7269
|
-
(opt) => opt.tokenAddress.toLowerCase() === tokenAddress.toLowerCase() && opt.chainId.toLowerCase() === chainIdHex.toLowerCase()
|
|
7270
|
-
);
|
|
7271
|
-
if (match) {
|
|
7272
|
-
setSelectSourceChainName(match.chainName);
|
|
7273
|
-
setSelectSourceTokenSymbol(match.tokenSymbol);
|
|
7274
|
-
initializedSelectSourceActionRef.current = pendingSelectSourceAction.id;
|
|
7275
|
-
return;
|
|
7276
|
-
}
|
|
7277
|
-
}
|
|
7278
7363
|
const hasRecommended = !!selectSourceRecommended && selectSourceChoices.some(
|
|
7279
7364
|
(chain) => chain.chainName === selectSourceRecommended.chainName && chain.tokens.some((t) => t.tokenSymbol === selectSourceRecommended.tokenSymbol)
|
|
7280
7365
|
);
|
|
@@ -7289,7 +7374,14 @@ function SwypePaymentInner({
|
|
|
7289
7374
|
setSelectSourceTokenSymbol("USDC");
|
|
7290
7375
|
}
|
|
7291
7376
|
initializedSelectSourceActionRef.current = pendingSelectSourceAction.id;
|
|
7292
|
-
}, [
|
|
7377
|
+
}, [
|
|
7378
|
+
pendingSelectSourceAction,
|
|
7379
|
+
selectSourceChoices,
|
|
7380
|
+
selectSourceRecommended,
|
|
7381
|
+
setSelectSourceChainName,
|
|
7382
|
+
setSelectSourceTokenSymbol,
|
|
7383
|
+
initializedSelectSourceActionRef
|
|
7384
|
+
]);
|
|
7293
7385
|
react.useEffect(() => {
|
|
7294
7386
|
if (pendingSelectSourceAction && (state.step === "processing" || state.step === "open-wallet" || state.step === "setup-status")) {
|
|
7295
7387
|
const isDesktop = shouldUseWalletConnector({
|
|
@@ -7297,9 +7389,8 @@ function SwypePaymentInner({
|
|
|
7297
7389
|
userAgent: typeof navigator === "undefined" ? void 0 : navigator.userAgent
|
|
7298
7390
|
});
|
|
7299
7391
|
if (isDesktop && state.step === "setup-status") {
|
|
7300
|
-
|
|
7301
|
-
|
|
7302
|
-
});
|
|
7392
|
+
preSelectSourceStepRef.current = state.step;
|
|
7393
|
+
dispatch({ type: "NAVIGATE", step: "setup" });
|
|
7303
7394
|
return;
|
|
7304
7395
|
}
|
|
7305
7396
|
preSelectSourceStepRef.current = state.step;
|
|
@@ -7308,75 +7399,243 @@ function SwypePaymentInner({
|
|
|
7308
7399
|
dispatch({ type: "NAVIGATE", step: preSelectSourceStepRef.current ?? "processing" });
|
|
7309
7400
|
preSelectSourceStepRef.current = null;
|
|
7310
7401
|
}
|
|
7311
|
-
}, [pendingSelectSourceAction, state.step,
|
|
7402
|
+
}, [pendingSelectSourceAction, state.step, useWalletConnectorProp, dispatch, preSelectSourceStepRef, authExecutor]);
|
|
7312
7403
|
const pendingOneTapSetupAction = authExecutor.pendingOneTapSetup;
|
|
7313
7404
|
const preOneTapSetupStepRef = react.useRef(null);
|
|
7314
7405
|
react.useEffect(() => {
|
|
7315
7406
|
if (pendingOneTapSetupAction && state.step === "setup-status") {
|
|
7316
|
-
|
|
7317
|
-
|
|
7318
|
-
|
|
7319
|
-
}
|
|
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
|
+
}
|
|
7320
7416
|
} else if (!pendingOneTapSetupAction && state.step === "setup" && preOneTapSetupStepRef.current) {
|
|
7321
7417
|
dispatch({ type: "NAVIGATE", step: preOneTapSetupStepRef.current });
|
|
7322
7418
|
preOneTapSetupStepRef.current = null;
|
|
7323
7419
|
}
|
|
7324
|
-
}, [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
|
+
});
|
|
7325
7596
|
const handlers = react.useMemo(() => ({
|
|
7326
|
-
onSendLoginCode: handleSendLoginCode,
|
|
7327
|
-
onVerifyLoginCode: handleVerifyLoginCode,
|
|
7328
|
-
onResendLoginCode: handleResendLoginCode,
|
|
7597
|
+
onSendLoginCode: auth.handleSendLoginCode,
|
|
7598
|
+
onVerifyLoginCode: auth.handleVerifyLoginCode,
|
|
7599
|
+
onResendLoginCode: auth.handleResendLoginCode,
|
|
7329
7600
|
onBackFromOtp: () => {
|
|
7330
|
-
setOtpCode("");
|
|
7601
|
+
auth.setOtpCode("");
|
|
7331
7602
|
dispatch({ type: "BACK_TO_LOGIN" });
|
|
7332
7603
|
},
|
|
7333
|
-
onRegisterPasskey: handleRegisterPasskey,
|
|
7334
|
-
onCreatePasskeyViaPopup: handleCreatePasskeyViaPopup,
|
|
7335
|
-
onVerifyPasskeyViaPopup: handleVerifyPasskeyViaPopup,
|
|
7336
|
-
onSelectProvider: handleSelectProvider,
|
|
7337
|
-
onContinueConnection: handleContinueConnection,
|
|
7338
|
-
onSelectAccount: handleSelectAccount,
|
|
7339
|
-
onPay: handlePay,
|
|
7340
|
-
onIncreaseLimit: handleIncreaseLimit,
|
|
7341
|
-
onConfirmSign: handleConfirmSign,
|
|
7342
|
-
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,
|
|
7343
7614
|
onLogout: handleLogout,
|
|
7344
7615
|
onNewPayment: handleNewPayment,
|
|
7345
7616
|
onNavigate: (step) => dispatch({ type: "NAVIGATE", step }),
|
|
7346
|
-
onSetAuthInput: setAuthInput,
|
|
7617
|
+
onSetAuthInput: auth.setAuthInput,
|
|
7347
7618
|
onSetOtpCode: (code) => {
|
|
7348
|
-
setOtpCode(code);
|
|
7619
|
+
auth.setOtpCode(code);
|
|
7349
7620
|
dispatch({ type: "SET_ERROR", error: null });
|
|
7350
7621
|
},
|
|
7351
|
-
onSelectSourceChainChange: handleSelectSourceChainChange,
|
|
7352
|
-
onSetSelectSourceTokenSymbol: setSelectSourceTokenSymbol,
|
|
7353
|
-
onConfirmSelectSource: handleConfirmSelectSource,
|
|
7354
|
-
onSetupOneTap: handleSetupOneTap,
|
|
7355
|
-
onSelectToken: handleNavigateToTokenPicker,
|
|
7356
|
-
onSelectAuthorizedToken: handleSelectAuthorizedToken,
|
|
7357
|
-
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
|
|
7358
7629
|
}), [
|
|
7359
|
-
|
|
7360
|
-
|
|
7361
|
-
|
|
7362
|
-
|
|
7363
|
-
|
|
7364
|
-
|
|
7365
|
-
|
|
7366
|
-
handleContinueConnection,
|
|
7367
|
-
handleSelectAccount,
|
|
7368
|
-
handlePay,
|
|
7369
|
-
handleIncreaseLimit,
|
|
7370
|
-
handleConfirmSign,
|
|
7371
|
-
handleRetryMobileStatus,
|
|
7630
|
+
auth,
|
|
7631
|
+
passkey,
|
|
7632
|
+
provider,
|
|
7633
|
+
transfer,
|
|
7634
|
+
mobileFlow,
|
|
7635
|
+
sourceSelection,
|
|
7636
|
+
oneTapSetup,
|
|
7372
7637
|
handleLogout,
|
|
7373
|
-
handleNewPayment
|
|
7374
|
-
handleSelectSourceChainChange,
|
|
7375
|
-
handleConfirmSelectSource,
|
|
7376
|
-
handleSetupOneTap,
|
|
7377
|
-
handleNavigateToTokenPicker,
|
|
7378
|
-
handleSelectAuthorizedToken,
|
|
7379
|
-
handleAuthorizeToken
|
|
7638
|
+
handleNewPayment
|
|
7380
7639
|
]);
|
|
7381
7640
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
7382
7641
|
StepRenderer,
|
|
@@ -7384,29 +7643,29 @@ function SwypePaymentInner({
|
|
|
7384
7643
|
state,
|
|
7385
7644
|
ready,
|
|
7386
7645
|
authenticated,
|
|
7387
|
-
activeOtpStatus,
|
|
7646
|
+
activeOtpStatus: auth.activeOtpStatus,
|
|
7388
7647
|
pollingTransfer: polling.transfer,
|
|
7389
7648
|
pollingError: polling.error,
|
|
7390
7649
|
authExecutorError: authExecutor.error,
|
|
7391
7650
|
transferSigningSigning: transferSigning.signing,
|
|
7392
7651
|
transferSigningError: transferSigning.error,
|
|
7393
|
-
pendingConnections,
|
|
7394
|
-
depositEligibleAccounts,
|
|
7395
|
-
sourceName,
|
|
7396
|
-
sourceAddress,
|
|
7397
|
-
sourceVerified,
|
|
7398
|
-
maxSourceBalance,
|
|
7399
|
-
tokenCount,
|
|
7400
|
-
selectedAccount,
|
|
7401
|
-
selectedSource,
|
|
7402
|
-
selectSourceChoices,
|
|
7403
|
-
selectSourceRecommended,
|
|
7404
|
-
|
|
7405
|
-
|
|
7406
|
-
|
|
7407
|
-
|
|
7408
|
-
|
|
7409
|
-
|
|
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,
|
|
7410
7669
|
merchantName,
|
|
7411
7670
|
onBack,
|
|
7412
7671
|
onDismiss,
|