@swype-org/react-sdk 0.2.303 → 0.2.309

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 CHANGED
@@ -545,12 +545,16 @@ function buildSelectSourceChoices(options, minTransferAmountUsd = DEFAULT_MIN_SE
545
545
  } else if (!existing.walletName && option.walletName) {
546
546
  existing.walletName = option.walletName;
547
547
  }
548
+ if (!existing.logoURI && option.logoURI) {
549
+ existing.logoURI = option.logoURI;
550
+ }
548
551
  } else {
549
552
  chainChoice.tokens.push({
550
553
  tokenSymbol,
551
554
  balance,
552
555
  ...option.walletName ? { walletName: option.walletName } : {},
553
- ...option.walletLogoUrl ? { walletLogoUrl: option.walletLogoUrl } : {}
556
+ ...option.walletLogoUrl ? { walletLogoUrl: option.walletLogoUrl } : {},
557
+ ...option.logoURI ? { logoURI: option.logoURI } : {}
554
558
  });
555
559
  }
556
560
  }
@@ -1411,6 +1415,263 @@ async function revokeAndDisconnectActiveWagmiConnector(wagmiConfig) {
1411
1415
  });
1412
1416
  }
1413
1417
 
1418
+ // src/solanaWalletRuntime.ts
1419
+ function asSigner(adapter) {
1420
+ return adapter;
1421
+ }
1422
+ var PHANTOM_SOLANA_CONNECT_TIMEOUT_MESSAGE = "PHANTOM_SOLANA_CONNECT_TIMEOUT";
1423
+ var APPROVE_SPL_CONFIRMATION_TIMEOUT_MESSAGE = "APPROVE_SPL_CONFIRMATION_TIMEOUT";
1424
+ var APPROVE_SPL_ONCHAIN_FAILURE_PREFIX = "Solana transaction failed:";
1425
+ var DEFAULT_CONFIRM_TIMEOUT_MS = 45e3;
1426
+ var DEFAULT_POLL_INTERVAL_MS = 1e3;
1427
+ var DEFAULT_COMMITMENT = "confirmed";
1428
+ var cachedAdapter = null;
1429
+ var cachedProviderKey = null;
1430
+ function providerKey(selection) {
1431
+ const providerName = selection.providerName?.trim();
1432
+ if (!providerName) {
1433
+ throw new Error("Solana wallet metadata is missing providerName.");
1434
+ }
1435
+ return `${selection.providerId ?? ""}:${providerName.toLowerCase()}`;
1436
+ }
1437
+ function assertSupportedProvider(selection) {
1438
+ const name = selection.providerName?.trim().toLowerCase();
1439
+ if (name !== "phantom") {
1440
+ throw new Error(`Unsupported Solana wallet provider: ${selection.providerName ?? "unknown"}.`);
1441
+ }
1442
+ }
1443
+ async function createAdapter(selection) {
1444
+ assertSupportedProvider(selection);
1445
+ const { PhantomWalletAdapter } = await import('@solana/wallet-adapter-phantom');
1446
+ return new PhantomWalletAdapter();
1447
+ }
1448
+ function readPublicKey(adapter) {
1449
+ const publicKey = adapter.publicKey?.toBase58();
1450
+ if (!publicKey) {
1451
+ throw new Error("Solana wallet did not return a public key.");
1452
+ }
1453
+ return publicKey;
1454
+ }
1455
+ async function connectSolanaWallet(selection, options) {
1456
+ const key = providerKey(selection);
1457
+ if (!cachedAdapter || cachedProviderKey !== key) {
1458
+ cachedAdapter = await createAdapter(selection);
1459
+ cachedProviderKey = key;
1460
+ }
1461
+ if (!cachedAdapter.connected) {
1462
+ const adapter = cachedAdapter;
1463
+ const connectPromise = adapter.connect();
1464
+ const timeoutMs = options?.timeoutMs;
1465
+ if (typeof timeoutMs === "number" && timeoutMs > 0) {
1466
+ let timeoutHandle = null;
1467
+ const timeoutPromise = new Promise((_, reject) => {
1468
+ timeoutHandle = setTimeout(() => {
1469
+ reject(new Error(PHANTOM_SOLANA_CONNECT_TIMEOUT_MESSAGE));
1470
+ }, timeoutMs);
1471
+ });
1472
+ try {
1473
+ await Promise.race([connectPromise, timeoutPromise]);
1474
+ } finally {
1475
+ if (timeoutHandle) clearTimeout(timeoutHandle);
1476
+ }
1477
+ } else {
1478
+ await connectPromise;
1479
+ }
1480
+ }
1481
+ return {
1482
+ adapter: cachedAdapter,
1483
+ publicKey: readPublicKey(cachedAdapter)
1484
+ };
1485
+ }
1486
+ async function signSolanaTransaction(selection, unsignedTxBase64, expectedOwnerPubkey) {
1487
+ const { adapter, publicKey } = await connectSolanaWallet(selection);
1488
+ if (publicKey !== expectedOwnerPubkey) {
1489
+ throw new Error(
1490
+ `Connected Solana wallet ${publicKey} does not match the required source wallet ${expectedOwnerPubkey}. Please switch accounts in Phantom and retry.`
1491
+ );
1492
+ }
1493
+ const signer = asSigner(adapter);
1494
+ if (typeof signer.signTransaction !== "function") {
1495
+ throw new Error("Selected Solana wallet does not support transaction signing.");
1496
+ }
1497
+ const transaction = await deserializeTransaction(unsignedTxBase64);
1498
+ const signedTransaction = await signer.signTransaction(transaction);
1499
+ return {
1500
+ ownerPubkey: publicKey,
1501
+ signedTxBase64: bytesToBase64(serializeTransaction(signedTransaction))
1502
+ };
1503
+ }
1504
+ async function deserializeTransaction(unsignedTxBase64) {
1505
+ const { Transaction, VersionedTransaction } = await import('@solana/web3.js');
1506
+ const bytes = base64ToBytes(unsignedTxBase64);
1507
+ try {
1508
+ return Transaction.from(bytes);
1509
+ } catch {
1510
+ return VersionedTransaction.deserialize(bytes);
1511
+ }
1512
+ }
1513
+ function serializeTransaction(transaction) {
1514
+ if ("version" in transaction) {
1515
+ return transaction.serialize();
1516
+ }
1517
+ return transaction.serialize({
1518
+ requireAllSignatures: false,
1519
+ verifySignatures: false
1520
+ });
1521
+ }
1522
+ function base64ToBytes(value) {
1523
+ if (typeof globalThis.atob === "function") {
1524
+ const binary = globalThis.atob(value);
1525
+ const bytes = new Uint8Array(binary.length);
1526
+ for (let i = 0; i < binary.length; i++) {
1527
+ bytes[i] = binary.charCodeAt(i);
1528
+ }
1529
+ return bytes;
1530
+ }
1531
+ const bufferCtor = globalThis.Buffer;
1532
+ if (bufferCtor) {
1533
+ return bufferCtor.from(value, "base64");
1534
+ }
1535
+ throw new Error("Base64 decoding is not available in this environment.");
1536
+ }
1537
+ function bytesToBase64(bytes) {
1538
+ if (typeof globalThis.btoa === "function") {
1539
+ let binary = "";
1540
+ for (const byte of bytes) {
1541
+ binary += String.fromCharCode(byte);
1542
+ }
1543
+ return globalThis.btoa(binary);
1544
+ }
1545
+ const bufferCtor = globalThis.Buffer;
1546
+ if (bufferCtor) {
1547
+ return bufferCtor.from(bytes).toString("base64");
1548
+ }
1549
+ throw new Error("Base64 encoding is not available in this environment.");
1550
+ }
1551
+ async function signAndSendApproveSplViaWallet(params) {
1552
+ const rpcUrl = params.rpcUrl?.trim();
1553
+ if (!rpcUrl) {
1554
+ throw new Error("signAndSendApproveSplViaWallet requires an rpcUrl.");
1555
+ }
1556
+ const unsignedTxBase64 = params.unsignedTxBase64?.trim();
1557
+ if (!unsignedTxBase64) {
1558
+ throw new Error("signAndSendApproveSplViaWallet requires unsignedTxBase64.");
1559
+ }
1560
+ const commitment = params.commitment ?? DEFAULT_COMMITMENT;
1561
+ const { adapter, publicKey } = await connectSolanaWallet(params.selection);
1562
+ if (publicKey !== params.expectedOwnerPubkey) {
1563
+ throw new Error(
1564
+ `Connected Solana wallet ${publicKey} does not match the required source wallet ${params.expectedOwnerPubkey}. Please switch accounts in Phantom and retry.`
1565
+ );
1566
+ }
1567
+ if (!adapter.sendTransaction) {
1568
+ throw new Error("Selected Solana wallet does not support sendTransaction.");
1569
+ }
1570
+ const transaction = await deserializeTransaction(unsignedTxBase64);
1571
+ const connection = await defaultConnectionFactory(rpcUrl, commitment);
1572
+ const signature = await adapter.sendTransaction(
1573
+ transaction,
1574
+ connection,
1575
+ {
1576
+ preflightCommitment: commitment,
1577
+ maxRetries: 3
1578
+ }
1579
+ );
1580
+ return { ownerPubkey: publicKey, signature };
1581
+ }
1582
+ async function confirmApproveSplViaPolling(params) {
1583
+ const rpcUrl = params.rpcUrl?.trim();
1584
+ if (!rpcUrl) {
1585
+ throw new Error("confirmApproveSplViaPolling requires an rpcUrl.");
1586
+ }
1587
+ const signature = params.signature?.trim();
1588
+ if (!signature) {
1589
+ throw new Error("confirmApproveSplViaPolling requires a signature.");
1590
+ }
1591
+ const confirmTimeoutMs = params.confirmTimeoutMs ?? DEFAULT_CONFIRM_TIMEOUT_MS;
1592
+ const pollIntervalMs = params.pollIntervalMs ?? DEFAULT_POLL_INTERVAL_MS;
1593
+ const commitment = params.commitment ?? DEFAULT_COMMITMENT;
1594
+ const connection = await defaultConnectionFactory(rpcUrl, commitment);
1595
+ const slot = await pollForConfirmation({
1596
+ connection,
1597
+ signature,
1598
+ confirmTimeoutMs,
1599
+ pollIntervalMs
1600
+ });
1601
+ return { signature, slot };
1602
+ }
1603
+ async function defaultConnectionFactory(rpcUrl, commitment) {
1604
+ const { Connection } = await import('@solana/web3.js');
1605
+ return new Connection(rpcUrl, commitment);
1606
+ }
1607
+ async function pollForConfirmation(args) {
1608
+ const { connection, signature, confirmTimeoutMs, pollIntervalMs } = args;
1609
+ const expiresAt = Date.now() + confirmTimeoutMs;
1610
+ while (Date.now() <= expiresAt) {
1611
+ const result = await connection.getSignatureStatuses(
1612
+ [signature],
1613
+ { searchTransactionHistory: true }
1614
+ );
1615
+ const status = result.value[0];
1616
+ if (status?.err) {
1617
+ throw new Error(`${APPROVE_SPL_ONCHAIN_FAILURE_PREFIX} ${JSON.stringify(status.err)}`);
1618
+ }
1619
+ const confirmationStatus = status?.confirmationStatus;
1620
+ if (confirmationStatus === "confirmed" || confirmationStatus === "finalized") {
1621
+ return status?.slot;
1622
+ }
1623
+ await sleep(pollIntervalMs);
1624
+ }
1625
+ throw new Error(APPROVE_SPL_CONFIRMATION_TIMEOUT_MESSAGE);
1626
+ }
1627
+ function sleep(ms) {
1628
+ return new Promise((resolve) => setTimeout(resolve, ms));
1629
+ }
1630
+ function getInjectedSolanaProvider(windowImpl) {
1631
+ const win = (typeof window === "undefined" ? void 0 : window);
1632
+ if (!win) return null;
1633
+ return win.phantom?.solana ?? win.solana ?? null;
1634
+ }
1635
+ async function disconnectSolanaWallet(windowImpl) {
1636
+ const adapter = cachedAdapter;
1637
+ cachedAdapter = null;
1638
+ cachedProviderKey = null;
1639
+ if (adapter?.connected) {
1640
+ try {
1641
+ console.info("[blink-sdk][solana-disconnect] disconnecting cached adapter");
1642
+ await adapter.disconnect();
1643
+ console.info("[blink-sdk][solana-disconnect] ok (cached adapter)");
1644
+ return;
1645
+ } catch (err) {
1646
+ console.warn("[blink-sdk][solana-disconnect] cached adapter disconnect failed", {
1647
+ message: err instanceof Error ? err.message : String(err)
1648
+ });
1649
+ }
1650
+ }
1651
+ const provider = getInjectedSolanaProvider();
1652
+ if (!provider) {
1653
+ console.info("[blink-sdk][solana-disconnect] no cached adapter and no injected provider \u2014 nothing to disconnect");
1654
+ return;
1655
+ }
1656
+ if (provider.isConnected === false) {
1657
+ console.info("[blink-sdk][solana-disconnect] injected provider already disconnected");
1658
+ return;
1659
+ }
1660
+ if (typeof provider.disconnect !== "function") {
1661
+ console.warn("[blink-sdk][solana-disconnect] injected provider has no disconnect() method");
1662
+ return;
1663
+ }
1664
+ try {
1665
+ console.info("[blink-sdk][solana-disconnect] disconnecting injected provider");
1666
+ await provider.disconnect();
1667
+ console.info("[blink-sdk][solana-disconnect] ok (injected provider)");
1668
+ } catch (err) {
1669
+ console.warn("[blink-sdk][solana-disconnect] injected provider disconnect failed", {
1670
+ message: err instanceof Error ? err.message : String(err)
1671
+ });
1672
+ }
1673
+ }
1674
+
1414
1675
  // src/otherWalletConnect.ts
1415
1676
  function findWalletConnectConnector(connectors) {
1416
1677
  return connectors.find((connector) => {
@@ -1840,6 +2101,7 @@ __export(api_exports, {
1840
2101
  setAuthorizationSessionPaymentIntentAmount: () => setAuthorizationSessionPaymentIntentAmount,
1841
2102
  setAuthorizationSessionProvider: () => setAuthorizationSessionProvider,
1842
2103
  signTransfer: () => signTransfer,
2104
+ updateManualTransferDepositTargetChain: () => updateManualTransferDepositTargetChain,
1843
2105
  updateUserConfig: () => updateUserConfig,
1844
2106
  updateUserConfigBySession: () => updateUserConfigBySession,
1845
2107
  waitForActionTransactionReceipt: () => waitForActionTransactionReceipt
@@ -2238,6 +2500,15 @@ async function fetchManualTransferSession(apiBaseUrl, sessionId) {
2238
2500
  if (!res.ok) await throwApiError(res);
2239
2501
  return await res.json();
2240
2502
  }
2503
+ async function updateManualTransferDepositTargetChain(apiBaseUrl, sessionId, selectedChainId) {
2504
+ const res = await fetch(`${apiBaseUrl}/v1/manual-transfers/${sessionId}`, {
2505
+ method: "PATCH",
2506
+ headers: { "Content-Type": "application/json" },
2507
+ body: JSON.stringify({ selectedChainId })
2508
+ });
2509
+ if (!res.ok) await throwApiError(res);
2510
+ return await res.json();
2511
+ }
2241
2512
  async function refreshManualTransferQuote(apiBaseUrl, sessionId) {
2242
2513
  const res = await fetch(
2243
2514
  `${apiBaseUrl}/v1/manual-transfers/${sessionId}/refresh-quote`,
@@ -2990,7 +3261,7 @@ async function waitForWalletNonceAgreement(params) {
2990
3261
  }
2991
3262
 
2992
3263
  // src/walletCallsStatus.ts
2993
- var DEFAULT_POLL_INTERVAL_MS = 2e3;
3264
+ var DEFAULT_POLL_INTERVAL_MS2 = 2e3;
2994
3265
  var DEFAULT_MAX_ATTEMPTS = 60;
2995
3266
  var DEFAULT_REQUEST_TIMEOUT_MS = 8e3;
2996
3267
  var DEFAULT_MAX_CONSECUTIVE_ERRORS = 5;
@@ -3012,7 +3283,7 @@ function classifyCallsStatus(status) {
3012
3283
  return "pending";
3013
3284
  }
3014
3285
  async function pollWalletCallsStatus(walletClient, callsId, options = {}) {
3015
- const pollIntervalMs = options.pollIntervalMs ?? DEFAULT_POLL_INTERVAL_MS;
3286
+ const pollIntervalMs = options.pollIntervalMs ?? DEFAULT_POLL_INTERVAL_MS2;
3016
3287
  const maxAttempts = options.maxAttempts ?? DEFAULT_MAX_ATTEMPTS;
3017
3288
  const requestTimeoutMs = options.requestTimeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS;
3018
3289
  const maxConsecutiveErrors = options.maxConsecutiveErrors ?? DEFAULT_MAX_CONSECUTIVE_ERRORS;
@@ -3130,219 +3401,6 @@ async function withWatchdog(promise, label, options = {}) {
3130
3401
  }
3131
3402
  }
3132
3403
 
3133
- // src/solanaWalletRuntime.ts
3134
- function asSigner(adapter) {
3135
- return adapter;
3136
- }
3137
- var PHANTOM_SOLANA_CONNECT_TIMEOUT_MESSAGE = "PHANTOM_SOLANA_CONNECT_TIMEOUT";
3138
- var APPROVE_SPL_CONFIRMATION_TIMEOUT_MESSAGE = "APPROVE_SPL_CONFIRMATION_TIMEOUT";
3139
- var APPROVE_SPL_ONCHAIN_FAILURE_PREFIX = "Solana transaction failed:";
3140
- var DEFAULT_CONFIRM_TIMEOUT_MS = 45e3;
3141
- var DEFAULT_POLL_INTERVAL_MS2 = 1e3;
3142
- var DEFAULT_COMMITMENT = "confirmed";
3143
- var cachedAdapter = null;
3144
- var cachedProviderKey = null;
3145
- function providerKey(selection) {
3146
- const providerName = selection.providerName?.trim();
3147
- if (!providerName) {
3148
- throw new Error("Solana wallet metadata is missing providerName.");
3149
- }
3150
- return `${selection.providerId ?? ""}:${providerName.toLowerCase()}`;
3151
- }
3152
- function assertSupportedProvider(selection) {
3153
- const name = selection.providerName?.trim().toLowerCase();
3154
- if (name !== "phantom") {
3155
- throw new Error(`Unsupported Solana wallet provider: ${selection.providerName ?? "unknown"}.`);
3156
- }
3157
- }
3158
- async function createAdapter(selection) {
3159
- assertSupportedProvider(selection);
3160
- const { PhantomWalletAdapter } = await import('@solana/wallet-adapter-phantom');
3161
- return new PhantomWalletAdapter();
3162
- }
3163
- function readPublicKey(adapter) {
3164
- const publicKey = adapter.publicKey?.toBase58();
3165
- if (!publicKey) {
3166
- throw new Error("Solana wallet did not return a public key.");
3167
- }
3168
- return publicKey;
3169
- }
3170
- async function connectSolanaWallet(selection, options) {
3171
- const key = providerKey(selection);
3172
- if (!cachedAdapter || cachedProviderKey !== key) {
3173
- cachedAdapter = await createAdapter(selection);
3174
- cachedProviderKey = key;
3175
- }
3176
- if (!cachedAdapter.connected) {
3177
- const adapter = cachedAdapter;
3178
- const connectPromise = adapter.connect();
3179
- const timeoutMs = options?.timeoutMs;
3180
- if (typeof timeoutMs === "number" && timeoutMs > 0) {
3181
- let timeoutHandle = null;
3182
- const timeoutPromise = new Promise((_, reject) => {
3183
- timeoutHandle = setTimeout(() => {
3184
- reject(new Error(PHANTOM_SOLANA_CONNECT_TIMEOUT_MESSAGE));
3185
- }, timeoutMs);
3186
- });
3187
- try {
3188
- await Promise.race([connectPromise, timeoutPromise]);
3189
- } finally {
3190
- if (timeoutHandle) clearTimeout(timeoutHandle);
3191
- }
3192
- } else {
3193
- await connectPromise;
3194
- }
3195
- }
3196
- return {
3197
- adapter: cachedAdapter,
3198
- publicKey: readPublicKey(cachedAdapter)
3199
- };
3200
- }
3201
- async function signSolanaTransaction(selection, unsignedTxBase64, expectedOwnerPubkey) {
3202
- const { adapter, publicKey } = await connectSolanaWallet(selection);
3203
- if (publicKey !== expectedOwnerPubkey) {
3204
- throw new Error(
3205
- `Connected Solana wallet ${publicKey} does not match the required source wallet ${expectedOwnerPubkey}. Please switch accounts in Phantom and retry.`
3206
- );
3207
- }
3208
- const signer = asSigner(adapter);
3209
- if (typeof signer.signTransaction !== "function") {
3210
- throw new Error("Selected Solana wallet does not support transaction signing.");
3211
- }
3212
- const transaction = await deserializeTransaction(unsignedTxBase64);
3213
- const signedTransaction = await signer.signTransaction(transaction);
3214
- return {
3215
- ownerPubkey: publicKey,
3216
- signedTxBase64: bytesToBase64(serializeTransaction(signedTransaction))
3217
- };
3218
- }
3219
- async function deserializeTransaction(unsignedTxBase64) {
3220
- const { Transaction, VersionedTransaction } = await import('@solana/web3.js');
3221
- const bytes = base64ToBytes(unsignedTxBase64);
3222
- try {
3223
- return Transaction.from(bytes);
3224
- } catch {
3225
- return VersionedTransaction.deserialize(bytes);
3226
- }
3227
- }
3228
- function serializeTransaction(transaction) {
3229
- if ("version" in transaction) {
3230
- return transaction.serialize();
3231
- }
3232
- return transaction.serialize({
3233
- requireAllSignatures: false,
3234
- verifySignatures: false
3235
- });
3236
- }
3237
- function base64ToBytes(value) {
3238
- if (typeof globalThis.atob === "function") {
3239
- const binary = globalThis.atob(value);
3240
- const bytes = new Uint8Array(binary.length);
3241
- for (let i = 0; i < binary.length; i++) {
3242
- bytes[i] = binary.charCodeAt(i);
3243
- }
3244
- return bytes;
3245
- }
3246
- const bufferCtor = globalThis.Buffer;
3247
- if (bufferCtor) {
3248
- return bufferCtor.from(value, "base64");
3249
- }
3250
- throw new Error("Base64 decoding is not available in this environment.");
3251
- }
3252
- function bytesToBase64(bytes) {
3253
- if (typeof globalThis.btoa === "function") {
3254
- let binary = "";
3255
- for (const byte of bytes) {
3256
- binary += String.fromCharCode(byte);
3257
- }
3258
- return globalThis.btoa(binary);
3259
- }
3260
- const bufferCtor = globalThis.Buffer;
3261
- if (bufferCtor) {
3262
- return bufferCtor.from(bytes).toString("base64");
3263
- }
3264
- throw new Error("Base64 encoding is not available in this environment.");
3265
- }
3266
- async function signAndSendApproveSplViaWallet(params) {
3267
- const rpcUrl = params.rpcUrl?.trim();
3268
- if (!rpcUrl) {
3269
- throw new Error("signAndSendApproveSplViaWallet requires an rpcUrl.");
3270
- }
3271
- const unsignedTxBase64 = params.unsignedTxBase64?.trim();
3272
- if (!unsignedTxBase64) {
3273
- throw new Error("signAndSendApproveSplViaWallet requires unsignedTxBase64.");
3274
- }
3275
- const commitment = params.commitment ?? DEFAULT_COMMITMENT;
3276
- const { adapter, publicKey } = await connectSolanaWallet(params.selection);
3277
- if (publicKey !== params.expectedOwnerPubkey) {
3278
- throw new Error(
3279
- `Connected Solana wallet ${publicKey} does not match the required source wallet ${params.expectedOwnerPubkey}. Please switch accounts in Phantom and retry.`
3280
- );
3281
- }
3282
- if (!adapter.sendTransaction) {
3283
- throw new Error("Selected Solana wallet does not support sendTransaction.");
3284
- }
3285
- const transaction = await deserializeTransaction(unsignedTxBase64);
3286
- const connection = await defaultConnectionFactory(rpcUrl, commitment);
3287
- const signature = await adapter.sendTransaction(
3288
- transaction,
3289
- connection,
3290
- {
3291
- preflightCommitment: commitment,
3292
- maxRetries: 3
3293
- }
3294
- );
3295
- return { ownerPubkey: publicKey, signature };
3296
- }
3297
- async function confirmApproveSplViaPolling(params) {
3298
- const rpcUrl = params.rpcUrl?.trim();
3299
- if (!rpcUrl) {
3300
- throw new Error("confirmApproveSplViaPolling requires an rpcUrl.");
3301
- }
3302
- const signature = params.signature?.trim();
3303
- if (!signature) {
3304
- throw new Error("confirmApproveSplViaPolling requires a signature.");
3305
- }
3306
- const confirmTimeoutMs = params.confirmTimeoutMs ?? DEFAULT_CONFIRM_TIMEOUT_MS;
3307
- const pollIntervalMs = params.pollIntervalMs ?? DEFAULT_POLL_INTERVAL_MS2;
3308
- const commitment = params.commitment ?? DEFAULT_COMMITMENT;
3309
- const connection = await defaultConnectionFactory(rpcUrl, commitment);
3310
- const slot = await pollForConfirmation({
3311
- connection,
3312
- signature,
3313
- confirmTimeoutMs,
3314
- pollIntervalMs
3315
- });
3316
- return { signature, slot };
3317
- }
3318
- async function defaultConnectionFactory(rpcUrl, commitment) {
3319
- const { Connection } = await import('@solana/web3.js');
3320
- return new Connection(rpcUrl, commitment);
3321
- }
3322
- async function pollForConfirmation(args) {
3323
- const { connection, signature, confirmTimeoutMs, pollIntervalMs } = args;
3324
- const expiresAt = Date.now() + confirmTimeoutMs;
3325
- while (Date.now() <= expiresAt) {
3326
- const result = await connection.getSignatureStatuses(
3327
- [signature],
3328
- { searchTransactionHistory: true }
3329
- );
3330
- const status = result.value[0];
3331
- if (status?.err) {
3332
- throw new Error(`${APPROVE_SPL_ONCHAIN_FAILURE_PREFIX} ${JSON.stringify(status.err)}`);
3333
- }
3334
- const confirmationStatus = status?.confirmationStatus;
3335
- if (confirmationStatus === "confirmed" || confirmationStatus === "finalized") {
3336
- return status?.slot;
3337
- }
3338
- await sleep(pollIntervalMs);
3339
- }
3340
- throw new Error(APPROVE_SPL_CONFIRMATION_TIMEOUT_MESSAGE);
3341
- }
3342
- function sleep(ms) {
3343
- return new Promise((resolve) => setTimeout(resolve, ms));
3344
- }
3345
-
3346
3404
  // src/walletConnectRuntime.ts
3347
3405
  var PRIMARY_CHAIN_ID = 8453;
3348
3406
  var OPTIONAL_CHAIN_IDS = [1, 42161, 137, 56, 6342, 10143, 999, 84532];
@@ -6994,6 +7052,7 @@ function useManualTransferSession({
6994
7052
  const completedRef = react.useRef(/* @__PURE__ */ new Set());
6995
7053
  const premintedFamiliesRef = react.useRef(/* @__PURE__ */ new Set());
6996
7054
  const inFlightPerTokenRef = react.useRef(/* @__PURE__ */ new Set());
7055
+ const reportedTargetChainRef = react.useRef(/* @__PURE__ */ new Map());
6997
7056
  react.useEffect(() => {
6998
7057
  if (!merchantAuthorization) return;
6999
7058
  let cancelled = false;
@@ -7146,6 +7205,51 @@ function useManualTransferSession({
7146
7205
  }, 2e3);
7147
7206
  return () => window.clearInterval(timer);
7148
7207
  }, [apiBaseUrl, activeSessionId, activeSessionStatus, pollEnabled]);
7208
+ const selectedSourceChainId = selectedOption?.chainId;
7209
+ const sessionRegistrationChainId = session?.source.chainId;
7210
+ react.useEffect(() => {
7211
+ if (!activeSessionId) return;
7212
+ if (selectedSourceChainId === void 0) return;
7213
+ if (sessionRegistrationChainId === void 0) return;
7214
+ if (!selectedOption) return;
7215
+ if (selectedOption.chainFamily !== "evm") return;
7216
+ if (isSameChainSameTokenSelection(selectedOption, destination)) return;
7217
+ const lastReported = reportedTargetChainRef.current.get(activeSessionId) ?? sessionRegistrationChainId;
7218
+ if (selectedSourceChainId === lastReported) return;
7219
+ reportedTargetChainRef.current.set(activeSessionId, selectedSourceChainId);
7220
+ let cancelled = false;
7221
+ updateManualTransferDepositTargetChain(apiBaseUrl, activeSessionId, selectedSourceChainId).then((updated) => {
7222
+ if (cancelled) return;
7223
+ setSessionsByFamily((prev) => {
7224
+ for (const family of Object.keys(prev)) {
7225
+ if (prev[family]?.sessionId === updated.sessionId) {
7226
+ return { ...prev, [family]: updated };
7227
+ }
7228
+ }
7229
+ return prev;
7230
+ });
7231
+ setPerTokenSessions((prev) => {
7232
+ for (const k of Object.keys(prev)) {
7233
+ if (prev[k]?.sessionId === updated.sessionId) {
7234
+ return { ...prev, [k]: updated };
7235
+ }
7236
+ }
7237
+ return prev;
7238
+ });
7239
+ }).catch(() => {
7240
+ reportedTargetChainRef.current.set(activeSessionId, lastReported);
7241
+ });
7242
+ return () => {
7243
+ cancelled = true;
7244
+ };
7245
+ }, [
7246
+ apiBaseUrl,
7247
+ activeSessionId,
7248
+ selectedSourceChainId,
7249
+ sessionRegistrationChainId,
7250
+ selectedOption,
7251
+ destination
7252
+ ]);
7149
7253
  const completionSignature = react.useMemo(() => {
7150
7254
  const entries2 = [];
7151
7255
  for (const family of Object.keys(sessionsByFamily)) {
@@ -12579,6 +12683,7 @@ function SelectDepositSourceScreen({
12579
12683
  {
12580
12684
  symbol: opt.symbol,
12581
12685
  chainName: opt.chainName,
12686
+ tokenLogoUri: opt.logoURI,
12582
12687
  balance: opt.balance,
12583
12688
  selected: !hasPendingMobileSelection && isSelected(opt),
12584
12689
  onClick: () => handleAuthorizedPick(opt)
@@ -12590,6 +12695,7 @@ function SelectDepositSourceScreen({
12590
12695
  {
12591
12696
  symbol: opt.symbol,
12592
12697
  chainName: opt.chainName,
12698
+ tokenLogoUri: opt.logoURI,
12593
12699
  balance: opt.balance,
12594
12700
  requiresAuth: true,
12595
12701
  selected: hasPendingMobileSelection ? pendingMobileSelection?.key === tokenOptionKey(opt) : isSelected(opt),
@@ -13627,7 +13733,7 @@ function SelectSourceScreen({
13627
13733
  /* @__PURE__ */ jsxRuntime.jsx("label", { style: labelStyle5(tokens.textSecondary), children: "Token" }),
13628
13734
  /* @__PURE__ */ jsxRuntime.jsx("div", { style: optionListStyle, children: tokenChoices.map((token) => {
13629
13735
  const isSelected = token.tokenSymbol === selectedTokenSymbol;
13630
- const logo = token.walletLogoUrl ?? TOKEN_LOGOS[token.tokenSymbol];
13736
+ const logo = token.walletLogoUrl ?? token.logoURI ?? TOKEN_LOGOS[token.tokenSymbol];
13631
13737
  const logoAlt = token.walletLogoUrl ? token.walletName ?? token.tokenSymbol : token.tokenSymbol;
13632
13738
  return /* @__PURE__ */ jsxRuntime.jsxs(
13633
13739
  "button",
@@ -15224,10 +15330,12 @@ function TokenPickerScreen({
15224
15330
  tokenSymbol: source.token.symbol,
15225
15331
  tokenAddress: source.address,
15226
15332
  balance: visibleBalance,
15227
- status: source.token.status
15333
+ status: source.token.status,
15334
+ logoURI: source.token.logoURI
15228
15335
  });
15229
15336
  }
15230
15337
  }
15338
+ const selectedEntryLogo = selectedTokenSymbol ? entries2.find((e) => e.tokenSymbol === selectedTokenSymbol)?.logoURI ?? TOKEN_LOGOS[selectedTokenSymbol] : void 0;
15231
15339
  const handleSelect = (entry) => {
15232
15340
  if (entry.status === "AUTHORIZED") {
15233
15341
  onSelectAuthorized(entry.walletId, entry.tokenSymbol);
@@ -15254,7 +15362,7 @@ function TokenPickerScreen({
15254
15362
  onClick: onBack,
15255
15363
  style: tokenIconButtonStyle,
15256
15364
  children: [
15257
- /* @__PURE__ */ jsxRuntime.jsx("div", { style: tokenIconWrapStyle, children: selectedTokenSymbol && TOKEN_LOGOS[selectedTokenSymbol] ? /* @__PURE__ */ jsxRuntime.jsx("img", { src: TOKEN_LOGOS[selectedTokenSymbol], alt: selectedTokenSymbol, width: 36, height: 36, style: { borderRadius: "50%" } }) : /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: "36", height: "36", viewBox: "0 0 36 36", fill: "none", children: [
15365
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: tokenIconWrapStyle, children: selectedEntryLogo ? /* @__PURE__ */ jsxRuntime.jsx("img", { src: selectedEntryLogo, alt: selectedTokenSymbol, width: 36, height: 36, style: { borderRadius: "50%" } }) : /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: "36", height: "36", viewBox: "0 0 36 36", fill: "none", children: [
15258
15366
  /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "18", cy: "18", r: "18", fill: "#2DB84B" }),
15259
15367
  /* @__PURE__ */ jsxRuntime.jsx("text", { x: "18", y: "23", textAnchor: "middle", fontSize: "18", fill: "#fff", fontWeight: "700", children: "$" })
15260
15368
  ] }) }),
@@ -15268,6 +15376,7 @@ function TokenPickerScreen({
15268
15376
  /* @__PURE__ */ jsxRuntime.jsx("div", { style: tokenListStyle2, children: entries2.map((entry) => {
15269
15377
  const authorized = entry.status === "AUTHORIZED";
15270
15378
  const isSelected = entry.walletId === selectedWalletId && entry.tokenSymbol === selectedTokenSymbol;
15379
+ const entryLogo = entry.logoURI ?? TOKEN_LOGOS[entry.tokenSymbol];
15271
15380
  return /* @__PURE__ */ jsxRuntime.jsxs(
15272
15381
  "button",
15273
15382
  {
@@ -15275,7 +15384,7 @@ function TokenPickerScreen({
15275
15384
  onClick: () => handleSelect(entry),
15276
15385
  style: tokenRowStyle2(t),
15277
15386
  children: [
15278
- /* @__PURE__ */ jsxRuntime.jsx("div", { style: tokenIconCircleStyle2(t, !!TOKEN_LOGOS[entry.tokenSymbol]), children: TOKEN_LOGOS[entry.tokenSymbol] ? /* @__PURE__ */ jsxRuntime.jsx("img", { src: TOKEN_LOGOS[entry.tokenSymbol], alt: entry.tokenSymbol, style: tokenLogoImgStyle2 }) : /* @__PURE__ */ jsxRuntime.jsx("span", { style: tokenIconTextStyle2(t.textMuted), children: "$" }) }),
15387
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: tokenIconCircleStyle2(t, !!entryLogo), children: entryLogo ? /* @__PURE__ */ jsxRuntime.jsx("img", { src: entryLogo, alt: entry.tokenSymbol, style: tokenLogoImgStyle2 }) : /* @__PURE__ */ jsxRuntime.jsx("span", { style: tokenIconTextStyle2(t.textMuted), children: "$" }) }),
15279
15388
  /* @__PURE__ */ jsxRuntime.jsxs("div", { style: tokenInfoStyle2, children: [
15280
15389
  /* @__PURE__ */ jsxRuntime.jsxs("div", { style: tokenNameRowStyle, children: [
15281
15390
  /* @__PURE__ */ jsxRuntime.jsx("span", { style: tokenSymbolTextStyle(t.text), children: entry.tokenSymbol }),
@@ -16162,7 +16271,8 @@ function buildDepositScreenProps({
16162
16271
  status: source.token.status,
16163
16272
  tokenAddress: source.address,
16164
16273
  chainId: chain?.commonId ?? void 0,
16165
- accountId: account.id
16274
+ accountId: account.id,
16275
+ logoURI: source.token.logoURI
16166
16276
  });
16167
16277
  }
16168
16278
  }
@@ -16215,6 +16325,7 @@ function buildDepositScreenProps({
16215
16325
  },
16216
16326
  selectedTokenSymbol: selectedSource?.token.symbol,
16217
16327
  selectedChainName: selectedWallet?.chain.name,
16328
+ selectedTokenLogoUri: selectedSource?.token.logoURI,
16218
16329
  selectedWalletId: selectedWallet?.id ?? null,
16219
16330
  selectedTokenStatus,
16220
16331
  onAuthorizeSelectedToken,
@@ -19612,12 +19723,20 @@ function BlinkPaymentInner({
19612
19723
  dispatch,
19613
19724
  orchestrator
19614
19725
  ]);
19726
+ const disconnectWallets = react.useCallback(async () => {
19727
+ await Promise.allSettled([
19728
+ revokeAndDisconnectActiveWagmiConnector(wagmiConfig),
19729
+ authExecutor.resetWalletConnect().catch(() => {
19730
+ }),
19731
+ disconnectSolanaWallet()
19732
+ ]);
19733
+ }, [authExecutor, wagmiConfig]);
19615
19734
  const handleBackFromSetupDeposit = react.useCallback(async () => {
19616
19735
  orchestrator.cancelPendingFlow();
19617
19736
  authExecutor.cancelPendingExecution();
19618
19737
  clearScreenErrors();
19619
19738
  if (isDesktop) {
19620
- await revokeAndDisconnectActiveWagmiConnector(wagmiConfig);
19739
+ await disconnectWallets();
19621
19740
  }
19622
19741
  dispatch({ type: "RESTORE_SELECTION" });
19623
19742
  dispatch({ type: "CLEAR_SETUP_DEPOSIT_TOKEN" });
@@ -19625,7 +19744,7 @@ function BlinkPaymentInner({
19625
19744
  dispatch({ type: "DESKTOP_WAIT_CLEARED" });
19626
19745
  dispatch({ type: "SET_STANDARD_DESKTOP_INLINE_OPEN_WALLET", value: false });
19627
19746
  dispatch({ type: "SET_USER_INTENT", intent: { step: "wallet-picker", reason: "switch" } });
19628
- }, [authExecutor, clearScreenErrors, orchestrator, dispatch, isDesktop, wagmiConfig]);
19747
+ }, [authExecutor, clearScreenErrors, orchestrator, dispatch, isDesktop, disconnectWallets]);
19629
19748
  const handleAuthorizationRetry = react.useCallback(() => {
19630
19749
  void (async () => {
19631
19750
  try {
@@ -19670,11 +19789,7 @@ function BlinkPaymentInner({
19670
19789
  dispatch({ type: "DESKTOP_WAIT_CLEARED" });
19671
19790
  dispatch({ type: "SET_STANDARD_DESKTOP_INLINE_OPEN_WALLET", value: false });
19672
19791
  dispatch({ type: "SET_USER_INTENT", intent: { step: "wallet-picker", reason: "switch" } });
19673
- void (async () => {
19674
- await revokeAndDisconnectActiveWagmiConnector(wagmiConfig);
19675
- await authExecutor.resetWalletConnect().catch(() => {
19676
- });
19677
- })();
19792
+ void disconnectWallets();
19678
19793
  },
19679
19794
  onSendManually: () => handleSetPhase({ step: "manual-transfer" }),
19680
19795
  onBackFromSetupDeposit: handleBackFromSetupDeposit,
@@ -19721,7 +19836,7 @@ function BlinkPaymentInner({
19721
19836
  handleConfirmSetupDeposit,
19722
19837
  handleBackFromSetupDeposit,
19723
19838
  handleAuthorizationRetry,
19724
- wagmiConfig
19839
+ disconnectWallets
19725
19840
  ]);
19726
19841
  return /* @__PURE__ */ jsxRuntime.jsx(EffectiveDepositAmountProvider, { value: effectiveDepositAmount, children: /* @__PURE__ */ jsxRuntime.jsx(
19727
19842
  ManualTransferSessionProvider,