@swype-org/react-sdk 0.1.229 → 0.1.232
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 +1437 -1184
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +62 -42
- package/dist/index.d.ts +62 -42
- package/dist/index.js +1437 -1184
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -158,339 +158,358 @@ function useBlinkDepositAmount() {
|
|
|
158
158
|
};
|
|
159
159
|
}
|
|
160
160
|
|
|
161
|
-
//
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
if (typeof action_explicit === "function")
|
|
168
|
-
return action_explicit;
|
|
169
|
-
return (params) => actionFn(client, params);
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
// node_modules/@wagmi/core/dist/esm/version.js
|
|
173
|
-
var version = "2.22.1";
|
|
174
|
-
|
|
175
|
-
// node_modules/@wagmi/core/dist/esm/utils/getVersion.js
|
|
176
|
-
var getVersion = () => `@wagmi/core@${version}`;
|
|
177
|
-
|
|
178
|
-
// node_modules/@wagmi/core/dist/esm/errors/base.js
|
|
179
|
-
var __classPrivateFieldGet = function(receiver, state, kind, f) {
|
|
180
|
-
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
181
|
-
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
161
|
+
// src/passkey-delegation.ts
|
|
162
|
+
var PasskeyIframeBlockedError = class extends Error {
|
|
163
|
+
constructor(message = "Passkey creation is not supported in this browser context.") {
|
|
164
|
+
super(message);
|
|
165
|
+
this.name = "PasskeyIframeBlockedError";
|
|
166
|
+
}
|
|
182
167
|
};
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
168
|
+
function isInCrossOriginIframe() {
|
|
169
|
+
if (typeof window === "undefined") return false;
|
|
170
|
+
if (window.parent === window) return false;
|
|
171
|
+
try {
|
|
172
|
+
void window.parent.location.origin;
|
|
173
|
+
return false;
|
|
174
|
+
} catch {
|
|
175
|
+
return true;
|
|
188
176
|
}
|
|
189
|
-
|
|
190
|
-
|
|
177
|
+
}
|
|
178
|
+
function isSafari() {
|
|
179
|
+
if (typeof navigator === "undefined") return false;
|
|
180
|
+
const ua = navigator.userAgent;
|
|
181
|
+
return /Safari/i.test(ua) && !/Chrome|CriOS|Chromium|Edg|OPR|Firefox/i.test(ua);
|
|
182
|
+
}
|
|
183
|
+
var POPUP_RESULT_TIMEOUT_MS = 12e4;
|
|
184
|
+
var POPUP_CLOSED_POLL_MS = 500;
|
|
185
|
+
var POPUP_CLOSED_GRACE_MS = 1e3;
|
|
186
|
+
function createPasskeyViaPopup(options) {
|
|
187
|
+
return new Promise((resolve, reject) => {
|
|
188
|
+
const verificationToken = crypto.randomUUID();
|
|
189
|
+
const payload = { ...options, verificationToken };
|
|
190
|
+
const encoded = btoa(JSON.stringify(payload));
|
|
191
|
+
const popupUrl = `${window.location.origin}/passkey-register#${encoded}`;
|
|
192
|
+
const popup = window.open(popupUrl, "blink-passkey");
|
|
193
|
+
if (!popup) {
|
|
194
|
+
reject(new Error("Pop-up blocked. Please allow pop-ups for this site and try again."));
|
|
195
|
+
return;
|
|
196
|
+
}
|
|
197
|
+
let settled = false;
|
|
198
|
+
const timer = setTimeout(() => {
|
|
199
|
+
cleanup();
|
|
200
|
+
reject(new Error("Passkey creation timed out. Please try again."));
|
|
201
|
+
}, POPUP_RESULT_TIMEOUT_MS);
|
|
202
|
+
const closedPoll = setInterval(() => {
|
|
203
|
+
if (popup.closed) {
|
|
204
|
+
clearInterval(closedPoll);
|
|
205
|
+
setTimeout(() => {
|
|
206
|
+
if (!settled) {
|
|
207
|
+
settled = true;
|
|
208
|
+
cleanup();
|
|
209
|
+
checkServerForPasskeyByToken(
|
|
210
|
+
options.authToken,
|
|
211
|
+
options.apiBaseUrl,
|
|
212
|
+
verificationToken
|
|
213
|
+
).then((result) => {
|
|
214
|
+
if (result) {
|
|
215
|
+
resolve(result);
|
|
216
|
+
} else {
|
|
217
|
+
reject(new Error("Passkey window was closed before completing."));
|
|
218
|
+
}
|
|
219
|
+
}).catch(() => {
|
|
220
|
+
reject(new Error("Passkey window was closed before completing."));
|
|
221
|
+
});
|
|
222
|
+
}
|
|
223
|
+
}, POPUP_CLOSED_GRACE_MS);
|
|
224
|
+
}
|
|
225
|
+
}, POPUP_CLOSED_POLL_MS);
|
|
226
|
+
function cleanup() {
|
|
227
|
+
clearTimeout(timer);
|
|
228
|
+
clearInterval(closedPoll);
|
|
229
|
+
}
|
|
230
|
+
});
|
|
231
|
+
}
|
|
232
|
+
var VERIFY_POPUP_TIMEOUT_MS = 6e4;
|
|
233
|
+
function findDevicePasskeyViaPopup(options) {
|
|
234
|
+
return new Promise((resolve, reject) => {
|
|
235
|
+
const verificationToken = crypto.randomUUID();
|
|
236
|
+
const payload = {
|
|
237
|
+
...options,
|
|
238
|
+
verificationToken
|
|
239
|
+
};
|
|
240
|
+
const encoded = btoa(JSON.stringify(payload));
|
|
241
|
+
const popupUrl = `${window.location.origin}/passkey-verify#${encoded}`;
|
|
242
|
+
const popup = window.open(popupUrl, "blink-passkey-verify");
|
|
243
|
+
if (!popup) {
|
|
244
|
+
reject(new Error("Pop-up blocked. Please allow pop-ups for this site and try again."));
|
|
245
|
+
return;
|
|
246
|
+
}
|
|
247
|
+
let settled = false;
|
|
248
|
+
const timer = setTimeout(() => {
|
|
249
|
+
cleanup();
|
|
250
|
+
resolve(null);
|
|
251
|
+
}, VERIFY_POPUP_TIMEOUT_MS);
|
|
252
|
+
const closedPoll = setInterval(() => {
|
|
253
|
+
if (popup.closed && !settled) {
|
|
254
|
+
clearInterval(closedPoll);
|
|
255
|
+
setTimeout(() => {
|
|
256
|
+
if (!settled) {
|
|
257
|
+
settled = true;
|
|
258
|
+
cleanup();
|
|
259
|
+
checkServerForPasskeyByToken(
|
|
260
|
+
options.authToken,
|
|
261
|
+
options.apiBaseUrl,
|
|
262
|
+
verificationToken
|
|
263
|
+
).then((result) => {
|
|
264
|
+
resolve(result?.credentialId ?? null);
|
|
265
|
+
}).catch(() => {
|
|
266
|
+
resolve(null);
|
|
267
|
+
});
|
|
268
|
+
}
|
|
269
|
+
}, POPUP_CLOSED_GRACE_MS);
|
|
270
|
+
}
|
|
271
|
+
}, POPUP_CLOSED_POLL_MS);
|
|
272
|
+
function cleanup() {
|
|
273
|
+
clearTimeout(timer);
|
|
274
|
+
clearInterval(closedPoll);
|
|
275
|
+
}
|
|
276
|
+
});
|
|
277
|
+
}
|
|
278
|
+
async function checkServerForPasskeyByToken(authToken, apiBaseUrl, verificationToken) {
|
|
279
|
+
if (!authToken || !apiBaseUrl) return null;
|
|
280
|
+
const res = await fetch(`${apiBaseUrl}/v1/users/config`, {
|
|
281
|
+
headers: { Authorization: `Bearer ${authToken}` }
|
|
282
|
+
});
|
|
283
|
+
if (!res.ok) return null;
|
|
284
|
+
const body = await res.json();
|
|
285
|
+
const passkeys = body.config.passkeys ?? [];
|
|
286
|
+
const matched = passkeys.find((p) => p.lastVerificationToken === verificationToken);
|
|
287
|
+
return matched ? { credentialId: matched.credentialId, publicKey: matched.publicKey } : null;
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
// src/passkeyRpId.ts
|
|
291
|
+
function normalizeConfiguredDomain(value) {
|
|
292
|
+
return value.replace(/^https?:\/\//, "").replace(/\/.*$/, "").replace(/^\./, "").trim();
|
|
293
|
+
}
|
|
294
|
+
function resolveRootDomainFromHostname(hostname) {
|
|
295
|
+
const trimmedHostname = hostname.trim().toLowerCase();
|
|
296
|
+
if (!trimmedHostname) {
|
|
297
|
+
return "localhost";
|
|
191
298
|
}
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
_BaseError_instances.add(this);
|
|
195
|
-
Object.defineProperty(this, "details", {
|
|
196
|
-
enumerable: true,
|
|
197
|
-
configurable: true,
|
|
198
|
-
writable: true,
|
|
199
|
-
value: void 0
|
|
200
|
-
});
|
|
201
|
-
Object.defineProperty(this, "docsPath", {
|
|
202
|
-
enumerable: true,
|
|
203
|
-
configurable: true,
|
|
204
|
-
writable: true,
|
|
205
|
-
value: void 0
|
|
206
|
-
});
|
|
207
|
-
Object.defineProperty(this, "metaMessages", {
|
|
208
|
-
enumerable: true,
|
|
209
|
-
configurable: true,
|
|
210
|
-
writable: true,
|
|
211
|
-
value: void 0
|
|
212
|
-
});
|
|
213
|
-
Object.defineProperty(this, "shortMessage", {
|
|
214
|
-
enumerable: true,
|
|
215
|
-
configurable: true,
|
|
216
|
-
writable: true,
|
|
217
|
-
value: void 0
|
|
218
|
-
});
|
|
219
|
-
Object.defineProperty(this, "name", {
|
|
220
|
-
enumerable: true,
|
|
221
|
-
configurable: true,
|
|
222
|
-
writable: true,
|
|
223
|
-
value: "WagmiCoreError"
|
|
224
|
-
});
|
|
225
|
-
const details = options.cause instanceof _BaseError ? options.cause.details : options.cause?.message ? options.cause.message : options.details;
|
|
226
|
-
const docsPath = options.cause instanceof _BaseError ? options.cause.docsPath || options.docsPath : options.docsPath;
|
|
227
|
-
this.message = [
|
|
228
|
-
shortMessage || "An error occurred.",
|
|
229
|
-
"",
|
|
230
|
-
...options.metaMessages ? [...options.metaMessages, ""] : [],
|
|
231
|
-
...docsPath ? [
|
|
232
|
-
`Docs: ${this.docsBaseUrl}${docsPath}.html${options.docsSlug ? `#${options.docsSlug}` : ""}`
|
|
233
|
-
] : [],
|
|
234
|
-
...details ? [`Details: ${details}`] : [],
|
|
235
|
-
`Version: ${this.version}`
|
|
236
|
-
].join("\n");
|
|
237
|
-
if (options.cause)
|
|
238
|
-
this.cause = options.cause;
|
|
239
|
-
this.details = details;
|
|
240
|
-
this.docsPath = docsPath;
|
|
241
|
-
this.metaMessages = options.metaMessages;
|
|
242
|
-
this.shortMessage = shortMessage;
|
|
299
|
+
if (trimmedHostname === "localhost" || /^\d{1,3}(?:\.\d{1,3}){3}$/.test(trimmedHostname)) {
|
|
300
|
+
return trimmedHostname;
|
|
243
301
|
}
|
|
244
|
-
|
|
245
|
-
|
|
302
|
+
const parts = trimmedHostname.split(".").filter(Boolean);
|
|
303
|
+
if (parts.length < 2) {
|
|
304
|
+
return trimmedHostname;
|
|
246
305
|
}
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
if (fn?.(err))
|
|
250
|
-
return err;
|
|
251
|
-
if (err.cause)
|
|
252
|
-
return __classPrivateFieldGet(this, _BaseError_instances, "m", _BaseError_walk2).call(this, err.cause, fn);
|
|
253
|
-
return err;
|
|
254
|
-
};
|
|
306
|
+
return parts.slice(-2).join(".");
|
|
307
|
+
}
|
|
255
308
|
|
|
256
|
-
//
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
});
|
|
277
|
-
}
|
|
278
|
-
};
|
|
279
|
-
var ConnectorChainMismatchError = class extends BaseError {
|
|
280
|
-
constructor({ connectionChainId, connectorChainId }) {
|
|
281
|
-
super(`The current chain of the connector (id: ${connectorChainId}) does not match the connection's chain (id: ${connectionChainId}).`, {
|
|
282
|
-
metaMessages: [
|
|
283
|
-
`Current Chain ID: ${connectorChainId}`,
|
|
284
|
-
`Expected Chain ID: ${connectionChainId}`
|
|
285
|
-
]
|
|
286
|
-
});
|
|
287
|
-
Object.defineProperty(this, "name", {
|
|
288
|
-
enumerable: true,
|
|
289
|
-
configurable: true,
|
|
290
|
-
writable: true,
|
|
291
|
-
value: "ConnectorChainMismatchError"
|
|
292
|
-
});
|
|
293
|
-
}
|
|
294
|
-
};
|
|
295
|
-
var ConnectorUnavailableReconnectingError = class extends BaseError {
|
|
296
|
-
constructor({ connector }) {
|
|
297
|
-
super(`Connector "${connector.name}" unavailable while reconnecting.`, {
|
|
298
|
-
details: [
|
|
299
|
-
"During the reconnection step, the only connector methods guaranteed to be available are: `id`, `name`, `type`, `uid`.",
|
|
300
|
-
"All other methods are not guaranteed to be available until reconnection completes and connectors are fully restored.",
|
|
301
|
-
"This error commonly occurs for connectors that asynchronously inject after reconnection has already started."
|
|
302
|
-
].join(" ")
|
|
303
|
-
});
|
|
304
|
-
Object.defineProperty(this, "name", {
|
|
305
|
-
enumerable: true,
|
|
306
|
-
configurable: true,
|
|
307
|
-
writable: true,
|
|
308
|
-
value: "ConnectorUnavailableReconnectingError"
|
|
309
|
-
});
|
|
310
|
-
}
|
|
311
|
-
};
|
|
312
|
-
async function getConnectorClient(config, parameters = {}) {
|
|
313
|
-
const { assertChainId = true } = parameters;
|
|
314
|
-
let connection;
|
|
315
|
-
if (parameters.connector) {
|
|
316
|
-
const { connector: connector2 } = parameters;
|
|
317
|
-
if (config.state.status === "reconnecting" && !connector2.getAccounts && !connector2.getChainId)
|
|
318
|
-
throw new ConnectorUnavailableReconnectingError({ connector: connector2 });
|
|
319
|
-
const [accounts, chainId2] = await Promise.all([
|
|
320
|
-
connector2.getAccounts().catch((e) => {
|
|
321
|
-
if (parameters.account === null)
|
|
322
|
-
return [];
|
|
323
|
-
throw e;
|
|
324
|
-
}),
|
|
325
|
-
connector2.getChainId()
|
|
326
|
-
]);
|
|
327
|
-
connection = {
|
|
328
|
-
accounts,
|
|
329
|
-
chainId: chainId2,
|
|
330
|
-
connector: connector2
|
|
331
|
-
};
|
|
332
|
-
} else
|
|
333
|
-
connection = config.state.connections.get(config.state.current);
|
|
334
|
-
if (!connection)
|
|
335
|
-
throw new ConnectorNotConnectedError();
|
|
336
|
-
const chainId = parameters.chainId ?? connection.chainId;
|
|
337
|
-
const connectorChainId = await connection.connector.getChainId();
|
|
338
|
-
if (assertChainId && connectorChainId !== chainId)
|
|
339
|
-
throw new ConnectorChainMismatchError({
|
|
340
|
-
connectionChainId: chainId,
|
|
341
|
-
connectorChainId
|
|
342
|
-
});
|
|
343
|
-
const connector = connection.connector;
|
|
344
|
-
if (connector.getClient)
|
|
345
|
-
return connector.getClient({ chainId });
|
|
346
|
-
const account = utils.parseAccount(parameters.account ?? connection.accounts[0]);
|
|
347
|
-
if (account)
|
|
348
|
-
account.address = utils.getAddress(account.address);
|
|
349
|
-
if (parameters.account && !connection.accounts.some((x) => x.toLowerCase() === account.address.toLowerCase()))
|
|
350
|
-
throw new ConnectorAccountNotFoundError({
|
|
351
|
-
address: account.address,
|
|
352
|
-
connector
|
|
353
|
-
});
|
|
354
|
-
const chain = config.chains.find((chain2) => chain2.id === chainId);
|
|
355
|
-
const provider = await connection.connector.getProvider({ chainId });
|
|
356
|
-
return viem.createClient({
|
|
357
|
-
account,
|
|
358
|
-
chain,
|
|
359
|
-
name: "Connector Client",
|
|
360
|
-
transport: (opts) => viem.custom(provider)({ ...opts, retryCount: 0 })
|
|
309
|
+
// src/hooks/passkeyPublic.ts
|
|
310
|
+
function waitForDocumentFocus(timeoutMs = 5e3, intervalMs = 100) {
|
|
311
|
+
return new Promise((resolve, reject) => {
|
|
312
|
+
if (typeof document === "undefined") {
|
|
313
|
+
resolve();
|
|
314
|
+
return;
|
|
315
|
+
}
|
|
316
|
+
if (document.hasFocus()) {
|
|
317
|
+
resolve();
|
|
318
|
+
return;
|
|
319
|
+
}
|
|
320
|
+
const deadline = Date.now() + timeoutMs;
|
|
321
|
+
const timer = setInterval(() => {
|
|
322
|
+
if (document.hasFocus()) {
|
|
323
|
+
clearInterval(timer);
|
|
324
|
+
resolve();
|
|
325
|
+
} else if (Date.now() >= deadline) {
|
|
326
|
+
clearInterval(timer);
|
|
327
|
+
resolve();
|
|
328
|
+
}
|
|
329
|
+
}, intervalMs);
|
|
361
330
|
});
|
|
362
331
|
}
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
const
|
|
368
|
-
const
|
|
369
|
-
const
|
|
370
|
-
const
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
case "connected":
|
|
374
|
-
return {
|
|
375
|
-
address,
|
|
376
|
-
addresses,
|
|
377
|
-
chain,
|
|
378
|
-
chainId: connection?.chainId,
|
|
379
|
-
connector: connection?.connector,
|
|
380
|
-
isConnected: true,
|
|
381
|
-
isConnecting: false,
|
|
382
|
-
isDisconnected: false,
|
|
383
|
-
isReconnecting: false,
|
|
384
|
-
status
|
|
385
|
-
};
|
|
386
|
-
case "reconnecting":
|
|
387
|
-
return {
|
|
388
|
-
address,
|
|
389
|
-
addresses,
|
|
390
|
-
chain,
|
|
391
|
-
chainId: connection?.chainId,
|
|
392
|
-
connector: connection?.connector,
|
|
393
|
-
isConnected: !!address,
|
|
394
|
-
isConnecting: false,
|
|
395
|
-
isDisconnected: false,
|
|
396
|
-
isReconnecting: true,
|
|
397
|
-
status
|
|
398
|
-
};
|
|
399
|
-
case "connecting":
|
|
400
|
-
return {
|
|
401
|
-
address,
|
|
402
|
-
addresses,
|
|
403
|
-
chain,
|
|
404
|
-
chainId: connection?.chainId,
|
|
405
|
-
connector: connection?.connector,
|
|
406
|
-
isConnected: false,
|
|
407
|
-
isConnecting: true,
|
|
408
|
-
isDisconnected: false,
|
|
409
|
-
isReconnecting: false,
|
|
410
|
-
status
|
|
411
|
-
};
|
|
412
|
-
case "disconnected":
|
|
413
|
-
return {
|
|
414
|
-
address: void 0,
|
|
415
|
-
addresses: void 0,
|
|
416
|
-
chain: void 0,
|
|
417
|
-
chainId: void 0,
|
|
418
|
-
connector: void 0,
|
|
419
|
-
isConnected: false,
|
|
420
|
-
isConnecting: false,
|
|
421
|
-
isDisconnected: true,
|
|
422
|
-
isReconnecting: false,
|
|
423
|
-
status
|
|
424
|
-
};
|
|
332
|
+
function toBase64(buffer) {
|
|
333
|
+
return btoa(String.fromCharCode(...new Uint8Array(buffer)));
|
|
334
|
+
}
|
|
335
|
+
function base64ToBytes(value) {
|
|
336
|
+
const normalized = value.replace(/-/g, "+").replace(/_/g, "/");
|
|
337
|
+
const padded = normalized + "=".repeat((4 - normalized.length % 4) % 4);
|
|
338
|
+
const raw = atob(padded);
|
|
339
|
+
const bytes = new Uint8Array(raw.length);
|
|
340
|
+
for (let i = 0; i < raw.length; i++) {
|
|
341
|
+
bytes[i] = raw.charCodeAt(i);
|
|
425
342
|
}
|
|
343
|
+
return bytes;
|
|
426
344
|
}
|
|
427
|
-
|
|
428
|
-
const
|
|
429
|
-
|
|
345
|
+
function readEnvValue(name) {
|
|
346
|
+
const meta = ({ url: (typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index.cjs', document.baseURI).href)) });
|
|
347
|
+
const metaValue = meta.env?.[name];
|
|
348
|
+
if (typeof metaValue === "string" && metaValue.trim().length > 0) {
|
|
349
|
+
return metaValue.trim();
|
|
350
|
+
}
|
|
351
|
+
const processValue = globalThis.process?.env?.[name];
|
|
352
|
+
if (typeof processValue === "string" && processValue.trim().length > 0) {
|
|
353
|
+
return processValue.trim();
|
|
354
|
+
}
|
|
355
|
+
return void 0;
|
|
430
356
|
}
|
|
431
|
-
|
|
432
|
-
const
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
const receipt = await action({ ...rest, timeout });
|
|
436
|
-
if (receipt.status === "reverted") {
|
|
437
|
-
const action_getTransaction = getAction(client, actions.getTransaction, "getTransaction");
|
|
438
|
-
const { from: account, ...txn } = await action_getTransaction({
|
|
439
|
-
hash: receipt.transactionHash
|
|
440
|
-
});
|
|
441
|
-
const action_call = getAction(client, actions.call, "call");
|
|
442
|
-
const code = await action_call({
|
|
443
|
-
...txn,
|
|
444
|
-
account,
|
|
445
|
-
data: txn.input,
|
|
446
|
-
gasPrice: txn.type !== "eip1559" ? txn.gasPrice : void 0,
|
|
447
|
-
maxFeePerGas: txn.type === "eip1559" ? txn.maxFeePerGas : void 0,
|
|
448
|
-
maxPriorityFeePerGas: txn.type === "eip1559" ? txn.maxPriorityFeePerGas : void 0
|
|
449
|
-
});
|
|
450
|
-
const reason = code?.data ? viem.hexToString(`0x${code.data.substring(138)}`) : "unknown reason";
|
|
451
|
-
throw new Error(reason);
|
|
357
|
+
function resolvePasskeyRpId() {
|
|
358
|
+
const configuredDomain = readEnvValue("VITE_DOMAIN") ?? readEnvValue("BLINK_DOMAIN");
|
|
359
|
+
if (configuredDomain) {
|
|
360
|
+
return normalizeConfiguredDomain(configuredDomain);
|
|
452
361
|
}
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
362
|
+
if (typeof window !== "undefined") {
|
|
363
|
+
return resolveRootDomainFromHostname(window.location.hostname);
|
|
364
|
+
}
|
|
365
|
+
return "localhost";
|
|
457
366
|
}
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
367
|
+
async function createPasskeyCredential(params) {
|
|
368
|
+
const challenge = new Uint8Array(32);
|
|
369
|
+
crypto.getRandomValues(challenge);
|
|
370
|
+
const rpId = resolvePasskeyRpId();
|
|
371
|
+
const publicKeyOptions = {
|
|
372
|
+
challenge,
|
|
373
|
+
rp: { name: "Blink", id: rpId },
|
|
374
|
+
user: {
|
|
375
|
+
id: new TextEncoder().encode(params.userId),
|
|
376
|
+
name: params.displayName,
|
|
377
|
+
displayName: params.displayName
|
|
378
|
+
},
|
|
379
|
+
pubKeyCredParams: [
|
|
380
|
+
{ alg: -7, type: "public-key" },
|
|
381
|
+
{ alg: -257, type: "public-key" }
|
|
382
|
+
],
|
|
383
|
+
authenticatorSelection: {
|
|
384
|
+
authenticatorAttachment: "platform",
|
|
385
|
+
residentKey: "preferred",
|
|
386
|
+
userVerification: "required"
|
|
387
|
+
},
|
|
388
|
+
timeout: 6e4
|
|
389
|
+
};
|
|
390
|
+
if (isInCrossOriginIframe()) {
|
|
391
|
+
try {
|
|
392
|
+
await waitForDocumentFocus();
|
|
393
|
+
const credential2 = await navigator.credentials.create({
|
|
394
|
+
publicKey: publicKeyOptions
|
|
395
|
+
});
|
|
396
|
+
if (!credential2) {
|
|
397
|
+
throw new Error("Passkey creation was cancelled.");
|
|
398
|
+
}
|
|
399
|
+
return extractPasskeyResult(credential2);
|
|
400
|
+
} catch (err) {
|
|
401
|
+
if (err instanceof PasskeyIframeBlockedError) throw err;
|
|
402
|
+
if (err instanceof Error && err.message === "Passkey creation was cancelled.") throw err;
|
|
403
|
+
throw new PasskeyIframeBlockedError();
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
await waitForDocumentFocus();
|
|
407
|
+
const credential = await navigator.credentials.create({
|
|
408
|
+
publicKey: publicKeyOptions
|
|
409
|
+
});
|
|
410
|
+
if (!credential) {
|
|
411
|
+
throw new Error("Passkey creation was cancelled.");
|
|
412
|
+
}
|
|
413
|
+
return extractPasskeyResult(credential);
|
|
414
|
+
}
|
|
415
|
+
function extractPasskeyResult(credential) {
|
|
416
|
+
const response = credential.response;
|
|
417
|
+
const publicKeyBytes = response.getPublicKey?.();
|
|
418
|
+
return {
|
|
419
|
+
credentialId: toBase64(credential.rawId),
|
|
420
|
+
publicKey: publicKeyBytes ? toBase64(publicKeyBytes) : ""
|
|
421
|
+
};
|
|
422
|
+
}
|
|
423
|
+
function buildPasskeyPopupOptions(params) {
|
|
424
|
+
const challenge = new Uint8Array(32);
|
|
425
|
+
crypto.getRandomValues(challenge);
|
|
426
|
+
const rpId = resolvePasskeyRpId();
|
|
427
|
+
return {
|
|
428
|
+
challenge: toBase64(challenge),
|
|
429
|
+
rpId,
|
|
430
|
+
rpName: "Blink",
|
|
431
|
+
userId: toBase64(new TextEncoder().encode(params.userId)),
|
|
432
|
+
userName: params.displayName,
|
|
433
|
+
userDisplayName: params.displayName,
|
|
434
|
+
pubKeyCredParams: [
|
|
435
|
+
{ alg: -7, type: "public-key" },
|
|
436
|
+
{ alg: -257, type: "public-key" }
|
|
437
|
+
],
|
|
438
|
+
authenticatorSelection: {
|
|
439
|
+
authenticatorAttachment: "platform",
|
|
440
|
+
residentKey: "preferred",
|
|
441
|
+
userVerification: "required"
|
|
442
|
+
},
|
|
443
|
+
timeout: 6e4,
|
|
444
|
+
authToken: params.authToken,
|
|
445
|
+
apiBaseUrl: params.apiBaseUrl
|
|
446
|
+
};
|
|
447
|
+
}
|
|
448
|
+
async function deviceHasPasskey(credentialId) {
|
|
449
|
+
const found = await findDevicePasskey([credentialId]);
|
|
450
|
+
return found != null;
|
|
451
|
+
}
|
|
452
|
+
async function findDevicePasskey(credentialIds) {
|
|
453
|
+
if (credentialIds.length === 0) return null;
|
|
454
|
+
try {
|
|
455
|
+
const challenge = new Uint8Array(32);
|
|
456
|
+
crypto.getRandomValues(challenge);
|
|
457
|
+
await waitForDocumentFocus();
|
|
458
|
+
const assertion = await navigator.credentials.get({
|
|
459
|
+
publicKey: {
|
|
460
|
+
challenge,
|
|
461
|
+
rpId: resolvePasskeyRpId(),
|
|
462
|
+
allowCredentials: credentialIds.map((id) => ({
|
|
463
|
+
type: "public-key",
|
|
464
|
+
id: base64ToBytes(id)
|
|
465
|
+
})),
|
|
466
|
+
userVerification: "discouraged",
|
|
467
|
+
timeout: 3e4
|
|
468
|
+
}
|
|
469
|
+
});
|
|
470
|
+
if (!assertion) return null;
|
|
471
|
+
return toBase64(assertion.rawId);
|
|
472
|
+
} catch {
|
|
473
|
+
return null;
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
// src/api.ts
|
|
478
|
+
var api_exports = {};
|
|
479
|
+
__export(api_exports, {
|
|
480
|
+
createAccount: () => createAccount,
|
|
481
|
+
createAccountAuthorizationSession: () => createAccountAuthorizationSession,
|
|
482
|
+
createGuestAccount: () => createGuestAccount,
|
|
483
|
+
createGuestTransfer: () => createGuestTransfer,
|
|
484
|
+
createTransfer: () => createTransfer,
|
|
485
|
+
fetchAccount: () => fetchAccount,
|
|
486
|
+
fetchAccounts: () => fetchAccounts,
|
|
487
|
+
fetchAuthorizationSession: () => fetchAuthorizationSession,
|
|
488
|
+
fetchAuthorizationSessionByToken: () => fetchAuthorizationSessionByToken,
|
|
489
|
+
fetchChains: () => fetchChains,
|
|
490
|
+
fetchGuestAccount: () => fetchGuestAccount,
|
|
491
|
+
fetchGuestTransferBalances: () => fetchGuestTransferBalances,
|
|
492
|
+
fetchMerchantPublicKey: () => fetchMerchantPublicKey,
|
|
493
|
+
fetchProviders: () => fetchProviders,
|
|
494
|
+
fetchTransfer: () => fetchTransfer,
|
|
495
|
+
fetchUserConfig: () => fetchUserConfig,
|
|
496
|
+
getGuestTransfer: () => getGuestTransfer,
|
|
497
|
+
getTransferByGuestToken: () => getTransferByGuestToken,
|
|
498
|
+
registerPasskey: () => registerPasskey,
|
|
499
|
+
reportActionCompletion: () => reportActionCompletion,
|
|
500
|
+
reportPasskeyActivity: () => reportPasskeyActivity,
|
|
501
|
+
setAccountOwner: () => setAccountOwner,
|
|
502
|
+
setTransferSender: () => setTransferSender,
|
|
503
|
+
signGuestTransfer: () => signGuestTransfer,
|
|
504
|
+
signTransfer: () => signTransfer,
|
|
505
|
+
updateUserConfig: () => updateUserConfig,
|
|
506
|
+
updateUserConfigBySession: () => updateUserConfigBySession
|
|
507
|
+
});
|
|
508
|
+
async function throwApiError(res) {
|
|
509
|
+
const body = await res.json().catch(() => null);
|
|
510
|
+
const detail = body?.error ?? body;
|
|
511
|
+
const msg = detail?.message ?? res.statusText;
|
|
512
|
+
const code = detail?.code ?? String(res.status);
|
|
494
513
|
throw new Error(`${res.status} \u2014 ${code}: ${msg}`);
|
|
495
514
|
}
|
|
496
515
|
async function fetchProviders(apiBaseUrl, token) {
|
|
@@ -646,6 +665,13 @@ async function fetchAuthorizationSession(apiBaseUrl, sessionId) {
|
|
|
646
665
|
if (!res.ok) await throwApiError(res);
|
|
647
666
|
return await res.json();
|
|
648
667
|
}
|
|
668
|
+
async function fetchAuthorizationSessionByToken(apiBaseUrl, token) {
|
|
669
|
+
const res = await fetch(
|
|
670
|
+
`${apiBaseUrl}/v1/authorization-sessions?token=${encodeURIComponent(token)}`
|
|
671
|
+
);
|
|
672
|
+
if (!res.ok) await throwApiError(res);
|
|
673
|
+
return await res.json();
|
|
674
|
+
}
|
|
649
675
|
async function registerPasskey(apiBaseUrl, token, credentialId, publicKey) {
|
|
650
676
|
const res = await fetch(`${apiBaseUrl}/v1/users/config/passkey`, {
|
|
651
677
|
method: "POST",
|
|
@@ -814,24 +840,373 @@ async function reportActionCompletion(apiBaseUrl, actionId, result) {
|
|
|
814
840
|
if (!res.ok) await throwApiError(res);
|
|
815
841
|
return await res.json();
|
|
816
842
|
}
|
|
817
|
-
|
|
818
|
-
// src/
|
|
819
|
-
function
|
|
820
|
-
|
|
843
|
+
|
|
844
|
+
// src/transferPolling.ts
|
|
845
|
+
async function pollTransferTick(params) {
|
|
846
|
+
const fetchTransfer2 = params.fetchTransfer ?? fetchTransfer;
|
|
847
|
+
const token = await params.getAccessToken();
|
|
848
|
+
if (!token) {
|
|
849
|
+
return { kind: "retry" };
|
|
850
|
+
}
|
|
851
|
+
try {
|
|
852
|
+
const transfer = await fetchTransfer2(params.apiBaseUrl, token, params.transferId);
|
|
853
|
+
return { kind: "success", transfer };
|
|
854
|
+
} catch (err) {
|
|
855
|
+
return {
|
|
856
|
+
kind: "error",
|
|
857
|
+
message: err instanceof Error ? err.message : "Polling error"
|
|
858
|
+
};
|
|
859
|
+
}
|
|
860
|
+
}
|
|
861
|
+
|
|
862
|
+
// src/hooks/useTransferPolling.ts
|
|
863
|
+
function useTransferPolling(intervalMs = 3e3) {
|
|
864
|
+
const { apiBaseUrl } = useBlinkConfig();
|
|
865
|
+
const { getAccessToken } = reactAuth.usePrivy();
|
|
866
|
+
const [transfer, setTransfer] = react.useState(null);
|
|
867
|
+
const [error, setError] = react.useState(null);
|
|
868
|
+
const [isPolling, setIsPolling] = react.useState(false);
|
|
869
|
+
const intervalRef = react.useRef(null);
|
|
870
|
+
const transferIdRef = react.useRef(null);
|
|
871
|
+
const stopPolling = react.useCallback(() => {
|
|
872
|
+
if (intervalRef.current) {
|
|
873
|
+
clearInterval(intervalRef.current);
|
|
874
|
+
intervalRef.current = null;
|
|
875
|
+
}
|
|
876
|
+
setIsPolling(false);
|
|
877
|
+
}, []);
|
|
878
|
+
const poll = react.useCallback(async () => {
|
|
879
|
+
if (!transferIdRef.current) return;
|
|
880
|
+
const result = await pollTransferTick({
|
|
881
|
+
apiBaseUrl,
|
|
882
|
+
transferId: transferIdRef.current,
|
|
883
|
+
getAccessToken
|
|
884
|
+
});
|
|
885
|
+
if (result.kind === "retry") {
|
|
886
|
+
return;
|
|
887
|
+
}
|
|
888
|
+
if (result.kind === "error") {
|
|
889
|
+
setError(result.message);
|
|
890
|
+
stopPolling();
|
|
891
|
+
return;
|
|
892
|
+
}
|
|
893
|
+
setError(null);
|
|
894
|
+
setTransfer(result.transfer);
|
|
895
|
+
if (result.transfer.status === "COMPLETED" || result.transfer.status === "FAILED") {
|
|
896
|
+
stopPolling();
|
|
897
|
+
}
|
|
898
|
+
}, [apiBaseUrl, getAccessToken, stopPolling]);
|
|
899
|
+
const startPolling = react.useCallback(
|
|
900
|
+
(transferId) => {
|
|
901
|
+
stopPolling();
|
|
902
|
+
transferIdRef.current = transferId;
|
|
903
|
+
setIsPolling(true);
|
|
904
|
+
setError(null);
|
|
905
|
+
poll();
|
|
906
|
+
intervalRef.current = setInterval(poll, intervalMs);
|
|
907
|
+
},
|
|
908
|
+
[poll, intervalMs, stopPolling]
|
|
909
|
+
);
|
|
910
|
+
react.useEffect(() => () => stopPolling(), [stopPolling]);
|
|
911
|
+
return { transfer, error, isPolling, startPolling, stopPolling };
|
|
912
|
+
}
|
|
913
|
+
|
|
914
|
+
// node_modules/@wagmi/core/dist/esm/utils/getAction.js
|
|
915
|
+
function getAction(client, actionFn, name) {
|
|
916
|
+
const action_implicit = client[actionFn.name];
|
|
917
|
+
if (typeof action_implicit === "function")
|
|
918
|
+
return action_implicit;
|
|
919
|
+
const action_explicit = client[name];
|
|
920
|
+
if (typeof action_explicit === "function")
|
|
921
|
+
return action_explicit;
|
|
922
|
+
return (params) => actionFn(client, params);
|
|
923
|
+
}
|
|
924
|
+
|
|
925
|
+
// node_modules/@wagmi/core/dist/esm/version.js
|
|
926
|
+
var version = "2.22.1";
|
|
927
|
+
|
|
928
|
+
// node_modules/@wagmi/core/dist/esm/utils/getVersion.js
|
|
929
|
+
var getVersion = () => `@wagmi/core@${version}`;
|
|
930
|
+
|
|
931
|
+
// node_modules/@wagmi/core/dist/esm/errors/base.js
|
|
932
|
+
var __classPrivateFieldGet = function(receiver, state, kind, f) {
|
|
933
|
+
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
934
|
+
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
935
|
+
};
|
|
936
|
+
var _BaseError_instances;
|
|
937
|
+
var _BaseError_walk;
|
|
938
|
+
var BaseError = class _BaseError extends Error {
|
|
939
|
+
get docsBaseUrl() {
|
|
940
|
+
return "https://wagmi.sh/core";
|
|
941
|
+
}
|
|
942
|
+
get version() {
|
|
943
|
+
return getVersion();
|
|
944
|
+
}
|
|
945
|
+
constructor(shortMessage, options = {}) {
|
|
946
|
+
super();
|
|
947
|
+
_BaseError_instances.add(this);
|
|
948
|
+
Object.defineProperty(this, "details", {
|
|
949
|
+
enumerable: true,
|
|
950
|
+
configurable: true,
|
|
951
|
+
writable: true,
|
|
952
|
+
value: void 0
|
|
953
|
+
});
|
|
954
|
+
Object.defineProperty(this, "docsPath", {
|
|
955
|
+
enumerable: true,
|
|
956
|
+
configurable: true,
|
|
957
|
+
writable: true,
|
|
958
|
+
value: void 0
|
|
959
|
+
});
|
|
960
|
+
Object.defineProperty(this, "metaMessages", {
|
|
961
|
+
enumerable: true,
|
|
962
|
+
configurable: true,
|
|
963
|
+
writable: true,
|
|
964
|
+
value: void 0
|
|
965
|
+
});
|
|
966
|
+
Object.defineProperty(this, "shortMessage", {
|
|
967
|
+
enumerable: true,
|
|
968
|
+
configurable: true,
|
|
969
|
+
writable: true,
|
|
970
|
+
value: void 0
|
|
971
|
+
});
|
|
972
|
+
Object.defineProperty(this, "name", {
|
|
973
|
+
enumerable: true,
|
|
974
|
+
configurable: true,
|
|
975
|
+
writable: true,
|
|
976
|
+
value: "WagmiCoreError"
|
|
977
|
+
});
|
|
978
|
+
const details = options.cause instanceof _BaseError ? options.cause.details : options.cause?.message ? options.cause.message : options.details;
|
|
979
|
+
const docsPath = options.cause instanceof _BaseError ? options.cause.docsPath || options.docsPath : options.docsPath;
|
|
980
|
+
this.message = [
|
|
981
|
+
shortMessage || "An error occurred.",
|
|
982
|
+
"",
|
|
983
|
+
...options.metaMessages ? [...options.metaMessages, ""] : [],
|
|
984
|
+
...docsPath ? [
|
|
985
|
+
`Docs: ${this.docsBaseUrl}${docsPath}.html${options.docsSlug ? `#${options.docsSlug}` : ""}`
|
|
986
|
+
] : [],
|
|
987
|
+
...details ? [`Details: ${details}`] : [],
|
|
988
|
+
`Version: ${this.version}`
|
|
989
|
+
].join("\n");
|
|
990
|
+
if (options.cause)
|
|
991
|
+
this.cause = options.cause;
|
|
992
|
+
this.details = details;
|
|
993
|
+
this.docsPath = docsPath;
|
|
994
|
+
this.metaMessages = options.metaMessages;
|
|
995
|
+
this.shortMessage = shortMessage;
|
|
996
|
+
}
|
|
997
|
+
walk(fn) {
|
|
998
|
+
return __classPrivateFieldGet(this, _BaseError_instances, "m", _BaseError_walk).call(this, this, fn);
|
|
999
|
+
}
|
|
1000
|
+
};
|
|
1001
|
+
_BaseError_instances = /* @__PURE__ */ new WeakSet(), _BaseError_walk = function _BaseError_walk2(err, fn) {
|
|
1002
|
+
if (fn?.(err))
|
|
1003
|
+
return err;
|
|
1004
|
+
if (err.cause)
|
|
1005
|
+
return __classPrivateFieldGet(this, _BaseError_instances, "m", _BaseError_walk2).call(this, err.cause, fn);
|
|
1006
|
+
return err;
|
|
1007
|
+
};
|
|
1008
|
+
|
|
1009
|
+
// node_modules/@wagmi/core/dist/esm/errors/config.js
|
|
1010
|
+
var ConnectorNotConnectedError = class extends BaseError {
|
|
1011
|
+
constructor() {
|
|
1012
|
+
super("Connector not connected.");
|
|
1013
|
+
Object.defineProperty(this, "name", {
|
|
1014
|
+
enumerable: true,
|
|
1015
|
+
configurable: true,
|
|
1016
|
+
writable: true,
|
|
1017
|
+
value: "ConnectorNotConnectedError"
|
|
1018
|
+
});
|
|
1019
|
+
}
|
|
1020
|
+
};
|
|
1021
|
+
var ConnectorAccountNotFoundError = class extends BaseError {
|
|
1022
|
+
constructor({ address, connector }) {
|
|
1023
|
+
super(`Account "${address}" not found for connector "${connector.name}".`);
|
|
1024
|
+
Object.defineProperty(this, "name", {
|
|
1025
|
+
enumerable: true,
|
|
1026
|
+
configurable: true,
|
|
1027
|
+
writable: true,
|
|
1028
|
+
value: "ConnectorAccountNotFoundError"
|
|
1029
|
+
});
|
|
1030
|
+
}
|
|
1031
|
+
};
|
|
1032
|
+
var ConnectorChainMismatchError = class extends BaseError {
|
|
1033
|
+
constructor({ connectionChainId, connectorChainId }) {
|
|
1034
|
+
super(`The current chain of the connector (id: ${connectorChainId}) does not match the connection's chain (id: ${connectionChainId}).`, {
|
|
1035
|
+
metaMessages: [
|
|
1036
|
+
`Current Chain ID: ${connectorChainId}`,
|
|
1037
|
+
`Expected Chain ID: ${connectionChainId}`
|
|
1038
|
+
]
|
|
1039
|
+
});
|
|
1040
|
+
Object.defineProperty(this, "name", {
|
|
1041
|
+
enumerable: true,
|
|
1042
|
+
configurable: true,
|
|
1043
|
+
writable: true,
|
|
1044
|
+
value: "ConnectorChainMismatchError"
|
|
1045
|
+
});
|
|
1046
|
+
}
|
|
1047
|
+
};
|
|
1048
|
+
var ConnectorUnavailableReconnectingError = class extends BaseError {
|
|
1049
|
+
constructor({ connector }) {
|
|
1050
|
+
super(`Connector "${connector.name}" unavailable while reconnecting.`, {
|
|
1051
|
+
details: [
|
|
1052
|
+
"During the reconnection step, the only connector methods guaranteed to be available are: `id`, `name`, `type`, `uid`.",
|
|
1053
|
+
"All other methods are not guaranteed to be available until reconnection completes and connectors are fully restored.",
|
|
1054
|
+
"This error commonly occurs for connectors that asynchronously inject after reconnection has already started."
|
|
1055
|
+
].join(" ")
|
|
1056
|
+
});
|
|
1057
|
+
Object.defineProperty(this, "name", {
|
|
1058
|
+
enumerable: true,
|
|
1059
|
+
configurable: true,
|
|
1060
|
+
writable: true,
|
|
1061
|
+
value: "ConnectorUnavailableReconnectingError"
|
|
1062
|
+
});
|
|
1063
|
+
}
|
|
1064
|
+
};
|
|
1065
|
+
async function getConnectorClient(config, parameters = {}) {
|
|
1066
|
+
const { assertChainId = true } = parameters;
|
|
1067
|
+
let connection;
|
|
1068
|
+
if (parameters.connector) {
|
|
1069
|
+
const { connector: connector2 } = parameters;
|
|
1070
|
+
if (config.state.status === "reconnecting" && !connector2.getAccounts && !connector2.getChainId)
|
|
1071
|
+
throw new ConnectorUnavailableReconnectingError({ connector: connector2 });
|
|
1072
|
+
const [accounts, chainId2] = await Promise.all([
|
|
1073
|
+
connector2.getAccounts().catch((e) => {
|
|
1074
|
+
if (parameters.account === null)
|
|
1075
|
+
return [];
|
|
1076
|
+
throw e;
|
|
1077
|
+
}),
|
|
1078
|
+
connector2.getChainId()
|
|
1079
|
+
]);
|
|
1080
|
+
connection = {
|
|
1081
|
+
accounts,
|
|
1082
|
+
chainId: chainId2,
|
|
1083
|
+
connector: connector2
|
|
1084
|
+
};
|
|
1085
|
+
} else
|
|
1086
|
+
connection = config.state.connections.get(config.state.current);
|
|
1087
|
+
if (!connection)
|
|
1088
|
+
throw new ConnectorNotConnectedError();
|
|
1089
|
+
const chainId = parameters.chainId ?? connection.chainId;
|
|
1090
|
+
const connectorChainId = await connection.connector.getChainId();
|
|
1091
|
+
if (assertChainId && connectorChainId !== chainId)
|
|
1092
|
+
throw new ConnectorChainMismatchError({
|
|
1093
|
+
connectionChainId: chainId,
|
|
1094
|
+
connectorChainId
|
|
1095
|
+
});
|
|
1096
|
+
const connector = connection.connector;
|
|
1097
|
+
if (connector.getClient)
|
|
1098
|
+
return connector.getClient({ chainId });
|
|
1099
|
+
const account = utils.parseAccount(parameters.account ?? connection.accounts[0]);
|
|
1100
|
+
if (account)
|
|
1101
|
+
account.address = utils.getAddress(account.address);
|
|
1102
|
+
if (parameters.account && !connection.accounts.some((x) => x.toLowerCase() === account.address.toLowerCase()))
|
|
1103
|
+
throw new ConnectorAccountNotFoundError({
|
|
1104
|
+
address: account.address,
|
|
1105
|
+
connector
|
|
1106
|
+
});
|
|
1107
|
+
const chain = config.chains.find((chain2) => chain2.id === chainId);
|
|
1108
|
+
const provider = await connection.connector.getProvider({ chainId });
|
|
1109
|
+
return viem.createClient({
|
|
1110
|
+
account,
|
|
1111
|
+
chain,
|
|
1112
|
+
name: "Connector Client",
|
|
1113
|
+
transport: (opts) => viem.custom(provider)({ ...opts, retryCount: 0 })
|
|
1114
|
+
});
|
|
1115
|
+
}
|
|
1116
|
+
|
|
1117
|
+
// node_modules/@wagmi/core/dist/esm/actions/getAccount.js
|
|
1118
|
+
function getAccount(config) {
|
|
1119
|
+
const uid = config.state.current;
|
|
1120
|
+
const connection = config.state.connections.get(uid);
|
|
1121
|
+
const addresses = connection?.accounts;
|
|
1122
|
+
const address = addresses?.[0];
|
|
1123
|
+
const chain = config.chains.find((chain2) => chain2.id === connection?.chainId);
|
|
1124
|
+
const status = config.state.status;
|
|
1125
|
+
switch (status) {
|
|
1126
|
+
case "connected":
|
|
1127
|
+
return {
|
|
1128
|
+
address,
|
|
1129
|
+
addresses,
|
|
1130
|
+
chain,
|
|
1131
|
+
chainId: connection?.chainId,
|
|
1132
|
+
connector: connection?.connector,
|
|
1133
|
+
isConnected: true,
|
|
1134
|
+
isConnecting: false,
|
|
1135
|
+
isDisconnected: false,
|
|
1136
|
+
isReconnecting: false,
|
|
1137
|
+
status
|
|
1138
|
+
};
|
|
1139
|
+
case "reconnecting":
|
|
1140
|
+
return {
|
|
1141
|
+
address,
|
|
1142
|
+
addresses,
|
|
1143
|
+
chain,
|
|
1144
|
+
chainId: connection?.chainId,
|
|
1145
|
+
connector: connection?.connector,
|
|
1146
|
+
isConnected: !!address,
|
|
1147
|
+
isConnecting: false,
|
|
1148
|
+
isDisconnected: false,
|
|
1149
|
+
isReconnecting: true,
|
|
1150
|
+
status
|
|
1151
|
+
};
|
|
1152
|
+
case "connecting":
|
|
1153
|
+
return {
|
|
1154
|
+
address,
|
|
1155
|
+
addresses,
|
|
1156
|
+
chain,
|
|
1157
|
+
chainId: connection?.chainId,
|
|
1158
|
+
connector: connection?.connector,
|
|
1159
|
+
isConnected: false,
|
|
1160
|
+
isConnecting: true,
|
|
1161
|
+
isDisconnected: false,
|
|
1162
|
+
isReconnecting: false,
|
|
1163
|
+
status
|
|
1164
|
+
};
|
|
1165
|
+
case "disconnected":
|
|
1166
|
+
return {
|
|
1167
|
+
address: void 0,
|
|
1168
|
+
addresses: void 0,
|
|
1169
|
+
chain: void 0,
|
|
1170
|
+
chainId: void 0,
|
|
1171
|
+
connector: void 0,
|
|
1172
|
+
isConnected: false,
|
|
1173
|
+
isConnecting: false,
|
|
1174
|
+
isDisconnected: true,
|
|
1175
|
+
isReconnecting: false,
|
|
1176
|
+
status
|
|
1177
|
+
};
|
|
1178
|
+
}
|
|
1179
|
+
}
|
|
1180
|
+
async function getWalletClient(config, parameters = {}) {
|
|
1181
|
+
const client = await getConnectorClient(config, parameters);
|
|
1182
|
+
return client.extend(viem.walletActions);
|
|
821
1183
|
}
|
|
822
|
-
function
|
|
823
|
-
const
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
}
|
|
827
|
-
if (
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
1184
|
+
async function waitForTransactionReceipt(config, parameters) {
|
|
1185
|
+
const { chainId, timeout = 0, ...rest } = parameters;
|
|
1186
|
+
const client = config.getClient({ chainId });
|
|
1187
|
+
const action = getAction(client, actions.waitForTransactionReceipt, "waitForTransactionReceipt");
|
|
1188
|
+
const receipt = await action({ ...rest, timeout });
|
|
1189
|
+
if (receipt.status === "reverted") {
|
|
1190
|
+
const action_getTransaction = getAction(client, actions.getTransaction, "getTransaction");
|
|
1191
|
+
const { from: account, ...txn } = await action_getTransaction({
|
|
1192
|
+
hash: receipt.transactionHash
|
|
1193
|
+
});
|
|
1194
|
+
const action_call = getAction(client, actions.call, "call");
|
|
1195
|
+
const code = await action_call({
|
|
1196
|
+
...txn,
|
|
1197
|
+
account,
|
|
1198
|
+
data: txn.input,
|
|
1199
|
+
gasPrice: txn.type !== "eip1559" ? txn.gasPrice : void 0,
|
|
1200
|
+
maxFeePerGas: txn.type === "eip1559" ? txn.maxFeePerGas : void 0,
|
|
1201
|
+
maxPriorityFeePerGas: txn.type === "eip1559" ? txn.maxPriorityFeePerGas : void 0
|
|
1202
|
+
});
|
|
1203
|
+
const reason = code?.data ? viem.hexToString(`0x${code.data.substring(138)}`) : "unknown reason";
|
|
1204
|
+
throw new Error(reason);
|
|
833
1205
|
}
|
|
834
|
-
return
|
|
1206
|
+
return {
|
|
1207
|
+
...receipt,
|
|
1208
|
+
chainId: client.chain.id
|
|
1209
|
+
};
|
|
835
1210
|
}
|
|
836
1211
|
var ERC_6492_MAGIC_SUFFIX = "6492649264926492649264926492649264926492649264926492649264926492";
|
|
837
1212
|
function normalizeSignature(sig) {
|
|
@@ -881,232 +1256,22 @@ function normalizeSignature(sig) {
|
|
|
881
1256
|
);
|
|
882
1257
|
}
|
|
883
1258
|
|
|
884
|
-
// src/
|
|
885
|
-
async function pollTransferTick(params) {
|
|
886
|
-
const fetchTransfer2 = params.fetchTransfer ?? fetchTransfer;
|
|
887
|
-
const token = await params.getAccessToken();
|
|
888
|
-
if (!token) {
|
|
889
|
-
return { kind: "retry" };
|
|
890
|
-
}
|
|
891
|
-
try {
|
|
892
|
-
const transfer = await fetchTransfer2(params.apiBaseUrl, token, params.transferId);
|
|
893
|
-
return { kind: "success", transfer };
|
|
894
|
-
} catch (err) {
|
|
895
|
-
return {
|
|
896
|
-
kind: "error",
|
|
897
|
-
message: err instanceof Error ? err.message : "Polling error"
|
|
898
|
-
};
|
|
899
|
-
}
|
|
900
|
-
}
|
|
901
|
-
|
|
902
|
-
// src/passkey-delegation.ts
|
|
903
|
-
var PasskeyIframeBlockedError = class extends Error {
|
|
904
|
-
constructor(message = "Passkey creation is not supported in this browser context.") {
|
|
905
|
-
super(message);
|
|
906
|
-
this.name = "PasskeyIframeBlockedError";
|
|
907
|
-
}
|
|
908
|
-
};
|
|
909
|
-
function isInCrossOriginIframe() {
|
|
910
|
-
if (typeof window === "undefined") return false;
|
|
911
|
-
if (window.parent === window) return false;
|
|
912
|
-
try {
|
|
913
|
-
void window.parent.location.origin;
|
|
914
|
-
return false;
|
|
915
|
-
} catch {
|
|
916
|
-
return true;
|
|
917
|
-
}
|
|
918
|
-
}
|
|
919
|
-
function isSafari() {
|
|
920
|
-
if (typeof navigator === "undefined") return false;
|
|
921
|
-
const ua = navigator.userAgent;
|
|
922
|
-
return /Safari/i.test(ua) && !/Chrome|CriOS|Chromium|Edg|OPR|Firefox/i.test(ua);
|
|
923
|
-
}
|
|
924
|
-
var POPUP_RESULT_TIMEOUT_MS = 12e4;
|
|
925
|
-
var POPUP_CLOSED_POLL_MS = 500;
|
|
926
|
-
var POPUP_CLOSED_GRACE_MS = 1e3;
|
|
927
|
-
function createPasskeyViaPopup(options) {
|
|
928
|
-
return new Promise((resolve, reject) => {
|
|
929
|
-
const verificationToken = crypto.randomUUID();
|
|
930
|
-
const payload = { ...options, verificationToken };
|
|
931
|
-
const encoded = btoa(JSON.stringify(payload));
|
|
932
|
-
const popupUrl = `${window.location.origin}/passkey-register#${encoded}`;
|
|
933
|
-
const popup = window.open(popupUrl, "blink-passkey");
|
|
934
|
-
if (!popup) {
|
|
935
|
-
reject(new Error("Pop-up blocked. Please allow pop-ups for this site and try again."));
|
|
936
|
-
return;
|
|
937
|
-
}
|
|
938
|
-
let settled = false;
|
|
939
|
-
const timer = setTimeout(() => {
|
|
940
|
-
cleanup();
|
|
941
|
-
reject(new Error("Passkey creation timed out. Please try again."));
|
|
942
|
-
}, POPUP_RESULT_TIMEOUT_MS);
|
|
943
|
-
const closedPoll = setInterval(() => {
|
|
944
|
-
if (popup.closed) {
|
|
945
|
-
clearInterval(closedPoll);
|
|
946
|
-
setTimeout(() => {
|
|
947
|
-
if (!settled) {
|
|
948
|
-
settled = true;
|
|
949
|
-
cleanup();
|
|
950
|
-
checkServerForPasskeyByToken(
|
|
951
|
-
options.authToken,
|
|
952
|
-
options.apiBaseUrl,
|
|
953
|
-
verificationToken
|
|
954
|
-
).then((result) => {
|
|
955
|
-
if (result) {
|
|
956
|
-
resolve(result);
|
|
957
|
-
} else {
|
|
958
|
-
reject(new Error("Passkey window was closed before completing."));
|
|
959
|
-
}
|
|
960
|
-
}).catch(() => {
|
|
961
|
-
reject(new Error("Passkey window was closed before completing."));
|
|
962
|
-
});
|
|
963
|
-
}
|
|
964
|
-
}, POPUP_CLOSED_GRACE_MS);
|
|
965
|
-
}
|
|
966
|
-
}, POPUP_CLOSED_POLL_MS);
|
|
967
|
-
function cleanup() {
|
|
968
|
-
clearTimeout(timer);
|
|
969
|
-
clearInterval(closedPoll);
|
|
970
|
-
}
|
|
971
|
-
});
|
|
972
|
-
}
|
|
973
|
-
var VERIFY_POPUP_TIMEOUT_MS = 6e4;
|
|
974
|
-
function findDevicePasskeyViaPopup(options) {
|
|
975
|
-
return new Promise((resolve, reject) => {
|
|
976
|
-
const verificationToken = crypto.randomUUID();
|
|
977
|
-
const payload = {
|
|
978
|
-
...options,
|
|
979
|
-
verificationToken
|
|
980
|
-
};
|
|
981
|
-
const encoded = btoa(JSON.stringify(payload));
|
|
982
|
-
const popupUrl = `${window.location.origin}/passkey-verify#${encoded}`;
|
|
983
|
-
const popup = window.open(popupUrl, "blink-passkey-verify");
|
|
984
|
-
if (!popup) {
|
|
985
|
-
reject(new Error("Pop-up blocked. Please allow pop-ups for this site and try again."));
|
|
986
|
-
return;
|
|
987
|
-
}
|
|
988
|
-
let settled = false;
|
|
989
|
-
const timer = setTimeout(() => {
|
|
990
|
-
cleanup();
|
|
991
|
-
resolve(null);
|
|
992
|
-
}, VERIFY_POPUP_TIMEOUT_MS);
|
|
993
|
-
const closedPoll = setInterval(() => {
|
|
994
|
-
if (popup.closed && !settled) {
|
|
995
|
-
clearInterval(closedPoll);
|
|
996
|
-
setTimeout(() => {
|
|
997
|
-
if (!settled) {
|
|
998
|
-
settled = true;
|
|
999
|
-
cleanup();
|
|
1000
|
-
checkServerForPasskeyByToken(
|
|
1001
|
-
options.authToken,
|
|
1002
|
-
options.apiBaseUrl,
|
|
1003
|
-
verificationToken
|
|
1004
|
-
).then((result) => {
|
|
1005
|
-
resolve(result?.credentialId ?? null);
|
|
1006
|
-
}).catch(() => {
|
|
1007
|
-
resolve(null);
|
|
1008
|
-
});
|
|
1009
|
-
}
|
|
1010
|
-
}, POPUP_CLOSED_GRACE_MS);
|
|
1011
|
-
}
|
|
1012
|
-
}, POPUP_CLOSED_POLL_MS);
|
|
1013
|
-
function cleanup() {
|
|
1014
|
-
clearTimeout(timer);
|
|
1015
|
-
clearInterval(closedPoll);
|
|
1016
|
-
}
|
|
1017
|
-
});
|
|
1018
|
-
}
|
|
1019
|
-
async function checkServerForPasskeyByToken(authToken, apiBaseUrl, verificationToken) {
|
|
1020
|
-
if (!authToken || !apiBaseUrl) return null;
|
|
1021
|
-
const res = await fetch(`${apiBaseUrl}/v1/users/config`, {
|
|
1022
|
-
headers: { Authorization: `Bearer ${authToken}` }
|
|
1023
|
-
});
|
|
1024
|
-
if (!res.ok) return null;
|
|
1025
|
-
const body = await res.json();
|
|
1026
|
-
const passkeys = body.config.passkeys ?? [];
|
|
1027
|
-
const matched = passkeys.find((p) => p.lastVerificationToken === verificationToken);
|
|
1028
|
-
return matched ? { credentialId: matched.credentialId, publicKey: matched.publicKey } : null;
|
|
1029
|
-
}
|
|
1030
|
-
|
|
1031
|
-
// src/hooks.ts
|
|
1259
|
+
// src/hooks/authorizationExecutor.ts
|
|
1032
1260
|
var WALLET_CLIENT_MAX_ATTEMPTS = 25;
|
|
1033
1261
|
var WALLET_CLIENT_POLL_MS = 400;
|
|
1034
1262
|
var ACTION_POLL_INTERVAL_MS = 500;
|
|
1035
1263
|
var ACTION_POLL_MAX_RETRIES = 20;
|
|
1036
1264
|
var SIGN_PERMIT2_POLL_MS = 1e3;
|
|
1037
1265
|
var SIGN_PERMIT2_MAX_POLLS = 15;
|
|
1038
|
-
var TRANSFER_SIGN_MAX_POLLS = 60;
|
|
1039
|
-
function waitForDocumentFocus(timeoutMs = 5e3, intervalMs = 100) {
|
|
1040
|
-
return new Promise((resolve, reject) => {
|
|
1041
|
-
if (typeof document === "undefined") {
|
|
1042
|
-
resolve();
|
|
1043
|
-
return;
|
|
1044
|
-
}
|
|
1045
|
-
if (document.hasFocus()) {
|
|
1046
|
-
resolve();
|
|
1047
|
-
return;
|
|
1048
|
-
}
|
|
1049
|
-
const deadline = Date.now() + timeoutMs;
|
|
1050
|
-
const timer = setInterval(() => {
|
|
1051
|
-
if (document.hasFocus()) {
|
|
1052
|
-
clearInterval(timer);
|
|
1053
|
-
resolve();
|
|
1054
|
-
} else if (Date.now() >= deadline) {
|
|
1055
|
-
clearInterval(timer);
|
|
1056
|
-
resolve();
|
|
1057
|
-
}
|
|
1058
|
-
}, intervalMs);
|
|
1059
|
-
});
|
|
1060
|
-
}
|
|
1061
1266
|
function actionSuccess(action, message, data) {
|
|
1062
1267
|
return { actionId: action.id, type: action.type, status: "success", message, data };
|
|
1063
1268
|
}
|
|
1064
|
-
function actionError(action, message) {
|
|
1065
|
-
return { actionId: action.id, type: action.type, status: "error", message };
|
|
1066
|
-
}
|
|
1067
|
-
function isUserRejection(msg) {
|
|
1068
|
-
const lower = msg.toLowerCase();
|
|
1069
|
-
return lower.includes("rejected") || lower.includes("denied");
|
|
1070
|
-
}
|
|
1071
|
-
function hexToBytes(hex) {
|
|
1072
|
-
const clean = hex.startsWith("0x") ? hex.slice(2) : hex;
|
|
1073
|
-
const bytes = clean.match(/.{1,2}/g).map((b) => parseInt(b, 16));
|
|
1074
|
-
return new Uint8Array(bytes);
|
|
1075
|
-
}
|
|
1076
|
-
function toBase64(buffer) {
|
|
1077
|
-
return btoa(String.fromCharCode(...new Uint8Array(buffer)));
|
|
1078
|
-
}
|
|
1079
|
-
function base64ToBytes(value) {
|
|
1080
|
-
const normalized = value.replace(/-/g, "+").replace(/_/g, "/");
|
|
1081
|
-
const padded = normalized + "=".repeat((4 - normalized.length % 4) % 4);
|
|
1082
|
-
const raw = atob(padded);
|
|
1083
|
-
const bytes = new Uint8Array(raw.length);
|
|
1084
|
-
for (let i = 0; i < raw.length; i++) {
|
|
1085
|
-
bytes[i] = raw.charCodeAt(i);
|
|
1086
|
-
}
|
|
1087
|
-
return bytes;
|
|
1088
|
-
}
|
|
1089
|
-
function readEnvValue(name) {
|
|
1090
|
-
const meta = ({ url: (typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index.cjs', document.baseURI).href)) });
|
|
1091
|
-
const metaValue = meta.env?.[name];
|
|
1092
|
-
if (typeof metaValue === "string" && metaValue.trim().length > 0) {
|
|
1093
|
-
return metaValue.trim();
|
|
1094
|
-
}
|
|
1095
|
-
const processValue = globalThis.process?.env?.[name];
|
|
1096
|
-
if (typeof processValue === "string" && processValue.trim().length > 0) {
|
|
1097
|
-
return processValue.trim();
|
|
1098
|
-
}
|
|
1099
|
-
return void 0;
|
|
1269
|
+
function actionError(action, message) {
|
|
1270
|
+
return { actionId: action.id, type: action.type, status: "error", message };
|
|
1100
1271
|
}
|
|
1101
|
-
function
|
|
1102
|
-
const
|
|
1103
|
-
|
|
1104
|
-
return normalizeConfiguredDomain(configuredDomain);
|
|
1105
|
-
}
|
|
1106
|
-
if (typeof window !== "undefined") {
|
|
1107
|
-
return resolveRootDomainFromHostname(window.location.hostname);
|
|
1108
|
-
}
|
|
1109
|
-
return "localhost";
|
|
1272
|
+
function isUserRejection(msg) {
|
|
1273
|
+
const lower = msg.toLowerCase();
|
|
1274
|
+
return lower.includes("rejected") || lower.includes("denied");
|
|
1110
1275
|
}
|
|
1111
1276
|
async function waitForWalletClient(wagmiConfig2, params = {}) {
|
|
1112
1277
|
for (let i = 0; i < WALLET_CLIENT_MAX_ATTEMPTS; i++) {
|
|
@@ -1147,165 +1312,6 @@ function parseSignTypedDataPayload(typedData) {
|
|
|
1147
1312
|
function getPendingActions(session, completedIds) {
|
|
1148
1313
|
return session.actions.filter((a) => a.status === "PENDING" && !completedIds.has(a.id)).sort((a, b) => a.orderIndex - b.orderIndex);
|
|
1149
1314
|
}
|
|
1150
|
-
async function createPasskeyCredential(params) {
|
|
1151
|
-
const challenge = new Uint8Array(32);
|
|
1152
|
-
crypto.getRandomValues(challenge);
|
|
1153
|
-
const rpId = resolvePasskeyRpId();
|
|
1154
|
-
const publicKeyOptions = {
|
|
1155
|
-
challenge,
|
|
1156
|
-
rp: { name: "Blink", id: rpId },
|
|
1157
|
-
user: {
|
|
1158
|
-
id: new TextEncoder().encode(params.userId),
|
|
1159
|
-
name: params.displayName,
|
|
1160
|
-
displayName: params.displayName
|
|
1161
|
-
},
|
|
1162
|
-
pubKeyCredParams: [
|
|
1163
|
-
{ alg: -7, type: "public-key" },
|
|
1164
|
-
{ alg: -257, type: "public-key" }
|
|
1165
|
-
],
|
|
1166
|
-
authenticatorSelection: {
|
|
1167
|
-
authenticatorAttachment: "platform",
|
|
1168
|
-
residentKey: "preferred",
|
|
1169
|
-
userVerification: "required"
|
|
1170
|
-
},
|
|
1171
|
-
timeout: 6e4
|
|
1172
|
-
};
|
|
1173
|
-
if (isInCrossOriginIframe()) {
|
|
1174
|
-
try {
|
|
1175
|
-
await waitForDocumentFocus();
|
|
1176
|
-
const credential2 = await navigator.credentials.create({
|
|
1177
|
-
publicKey: publicKeyOptions
|
|
1178
|
-
});
|
|
1179
|
-
if (!credential2) {
|
|
1180
|
-
throw new Error("Passkey creation was cancelled.");
|
|
1181
|
-
}
|
|
1182
|
-
return extractPasskeyResult(credential2);
|
|
1183
|
-
} catch (err) {
|
|
1184
|
-
if (err instanceof PasskeyIframeBlockedError) throw err;
|
|
1185
|
-
if (err instanceof Error && err.message === "Passkey creation was cancelled.") throw err;
|
|
1186
|
-
throw new PasskeyIframeBlockedError();
|
|
1187
|
-
}
|
|
1188
|
-
}
|
|
1189
|
-
await waitForDocumentFocus();
|
|
1190
|
-
const credential = await navigator.credentials.create({
|
|
1191
|
-
publicKey: publicKeyOptions
|
|
1192
|
-
});
|
|
1193
|
-
if (!credential) {
|
|
1194
|
-
throw new Error("Passkey creation was cancelled.");
|
|
1195
|
-
}
|
|
1196
|
-
return extractPasskeyResult(credential);
|
|
1197
|
-
}
|
|
1198
|
-
function extractPasskeyResult(credential) {
|
|
1199
|
-
const response = credential.response;
|
|
1200
|
-
const publicKeyBytes = response.getPublicKey?.();
|
|
1201
|
-
return {
|
|
1202
|
-
credentialId: toBase64(credential.rawId),
|
|
1203
|
-
publicKey: publicKeyBytes ? toBase64(publicKeyBytes) : ""
|
|
1204
|
-
};
|
|
1205
|
-
}
|
|
1206
|
-
function buildPasskeyPopupOptions(params) {
|
|
1207
|
-
const challenge = new Uint8Array(32);
|
|
1208
|
-
crypto.getRandomValues(challenge);
|
|
1209
|
-
const rpId = resolvePasskeyRpId();
|
|
1210
|
-
return {
|
|
1211
|
-
challenge: toBase64(challenge),
|
|
1212
|
-
rpId,
|
|
1213
|
-
rpName: "Blink",
|
|
1214
|
-
userId: toBase64(new TextEncoder().encode(params.userId)),
|
|
1215
|
-
userName: params.displayName,
|
|
1216
|
-
userDisplayName: params.displayName,
|
|
1217
|
-
pubKeyCredParams: [
|
|
1218
|
-
{ alg: -7, type: "public-key" },
|
|
1219
|
-
{ alg: -257, type: "public-key" }
|
|
1220
|
-
],
|
|
1221
|
-
authenticatorSelection: {
|
|
1222
|
-
authenticatorAttachment: "platform",
|
|
1223
|
-
residentKey: "preferred",
|
|
1224
|
-
userVerification: "required"
|
|
1225
|
-
},
|
|
1226
|
-
timeout: 6e4,
|
|
1227
|
-
authToken: params.authToken,
|
|
1228
|
-
apiBaseUrl: params.apiBaseUrl
|
|
1229
|
-
};
|
|
1230
|
-
}
|
|
1231
|
-
async function deviceHasPasskey(credentialId) {
|
|
1232
|
-
const found = await findDevicePasskey([credentialId]);
|
|
1233
|
-
return found != null;
|
|
1234
|
-
}
|
|
1235
|
-
async function findDevicePasskey(credentialIds) {
|
|
1236
|
-
if (credentialIds.length === 0) return null;
|
|
1237
|
-
try {
|
|
1238
|
-
const challenge = new Uint8Array(32);
|
|
1239
|
-
crypto.getRandomValues(challenge);
|
|
1240
|
-
await waitForDocumentFocus();
|
|
1241
|
-
const assertion = await navigator.credentials.get({
|
|
1242
|
-
publicKey: {
|
|
1243
|
-
challenge,
|
|
1244
|
-
rpId: resolvePasskeyRpId(),
|
|
1245
|
-
allowCredentials: credentialIds.map((id) => ({
|
|
1246
|
-
type: "public-key",
|
|
1247
|
-
id: base64ToBytes(id)
|
|
1248
|
-
})),
|
|
1249
|
-
userVerification: "discouraged",
|
|
1250
|
-
timeout: 3e4
|
|
1251
|
-
}
|
|
1252
|
-
});
|
|
1253
|
-
if (!assertion) return null;
|
|
1254
|
-
return toBase64(assertion.rawId);
|
|
1255
|
-
} catch {
|
|
1256
|
-
return null;
|
|
1257
|
-
}
|
|
1258
|
-
}
|
|
1259
|
-
function useTransferPolling(intervalMs = 3e3) {
|
|
1260
|
-
const { apiBaseUrl } = useBlinkConfig();
|
|
1261
|
-
const { getAccessToken } = reactAuth.usePrivy();
|
|
1262
|
-
const [transfer, setTransfer] = react.useState(null);
|
|
1263
|
-
const [error, setError] = react.useState(null);
|
|
1264
|
-
const [isPolling, setIsPolling] = react.useState(false);
|
|
1265
|
-
const intervalRef = react.useRef(null);
|
|
1266
|
-
const transferIdRef = react.useRef(null);
|
|
1267
|
-
const stopPolling = react.useCallback(() => {
|
|
1268
|
-
if (intervalRef.current) {
|
|
1269
|
-
clearInterval(intervalRef.current);
|
|
1270
|
-
intervalRef.current = null;
|
|
1271
|
-
}
|
|
1272
|
-
setIsPolling(false);
|
|
1273
|
-
}, []);
|
|
1274
|
-
const poll = react.useCallback(async () => {
|
|
1275
|
-
if (!transferIdRef.current) return;
|
|
1276
|
-
const result = await pollTransferTick({
|
|
1277
|
-
apiBaseUrl,
|
|
1278
|
-
transferId: transferIdRef.current,
|
|
1279
|
-
getAccessToken
|
|
1280
|
-
});
|
|
1281
|
-
if (result.kind === "retry") {
|
|
1282
|
-
return;
|
|
1283
|
-
}
|
|
1284
|
-
if (result.kind === "error") {
|
|
1285
|
-
setError(result.message);
|
|
1286
|
-
stopPolling();
|
|
1287
|
-
return;
|
|
1288
|
-
}
|
|
1289
|
-
setError(null);
|
|
1290
|
-
setTransfer(result.transfer);
|
|
1291
|
-
if (result.transfer.status === "COMPLETED" || result.transfer.status === "FAILED") {
|
|
1292
|
-
stopPolling();
|
|
1293
|
-
}
|
|
1294
|
-
}, [apiBaseUrl, getAccessToken, stopPolling]);
|
|
1295
|
-
const startPolling = react.useCallback(
|
|
1296
|
-
(transferId) => {
|
|
1297
|
-
stopPolling();
|
|
1298
|
-
transferIdRef.current = transferId;
|
|
1299
|
-
setIsPolling(true);
|
|
1300
|
-
setError(null);
|
|
1301
|
-
poll();
|
|
1302
|
-
intervalRef.current = setInterval(poll, intervalMs);
|
|
1303
|
-
},
|
|
1304
|
-
[poll, intervalMs, stopPolling]
|
|
1305
|
-
);
|
|
1306
|
-
react.useEffect(() => () => stopPolling(), [stopPolling]);
|
|
1307
|
-
return { transfer, error, isPolling, startPolling, stopPolling };
|
|
1308
|
-
}
|
|
1309
1315
|
async function executeOpenProvider(action, wagmiConfig2, connectors, connectAsync) {
|
|
1310
1316
|
try {
|
|
1311
1317
|
const account = getAccount(wagmiConfig2);
|
|
@@ -1702,6 +1708,47 @@ function useAuthorizationExecutor(options) {
|
|
|
1702
1708
|
executeSessionById
|
|
1703
1709
|
};
|
|
1704
1710
|
}
|
|
1711
|
+
var TRANSFER_SIGN_MAX_POLLS = 60;
|
|
1712
|
+
function waitForDocumentFocus2(timeoutMs = 5e3, intervalMs = 100) {
|
|
1713
|
+
return new Promise((resolve, reject) => {
|
|
1714
|
+
if (typeof document === "undefined") {
|
|
1715
|
+
resolve();
|
|
1716
|
+
return;
|
|
1717
|
+
}
|
|
1718
|
+
if (document.hasFocus()) {
|
|
1719
|
+
resolve();
|
|
1720
|
+
return;
|
|
1721
|
+
}
|
|
1722
|
+
const deadline = Date.now() + timeoutMs;
|
|
1723
|
+
const timer = setInterval(() => {
|
|
1724
|
+
if (document.hasFocus()) {
|
|
1725
|
+
clearInterval(timer);
|
|
1726
|
+
resolve();
|
|
1727
|
+
} else if (Date.now() >= deadline) {
|
|
1728
|
+
clearInterval(timer);
|
|
1729
|
+
resolve();
|
|
1730
|
+
}
|
|
1731
|
+
}, intervalMs);
|
|
1732
|
+
});
|
|
1733
|
+
}
|
|
1734
|
+
function hexToBytes(hex) {
|
|
1735
|
+
const clean = hex.startsWith("0x") ? hex.slice(2) : hex;
|
|
1736
|
+
const bytes = clean.match(/.{1,2}/g).map((b) => parseInt(b, 16));
|
|
1737
|
+
return new Uint8Array(bytes);
|
|
1738
|
+
}
|
|
1739
|
+
function toBase642(buffer) {
|
|
1740
|
+
return btoa(String.fromCharCode(...new Uint8Array(buffer)));
|
|
1741
|
+
}
|
|
1742
|
+
function base64ToBytes2(value) {
|
|
1743
|
+
const normalized = value.replace(/-/g, "+").replace(/_/g, "/");
|
|
1744
|
+
const padded = normalized + "=".repeat((4 - normalized.length % 4) % 4);
|
|
1745
|
+
const raw = atob(padded);
|
|
1746
|
+
const bytes = new Uint8Array(raw.length);
|
|
1747
|
+
for (let i = 0; i < raw.length; i++) {
|
|
1748
|
+
bytes[i] = raw.charCodeAt(i);
|
|
1749
|
+
}
|
|
1750
|
+
return bytes;
|
|
1751
|
+
}
|
|
1705
1752
|
function useTransferSigning(pollIntervalMs = 2e3, options) {
|
|
1706
1753
|
const blinkConfig = useOptionalBlinkConfig();
|
|
1707
1754
|
const apiBaseUrl = options?.apiBaseUrl ?? blinkConfig?.apiBaseUrl;
|
|
@@ -1757,9 +1804,9 @@ function useTransferSigning(pollIntervalMs = 2e3, options) {
|
|
|
1757
1804
|
let signedUserOp;
|
|
1758
1805
|
const allowCredentials = payload.passkeyCredentialId ? [{
|
|
1759
1806
|
type: "public-key",
|
|
1760
|
-
id:
|
|
1807
|
+
id: base64ToBytes2(payload.passkeyCredentialId)
|
|
1761
1808
|
}] : void 0;
|
|
1762
|
-
await
|
|
1809
|
+
await waitForDocumentFocus2();
|
|
1763
1810
|
const assertion = await navigator.credentials.get({
|
|
1764
1811
|
publicKey: {
|
|
1765
1812
|
challenge: hashBytes,
|
|
@@ -1775,10 +1822,10 @@ function useTransferSigning(pollIntervalMs = 2e3, options) {
|
|
|
1775
1822
|
const response = assertion.response;
|
|
1776
1823
|
signedUserOp = {
|
|
1777
1824
|
...payload.userOp,
|
|
1778
|
-
credentialId:
|
|
1779
|
-
signature:
|
|
1780
|
-
authenticatorData:
|
|
1781
|
-
clientDataJSON:
|
|
1825
|
+
credentialId: toBase642(assertion.rawId),
|
|
1826
|
+
signature: toBase642(response.signature),
|
|
1827
|
+
authenticatorData: toBase642(response.authenticatorData),
|
|
1828
|
+
clientDataJSON: toBase642(response.clientDataJSON)
|
|
1782
1829
|
};
|
|
1783
1830
|
return await signTransfer(
|
|
1784
1831
|
apiBaseUrl,
|
|
@@ -1937,6 +1984,87 @@ function buildSelectSourceChoices(options) {
|
|
|
1937
1984
|
})).filter((chain) => chain.tokens.length > 0).sort((a, b) => b.balance - a.balance);
|
|
1938
1985
|
}
|
|
1939
1986
|
|
|
1987
|
+
// src/walletFlow.ts
|
|
1988
|
+
var MOBILE_USER_AGENT_PATTERN = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i;
|
|
1989
|
+
function isMobileUserAgent(userAgent) {
|
|
1990
|
+
if (!userAgent) {
|
|
1991
|
+
return false;
|
|
1992
|
+
}
|
|
1993
|
+
return MOBILE_USER_AGENT_PATTERN.test(userAgent);
|
|
1994
|
+
}
|
|
1995
|
+
function shouldUseWalletConnector(options) {
|
|
1996
|
+
return options.useWalletConnector ?? !isMobileUserAgent(options.userAgent);
|
|
1997
|
+
}
|
|
1998
|
+
|
|
1999
|
+
// src/paymentResolvePhase.ts
|
|
2000
|
+
function hasActiveWallet(accounts) {
|
|
2001
|
+
return accounts.some((a) => a.wallets.some((w) => w.status === "ACTIVE"));
|
|
2002
|
+
}
|
|
2003
|
+
function isTransferInFlight(transfer) {
|
|
2004
|
+
if (!transfer) return false;
|
|
2005
|
+
return ["CREATED", "SENDING", "SENT"].includes(transfer.status);
|
|
2006
|
+
}
|
|
2007
|
+
function resolvePhase(state) {
|
|
2008
|
+
const p = state.phase;
|
|
2009
|
+
if (p.step === "select-source" && state.transfer?.status === "COMPLETED" && state.guestPreauthorizing) {
|
|
2010
|
+
return p;
|
|
2011
|
+
}
|
|
2012
|
+
if (state.transfer?.status === "COMPLETED" && state.guestPreauthorizing) {
|
|
2013
|
+
return { step: "processing", transfer: state.transfer };
|
|
2014
|
+
}
|
|
2015
|
+
if (state.transfer?.status === "COMPLETED") {
|
|
2016
|
+
return { step: "completed", transfer: state.transfer };
|
|
2017
|
+
}
|
|
2018
|
+
if (state.transfer?.status === "FAILED") {
|
|
2019
|
+
return { step: "failed", transfer: state.transfer, error: state.error ?? "Transfer failed." };
|
|
2020
|
+
}
|
|
2021
|
+
if (state.creatingTransfer || isTransferInFlight(state.transfer)) {
|
|
2022
|
+
return { step: "processing", transfer: state.transfer };
|
|
2023
|
+
}
|
|
2024
|
+
if (p.step === "token-picker" || p.step === "one-tap-setup" || p.step === "select-source" || p.step === "confirm-sign" || p.step === "guest-token-picker") {
|
|
2025
|
+
return p;
|
|
2026
|
+
}
|
|
2027
|
+
if (p.step === "wallet-setup") return p;
|
|
2028
|
+
if (state.mobileFlow && state.deeplinkUri) {
|
|
2029
|
+
return {
|
|
2030
|
+
step: "wallet-setup",
|
|
2031
|
+
mobile: { deeplinkUri: state.deeplinkUri, providerId: state.selectedProviderId },
|
|
2032
|
+
accountId: null
|
|
2033
|
+
};
|
|
2034
|
+
}
|
|
2035
|
+
if (!state.activeCredentialId && !state.passkeyConfigLoaded) {
|
|
2036
|
+
return { step: "initializing" };
|
|
2037
|
+
}
|
|
2038
|
+
if (state.verificationTarget) {
|
|
2039
|
+
return { step: "otp-verify", target: state.verificationTarget };
|
|
2040
|
+
}
|
|
2041
|
+
if (state.loginRequested) {
|
|
2042
|
+
return { step: "login" };
|
|
2043
|
+
}
|
|
2044
|
+
if (state.passkeyConfigLoaded && !state.activeCredentialId) {
|
|
2045
|
+
if (state.knownCredentialIds.length > 0 && state.passkeyPopupNeeded) {
|
|
2046
|
+
return { step: "passkey-verify" };
|
|
2047
|
+
}
|
|
2048
|
+
return { step: "passkey-create", popupFallback: state.passkeyPopupNeeded };
|
|
2049
|
+
}
|
|
2050
|
+
if (state.loadingData && state.activeCredentialId && hasActiveWallet(state.accounts)) {
|
|
2051
|
+
return { step: "data-loading" };
|
|
2052
|
+
}
|
|
2053
|
+
if (state.isGuestFlow && state.selectedProviderId != null && !state.transfer) {
|
|
2054
|
+
return { step: "guest-token-picker" };
|
|
2055
|
+
}
|
|
2056
|
+
if (state.activeCredentialId && !hasActiveWallet(state.accounts) && !state.mobileFlow) {
|
|
2057
|
+
return { step: "wallet-picker", reason: "link" };
|
|
2058
|
+
}
|
|
2059
|
+
if (state.activeCredentialId && hasActiveWallet(state.accounts) && !state.loadingData) {
|
|
2060
|
+
return { step: "deposit" };
|
|
2061
|
+
}
|
|
2062
|
+
if (state.isGuestFlow) {
|
|
2063
|
+
return { step: "wallet-picker", reason: "guest-entry" };
|
|
2064
|
+
}
|
|
2065
|
+
return { step: "wallet-picker", reason: "entry" };
|
|
2066
|
+
}
|
|
2067
|
+
|
|
1940
2068
|
// src/paymentReducer.ts
|
|
1941
2069
|
function deriveSourceTypeAndId(state) {
|
|
1942
2070
|
if (state.selectedWalletId) {
|
|
@@ -1949,6 +2077,7 @@ function deriveSourceTypeAndId(state) {
|
|
|
1949
2077
|
}
|
|
1950
2078
|
function createInitialState(config) {
|
|
1951
2079
|
return {
|
|
2080
|
+
phase: { step: "initializing" },
|
|
1952
2081
|
error: null,
|
|
1953
2082
|
providers: [],
|
|
1954
2083
|
accounts: [],
|
|
@@ -1969,6 +2098,7 @@ function createInitialState(config) {
|
|
|
1969
2098
|
knownCredentialIds: [],
|
|
1970
2099
|
verificationTarget: null,
|
|
1971
2100
|
oneTapLimit: 100,
|
|
2101
|
+
oneTapLimitSavedDuringSetup: false,
|
|
1972
2102
|
mobileFlow: false,
|
|
1973
2103
|
deeplinkUri: null,
|
|
1974
2104
|
increasingLimit: false,
|
|
@@ -1976,12 +2106,17 @@ function createInitialState(config) {
|
|
|
1976
2106
|
guestTransferId: null,
|
|
1977
2107
|
guestSessionToken: null,
|
|
1978
2108
|
guestPreauthAccountId: null,
|
|
2109
|
+
guestPreauthSessionId: null,
|
|
1979
2110
|
activePublicKey: null,
|
|
1980
|
-
|
|
1981
|
-
|
|
2111
|
+
loginRequested: false,
|
|
2112
|
+
guestPreauthorizing: false
|
|
1982
2113
|
};
|
|
1983
2114
|
}
|
|
1984
2115
|
function paymentReducer(state, action) {
|
|
2116
|
+
const next = applyAction(state, action);
|
|
2117
|
+
return { ...next, phase: resolvePhase(next) };
|
|
2118
|
+
}
|
|
2119
|
+
function applyAction(state, action) {
|
|
1985
2120
|
switch (action.type) {
|
|
1986
2121
|
// ── Auth ──────────────────────────────────────────────────────
|
|
1987
2122
|
case "CODE_SENT":
|
|
@@ -2059,23 +2194,20 @@ function paymentReducer(state, action) {
|
|
|
2059
2194
|
selectedProviderId: action.providerId,
|
|
2060
2195
|
selectedAccountId: null,
|
|
2061
2196
|
selectedWalletId: null,
|
|
2062
|
-
selectedTokenSymbol: null
|
|
2063
|
-
userIntent: null
|
|
2197
|
+
selectedTokenSymbol: null
|
|
2064
2198
|
};
|
|
2065
2199
|
case "SELECT_ACCOUNT":
|
|
2066
2200
|
return {
|
|
2067
2201
|
...state,
|
|
2068
2202
|
selectedAccountId: action.accountId,
|
|
2069
2203
|
selectedWalletId: action.walletId,
|
|
2070
|
-
selectedTokenSymbol: null
|
|
2071
|
-
userIntent: null
|
|
2204
|
+
selectedTokenSymbol: null
|
|
2072
2205
|
};
|
|
2073
2206
|
case "SELECT_TOKEN":
|
|
2074
2207
|
return {
|
|
2075
2208
|
...state,
|
|
2076
2209
|
selectedWalletId: action.walletId,
|
|
2077
|
-
selectedTokenSymbol: action.tokenSymbol
|
|
2078
|
-
userIntent: null
|
|
2210
|
+
selectedTokenSymbol: action.tokenSymbol
|
|
2079
2211
|
};
|
|
2080
2212
|
// ── Transfer lifecycle ───────────────────────────────────────
|
|
2081
2213
|
case "PAY_STARTED":
|
|
@@ -2084,8 +2216,7 @@ function paymentReducer(state, action) {
|
|
|
2084
2216
|
error: null,
|
|
2085
2217
|
creatingTransfer: true,
|
|
2086
2218
|
deeplinkUri: null,
|
|
2087
|
-
mobileFlow: false
|
|
2088
|
-
userIntent: null
|
|
2219
|
+
mobileFlow: false
|
|
2089
2220
|
};
|
|
2090
2221
|
case "PAY_ENDED":
|
|
2091
2222
|
return { ...state, creatingTransfer: false };
|
|
@@ -2149,7 +2280,8 @@ function paymentReducer(state, action) {
|
|
|
2149
2280
|
transfer: action.transfer,
|
|
2150
2281
|
error: null,
|
|
2151
2282
|
mobileFlow: false,
|
|
2152
|
-
deeplinkUri: null
|
|
2283
|
+
deeplinkUri: null,
|
|
2284
|
+
phase: { step: "confirm-sign", transfer: action.transfer }
|
|
2153
2285
|
};
|
|
2154
2286
|
case "CLEAR_MOBILE_STATE":
|
|
2155
2287
|
return { ...state, mobileFlow: false, deeplinkUri: null };
|
|
@@ -2219,29 +2351,37 @@ function paymentReducer(state, action) {
|
|
|
2219
2351
|
case "GUEST_PREAUTH_DETECTED":
|
|
2220
2352
|
return {
|
|
2221
2353
|
...state,
|
|
2222
|
-
guestPreauthAccountId: action.accountId
|
|
2354
|
+
guestPreauthAccountId: action.accountId,
|
|
2355
|
+
guestPreauthSessionId: action.sessionId ?? state.guestPreauthSessionId
|
|
2223
2356
|
};
|
|
2357
|
+
case "GUEST_PREAUTH_BEGIN":
|
|
2358
|
+
return { ...state, guestPreauthorizing: true, error: null };
|
|
2359
|
+
case "GUEST_PREAUTH_END":
|
|
2360
|
+
return { ...state, guestPreauthorizing: false };
|
|
2224
2361
|
case "ACCOUNT_OWNER_SET":
|
|
2225
2362
|
return {
|
|
2226
2363
|
...state,
|
|
2227
2364
|
guestPreauthAccountId: null,
|
|
2365
|
+
guestPreauthSessionId: null,
|
|
2228
2366
|
activePublicKey: null,
|
|
2229
2367
|
error: null,
|
|
2230
|
-
|
|
2368
|
+
guestPreauthorizing: false,
|
|
2369
|
+
phase: { step: "one-tap-setup", action: null }
|
|
2231
2370
|
};
|
|
2232
2371
|
// ── User intent & error ──────────────────────────────────────
|
|
2233
2372
|
case "SET_USER_INTENT":
|
|
2234
|
-
return { ...state,
|
|
2373
|
+
return { ...state, phase: action.intent };
|
|
2235
2374
|
case "REQUEST_LOGIN":
|
|
2236
2375
|
return {
|
|
2237
2376
|
...state,
|
|
2238
2377
|
loginRequested: true,
|
|
2239
2378
|
transfer: null,
|
|
2240
|
-
isGuestFlow: false,
|
|
2241
2379
|
creatingTransfer: false
|
|
2242
2380
|
};
|
|
2243
2381
|
case "SET_ERROR":
|
|
2244
2382
|
return { ...state, error: action.error };
|
|
2383
|
+
case "SET_ONE_TAP_LIMIT_SAVED_DURING_SETUP":
|
|
2384
|
+
return { ...state, oneTapLimitSavedDuringSetup: action.saved };
|
|
2245
2385
|
// ── Lifecycle ────────────────────────────────────────────────
|
|
2246
2386
|
case "NEW_PAYMENT":
|
|
2247
2387
|
return {
|
|
@@ -2258,9 +2398,11 @@ function paymentReducer(state, action) {
|
|
|
2258
2398
|
guestTransferId: null,
|
|
2259
2399
|
guestSessionToken: null,
|
|
2260
2400
|
guestPreauthAccountId: null,
|
|
2401
|
+
guestPreauthSessionId: null,
|
|
2261
2402
|
activePublicKey: null,
|
|
2262
|
-
|
|
2263
|
-
|
|
2403
|
+
loginRequested: false,
|
|
2404
|
+
oneTapLimitSavedDuringSetup: false,
|
|
2405
|
+
guestPreauthorizing: false
|
|
2264
2406
|
};
|
|
2265
2407
|
case "LOGOUT":
|
|
2266
2408
|
return {
|
|
@@ -2317,97 +2459,43 @@ function maskAuthIdentifier(identifier) {
|
|
|
2317
2459
|
return `***-***-${visibleSuffix}`;
|
|
2318
2460
|
}
|
|
2319
2461
|
|
|
2320
|
-
// src/walletFlow.ts
|
|
2321
|
-
var MOBILE_USER_AGENT_PATTERN = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i;
|
|
2322
|
-
function isMobileUserAgent(userAgent) {
|
|
2323
|
-
if (!userAgent) {
|
|
2324
|
-
return false;
|
|
2325
|
-
}
|
|
2326
|
-
return MOBILE_USER_AGENT_PATTERN.test(userAgent);
|
|
2327
|
-
}
|
|
2328
|
-
function shouldUseWalletConnector(options) {
|
|
2329
|
-
return options.useWalletConnector ?? !isMobileUserAgent(options.userAgent);
|
|
2330
|
-
}
|
|
2331
|
-
|
|
2332
2462
|
// src/resolveScreen.ts
|
|
2333
|
-
function
|
|
2334
|
-
|
|
2335
|
-
|
|
2336
|
-
|
|
2337
|
-
|
|
2338
|
-
|
|
2339
|
-
|
|
2340
|
-
|
|
2341
|
-
|
|
2342
|
-
|
|
2343
|
-
|
|
2344
|
-
|
|
2345
|
-
|
|
2346
|
-
|
|
2347
|
-
|
|
2348
|
-
|
|
2349
|
-
|
|
2350
|
-
|
|
2351
|
-
|
|
2352
|
-
|
|
2353
|
-
|
|
2354
|
-
|
|
2355
|
-
|
|
2356
|
-
|
|
2357
|
-
|
|
2358
|
-
|
|
2359
|
-
|
|
2360
|
-
|
|
2361
|
-
|
|
2362
|
-
|
|
2363
|
-
|
|
2364
|
-
|
|
2365
|
-
|
|
2366
|
-
|
|
2367
|
-
|
|
2368
|
-
if (isTransferTerminal(state.transfer)) {
|
|
2369
|
-
return "success";
|
|
2370
|
-
}
|
|
2371
|
-
if (state.creatingTransfer || state.transfer != null && isTransferInFlight(state.transfer)) {
|
|
2372
|
-
return "processing";
|
|
2373
|
-
}
|
|
2374
|
-
if (state.transfer?.status === "AUTHORIZED" && !state.isDesktop && !isSetupTransfer(state.transfer)) {
|
|
2375
|
-
return "confirm-sign";
|
|
2376
|
-
}
|
|
2377
|
-
if (state.pendingSelectSource != null) {
|
|
2378
|
-
return state.isDesktop ? "setup" : "select-source";
|
|
2379
|
-
}
|
|
2380
|
-
if (state.pendingOneTapSetup != null && !state.oneTapLimitAlreadySaved) {
|
|
2381
|
-
return "setup";
|
|
2382
|
-
}
|
|
2383
|
-
if (state.mobileFlow || state.inlineAuthorizationExecuting) {
|
|
2384
|
-
return state.isDesktop ? "setup-status" : "open-wallet";
|
|
2385
|
-
}
|
|
2386
|
-
if (state.isGuestFlow && state.selectedProviderId != null && !state.transfer && !state.guestSettingSender) {
|
|
2387
|
-
return "guest-token-picker";
|
|
2388
|
-
}
|
|
2389
|
-
if (state.activeCredentialId && !hasActiveWallet(state.accounts) && !state.mobileFlow || !state.authenticated && !state.isReturningUser && !state.isGuestFlow) {
|
|
2390
|
-
return "wallet-picker";
|
|
2391
|
-
}
|
|
2392
|
-
if (state.loadingData && state.activeCredentialId != null && hasActiveWallet(state.accounts)) {
|
|
2393
|
-
return "loading";
|
|
2394
|
-
}
|
|
2395
|
-
if (state.userIntent === "pick-token" && state.selectedAccount != null) {
|
|
2396
|
-
return "token-picker";
|
|
2397
|
-
}
|
|
2398
|
-
if (state.userIntent === "configure-one-tap") {
|
|
2399
|
-
return "setup";
|
|
2400
|
-
}
|
|
2401
|
-
if (state.userIntent === "switch-wallet") {
|
|
2402
|
-
return "wallet-picker";
|
|
2403
|
-
}
|
|
2404
|
-
if (state.activeCredentialId != null && hasActiveWallet(state.accounts) && !state.loadingData) {
|
|
2405
|
-
return "deposit";
|
|
2406
|
-
}
|
|
2407
|
-
if (state.isGuestFlow) {
|
|
2408
|
-
return "wallet-picker";
|
|
2463
|
+
function screenForPhase(phase) {
|
|
2464
|
+
switch (phase.step) {
|
|
2465
|
+
case "initializing":
|
|
2466
|
+
case "data-loading":
|
|
2467
|
+
return "loading";
|
|
2468
|
+
case "login":
|
|
2469
|
+
return "login";
|
|
2470
|
+
case "otp-verify":
|
|
2471
|
+
return "otp-verify";
|
|
2472
|
+
case "passkey-create":
|
|
2473
|
+
return "create-passkey";
|
|
2474
|
+
case "passkey-verify":
|
|
2475
|
+
return "verify-passkey";
|
|
2476
|
+
case "wallet-picker":
|
|
2477
|
+
return "wallet-picker";
|
|
2478
|
+
case "wallet-setup":
|
|
2479
|
+
return phase.mobile ? "open-wallet" : "setup-status";
|
|
2480
|
+
case "select-source":
|
|
2481
|
+
if (phase.skipOneTapLimit) return "select-source";
|
|
2482
|
+
return phase.isDesktop ? "setup" : "select-source";
|
|
2483
|
+
case "one-tap-setup":
|
|
2484
|
+
return "setup";
|
|
2485
|
+
case "guest-token-picker":
|
|
2486
|
+
return "guest-token-picker";
|
|
2487
|
+
case "token-picker":
|
|
2488
|
+
return "token-picker";
|
|
2489
|
+
case "deposit":
|
|
2490
|
+
return "deposit";
|
|
2491
|
+
case "processing":
|
|
2492
|
+
return "processing";
|
|
2493
|
+
case "confirm-sign":
|
|
2494
|
+
return "confirm-sign";
|
|
2495
|
+
case "completed":
|
|
2496
|
+
case "failed":
|
|
2497
|
+
return "success";
|
|
2409
2498
|
}
|
|
2410
|
-
return "wallet-picker";
|
|
2411
2499
|
}
|
|
2412
2500
|
var MUTED = "#7fa4b0";
|
|
2413
2501
|
var LOGO_SIZE = 48;
|
|
@@ -5890,85 +5978,66 @@ var DEPOSIT_SCREENS = /* @__PURE__ */ new Set([
|
|
|
5890
5978
|
"processing",
|
|
5891
5979
|
"success"
|
|
5892
5980
|
]);
|
|
5893
|
-
function getFlowPhase(screen,
|
|
5981
|
+
function getFlowPhase(screen, phase) {
|
|
5894
5982
|
if (LINK_SCREENS.has(screen)) return "link";
|
|
5895
5983
|
if (DEPOSIT_SCREENS.has(screen)) return "deposit";
|
|
5896
5984
|
if (screen === "token-picker" || screen === "select-source" || screen === "guest-token-picker") {
|
|
5897
|
-
return
|
|
5985
|
+
return phase.step === "one-tap-setup" ? "link" : "deposit";
|
|
5898
5986
|
}
|
|
5899
5987
|
return null;
|
|
5900
5988
|
}
|
|
5901
5989
|
function StepRenderer(props) {
|
|
5902
|
-
const
|
|
5903
|
-
|
|
5904
|
-
});
|
|
5905
|
-
const isReturningUser = props.state.activeCredentialId != null || typeof window !== "undefined" && window.localStorage.getItem("blink_active_credential") != null;
|
|
5906
|
-
const screenState = {
|
|
5907
|
-
privyReady: props.ready,
|
|
5908
|
-
authenticated: props.authenticated,
|
|
5909
|
-
verificationTarget: props.state.verificationTarget,
|
|
5910
|
-
activeCredentialId: props.state.activeCredentialId,
|
|
5911
|
-
knownCredentialIds: props.state.knownCredentialIds,
|
|
5912
|
-
passkeyConfigLoaded: props.state.passkeyConfigLoaded,
|
|
5913
|
-
passkeyPopupNeeded: props.state.passkeyPopupNeeded,
|
|
5914
|
-
accounts: props.state.accounts,
|
|
5915
|
-
isGuestFlow: props.state.isGuestFlow,
|
|
5916
|
-
selectedProviderId: props.state.selectedProviderId,
|
|
5917
|
-
mobileFlow: props.state.mobileFlow,
|
|
5918
|
-
inlineAuthorizationExecuting: props.inlineAuthorizationExecuting,
|
|
5919
|
-
creatingTransfer: props.state.creatingTransfer,
|
|
5920
|
-
transfer: props.state.transfer,
|
|
5921
|
-
pendingSelectSource: props.pendingSelectSource,
|
|
5922
|
-
pendingOneTapSetup: props.pendingOneTapSetup,
|
|
5923
|
-
oneTapLimitAlreadySaved: props.oneTapLimitAlreadySaved,
|
|
5924
|
-
loadingData: props.state.loadingData,
|
|
5925
|
-
isDesktop,
|
|
5926
|
-
isReturningUser,
|
|
5927
|
-
guestPreauthRedirect: props.state.guestPreauthAccountId != null,
|
|
5928
|
-
loginRequested: props.state.loginRequested,
|
|
5929
|
-
userIntent: props.state.userIntent,
|
|
5930
|
-
selectedAccount: props.selectedAccount,
|
|
5931
|
-
guestSettingSender: props.guestSettingSender
|
|
5932
|
-
};
|
|
5933
|
-
const screen = resolveScreen(screenState);
|
|
5934
|
-
const phase = getFlowPhase(screen, props.state.userIntent);
|
|
5935
|
-
return /* @__PURE__ */ jsxRuntime.jsx(FlowPhaseProvider, { phase, children: /* @__PURE__ */ jsxRuntime.jsx(StepRendererContent, { ...props, screen, isDesktop }) });
|
|
5990
|
+
const screen = screenForPhase(props.flow.state.phase);
|
|
5991
|
+
const flowPhase = getFlowPhase(screen, props.flow.state.phase);
|
|
5992
|
+
return /* @__PURE__ */ jsxRuntime.jsx(FlowPhaseProvider, { phase: flowPhase, children: /* @__PURE__ */ jsxRuntime.jsx(StepRendererContent, { ...props, screen }) });
|
|
5936
5993
|
}
|
|
5937
5994
|
function StepRendererContent({
|
|
5938
|
-
|
|
5939
|
-
|
|
5940
|
-
|
|
5941
|
-
|
|
5942
|
-
pollingError,
|
|
5943
|
-
authExecutorError,
|
|
5944
|
-
transferSigningSigning,
|
|
5945
|
-
transferSigningError,
|
|
5946
|
-
pendingConnections,
|
|
5947
|
-
depositEligibleAccounts,
|
|
5948
|
-
sourceName,
|
|
5949
|
-
maxSourceBalance,
|
|
5950
|
-
tokenCount,
|
|
5951
|
-
selectedAccount,
|
|
5952
|
-
selectedSource,
|
|
5953
|
-
selectSourceChoices,
|
|
5954
|
-
selectSourceRecommended,
|
|
5955
|
-
selectSourceAvailableBalance,
|
|
5956
|
-
guestTokenEntries,
|
|
5957
|
-
guestLoadingBalances,
|
|
5958
|
-
guestSettingSender,
|
|
5959
|
-
authInput,
|
|
5960
|
-
otpCode,
|
|
5961
|
-
selectSourceChainName,
|
|
5962
|
-
selectSourceTokenSymbol,
|
|
5963
|
-
savingOneTapLimit,
|
|
5964
|
-
merchantName,
|
|
5965
|
-
onBack,
|
|
5966
|
-
onDismiss,
|
|
5967
|
-
depositAmount,
|
|
5995
|
+
flow,
|
|
5996
|
+
remote,
|
|
5997
|
+
derived,
|
|
5998
|
+
forms,
|
|
5968
5999
|
handlers,
|
|
5969
|
-
screen
|
|
5970
|
-
isDesktop
|
|
6000
|
+
screen
|
|
5971
6001
|
}) {
|
|
6002
|
+
const {
|
|
6003
|
+
state,
|
|
6004
|
+
authenticated,
|
|
6005
|
+
activeOtpStatus,
|
|
6006
|
+
isDesktop,
|
|
6007
|
+
merchantName,
|
|
6008
|
+
onBack,
|
|
6009
|
+
onDismiss,
|
|
6010
|
+
depositAmount
|
|
6011
|
+
} = flow;
|
|
6012
|
+
const {
|
|
6013
|
+
pollingTransfer,
|
|
6014
|
+
pollingError,
|
|
6015
|
+
authExecutorError,
|
|
6016
|
+
transferSigningSigning,
|
|
6017
|
+
transferSigningError
|
|
6018
|
+
} = remote;
|
|
6019
|
+
const {
|
|
6020
|
+
pendingConnections,
|
|
6021
|
+
depositEligibleAccounts,
|
|
6022
|
+
sourceName,
|
|
6023
|
+
maxSourceBalance,
|
|
6024
|
+
tokenCount,
|
|
6025
|
+
selectedAccount,
|
|
6026
|
+
selectedSource,
|
|
6027
|
+
selectSourceChoices,
|
|
6028
|
+
selectSourceRecommended,
|
|
6029
|
+
selectSourceAvailableBalance
|
|
6030
|
+
} = derived;
|
|
6031
|
+
const {
|
|
6032
|
+
guestTokenEntries,
|
|
6033
|
+
guestLoadingBalances,
|
|
6034
|
+
guestSettingSender,
|
|
6035
|
+
authInput,
|
|
6036
|
+
otpCode,
|
|
6037
|
+
selectSourceChainName,
|
|
6038
|
+
selectSourceTokenSymbol,
|
|
6039
|
+
savingOneTapLimit
|
|
6040
|
+
} = forms;
|
|
5972
6041
|
const selectedWallet = selectedAccount?.wallets.find((w) => w.id === state.selectedWalletId);
|
|
5973
6042
|
const selectedSourceLabel = selectedSource && selectedWallet ? `${selectedSource.token.symbol} on ${selectedWallet.chain.name}` : void 0;
|
|
5974
6043
|
switch (screen) {
|
|
@@ -6041,7 +6110,7 @@ function StepRendererContent({
|
|
|
6041
6110
|
onPrepareProvider: handlers.onPrepareProvider,
|
|
6042
6111
|
onSelectProvider: handlers.onSelectProvider,
|
|
6043
6112
|
onContinueConnection: handlers.onContinueConnection,
|
|
6044
|
-
onBack: isEntryPoint ? onBack : () => handlers.
|
|
6113
|
+
onBack: isEntryPoint ? onBack : () => handlers.onSetPhase({ step: "deposit" }),
|
|
6045
6114
|
onLogout: authenticated ? handlers.onLogout : void 0,
|
|
6046
6115
|
onLogin: handlers.onLogin,
|
|
6047
6116
|
showLoginOption: isEntryPoint
|
|
@@ -6072,7 +6141,7 @@ function StepRendererContent({
|
|
|
6072
6141
|
limit: state.oneTapLimit,
|
|
6073
6142
|
tokensApproved: 0,
|
|
6074
6143
|
merchantName,
|
|
6075
|
-
onContinue: () => handlers.
|
|
6144
|
+
onContinue: () => handlers.onSetPhase({ step: "one-tap-setup", action: null }),
|
|
6076
6145
|
onLogout: handlers.onLogout,
|
|
6077
6146
|
error: state.error || authExecutorError
|
|
6078
6147
|
}
|
|
@@ -6091,7 +6160,7 @@ function StepRendererContent({
|
|
|
6091
6160
|
tokenCount: effectiveTokenCount,
|
|
6092
6161
|
sourceName,
|
|
6093
6162
|
onSetupOneTap: handlers.onSetupOneTap,
|
|
6094
|
-
onBack: () => handlers.
|
|
6163
|
+
onBack: () => handlers.onSetPhase({ step: "deposit" }),
|
|
6095
6164
|
onLogout: handlers.onLogout,
|
|
6096
6165
|
onAdvanced: handlers.onSelectToken,
|
|
6097
6166
|
selectedSourceLabel: effectiveSourceLabel,
|
|
@@ -6127,7 +6196,7 @@ function StepRendererContent({
|
|
|
6127
6196
|
processing: state.creatingTransfer,
|
|
6128
6197
|
error: state.error,
|
|
6129
6198
|
onDeposit: handlers.onPay,
|
|
6130
|
-
onSwitchWallet: () => handlers.
|
|
6199
|
+
onSwitchWallet: () => handlers.onSetPhase({ step: "wallet-picker", reason: "switch" }),
|
|
6131
6200
|
onBack: onBack ?? (() => handlers.onLogout()),
|
|
6132
6201
|
onLogout: handlers.onLogout,
|
|
6133
6202
|
onIncreaseLimit: handlers.onIncreaseLimit,
|
|
@@ -6136,7 +6205,7 @@ function StepRendererContent({
|
|
|
6136
6205
|
selectedAccountId: state.selectedAccountId,
|
|
6137
6206
|
onSelectAccount: handlers.onSelectAccount,
|
|
6138
6207
|
onAuthorizeAccount: handlers.onContinueConnection,
|
|
6139
|
-
onAddProvider: () => handlers.
|
|
6208
|
+
onAddProvider: () => handlers.onSetPhase({ step: "wallet-picker", reason: "switch" }),
|
|
6140
6209
|
onSelectToken: handlers.onSelectToken,
|
|
6141
6210
|
selectedSourceLabel,
|
|
6142
6211
|
selectedTokenSymbol: selectedSource?.token.symbol
|
|
@@ -6154,7 +6223,7 @@ function StepRendererContent({
|
|
|
6154
6223
|
chains: state.chains,
|
|
6155
6224
|
onSelectAuthorized: handlers.onSelectAuthorizedToken,
|
|
6156
6225
|
onAuthorizeToken: handlers.onAuthorizeToken,
|
|
6157
|
-
onBack: () => handlers.
|
|
6226
|
+
onBack: () => handlers.onSetPhase({ step: "deposit" }),
|
|
6158
6227
|
onLogout: handlers.onLogout,
|
|
6159
6228
|
depositAmount: depositAmount ?? void 0,
|
|
6160
6229
|
selectedTokenSymbol: selectedSource?.token.symbol,
|
|
@@ -6172,7 +6241,7 @@ function StepRendererContent({
|
|
|
6172
6241
|
depositAmount: depositAmount ?? void 0,
|
|
6173
6242
|
error: state.error,
|
|
6174
6243
|
onSelect: handlers.onSelectGuestToken,
|
|
6175
|
-
onBack: () => handlers.
|
|
6244
|
+
onBack: () => handlers.onSetPhase({ step: "wallet-picker", reason: "guest-entry" })
|
|
6176
6245
|
}
|
|
6177
6246
|
);
|
|
6178
6247
|
case "processing": {
|
|
@@ -6311,56 +6380,41 @@ var buttonStyle3 = {
|
|
|
6311
6380
|
fontFamily: "inherit",
|
|
6312
6381
|
cursor: "pointer"
|
|
6313
6382
|
};
|
|
6314
|
-
function
|
|
6383
|
+
function selectedSourceForWallet(selectedWallet, selectedTokenSymbol) {
|
|
6384
|
+
if (!selectedWallet) return null;
|
|
6385
|
+
if (selectedTokenSymbol) {
|
|
6386
|
+
return selectedWallet.sources.find((s) => s.token.symbol === selectedTokenSymbol) ?? null;
|
|
6387
|
+
}
|
|
6388
|
+
return selectedWallet.sources.find((s) => s.token.status === "AUTHORIZED") ?? selectedWallet.sources[0] ?? null;
|
|
6389
|
+
}
|
|
6390
|
+
function computeDerivedState(state) {
|
|
6315
6391
|
const { sourceType, sourceId } = deriveSourceTypeAndId(state);
|
|
6316
6392
|
const selectedAccount = state.accounts.find((a) => a.id === state.selectedAccountId);
|
|
6317
6393
|
const selectedWallet = selectedAccount?.wallets.find(
|
|
6318
6394
|
(w) => w.id === state.selectedWalletId
|
|
6319
6395
|
);
|
|
6320
|
-
const selectedSource =
|
|
6321
|
-
if (!selectedWallet) return null;
|
|
6322
|
-
if (state.selectedTokenSymbol) {
|
|
6323
|
-
return selectedWallet.sources.find(
|
|
6324
|
-
(s) => s.token.symbol === state.selectedTokenSymbol
|
|
6325
|
-
) ?? null;
|
|
6326
|
-
}
|
|
6327
|
-
return selectedWallet.sources.find((s) => s.token.status === "AUTHORIZED") ?? selectedWallet.sources[0] ?? null;
|
|
6328
|
-
}, [selectedWallet, state.selectedTokenSymbol]);
|
|
6396
|
+
const selectedSource = selectedSourceForWallet(selectedWallet, state.selectedTokenSymbol);
|
|
6329
6397
|
const sourceName = selectedAccount?.name ?? selectedWallet?.chain.name ?? "Wallet";
|
|
6330
|
-
const pendingConnections =
|
|
6331
|
-
() =>
|
|
6332
|
-
(a) => a.wallets.length > 0 && !a.wallets.some((w) => w.status === "ACTIVE")
|
|
6333
|
-
),
|
|
6334
|
-
[state.accounts]
|
|
6398
|
+
const pendingConnections = state.accounts.filter(
|
|
6399
|
+
(a) => a.wallets.length > 0 && !a.wallets.some((w) => w.status === "ACTIVE")
|
|
6335
6400
|
);
|
|
6336
|
-
const depositEligibleAccounts =
|
|
6337
|
-
|
|
6338
|
-
|
|
6339
|
-
|
|
6340
|
-
|
|
6341
|
-
|
|
6342
|
-
|
|
6343
|
-
for (const wallet of acct.wallets) {
|
|
6344
|
-
for (const source of wallet.sources) {
|
|
6345
|
-
if (source.balance.available.amount > max) {
|
|
6346
|
-
max = source.balance.available.amount;
|
|
6347
|
-
}
|
|
6401
|
+
const depositEligibleAccounts = getDepositEligibleAccounts(state.accounts);
|
|
6402
|
+
let maxSourceBalance = 0;
|
|
6403
|
+
for (const acct of state.accounts) {
|
|
6404
|
+
for (const wallet of acct.wallets) {
|
|
6405
|
+
for (const source of wallet.sources) {
|
|
6406
|
+
if (source.balance.available.amount > maxSourceBalance) {
|
|
6407
|
+
maxSourceBalance = source.balance.available.amount;
|
|
6348
6408
|
}
|
|
6349
6409
|
}
|
|
6350
6410
|
}
|
|
6351
|
-
|
|
6352
|
-
|
|
6353
|
-
const
|
|
6354
|
-
|
|
6355
|
-
|
|
6356
|
-
for (const wallet of acct.wallets) {
|
|
6357
|
-
count += wallet.sources.filter(
|
|
6358
|
-
(s) => s.balance.available.amount > 0
|
|
6359
|
-
).length;
|
|
6360
|
-
}
|
|
6411
|
+
}
|
|
6412
|
+
let tokenCount = 0;
|
|
6413
|
+
for (const acct of state.accounts) {
|
|
6414
|
+
for (const wallet of acct.wallets) {
|
|
6415
|
+
tokenCount += wallet.sources.filter((s) => s.balance.available.amount > 0).length;
|
|
6361
6416
|
}
|
|
6362
|
-
|
|
6363
|
-
}, [state.accounts]);
|
|
6417
|
+
}
|
|
6364
6418
|
return {
|
|
6365
6419
|
sourceType,
|
|
6366
6420
|
sourceId,
|
|
@@ -6374,6 +6428,9 @@ function useDerivedState(state) {
|
|
|
6374
6428
|
tokenCount
|
|
6375
6429
|
};
|
|
6376
6430
|
}
|
|
6431
|
+
function useDerivedState(state) {
|
|
6432
|
+
return react.useMemo(() => computeDerivedState(state), [state]);
|
|
6433
|
+
}
|
|
6377
6434
|
function useAuthHandlers(dispatch, verificationTarget) {
|
|
6378
6435
|
const {
|
|
6379
6436
|
sendCode: sendEmailCode,
|
|
@@ -6939,7 +6996,9 @@ function useProviderHandlers(deps) {
|
|
|
6939
6996
|
reauthTokenRef,
|
|
6940
6997
|
authenticated,
|
|
6941
6998
|
merchantAuthorization,
|
|
6942
|
-
destination
|
|
6999
|
+
destination,
|
|
7000
|
+
guestSessionToken,
|
|
7001
|
+
selectedProviderId
|
|
6943
7002
|
} = deps;
|
|
6944
7003
|
const wagmiConfig2 = wagmi.useConfig();
|
|
6945
7004
|
const { connectAsync, connectors } = wagmi.useConnect();
|
|
@@ -7252,7 +7311,7 @@ function useProviderHandlers(deps) {
|
|
|
7252
7311
|
reauthTokenRef
|
|
7253
7312
|
]);
|
|
7254
7313
|
const handleNavigateToTokenPicker = react.useCallback(() => {
|
|
7255
|
-
dispatch({ type: "SET_USER_INTENT", intent: "
|
|
7314
|
+
dispatch({ type: "SET_USER_INTENT", intent: { step: "token-picker" } });
|
|
7256
7315
|
}, [dispatch]);
|
|
7257
7316
|
const handleSelectAuthorizedToken = react.useCallback((walletId, tokenSymbol) => {
|
|
7258
7317
|
dispatch({ type: "SELECT_TOKEN", walletId, tokenSymbol });
|
|
@@ -7335,6 +7394,76 @@ function useProviderHandlers(deps) {
|
|
|
7335
7394
|
reauthSessionIdRef,
|
|
7336
7395
|
reauthTokenRef
|
|
7337
7396
|
]);
|
|
7397
|
+
const handlePreauthorize = react.useCallback(async () => {
|
|
7398
|
+
if (!guestSessionToken || !selectedProviderId) {
|
|
7399
|
+
dispatch({
|
|
7400
|
+
type: "SET_ERROR",
|
|
7401
|
+
error: "Missing guest session or wallet provider. Try again from the payment screen."
|
|
7402
|
+
});
|
|
7403
|
+
return;
|
|
7404
|
+
}
|
|
7405
|
+
const isMobile = !shouldUseWalletConnector({
|
|
7406
|
+
useWalletConnector: useWalletConnectorProp,
|
|
7407
|
+
userAgent: typeof navigator === "undefined" ? void 0 : navigator.userAgent
|
|
7408
|
+
});
|
|
7409
|
+
const providerName = providers.find((p) => p.id === selectedProviderId)?.name ?? "Wallet";
|
|
7410
|
+
if (!isMobile) {
|
|
7411
|
+
dispatch({ type: "GUEST_PREAUTH_BEGIN" });
|
|
7412
|
+
}
|
|
7413
|
+
try {
|
|
7414
|
+
const created = await createGuestAccount(
|
|
7415
|
+
apiBaseUrl,
|
|
7416
|
+
guestSessionToken,
|
|
7417
|
+
selectedProviderId,
|
|
7418
|
+
providerName
|
|
7419
|
+
);
|
|
7420
|
+
const session = await fetchAuthorizationSessionByToken(
|
|
7421
|
+
apiBaseUrl,
|
|
7422
|
+
created.sessionToken
|
|
7423
|
+
);
|
|
7424
|
+
if (isMobile) {
|
|
7425
|
+
handlingMobileReturnRef.current = false;
|
|
7426
|
+
mobileSetupFlowRef.current = true;
|
|
7427
|
+
setupAccountIdRef.current = created.accountId;
|
|
7428
|
+
persistMobileFlowState({
|
|
7429
|
+
accountId: created.accountId,
|
|
7430
|
+
sessionId: session.id,
|
|
7431
|
+
deeplinkUri: created.sessionUri,
|
|
7432
|
+
providerId: selectedProviderId,
|
|
7433
|
+
isSetup: true,
|
|
7434
|
+
guestSessionToken
|
|
7435
|
+
});
|
|
7436
|
+
triggerDeeplink(created.sessionUri);
|
|
7437
|
+
dispatch({ type: "MOBILE_DEEPLINK_READY", deeplinkUri: created.sessionUri });
|
|
7438
|
+
}
|
|
7439
|
+
dispatch({
|
|
7440
|
+
type: "GUEST_PREAUTH_DETECTED",
|
|
7441
|
+
accountId: created.accountId,
|
|
7442
|
+
sessionId: session.id
|
|
7443
|
+
});
|
|
7444
|
+
} catch (err) {
|
|
7445
|
+
captureException(err);
|
|
7446
|
+
if (!isMobile) {
|
|
7447
|
+
dispatch({ type: "GUEST_PREAUTH_END" });
|
|
7448
|
+
}
|
|
7449
|
+
dispatch({
|
|
7450
|
+
type: "SET_ERROR",
|
|
7451
|
+
error: err instanceof Error ? err.message : "Failed to start preauthorization"
|
|
7452
|
+
});
|
|
7453
|
+
onError?.(err instanceof Error ? err.message : "Failed to start preauthorization");
|
|
7454
|
+
}
|
|
7455
|
+
}, [
|
|
7456
|
+
guestSessionToken,
|
|
7457
|
+
selectedProviderId,
|
|
7458
|
+
providers,
|
|
7459
|
+
apiBaseUrl,
|
|
7460
|
+
dispatch,
|
|
7461
|
+
onError,
|
|
7462
|
+
useWalletConnectorProp,
|
|
7463
|
+
mobileSetupFlowRef,
|
|
7464
|
+
handlingMobileReturnRef,
|
|
7465
|
+
setupAccountIdRef
|
|
7466
|
+
]);
|
|
7338
7467
|
return {
|
|
7339
7468
|
handlePrepareProvider,
|
|
7340
7469
|
handleSelectProvider,
|
|
@@ -7343,7 +7472,8 @@ function useProviderHandlers(deps) {
|
|
|
7343
7472
|
handleIncreaseLimit,
|
|
7344
7473
|
handleNavigateToTokenPicker,
|
|
7345
7474
|
handleSelectAuthorizedToken,
|
|
7346
|
-
handleAuthorizeToken
|
|
7475
|
+
handleAuthorizeToken,
|
|
7476
|
+
handlePreauthorize
|
|
7347
7477
|
};
|
|
7348
7478
|
}
|
|
7349
7479
|
|
|
@@ -7564,7 +7694,6 @@ function useOneTapSetupHandlers(deps) {
|
|
|
7564
7694
|
selectSourceTokenSymbol
|
|
7565
7695
|
} = deps;
|
|
7566
7696
|
const [savingOneTapLimit, setSavingOneTapLimit] = react.useState(false);
|
|
7567
|
-
const oneTapLimitSavedDuringSetupRef = react.useRef(false);
|
|
7568
7697
|
const handleSetupOneTap = react.useCallback(async (limit) => {
|
|
7569
7698
|
setSavingOneTapLimit(true);
|
|
7570
7699
|
try {
|
|
@@ -7585,12 +7714,12 @@ function useOneTapSetupHandlers(deps) {
|
|
|
7585
7714
|
chainName = recommended?.chainName ?? choices[0]?.chainName ?? "Base";
|
|
7586
7715
|
tokenSymbol = recommended?.tokenSymbol ?? choices[0]?.tokens[0]?.tokenSymbol ?? "USDC";
|
|
7587
7716
|
}
|
|
7588
|
-
|
|
7717
|
+
dispatch({ type: "SET_ONE_TAP_LIMIT_SAVED_DURING_SETUP", saved: true });
|
|
7589
7718
|
authExecutor.resolveSelectSource({ chainName, tokenSymbol });
|
|
7590
7719
|
} else if (authExecutor.pendingOneTapSetup) {
|
|
7591
7720
|
authExecutor.resolveOneTapSetup();
|
|
7592
7721
|
}
|
|
7593
|
-
dispatch({ type: "SET_USER_INTENT", intent:
|
|
7722
|
+
dispatch({ type: "SET_USER_INTENT", intent: { step: "deposit" } });
|
|
7594
7723
|
} catch (err) {
|
|
7595
7724
|
captureException(err);
|
|
7596
7725
|
dispatch({
|
|
@@ -7603,124 +7732,63 @@ function useOneTapSetupHandlers(deps) {
|
|
|
7603
7732
|
}, [getAccessToken, apiBaseUrl, authExecutor, dispatch, selectSourceChainName, selectSourceTokenSymbol]);
|
|
7604
7733
|
return {
|
|
7605
7734
|
handleSetupOneTap,
|
|
7606
|
-
savingOneTapLimit
|
|
7607
|
-
oneTapLimitSavedDuringSetupRef
|
|
7735
|
+
savingOneTapLimit
|
|
7608
7736
|
};
|
|
7609
7737
|
}
|
|
7610
|
-
|
|
7611
|
-
// src/dataLoading.ts
|
|
7612
|
-
function resolveDataLoadAction({
|
|
7613
|
-
authenticated,
|
|
7614
|
-
accountsCount,
|
|
7615
|
-
hasActiveCredential,
|
|
7616
|
-
loading
|
|
7617
|
-
}) {
|
|
7618
|
-
if (!authenticated || accountsCount > 0 || !hasActiveCredential) {
|
|
7619
|
-
return "reset";
|
|
7620
|
-
}
|
|
7621
|
-
if (loading) {
|
|
7622
|
-
return "wait";
|
|
7623
|
-
}
|
|
7624
|
-
return "load";
|
|
7625
|
-
}
|
|
7626
|
-
|
|
7627
|
-
// src/processingStatus.ts
|
|
7628
|
-
var PROCESSING_TIMEOUT_MS = 18e4;
|
|
7629
|
-
function resolvePreferredTransfer(polledTransfer, localTransfer) {
|
|
7630
|
-
return polledTransfer ?? localTransfer;
|
|
7631
|
-
}
|
|
7632
|
-
function getTransferStatus(polledTransfer, localTransfer) {
|
|
7633
|
-
const transfer = resolvePreferredTransfer(polledTransfer, localTransfer);
|
|
7634
|
-
return transfer?.status ?? "UNKNOWN";
|
|
7635
|
-
}
|
|
7636
|
-
function hasProcessingTimedOut(processingStartedAtMs, nowMs) {
|
|
7637
|
-
if (!processingStartedAtMs) return false;
|
|
7638
|
-
return nowMs - processingStartedAtMs >= PROCESSING_TIMEOUT_MS;
|
|
7639
|
-
}
|
|
7640
|
-
var STATUS_DISPLAY_LABELS = {
|
|
7641
|
-
CREATED: "created",
|
|
7642
|
-
AUTHORIZED: "authorized",
|
|
7643
|
-
SENDING: "sending",
|
|
7644
|
-
SENT: "confirming delivery",
|
|
7645
|
-
COMPLETED: "completed",
|
|
7646
|
-
FAILED: "failed"
|
|
7647
|
-
};
|
|
7648
|
-
function getStatusDisplayLabel(status) {
|
|
7649
|
-
return STATUS_DISPLAY_LABELS[status] ?? status;
|
|
7650
|
-
}
|
|
7651
|
-
function buildProcessingTimeoutMessage(status) {
|
|
7652
|
-
const label = getStatusDisplayLabel(status);
|
|
7653
|
-
return `Payment is taking longer than expected (status: ${label}). Please try again.`;
|
|
7654
|
-
}
|
|
7655
|
-
|
|
7656
|
-
// src/hooks/usePaymentEffects.ts
|
|
7657
|
-
function usePaymentEffects(deps) {
|
|
7738
|
+
function useOtpEffects(deps) {
|
|
7658
7739
|
const {
|
|
7659
7740
|
state,
|
|
7660
7741
|
dispatch,
|
|
7661
|
-
ready,
|
|
7662
7742
|
authenticated,
|
|
7663
|
-
apiBaseUrl,
|
|
7664
|
-
depositAmount,
|
|
7665
|
-
onComplete,
|
|
7666
|
-
onError,
|
|
7667
|
-
polling,
|
|
7668
|
-
authExecutor,
|
|
7669
|
-
reloadAccounts,
|
|
7670
7743
|
activeOtpStatus,
|
|
7671
7744
|
activeOtpErrorMessage,
|
|
7672
7745
|
otpCode,
|
|
7673
|
-
handleVerifyLoginCode
|
|
7746
|
+
handleVerifyLoginCode
|
|
7747
|
+
} = deps;
|
|
7748
|
+
react.useEffect(() => {
|
|
7749
|
+
if (authenticated || !state.verificationTarget) return;
|
|
7750
|
+
if (activeOtpErrorMessage) dispatch({ type: "SET_ERROR", error: activeOtpErrorMessage });
|
|
7751
|
+
}, [activeOtpErrorMessage, authenticated, state.verificationTarget, dispatch]);
|
|
7752
|
+
react.useEffect(() => {
|
|
7753
|
+
if (state.verificationTarget && !authenticated && /^\d{6}$/.test(otpCode.trim()) && activeOtpStatus === "awaiting-code-input") {
|
|
7754
|
+
handleVerifyLoginCode();
|
|
7755
|
+
}
|
|
7756
|
+
}, [otpCode, state.verificationTarget, authenticated, activeOtpStatus, handleVerifyLoginCode]);
|
|
7757
|
+
}
|
|
7758
|
+
function usePasskeyCheckEffect(deps) {
|
|
7759
|
+
const {
|
|
7760
|
+
dispatch,
|
|
7761
|
+
ready,
|
|
7762
|
+
authenticated,
|
|
7763
|
+
apiBaseUrl,
|
|
7764
|
+
activeCredentialId,
|
|
7765
|
+
passkeyConfigLoaded,
|
|
7766
|
+
checkingPasskeyRef,
|
|
7674
7767
|
setAuthInput,
|
|
7675
7768
|
setOtpCode,
|
|
7769
|
+
polling,
|
|
7676
7770
|
mobileSetupFlowRef,
|
|
7677
7771
|
handlingMobileReturnRef,
|
|
7678
7772
|
setupAccountIdRef,
|
|
7679
7773
|
reauthSessionIdRef,
|
|
7680
7774
|
reauthTokenRef,
|
|
7681
|
-
|
|
7682
|
-
pollingTransferIdRef,
|
|
7683
|
-
processingStartedAtRef,
|
|
7684
|
-
checkingPasskeyRef,
|
|
7685
|
-
pendingSelectSourceAction,
|
|
7686
|
-
selectSourceChoices,
|
|
7687
|
-
selectSourceRecommended,
|
|
7688
|
-
setSelectSourceChainName,
|
|
7689
|
-
setSelectSourceTokenSymbol,
|
|
7690
|
-
initializedSelectSourceActionRef,
|
|
7691
|
-
oneTapLimitSavedDuringSetupRef,
|
|
7692
|
-
handleAuthorizedMobileReturn
|
|
7775
|
+
pollingTransferIdRef
|
|
7693
7776
|
} = deps;
|
|
7694
7777
|
const { getAccessToken } = reactAuth.usePrivy();
|
|
7695
|
-
const onCompleteRef = react.useRef(onComplete);
|
|
7696
|
-
onCompleteRef.current = onComplete;
|
|
7778
|
+
const onCompleteRef = react.useRef(deps.onComplete);
|
|
7779
|
+
onCompleteRef.current = deps.onComplete;
|
|
7697
7780
|
const getAccessTokenRef = react.useRef(getAccessToken);
|
|
7698
7781
|
getAccessTokenRef.current = getAccessToken;
|
|
7699
7782
|
const pollingRef = react.useRef(polling);
|
|
7700
7783
|
pollingRef.current = polling;
|
|
7701
|
-
const handleAuthorizedMobileReturnRef = react.useRef(handleAuthorizedMobileReturn);
|
|
7702
|
-
handleAuthorizedMobileReturnRef.current = handleAuthorizedMobileReturn;
|
|
7703
|
-
const lastAccountFetchRef = react.useRef(0);
|
|
7704
|
-
react.useEffect(() => {
|
|
7705
|
-
if (depositAmount != null) {
|
|
7706
|
-
dispatch({ type: "SYNC_AMOUNT", amount: depositAmount.toString() });
|
|
7707
|
-
}
|
|
7708
|
-
}, [depositAmount, dispatch]);
|
|
7709
|
-
react.useEffect(() => {
|
|
7710
|
-
if (authenticated || !state.verificationTarget) return;
|
|
7711
|
-
if (activeOtpErrorMessage) dispatch({ type: "SET_ERROR", error: activeOtpErrorMessage });
|
|
7712
|
-
}, [activeOtpErrorMessage, authenticated, state.verificationTarget, dispatch]);
|
|
7713
|
-
react.useEffect(() => {
|
|
7714
|
-
if (state.verificationTarget && !authenticated && /^\d{6}$/.test(otpCode.trim()) && activeOtpStatus === "awaiting-code-input") {
|
|
7715
|
-
handleVerifyLoginCode();
|
|
7716
|
-
}
|
|
7717
|
-
}, [otpCode, state.verificationTarget, authenticated, activeOtpStatus, handleVerifyLoginCode]);
|
|
7784
|
+
const handleAuthorizedMobileReturnRef = react.useRef(deps.handleAuthorizedMobileReturn);
|
|
7785
|
+
handleAuthorizedMobileReturnRef.current = deps.handleAuthorizedMobileReturn;
|
|
7718
7786
|
react.useEffect(() => {
|
|
7719
7787
|
if (!ready || !authenticated) {
|
|
7720
7788
|
checkingPasskeyRef.current = false;
|
|
7721
7789
|
return;
|
|
7722
7790
|
}
|
|
7723
|
-
if (
|
|
7791
|
+
if (passkeyConfigLoaded || activeCredentialId) return;
|
|
7724
7792
|
if (checkingPasskeyRef.current) return;
|
|
7725
7793
|
checkingPasskeyRef.current = true;
|
|
7726
7794
|
let cancelled = false;
|
|
@@ -7818,11 +7886,7 @@ function usePaymentEffects(deps) {
|
|
|
7818
7886
|
return;
|
|
7819
7887
|
}
|
|
7820
7888
|
if (existingTransfer.status === "AUTHORIZED") {
|
|
7821
|
-
|
|
7822
|
-
await handleAuthorizedMobileReturnRef.current(existingTransfer, true);
|
|
7823
|
-
} else {
|
|
7824
|
-
await handleAuthorizedMobileReturnRef.current(existingTransfer, false);
|
|
7825
|
-
}
|
|
7889
|
+
await handleAuthorizedMobileReturnRef.current(existingTransfer, !!persisted.isSetup);
|
|
7826
7890
|
return;
|
|
7827
7891
|
}
|
|
7828
7892
|
if (persisted.isSetup) {
|
|
@@ -7873,11 +7937,9 @@ function usePaymentEffects(deps) {
|
|
|
7873
7937
|
knownIds: allPasskeys.map((p) => p.credentialId),
|
|
7874
7938
|
oneTapLimit: config.defaultAllowance ?? void 0
|
|
7875
7939
|
});
|
|
7876
|
-
if (allPasskeys.length === 0)
|
|
7877
|
-
|
|
7878
|
-
|
|
7879
|
-
if (state.activeCredentialId && allPasskeys.some((p) => p.credentialId === state.activeCredentialId)) {
|
|
7880
|
-
await restoreState(state.activeCredentialId, token);
|
|
7940
|
+
if (allPasskeys.length === 0) return;
|
|
7941
|
+
if (activeCredentialId && allPasskeys.some((p) => p.credentialId === activeCredentialId)) {
|
|
7942
|
+
await restoreState(activeCredentialId, token);
|
|
7881
7943
|
return;
|
|
7882
7944
|
}
|
|
7883
7945
|
if (cancelled) return;
|
|
@@ -7909,7 +7971,39 @@ function usePaymentEffects(deps) {
|
|
|
7909
7971
|
cancelled = true;
|
|
7910
7972
|
checkingPasskeyRef.current = false;
|
|
7911
7973
|
};
|
|
7912
|
-
}, [ready, authenticated, apiBaseUrl,
|
|
7974
|
+
}, [ready, authenticated, apiBaseUrl, activeCredentialId, passkeyConfigLoaded]);
|
|
7975
|
+
}
|
|
7976
|
+
|
|
7977
|
+
// src/dataLoading.ts
|
|
7978
|
+
function resolveDataLoadAction({
|
|
7979
|
+
authenticated,
|
|
7980
|
+
accountsCount,
|
|
7981
|
+
hasActiveCredential,
|
|
7982
|
+
loading
|
|
7983
|
+
}) {
|
|
7984
|
+
if (!authenticated || accountsCount > 0 || !hasActiveCredential) {
|
|
7985
|
+
return "reset";
|
|
7986
|
+
}
|
|
7987
|
+
if (loading) {
|
|
7988
|
+
return "wait";
|
|
7989
|
+
}
|
|
7990
|
+
return "load";
|
|
7991
|
+
}
|
|
7992
|
+
|
|
7993
|
+
// src/hooks/useDataLoadEffect.ts
|
|
7994
|
+
function useDataLoadEffect(deps) {
|
|
7995
|
+
const {
|
|
7996
|
+
state,
|
|
7997
|
+
dispatch,
|
|
7998
|
+
authenticated,
|
|
7999
|
+
apiBaseUrl,
|
|
8000
|
+
depositAmount,
|
|
8001
|
+
loadingDataRef
|
|
8002
|
+
} = deps;
|
|
8003
|
+
const { getAccessToken } = reactAuth.usePrivy();
|
|
8004
|
+
const getAccessTokenRef = react.useRef(getAccessToken);
|
|
8005
|
+
getAccessTokenRef.current = getAccessToken;
|
|
8006
|
+
const lastAccountFetchRef = react.useRef(0);
|
|
7913
8007
|
react.useEffect(() => {
|
|
7914
8008
|
const loadAction = resolveDataLoadAction({
|
|
7915
8009
|
authenticated,
|
|
@@ -8009,6 +8103,61 @@ function usePaymentEffects(deps) {
|
|
|
8009
8103
|
cancelled = true;
|
|
8010
8104
|
};
|
|
8011
8105
|
}, [authenticated, state.providers.length, state.activeCredentialId, apiBaseUrl]);
|
|
8106
|
+
react.useEffect(() => {
|
|
8107
|
+
if (state.accounts.length > 0 && state.activeCredentialId && !state.loadingData && !state.transfer && authenticated && Date.now() - lastAccountFetchRef.current > 15e3) {
|
|
8108
|
+
lastAccountFetchRef.current = Date.now();
|
|
8109
|
+
deps.reloadAccounts();
|
|
8110
|
+
}
|
|
8111
|
+
}, [
|
|
8112
|
+
state.accounts.length,
|
|
8113
|
+
state.activeCredentialId,
|
|
8114
|
+
state.loadingData,
|
|
8115
|
+
state.transfer,
|
|
8116
|
+
authenticated,
|
|
8117
|
+
deps
|
|
8118
|
+
]);
|
|
8119
|
+
}
|
|
8120
|
+
|
|
8121
|
+
// src/processingStatus.ts
|
|
8122
|
+
var PROCESSING_TIMEOUT_MS = 18e4;
|
|
8123
|
+
function resolvePreferredTransfer(polledTransfer, localTransfer) {
|
|
8124
|
+
return polledTransfer ?? localTransfer;
|
|
8125
|
+
}
|
|
8126
|
+
function getTransferStatus(polledTransfer, localTransfer) {
|
|
8127
|
+
const transfer = resolvePreferredTransfer(polledTransfer, localTransfer);
|
|
8128
|
+
return transfer?.status ?? "UNKNOWN";
|
|
8129
|
+
}
|
|
8130
|
+
function hasProcessingTimedOut(processingStartedAtMs, nowMs) {
|
|
8131
|
+
if (!processingStartedAtMs) return false;
|
|
8132
|
+
return nowMs - processingStartedAtMs >= PROCESSING_TIMEOUT_MS;
|
|
8133
|
+
}
|
|
8134
|
+
var STATUS_DISPLAY_LABELS = {
|
|
8135
|
+
CREATED: "created",
|
|
8136
|
+
AUTHORIZED: "authorized",
|
|
8137
|
+
SENDING: "sending",
|
|
8138
|
+
SENT: "confirming delivery",
|
|
8139
|
+
COMPLETED: "completed",
|
|
8140
|
+
FAILED: "failed"
|
|
8141
|
+
};
|
|
8142
|
+
function getStatusDisplayLabel(status) {
|
|
8143
|
+
return STATUS_DISPLAY_LABELS[status] ?? status;
|
|
8144
|
+
}
|
|
8145
|
+
function buildProcessingTimeoutMessage(status) {
|
|
8146
|
+
const label = getStatusDisplayLabel(status);
|
|
8147
|
+
return `Payment is taking longer than expected (status: ${label}). Please try again.`;
|
|
8148
|
+
}
|
|
8149
|
+
|
|
8150
|
+
// src/hooks/useProcessingEffect.ts
|
|
8151
|
+
function useProcessingEffect(deps) {
|
|
8152
|
+
const {
|
|
8153
|
+
state,
|
|
8154
|
+
dispatch,
|
|
8155
|
+
polling,
|
|
8156
|
+
processingStartedAtRef,
|
|
8157
|
+
onComplete,
|
|
8158
|
+
onError,
|
|
8159
|
+
reloadAccounts
|
|
8160
|
+
} = deps;
|
|
8012
8161
|
react.useEffect(() => {
|
|
8013
8162
|
if (!polling.transfer) return;
|
|
8014
8163
|
if (polling.transfer.status === "COMPLETED") {
|
|
@@ -8021,19 +8170,6 @@ function usePaymentEffects(deps) {
|
|
|
8021
8170
|
dispatch({ type: "TRANSFER_FAILED", transfer: polling.transfer, error: "Transfer failed." });
|
|
8022
8171
|
}
|
|
8023
8172
|
}, [polling.transfer, onComplete, dispatch, reloadAccounts]);
|
|
8024
|
-
react.useEffect(() => {
|
|
8025
|
-
if (state.accounts.length > 0 && state.activeCredentialId && !state.loadingData && !state.transfer && authenticated && Date.now() - lastAccountFetchRef.current > 15e3) {
|
|
8026
|
-
lastAccountFetchRef.current = Date.now();
|
|
8027
|
-
reloadAccounts();
|
|
8028
|
-
}
|
|
8029
|
-
}, [
|
|
8030
|
-
state.accounts.length,
|
|
8031
|
-
state.activeCredentialId,
|
|
8032
|
-
state.loadingData,
|
|
8033
|
-
state.transfer,
|
|
8034
|
-
authenticated,
|
|
8035
|
-
reloadAccounts
|
|
8036
|
-
]);
|
|
8037
8173
|
react.useEffect(() => {
|
|
8038
8174
|
const isProcessing = state.creatingTransfer || state.transfer != null && ["CREATED", "SENDING", "SENT"].includes(state.transfer.status);
|
|
8039
8175
|
if (!isProcessing) {
|
|
@@ -8069,6 +8205,26 @@ function usePaymentEffects(deps) {
|
|
|
8069
8205
|
dispatch,
|
|
8070
8206
|
processingStartedAtRef
|
|
8071
8207
|
]);
|
|
8208
|
+
}
|
|
8209
|
+
function useMobilePollingEffect(deps) {
|
|
8210
|
+
const {
|
|
8211
|
+
state,
|
|
8212
|
+
dispatch,
|
|
8213
|
+
polling,
|
|
8214
|
+
mobileSetupFlowRef,
|
|
8215
|
+
handlingMobileReturnRef,
|
|
8216
|
+
setupAccountIdRef,
|
|
8217
|
+
reauthSessionIdRef,
|
|
8218
|
+
reauthTokenRef,
|
|
8219
|
+
pollingTransferIdRef,
|
|
8220
|
+
reloadAccounts,
|
|
8221
|
+
apiBaseUrl
|
|
8222
|
+
} = deps;
|
|
8223
|
+
const { getAccessToken } = reactAuth.usePrivy();
|
|
8224
|
+
const getAccessTokenRef = react.useRef(getAccessToken);
|
|
8225
|
+
getAccessTokenRef.current = getAccessToken;
|
|
8226
|
+
const handleAuthorizedMobileReturnRef = react.useRef(deps.handleAuthorizedMobileReturn);
|
|
8227
|
+
handleAuthorizedMobileReturnRef.current = deps.handleAuthorizedMobileReturn;
|
|
8072
8228
|
react.useEffect(() => {
|
|
8073
8229
|
if (!state.mobileFlow) {
|
|
8074
8230
|
handlingMobileReturnRef.current = false;
|
|
@@ -8077,8 +8233,8 @@ function usePaymentEffects(deps) {
|
|
|
8077
8233
|
if (handlingMobileReturnRef.current) return;
|
|
8078
8234
|
const polledTransfer = polling.transfer;
|
|
8079
8235
|
if (!polledTransfer || polledTransfer.status !== "AUTHORIZED") return;
|
|
8080
|
-
void
|
|
8081
|
-
}, [state.mobileFlow, polling.transfer,
|
|
8236
|
+
void handleAuthorizedMobileReturnRef.current(polledTransfer, mobileSetupFlowRef.current);
|
|
8237
|
+
}, [state.mobileFlow, polling.transfer, handlingMobileReturnRef, mobileSetupFlowRef]);
|
|
8082
8238
|
react.useEffect(() => {
|
|
8083
8239
|
if (!state.mobileFlow || !mobileSetupFlowRef.current) return;
|
|
8084
8240
|
if (!state.activeCredentialId || !setupAccountIdRef.current) return;
|
|
@@ -8154,14 +8310,10 @@ function usePaymentEffects(deps) {
|
|
|
8154
8310
|
poll();
|
|
8155
8311
|
const intervalId = window.setInterval(poll, POLL_INTERVAL_MS);
|
|
8156
8312
|
const handleVisibility = () => {
|
|
8157
|
-
if (document.visibilityState === "visible" && !cancelled)
|
|
8158
|
-
poll();
|
|
8159
|
-
}
|
|
8313
|
+
if (document.visibilityState === "visible" && !cancelled) poll();
|
|
8160
8314
|
};
|
|
8161
8315
|
const handlePageShow = (e) => {
|
|
8162
|
-
if (e.persisted && !cancelled)
|
|
8163
|
-
poll();
|
|
8164
|
-
}
|
|
8316
|
+
if (e.persisted && !cancelled) poll();
|
|
8165
8317
|
};
|
|
8166
8318
|
document.addEventListener("visibilitychange", handleVisibility);
|
|
8167
8319
|
window.addEventListener("pageshow", handlePageShow);
|
|
@@ -8212,6 +8364,16 @@ function usePaymentEffects(deps) {
|
|
|
8212
8364
|
handlingMobileReturnRef,
|
|
8213
8365
|
pollingTransferIdRef
|
|
8214
8366
|
]);
|
|
8367
|
+
}
|
|
8368
|
+
function useSelectSourceEffect(deps) {
|
|
8369
|
+
const {
|
|
8370
|
+
pendingSelectSourceAction,
|
|
8371
|
+
selectSourceChoices,
|
|
8372
|
+
selectSourceRecommended,
|
|
8373
|
+
setSelectSourceChainName,
|
|
8374
|
+
setSelectSourceTokenSymbol,
|
|
8375
|
+
initializedSelectSourceActionRef
|
|
8376
|
+
} = deps;
|
|
8215
8377
|
react.useEffect(() => {
|
|
8216
8378
|
if (!pendingSelectSourceAction) {
|
|
8217
8379
|
initializedSelectSourceActionRef.current = null;
|
|
@@ -8242,57 +8404,27 @@ function usePaymentEffects(deps) {
|
|
|
8242
8404
|
setSelectSourceTokenSymbol,
|
|
8243
8405
|
initializedSelectSourceActionRef
|
|
8244
8406
|
]);
|
|
8407
|
+
}
|
|
8408
|
+
function useOneTapAutoResolveEffect(deps) {
|
|
8409
|
+
const { authExecutor, dispatch, oneTapLimitSavedDuringSetup, reloadAccounts } = deps;
|
|
8245
8410
|
const pendingOneTapSetupAction = authExecutor.pendingOneTapSetup;
|
|
8246
8411
|
react.useEffect(() => {
|
|
8247
|
-
if (pendingOneTapSetupAction &&
|
|
8248
|
-
|
|
8412
|
+
if (pendingOneTapSetupAction && oneTapLimitSavedDuringSetup) {
|
|
8413
|
+
dispatch({ type: "SET_ONE_TAP_LIMIT_SAVED_DURING_SETUP", saved: false });
|
|
8249
8414
|
authExecutor.resolveOneTapSetup();
|
|
8250
8415
|
}
|
|
8251
|
-
}, [pendingOneTapSetupAction, authExecutor,
|
|
8416
|
+
}, [pendingOneTapSetupAction, authExecutor, dispatch, oneTapLimitSavedDuringSetup]);
|
|
8252
8417
|
react.useEffect(() => {
|
|
8253
|
-
if (pendingOneTapSetupAction && !
|
|
8418
|
+
if (pendingOneTapSetupAction && !oneTapLimitSavedDuringSetup) {
|
|
8254
8419
|
reloadAccounts();
|
|
8255
8420
|
}
|
|
8256
|
-
}, [pendingOneTapSetupAction, reloadAccounts,
|
|
8257
|
-
|
|
8258
|
-
|
|
8259
|
-
|
|
8260
|
-
|
|
8261
|
-
|
|
8262
|
-
|
|
8263
|
-
try {
|
|
8264
|
-
let result = await fetchGuestAccount(apiBaseUrl, state.guestSessionToken);
|
|
8265
|
-
if (cancelled) return;
|
|
8266
|
-
if (!result && state.selectedProviderId) {
|
|
8267
|
-
const providerName = state.providers.find((p) => p.id === state.selectedProviderId)?.name ?? "Wallet";
|
|
8268
|
-
const created = await createGuestAccount(
|
|
8269
|
-
apiBaseUrl,
|
|
8270
|
-
state.guestSessionToken,
|
|
8271
|
-
state.selectedProviderId,
|
|
8272
|
-
providerName
|
|
8273
|
-
);
|
|
8274
|
-
if (cancelled) return;
|
|
8275
|
-
result = { accountId: created.accountId, hasPasskey: false, walletAddress: null };
|
|
8276
|
-
}
|
|
8277
|
-
if (result && !result.hasPasskey) {
|
|
8278
|
-
dispatch({ type: "GUEST_PREAUTH_DETECTED", accountId: result.accountId });
|
|
8279
|
-
}
|
|
8280
|
-
} catch {
|
|
8281
|
-
}
|
|
8282
|
-
};
|
|
8283
|
-
ensureGuestAccount();
|
|
8284
|
-
return () => {
|
|
8285
|
-
cancelled = true;
|
|
8286
|
-
};
|
|
8287
|
-
}, [
|
|
8288
|
-
state.transfer,
|
|
8289
|
-
state.guestSessionToken,
|
|
8290
|
-
state.guestPreauthAccountId,
|
|
8291
|
-
state.selectedProviderId,
|
|
8292
|
-
state.providers,
|
|
8293
|
-
apiBaseUrl,
|
|
8294
|
-
dispatch
|
|
8295
|
-
]);
|
|
8421
|
+
}, [pendingOneTapSetupAction, reloadAccounts, oneTapLimitSavedDuringSetup]);
|
|
8422
|
+
}
|
|
8423
|
+
function useGuestPreauthEffect(deps) {
|
|
8424
|
+
const { state, dispatch, authenticated, apiBaseUrl, reloadAccounts } = deps;
|
|
8425
|
+
const { getAccessToken } = reactAuth.usePrivy();
|
|
8426
|
+
const getAccessTokenRef = react.useRef(getAccessToken);
|
|
8427
|
+
getAccessTokenRef.current = getAccessToken;
|
|
8296
8428
|
const settingOwnerRef = react.useRef(false);
|
|
8297
8429
|
react.useEffect(() => {
|
|
8298
8430
|
if (!state.guestPreauthAccountId) return;
|
|
@@ -8301,6 +8433,8 @@ function usePaymentEffects(deps) {
|
|
|
8301
8433
|
if (!authenticated) return;
|
|
8302
8434
|
if (!state.guestSessionToken) return;
|
|
8303
8435
|
if (settingOwnerRef.current) return;
|
|
8436
|
+
const hasActive = state.accounts.some((a) => a.wallets.some((w) => w.status === "ACTIVE"));
|
|
8437
|
+
if (!hasActive) return;
|
|
8304
8438
|
settingOwnerRef.current = true;
|
|
8305
8439
|
let cancelled = false;
|
|
8306
8440
|
const setOwner = async () => {
|
|
@@ -8338,12 +8472,73 @@ function usePaymentEffects(deps) {
|
|
|
8338
8472
|
state.activeCredentialId,
|
|
8339
8473
|
state.activePublicKey,
|
|
8340
8474
|
state.guestSessionToken,
|
|
8475
|
+
state.accounts,
|
|
8341
8476
|
authenticated,
|
|
8342
8477
|
apiBaseUrl,
|
|
8343
8478
|
dispatch,
|
|
8344
8479
|
reloadAccounts
|
|
8345
8480
|
]);
|
|
8346
8481
|
}
|
|
8482
|
+
function useGuestDesktopPreauthSessionEffect(deps) {
|
|
8483
|
+
const { state, authExecutor, reloadAccounts, dispatch, desktopGuestPreauth } = deps;
|
|
8484
|
+
const preauthExecutingRef = react.useRef(false);
|
|
8485
|
+
react.useEffect(() => {
|
|
8486
|
+
if (!desktopGuestPreauth) return;
|
|
8487
|
+
if (!state.guestPreauthorizing) return;
|
|
8488
|
+
if (!state.guestPreauthSessionId || preauthExecutingRef.current) return;
|
|
8489
|
+
preauthExecutingRef.current = true;
|
|
8490
|
+
const runPreauthSession = async () => {
|
|
8491
|
+
try {
|
|
8492
|
+
await authExecutor.executeSessionById(state.guestPreauthSessionId);
|
|
8493
|
+
await reloadAccounts();
|
|
8494
|
+
} catch {
|
|
8495
|
+
} finally {
|
|
8496
|
+
preauthExecutingRef.current = false;
|
|
8497
|
+
dispatch({ type: "GUEST_PREAUTH_END" });
|
|
8498
|
+
}
|
|
8499
|
+
};
|
|
8500
|
+
void runPreauthSession();
|
|
8501
|
+
}, [
|
|
8502
|
+
desktopGuestPreauth,
|
|
8503
|
+
state.guestPreauthorizing,
|
|
8504
|
+
state.guestPreauthSessionId,
|
|
8505
|
+
authExecutor,
|
|
8506
|
+
reloadAccounts,
|
|
8507
|
+
dispatch
|
|
8508
|
+
]);
|
|
8509
|
+
}
|
|
8510
|
+
function useGuestPreauthPhaseSyncEffect(deps) {
|
|
8511
|
+
const { state, dispatch, authExecutor, isDesktop } = deps;
|
|
8512
|
+
react.useEffect(() => {
|
|
8513
|
+
if (!state.guestPreauthorizing || !isDesktop) return;
|
|
8514
|
+
const pending = authExecutor.pendingSelectSource;
|
|
8515
|
+
if (pending) {
|
|
8516
|
+
const intent = {
|
|
8517
|
+
step: "select-source",
|
|
8518
|
+
action: pending,
|
|
8519
|
+
isDesktop,
|
|
8520
|
+
skipOneTapLimit: true
|
|
8521
|
+
};
|
|
8522
|
+
if (state.phase.step === "select-source") {
|
|
8523
|
+
const ph = state.phase;
|
|
8524
|
+
if (ph.skipOneTapLimit && ph.action.id === pending.id) {
|
|
8525
|
+
return;
|
|
8526
|
+
}
|
|
8527
|
+
}
|
|
8528
|
+
dispatch({ type: "SET_USER_INTENT", intent });
|
|
8529
|
+
return;
|
|
8530
|
+
}
|
|
8531
|
+
if (state.phase.step === "select-source" && state.phase.skipOneTapLimit === true) {
|
|
8532
|
+
dispatch({ type: "SET_USER_INTENT", intent: { step: "one-tap-setup", action: null } });
|
|
8533
|
+
}
|
|
8534
|
+
}, [
|
|
8535
|
+
state.guestPreauthorizing,
|
|
8536
|
+
state.phase,
|
|
8537
|
+
isDesktop,
|
|
8538
|
+
authExecutor.pendingSelectSource,
|
|
8539
|
+
dispatch
|
|
8540
|
+
]);
|
|
8541
|
+
}
|
|
8347
8542
|
function BlinkPayment(props) {
|
|
8348
8543
|
const resetKey = react.useRef(0);
|
|
8349
8544
|
const handleBoundaryReset = react.useCallback(() => {
|
|
@@ -8365,6 +8560,10 @@ function BlinkPaymentInner({
|
|
|
8365
8560
|
const { apiBaseUrl, depositAmount } = useBlinkConfig();
|
|
8366
8561
|
const { ready, authenticated, logout, getAccessToken } = reactAuth.usePrivy();
|
|
8367
8562
|
reactAuth.useLoginWithOAuth();
|
|
8563
|
+
const isDesktop = shouldUseWalletConnector({
|
|
8564
|
+
useWalletConnector: useWalletConnectorProp,
|
|
8565
|
+
userAgent: typeof navigator === "undefined" ? void 0 : navigator.userAgent
|
|
8566
|
+
});
|
|
8368
8567
|
const [state, dispatch] = react.useReducer(
|
|
8369
8568
|
paymentReducer,
|
|
8370
8569
|
{
|
|
@@ -8448,7 +8647,9 @@ function BlinkPaymentInner({
|
|
|
8448
8647
|
reauthTokenRef: mobileFlowRefs.reauthTokenRef,
|
|
8449
8648
|
authenticated,
|
|
8450
8649
|
merchantAuthorization,
|
|
8451
|
-
destination
|
|
8650
|
+
destination,
|
|
8651
|
+
guestSessionToken: state.guestSessionToken,
|
|
8652
|
+
selectedProviderId: state.selectedProviderId
|
|
8452
8653
|
});
|
|
8453
8654
|
const oneTapSetup = useOneTapSetupHandlers({
|
|
8454
8655
|
dispatch,
|
|
@@ -8470,13 +8671,12 @@ function BlinkPaymentInner({
|
|
|
8470
8671
|
clearMobileFlowState();
|
|
8471
8672
|
transfer.processingStartedAtRef.current = null;
|
|
8472
8673
|
transfer.pollingTransferIdRef.current = null;
|
|
8473
|
-
oneTapSetup.oneTapLimitSavedDuringSetupRef.current = false;
|
|
8474
8674
|
dispatch({
|
|
8475
8675
|
type: "NEW_PAYMENT",
|
|
8476
8676
|
depositAmount,
|
|
8477
8677
|
firstAccountId: state.accounts.length > 0 ? state.accounts[0].id : null
|
|
8478
8678
|
});
|
|
8479
|
-
}, [depositAmount, state.accounts, transfer
|
|
8679
|
+
}, [depositAmount, state.accounts, transfer]);
|
|
8480
8680
|
const handleLogout = react.useCallback(async () => {
|
|
8481
8681
|
try {
|
|
8482
8682
|
await logout();
|
|
@@ -8488,65 +8688,112 @@ function BlinkPaymentInner({
|
|
|
8488
8688
|
}
|
|
8489
8689
|
polling.stopPolling();
|
|
8490
8690
|
passkey.checkingPasskeyRef.current = false;
|
|
8491
|
-
oneTapSetup.oneTapLimitSavedDuringSetupRef.current = false;
|
|
8492
8691
|
auth.setAuthInput("");
|
|
8493
8692
|
auth.setOtpCode("");
|
|
8494
8693
|
dispatch({ type: "LOGOUT", depositAmount });
|
|
8495
|
-
}, [logout, polling, depositAmount, auth, passkey
|
|
8496
|
-
|
|
8694
|
+
}, [logout, polling, depositAmount, auth, passkey]);
|
|
8695
|
+
react.useEffect(() => {
|
|
8696
|
+
if (depositAmount != null) {
|
|
8697
|
+
dispatch({ type: "SYNC_AMOUNT", amount: depositAmount.toString() });
|
|
8698
|
+
}
|
|
8699
|
+
}, [depositAmount, dispatch]);
|
|
8700
|
+
useOtpEffects({
|
|
8497
8701
|
state,
|
|
8498
8702
|
dispatch,
|
|
8499
|
-
ready,
|
|
8500
8703
|
authenticated,
|
|
8501
|
-
apiBaseUrl,
|
|
8502
|
-
depositAmount,
|
|
8503
|
-
onComplete,
|
|
8504
|
-
onError,
|
|
8505
|
-
polling,
|
|
8506
|
-
authExecutor,
|
|
8507
|
-
reloadAccounts: transfer.reloadAccounts,
|
|
8508
8704
|
activeOtpStatus: auth.activeOtpStatus,
|
|
8509
8705
|
activeOtpErrorMessage: auth.activeOtpErrorMessage,
|
|
8510
8706
|
otpCode: auth.otpCode,
|
|
8511
8707
|
handleVerifyLoginCode: auth.handleVerifyLoginCode,
|
|
8512
8708
|
setAuthInput: auth.setAuthInput,
|
|
8709
|
+
setOtpCode: auth.setOtpCode
|
|
8710
|
+
});
|
|
8711
|
+
usePasskeyCheckEffect({
|
|
8712
|
+
dispatch,
|
|
8713
|
+
ready,
|
|
8714
|
+
authenticated,
|
|
8715
|
+
apiBaseUrl,
|
|
8716
|
+
activeCredentialId: state.activeCredentialId,
|
|
8717
|
+
passkeyConfigLoaded: state.passkeyConfigLoaded,
|
|
8718
|
+
checkingPasskeyRef: passkey.checkingPasskeyRef,
|
|
8719
|
+
setAuthInput: auth.setAuthInput,
|
|
8513
8720
|
setOtpCode: auth.setOtpCode,
|
|
8721
|
+
polling,
|
|
8514
8722
|
mobileSetupFlowRef: mobileFlowRefs.mobileSetupFlowRef,
|
|
8515
8723
|
handlingMobileReturnRef: mobileFlowRefs.handlingMobileReturnRef,
|
|
8516
8724
|
setupAccountIdRef: mobileFlowRefs.setupAccountIdRef,
|
|
8517
8725
|
reauthSessionIdRef: mobileFlowRefs.reauthSessionIdRef,
|
|
8518
8726
|
reauthTokenRef: mobileFlowRefs.reauthTokenRef,
|
|
8519
|
-
loadingDataRef: mobileFlowRefs.loadingDataRef,
|
|
8520
8727
|
pollingTransferIdRef: transfer.pollingTransferIdRef,
|
|
8728
|
+
handleAuthorizedMobileReturn: mobileFlow.handleAuthorizedMobileReturn,
|
|
8729
|
+
onComplete
|
|
8730
|
+
});
|
|
8731
|
+
useDataLoadEffect({
|
|
8732
|
+
state,
|
|
8733
|
+
dispatch,
|
|
8734
|
+
authenticated,
|
|
8735
|
+
apiBaseUrl,
|
|
8736
|
+
depositAmount,
|
|
8737
|
+
loadingDataRef: mobileFlowRefs.loadingDataRef,
|
|
8738
|
+
reloadAccounts: transfer.reloadAccounts
|
|
8739
|
+
});
|
|
8740
|
+
useProcessingEffect({
|
|
8741
|
+
state,
|
|
8742
|
+
dispatch,
|
|
8743
|
+
polling,
|
|
8521
8744
|
processingStartedAtRef: transfer.processingStartedAtRef,
|
|
8522
|
-
|
|
8745
|
+
onComplete,
|
|
8746
|
+
onError,
|
|
8747
|
+
reloadAccounts: transfer.reloadAccounts
|
|
8748
|
+
});
|
|
8749
|
+
useMobilePollingEffect({
|
|
8750
|
+
state,
|
|
8751
|
+
dispatch,
|
|
8752
|
+
polling,
|
|
8753
|
+
mobileSetupFlowRef: mobileFlowRefs.mobileSetupFlowRef,
|
|
8754
|
+
handlingMobileReturnRef: mobileFlowRefs.handlingMobileReturnRef,
|
|
8755
|
+
setupAccountIdRef: mobileFlowRefs.setupAccountIdRef,
|
|
8756
|
+
reauthSessionIdRef: mobileFlowRefs.reauthSessionIdRef,
|
|
8757
|
+
reauthTokenRef: mobileFlowRefs.reauthTokenRef,
|
|
8758
|
+
pollingTransferIdRef: transfer.pollingTransferIdRef,
|
|
8759
|
+
reloadAccounts: transfer.reloadAccounts,
|
|
8760
|
+
handleAuthorizedMobileReturn: mobileFlow.handleAuthorizedMobileReturn,
|
|
8761
|
+
apiBaseUrl
|
|
8762
|
+
});
|
|
8763
|
+
useSelectSourceEffect({
|
|
8523
8764
|
pendingSelectSourceAction: sourceSelection.pendingSelectSourceAction,
|
|
8524
8765
|
selectSourceChoices: sourceSelection.selectSourceChoices,
|
|
8525
8766
|
selectSourceRecommended: sourceSelection.selectSourceRecommended,
|
|
8526
8767
|
setSelectSourceChainName: sourceSelection.setSelectSourceChainName,
|
|
8527
8768
|
setSelectSourceTokenSymbol: sourceSelection.setSelectSourceTokenSymbol,
|
|
8528
|
-
initializedSelectSourceActionRef: sourceSelection.initializedSelectSourceActionRef
|
|
8529
|
-
oneTapLimitSavedDuringSetupRef: oneTapSetup.oneTapLimitSavedDuringSetupRef,
|
|
8530
|
-
handleAuthorizedMobileReturn: mobileFlow.handleAuthorizedMobileReturn
|
|
8769
|
+
initializedSelectSourceActionRef: sourceSelection.initializedSelectSourceActionRef
|
|
8531
8770
|
});
|
|
8532
|
-
|
|
8533
|
-
|
|
8534
|
-
|
|
8535
|
-
|
|
8536
|
-
|
|
8537
|
-
|
|
8538
|
-
|
|
8539
|
-
|
|
8540
|
-
|
|
8541
|
-
}, [
|
|
8542
|
-
state.isGuestFlow,
|
|
8543
|
-
state.selectedProviderId,
|
|
8544
|
-
state.activeCredentialId,
|
|
8545
|
-
state.transfer,
|
|
8546
|
-
state.accounts,
|
|
8771
|
+
useOneTapAutoResolveEffect({
|
|
8772
|
+
authExecutor,
|
|
8773
|
+
dispatch,
|
|
8774
|
+
oneTapLimitSavedDuringSetup: state.oneTapLimitSavedDuringSetup,
|
|
8775
|
+
reloadAccounts: transfer.reloadAccounts
|
|
8776
|
+
});
|
|
8777
|
+
useGuestPreauthEffect({
|
|
8778
|
+
state,
|
|
8779
|
+
dispatch,
|
|
8547
8780
|
authenticated,
|
|
8548
|
-
|
|
8549
|
-
|
|
8781
|
+
apiBaseUrl,
|
|
8782
|
+
reloadAccounts: transfer.reloadAccounts
|
|
8783
|
+
});
|
|
8784
|
+
useGuestPreauthPhaseSyncEffect({
|
|
8785
|
+
state,
|
|
8786
|
+
dispatch,
|
|
8787
|
+
authExecutor,
|
|
8788
|
+
isDesktop
|
|
8789
|
+
});
|
|
8790
|
+
useGuestDesktopPreauthSessionEffect({
|
|
8791
|
+
state,
|
|
8792
|
+
authExecutor,
|
|
8793
|
+
reloadAccounts: transfer.reloadAccounts,
|
|
8794
|
+
dispatch,
|
|
8795
|
+
desktopGuestPreauth: isDesktop
|
|
8796
|
+
});
|
|
8550
8797
|
const handlers = react.useMemo(() => ({
|
|
8551
8798
|
onSendLoginCode: auth.handleSendLoginCode,
|
|
8552
8799
|
onVerifyLoginCode: auth.handleVerifyLoginCode,
|
|
@@ -8569,7 +8816,7 @@ function BlinkPaymentInner({
|
|
|
8569
8816
|
onBackFromOpenWallet: () => dispatch({ type: "CLEAR_MOBILE_STATE" }),
|
|
8570
8817
|
onLogout: handleLogout,
|
|
8571
8818
|
onNewPayment: handleNewPayment,
|
|
8572
|
-
|
|
8819
|
+
onSetPhase: (phase) => dispatch({ type: "SET_USER_INTENT", intent: phase }),
|
|
8573
8820
|
onSetAuthInput: auth.setAuthInput,
|
|
8574
8821
|
onSetOtpCode: (code) => {
|
|
8575
8822
|
auth.setOtpCode(code);
|
|
@@ -8584,7 +8831,7 @@ function BlinkPaymentInner({
|
|
|
8584
8831
|
onAuthorizeToken: provider.handleAuthorizeToken,
|
|
8585
8832
|
onSelectGuestToken: guestTransfer.handleSelectGuestToken,
|
|
8586
8833
|
onLogin: () => dispatch({ type: "REQUEST_LOGIN" }),
|
|
8587
|
-
onPreauthorize:
|
|
8834
|
+
onPreauthorize: provider.handlePreauthorize
|
|
8588
8835
|
}), [
|
|
8589
8836
|
auth,
|
|
8590
8837
|
passkey,
|
|
@@ -8600,41 +8847,47 @@ function BlinkPaymentInner({
|
|
|
8600
8847
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
8601
8848
|
StepRenderer,
|
|
8602
8849
|
{
|
|
8603
|
-
|
|
8604
|
-
|
|
8605
|
-
|
|
8606
|
-
|
|
8607
|
-
|
|
8608
|
-
|
|
8609
|
-
|
|
8610
|
-
|
|
8611
|
-
|
|
8612
|
-
|
|
8613
|
-
|
|
8614
|
-
|
|
8615
|
-
|
|
8616
|
-
|
|
8617
|
-
|
|
8618
|
-
|
|
8619
|
-
|
|
8620
|
-
|
|
8621
|
-
|
|
8622
|
-
|
|
8623
|
-
|
|
8624
|
-
|
|
8625
|
-
|
|
8626
|
-
|
|
8627
|
-
|
|
8628
|
-
|
|
8629
|
-
|
|
8630
|
-
|
|
8631
|
-
|
|
8632
|
-
|
|
8633
|
-
|
|
8634
|
-
|
|
8635
|
-
|
|
8636
|
-
|
|
8637
|
-
|
|
8850
|
+
flow: {
|
|
8851
|
+
state,
|
|
8852
|
+
authenticated,
|
|
8853
|
+
activeOtpStatus: auth.activeOtpStatus,
|
|
8854
|
+
isDesktop,
|
|
8855
|
+
merchantName,
|
|
8856
|
+
onBack,
|
|
8857
|
+
onDismiss,
|
|
8858
|
+
depositAmount
|
|
8859
|
+
},
|
|
8860
|
+
remote: {
|
|
8861
|
+
pollingTransfer: polling.transfer,
|
|
8862
|
+
pollingError: polling.error,
|
|
8863
|
+
authExecutorError: authExecutor.error,
|
|
8864
|
+
transferSigningSigning: transferSigning.signing,
|
|
8865
|
+
transferSigningError: transferSigning.error,
|
|
8866
|
+
pendingSelectSource: authExecutor.pendingSelectSource,
|
|
8867
|
+
pendingOneTapSetup: authExecutor.pendingOneTapSetup
|
|
8868
|
+
},
|
|
8869
|
+
derived: {
|
|
8870
|
+
pendingConnections: derived.pendingConnections,
|
|
8871
|
+
depositEligibleAccounts: derived.depositEligibleAccounts,
|
|
8872
|
+
sourceName: derived.sourceName,
|
|
8873
|
+
maxSourceBalance: derived.maxSourceBalance,
|
|
8874
|
+
tokenCount: derived.tokenCount,
|
|
8875
|
+
selectedAccount: derived.selectedAccount,
|
|
8876
|
+
selectedSource: derived.selectedSource,
|
|
8877
|
+
selectSourceChoices: sourceSelection.selectSourceChoices,
|
|
8878
|
+
selectSourceRecommended: sourceSelection.selectSourceRecommended,
|
|
8879
|
+
selectSourceAvailableBalance: sourceSelection.selectSourceAvailableBalance
|
|
8880
|
+
},
|
|
8881
|
+
forms: {
|
|
8882
|
+
authInput: auth.authInput,
|
|
8883
|
+
otpCode: auth.otpCode,
|
|
8884
|
+
selectSourceChainName: sourceSelection.selectSourceChainName,
|
|
8885
|
+
selectSourceTokenSymbol: sourceSelection.selectSourceTokenSymbol,
|
|
8886
|
+
savingOneTapLimit: oneTapSetup.savingOneTapLimit,
|
|
8887
|
+
guestTokenEntries: guestTransfer.guestTokenEntries,
|
|
8888
|
+
guestLoadingBalances: guestTransfer.loadingBalances,
|
|
8889
|
+
guestSettingSender: guestTransfer.settingSender
|
|
8890
|
+
},
|
|
8638
8891
|
handlers
|
|
8639
8892
|
}
|
|
8640
8893
|
);
|
|
@@ -8673,7 +8926,7 @@ exports.findDevicePasskeyViaPopup = findDevicePasskeyViaPopup;
|
|
|
8673
8926
|
exports.getTheme = getTheme;
|
|
8674
8927
|
exports.lightTheme = lightTheme;
|
|
8675
8928
|
exports.resolvePasskeyRpId = resolvePasskeyRpId;
|
|
8676
|
-
exports.
|
|
8929
|
+
exports.screenForPhase = screenForPhase;
|
|
8677
8930
|
exports.useAuthorizationExecutor = useAuthorizationExecutor;
|
|
8678
8931
|
exports.useBlinkConfig = useBlinkConfig;
|
|
8679
8932
|
exports.useBlinkDepositAmount = useBlinkDepositAmount;
|