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