@openfort/react 1.2.0 → 1.4.0

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.
Files changed (146) hide show
  1. package/build/assets/logos.d.ts +3 -0
  2. package/build/assets/logos.js +2 -0
  3. package/build/assets/logos.js.map +1 -1
  4. package/build/components/Common/Modal/styles.js +3 -0
  5. package/build/components/Common/Modal/styles.js.map +1 -1
  6. package/build/components/Common/ScrollArea/index.d.ts +5 -1
  7. package/build/components/Common/ScrollArea/index.js +2 -2
  8. package/build/components/Common/ScrollArea/styles.d.ts +4 -1
  9. package/build/components/Common/ScrollArea/styles.js +19 -4
  10. package/build/components/Common/ScrollArea/styles.js.map +1 -1
  11. package/build/components/Common/SolanaChain/index.d.ts +8 -0
  12. package/build/components/Common/SolanaChain/index.js +40 -0
  13. package/build/components/Common/SolanaChain/index.js.map +1 -0
  14. package/build/components/ConnectModal/index.js +17 -5
  15. package/build/components/ConnectModal/index.js.map +1 -1
  16. package/build/components/Openfort/types.d.ts +17 -11
  17. package/build/components/Openfort/types.js +1 -0
  18. package/build/components/Openfort/types.js.map +1 -1
  19. package/build/components/PageContent/index.d.ts +2 -1
  20. package/build/components/PageContent/index.js +2 -2
  21. package/build/components/Pages/Buy/coinbaseApi.d.ts +1 -1
  22. package/build/components/Pages/Buy/coinbaseApi.js +2 -13
  23. package/build/components/Pages/Buy/coinbaseApi.js.map +1 -1
  24. package/build/components/Pages/Buy/evmCurrencies.d.ts +11 -0
  25. package/build/components/Pages/Buy/evmCurrencies.js +27 -0
  26. package/build/components/Pages/Buy/evmCurrencies.js.map +1 -0
  27. package/build/components/Pages/Buy/index.js +8 -1
  28. package/build/components/Pages/Buy/index.js.map +1 -1
  29. package/build/components/Pages/Buy/onrampApi.d.ts +8 -1
  30. package/build/components/Pages/Buy/onrampApi.js +24 -14
  31. package/build/components/Pages/Buy/onrampApi.js.map +1 -1
  32. package/build/components/Pages/Buy/solanaCurrencies.d.ts +9 -0
  33. package/build/components/Pages/Buy/solanaCurrencies.js +25 -0
  34. package/build/components/Pages/Buy/solanaCurrencies.js.map +1 -0
  35. package/build/components/Pages/Buy/stripeApi.d.ts +1 -1
  36. package/build/components/Pages/Buy/stripeApi.js +2 -13
  37. package/build/components/Pages/Buy/stripeApi.js.map +1 -1
  38. package/build/components/Pages/BuyComplete/index.js +7 -1
  39. package/build/components/Pages/BuyComplete/index.js.map +1 -1
  40. package/build/components/Pages/BuyProcessing/index.js +9 -5
  41. package/build/components/Pages/BuyProcessing/index.js.map +1 -1
  42. package/build/components/Pages/BuyProviderSelect/styles.d.ts +2 -1
  43. package/build/components/Pages/BuySelectProvider/index.js +10 -5
  44. package/build/components/Pages/BuySelectProvider/index.js.map +1 -1
  45. package/build/components/Pages/Connected/EthereumConnected.js +7 -3
  46. package/build/components/Pages/Connected/EthereumConnected.js.map +1 -1
  47. package/build/components/Pages/Connected/SolanaConnected.js +3 -2
  48. package/build/components/Pages/Connected/SolanaConnected.js.map +1 -1
  49. package/build/components/Pages/Deposit/AssetChainLogo.d.ts +5 -2
  50. package/build/components/Pages/Deposit/AssetChainLogo.js +21 -4
  51. package/build/components/Pages/Deposit/AssetChainLogo.js.map +1 -1
  52. package/build/components/Pages/Deposit/DepositAddressBlock.js +1 -1
  53. package/build/components/Pages/Deposit/DepositProgress.js +3 -2
  54. package/build/components/Pages/Deposit/DepositProgress.js.map +1 -1
  55. package/build/components/Pages/Deposit/DepositSuccess.js +2 -1
  56. package/build/components/Pages/Deposit/DepositSuccess.js.map +1 -1
  57. package/build/components/Pages/Deposit/RouteSelectors.js +11 -1
  58. package/build/components/Pages/Deposit/RouteSelectors.js.map +1 -1
  59. package/build/components/Pages/Deposit/SameChainDepositStatus.d.ts +7 -0
  60. package/build/components/Pages/Deposit/SameChainDepositStatus.js +34 -0
  61. package/build/components/Pages/Deposit/SameChainDepositStatus.js.map +1 -0
  62. package/build/components/Pages/Deposit/SameChainDepositSuccess.d.ts +11 -0
  63. package/build/components/Pages/Deposit/SameChainDepositSuccess.js +30 -0
  64. package/build/components/Pages/Deposit/SameChainDepositSuccess.js.map +1 -0
  65. package/build/components/Pages/Deposit/TestnetNotice.d.ts +10 -0
  66. package/build/components/Pages/Deposit/TestnetNotice.js +131 -0
  67. package/build/components/Pages/Deposit/TestnetNotice.js.map +1 -0
  68. package/build/components/Pages/Deposit/UnsupportedNetworkNotice.d.ts +12 -0
  69. package/build/components/Pages/Deposit/UnsupportedNetworkNotice.js +111 -0
  70. package/build/components/Pages/Deposit/UnsupportedNetworkNotice.js.map +1 -0
  71. package/build/components/Pages/Deposit/index.js +35 -5
  72. package/build/components/Pages/Deposit/index.js.map +1 -1
  73. package/build/components/Pages/Deposit/paymentOptions.d.ts +6 -0
  74. package/build/components/Pages/Deposit/paymentOptions.js +10 -4
  75. package/build/components/Pages/Deposit/paymentOptions.js.map +1 -1
  76. package/build/components/Pages/Deposit/useDepositRoute.d.ts +2 -1
  77. package/build/components/Pages/Deposit/useDepositRoute.js +36 -13
  78. package/build/components/Pages/Deposit/useDepositRoute.js.map +1 -1
  79. package/build/components/Pages/Deposit/useFundingTarget.d.ts +2 -4
  80. package/build/components/Pages/Deposit/useFundingTarget.js +3 -5
  81. package/build/components/Pages/Deposit/useFundingTarget.js.map +1 -1
  82. package/build/components/Pages/Deposit/useSameChainArrival.d.ts +19 -0
  83. package/build/components/Pages/Deposit/useSameChainArrival.js +86 -0
  84. package/build/components/Pages/Deposit/useSameChainArrival.js.map +1 -0
  85. package/build/components/Pages/DepositCex/index.js +7 -8
  86. package/build/components/Pages/DepositCex/index.js.map +1 -1
  87. package/build/components/Pages/DepositCrypto/index.js +26 -3
  88. package/build/components/Pages/DepositCrypto/index.js.map +1 -1
  89. package/build/components/Pages/DepositWallet/DepositWalletDesktop.d.ts +4 -1
  90. package/build/components/Pages/DepositWallet/DepositWalletDesktop.js +19 -27
  91. package/build/components/Pages/DepositWallet/DepositWalletDesktop.js.map +1 -1
  92. package/build/components/Pages/DepositWallet/index.d.ts +5 -5
  93. package/build/components/Pages/DepositWallet/index.js +82 -39
  94. package/build/components/Pages/DepositWallet/index.js.map +1 -1
  95. package/build/components/Pages/DepositWallet/walletDeeplinks.d.ts +6 -4
  96. package/build/components/Pages/DepositWallet/walletDeeplinks.js +3 -1
  97. package/build/components/Pages/DepositWallet/walletDeeplinks.js.map +1 -1
  98. package/build/components/Pages/SelectToken/SolanaSelectToken.d.ts +1 -0
  99. package/build/components/Pages/SelectToken/SolanaSelectToken.js +50 -0
  100. package/build/components/Pages/SelectToken/SolanaSelectToken.js.map +1 -0
  101. package/build/components/Pages/SelectToken/index.js +13 -2
  102. package/build/components/Pages/SelectToken/index.js.map +1 -1
  103. package/build/components/Pages/SelectToken/styles.d.ts +2 -1
  104. package/build/components/Pages/Send/SolanaSend.js +32 -31
  105. package/build/components/Pages/Send/SolanaSend.js.map +1 -1
  106. package/build/components/Pages/Send/utils.js +4 -1
  107. package/build/components/Pages/Send/utils.js.map +1 -1
  108. package/build/components/Pages/SendConfirmation/SolanaSendConfirmation.js +57 -13
  109. package/build/components/Pages/SendConfirmation/SolanaSendConfirmation.js.map +1 -1
  110. package/build/components/Pages/SendConfirmation/index.js +1 -1
  111. package/build/components/Pages/SendConfirmation/styles.d.ts +0 -5
  112. package/build/components/Pages/SendConfirmation/styles.js +1 -39
  113. package/build/components/Pages/SendConfirmation/styles.js.map +1 -1
  114. package/build/constants/chainConfigs.js +32 -32
  115. package/build/constants/logos.d.ts +4 -0
  116. package/build/constants/logos.js +25 -1
  117. package/build/constants/logos.js.map +1 -1
  118. package/build/ethereum/hooks/useEthereumWalletAssets.js +39 -3
  119. package/build/ethereum/hooks/useEthereumWalletAssets.js.map +1 -1
  120. package/build/hooks/openfort/useFunding.js +7 -7
  121. package/build/hooks/openfort/useFundingChains.d.ts +6 -0
  122. package/build/hooks/openfort/useFundingChains.js +22 -10
  123. package/build/hooks/openfort/useFundingChains.js.map +1 -1
  124. package/build/shared/hooks/useAsyncData.js +15 -2
  125. package/build/shared/hooks/useAsyncData.js.map +1 -1
  126. package/build/shared/utils/explorer.js +6 -4
  127. package/build/shared/utils/explorer.js.map +1 -1
  128. package/build/solana/transfer.d.ts +35 -6
  129. package/build/solana/transfer.js +112 -18
  130. package/build/solana/transfer.js.map +1 -1
  131. package/build/solana/types.d.ts +8 -0
  132. package/build/utils/validation.d.ts +9 -0
  133. package/build/utils/validation.js +14 -1
  134. package/build/utils/validation.js.map +1 -1
  135. package/build/version.d.ts +1 -1
  136. package/build/version.js +1 -1
  137. package/build/wagmi/components/ChainSelect/index.js +3 -2
  138. package/build/wagmi/components/ChainSelect/index.js.map +1 -1
  139. package/build/wagmi/components/ChainSelectList/index.js +3 -2
  140. package/build/wagmi/components/ChainSelectList/index.js.map +1 -1
  141. package/build/wagmi/components/SwitchNetworks/index.js +3 -2
  142. package/build/wagmi/components/SwitchNetworks/index.js.map +1 -1
  143. package/build/wagmi/useSwitchChainFiltered.d.ts +199 -0
  144. package/build/wagmi/useSwitchChainFiltered.js +53 -0
  145. package/build/wagmi/useSwitchChainFiltered.js.map +1 -0
  146. package/package.json +5 -1
@@ -1,2 +1,6 @@
1
1
  export declare const TOKEN_LOGO: Record<string, string>;
2
2
  export declare function symbolToColor(symbol: string): string;
3
+ /** Network logo for a chain: the curated brand first (clean + testnet-aware), then the backend value. */
4
+ export declare function chainLogoUrl(chainId?: number, apiLogo?: string | null): string | null;
5
+ /** Token logo for a symbol: the backend value first, then the curated map (covers native ETH/SOL/… which the rail returns null for). */
6
+ export declare function currencyLogoUrl(symbol?: string, apiLogo?: string | null): string | null;
@@ -54,6 +54,30 @@ function symbolToColor(symbol) {
54
54
  const h = ((hash % 360) + 360) % 360;
55
55
  return `hsl(${h}, 55%, 50%)`;
56
56
  }
57
+ // EVM chain id -> network logo URL. Testnet ids reuse their mainnet brand. Used
58
+ // instead of the funding rail's icon CDN, which serves a generic prism for
59
+ // testnets and a blank square for some mainnets.
60
+ const CHAIN_LOGO = {
61
+ 1: `${TW}/ethereum/info/logo.png`,
62
+ 11155111: `${TW}/ethereum/info/logo.png`, // Sepolia
63
+ 8453: `${TW}/base/info/logo.png`,
64
+ 84532: `${TW}/base/info/logo.png`, // Base Sepolia
65
+ 10: `${TW}/optimism/info/logo.png`,
66
+ 11155420: `${TW}/optimism/info/logo.png`, // OP Sepolia
67
+ 42161: `${TW}/arbitrum/info/logo.png`,
68
+ 421614: `${TW}/arbitrum/info/logo.png`, // Arbitrum Sepolia
69
+ 137: `${TW}/polygon/info/logo.png`,
70
+ 80002: `${TW}/polygon/info/logo.png`, // Polygon Amoy
71
+ 56: `${TW}/smartchain/info/logo.png`,
72
+ };
73
+ /** Network logo for a chain: the curated brand first (clean + testnet-aware), then the backend value. */
74
+ function chainLogoUrl(chainId, apiLogo) {
75
+ return (chainId !== undefined && CHAIN_LOGO[chainId]) || apiLogo || null;
76
+ }
77
+ /** Token logo for a symbol: the backend value first, then the curated map (covers native ETH/SOL/… which the rail returns null for). */
78
+ function currencyLogoUrl(symbol, apiLogo) {
79
+ return apiLogo || (symbol && TOKEN_LOGO[symbol.toUpperCase()]) || null;
80
+ }
57
81
 
58
- export { TOKEN_LOGO, symbolToColor };
82
+ export { TOKEN_LOGO, chainLogoUrl, currencyLogoUrl, symbolToColor };
59
83
  //# sourceMappingURL=logos.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"logos.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"logos.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -195,7 +195,7 @@ const useEthereumWalletAssets = ({ assets: hookCustomAssets, multiChain = false,
195
195
  ? ['wallet-assets', 'multi', address, customAssetsMultiChain]
196
196
  : [...openfortKeys.walletAssets(chainId, customAssetsToFetch, address)],
197
197
  queryFn: async () => {
198
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0, _1, _2;
198
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0, _1, _2, _3, _4, _5;
199
199
  if (multiChain) {
200
200
  if (!address) {
201
201
  throw new OpenfortError('No wallet address available', OpenfortReactErrorType.UNEXPECTED_ERROR);
@@ -292,6 +292,26 @@ const useEthereumWalletAssets = ({ assets: hookCustomAssets, multiChain = false,
292
292
  }
293
293
  }
294
294
  }
295
+ // The ERC-7811 proxy indexes mainnet; testnet natives (e.g. Base Sepolia ETH)
296
+ // come back missing or stale. For configured testnet chains, read the native
297
+ // balance straight from RPC — the same source Rabby uses — and upsert it.
298
+ const testnetChains = chains.filter((c) => c.testnet === true);
299
+ const rpcNatives = await Promise.all(testnetChains.map(async (c) => {
300
+ var _a, _b, _c;
301
+ const rpcUrl = (_c = (_b = (_a = walletConfig === null || walletConfig === void 0 ? void 0 : walletConfig.ethereum) === null || _a === void 0 ? void 0 : _a.rpcUrls) === null || _b === void 0 ? void 0 : _b[c.id]) !== null && _c !== void 0 ? _c : getDefaultEthereumRpcUrl(c.id);
302
+ const read = await readEvmAssetsViaRpc({ address: address, chain: c, rpcUrl, tokens: [] });
303
+ const native = read.find((a) => a.type === 'native');
304
+ return native ? { ...native, chainId: c.id } : null;
305
+ }));
306
+ for (const native of rpcNatives) {
307
+ if (!native)
308
+ continue;
309
+ const idx = allAssets.findIndex((a) => a.type === 'native' && a.chainId === native.chainId);
310
+ if (idx >= 0)
311
+ allAssets[idx] = native;
312
+ else
313
+ allAssets.push(native);
314
+ }
295
315
  allAssets.sort((a, b) => getUsdValue(b) - getUsdValue(a));
296
316
  return allAssets;
297
317
  }
@@ -389,9 +409,25 @@ const useEthereumWalletAssets = ({ assets: hookCustomAssets, multiChain = false,
389
409
  mergedAssets.push(asset);
390
410
  }
391
411
  });
412
+ // The ERC-7811 proxy indexes mainnet; a testnet native (e.g. Base Sepolia
413
+ // ETH) comes back missing or stale, so the single-chain path would report
414
+ // "no assets" while the multi-chain inventory shows the balance. Read the
415
+ // native straight from RPC and upsert it to keep the two consistent.
416
+ if (chain.testnet === true) {
417
+ const rpcUrl = (_z = (_y = (_x = walletConfig === null || walletConfig === void 0 ? void 0 : walletConfig.ethereum) === null || _x === void 0 ? void 0 : _x.rpcUrls) === null || _y === void 0 ? void 0 : _y[chainId]) !== null && _z !== void 0 ? _z : getDefaultEthereumRpcUrl(chainId);
418
+ const read = await readEvmAssetsViaRpc({ address: address, chain, rpcUrl, tokens: [] });
419
+ const native = read.find((a) => a.type === 'native');
420
+ if (native) {
421
+ const idx = mergedAssets.findIndex((a) => a.type === 'native');
422
+ if (idx >= 0)
423
+ mergedAssets[idx] = native;
424
+ else
425
+ mergedAssets.unshift(native);
426
+ }
427
+ }
392
428
  if (mergedAssets.length === 0 && customAssetsToFetch.length > 0) {
393
429
  // Proxy succeeded but returned nothing while we expect tokens — read direct.
394
- const rpcUrl = (_z = (_y = (_x = walletConfig === null || walletConfig === void 0 ? void 0 : walletConfig.ethereum) === null || _x === void 0 ? void 0 : _x.rpcUrls) === null || _y === void 0 ? void 0 : _y[chainId]) !== null && _z !== void 0 ? _z : getDefaultEthereumRpcUrl(chainId);
430
+ const rpcUrl = (_2 = (_1 = (_0 = walletConfig === null || walletConfig === void 0 ? void 0 : walletConfig.ethereum) === null || _0 === void 0 ? void 0 : _0.rpcUrls) === null || _1 === void 0 ? void 0 : _1[chainId]) !== null && _2 !== void 0 ? _2 : getDefaultEthereumRpcUrl(chainId);
395
431
  const fb = await readEvmAssetsViaRpc({
396
432
  address: address,
397
433
  chain,
@@ -405,7 +441,7 @@ const useEthereumWalletAssets = ({ assets: hookCustomAssets, multiChain = false,
405
441
  }
406
442
  catch {
407
443
  // ERC-7811 asset proxy failed — fall back to direct chain-RPC balance reads.
408
- const rpcUrl = (_2 = (_1 = (_0 = walletConfig === null || walletConfig === void 0 ? void 0 : walletConfig.ethereum) === null || _0 === void 0 ? void 0 : _0.rpcUrls) === null || _1 === void 0 ? void 0 : _1[chainId]) !== null && _2 !== void 0 ? _2 : getDefaultEthereumRpcUrl(chainId);
444
+ const rpcUrl = (_5 = (_4 = (_3 = walletConfig === null || walletConfig === void 0 ? void 0 : walletConfig.ethereum) === null || _3 === void 0 ? void 0 : _3.rpcUrls) === null || _4 === void 0 ? void 0 : _4[chainId]) !== null && _5 !== void 0 ? _5 : getDefaultEthereumRpcUrl(chainId);
409
445
  return (await readEvmAssetsViaRpc({
410
446
  address: address,
411
447
  chain,
@@ -1 +1 @@
1
- {"version":3,"file":"useEthereumWalletAssets.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"useEthereumWalletAssets.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -53,14 +53,14 @@ async function pollUntilTerminal(client, onUpdate, start, isCurrent) {
53
53
  * @returns Session state plus `fund` (run the deposit flow) and `reset`.
54
54
  */
55
55
  function useFunding(options) {
56
- var _a, _b, _c;
56
+ var _a, _b;
57
57
  const { uiConfig, publishableKey } = useOpenfort();
58
58
  const { client: coreClient } = useOpenfortCore();
59
- // The CEX rail (DepositCex) is served by the Openfort API; everything else uses
60
- // the standalone funding service at uiConfig.fundingBaseUrl.
61
- const baseUrl = (options === null || options === void 0 ? void 0 : options.useBackendUrl)
62
- ? ((_a = SDKConfiguration.getInstance()) === null || _a === void 0 ? void 0 : _a.backendUrl) || 'https://api.openfort.io'
63
- : ((_b = uiConfig.fundingBaseUrl) !== null && _b !== void 0 ? _b : '');
59
+ // The funding JSON API defaults to the Openfort backend (api.openfort.io);
60
+ // integrators can point the crypto rails at a custom service via
61
+ // uiConfig.fundingBaseUrl. The CEX rail always uses the backend (Coinbase pay-link).
62
+ const backendUrl = ((_a = SDKConfiguration.getInstance()) === null || _a === void 0 ? void 0 : _a.backendUrl) || 'https://api.openfort.io';
63
+ const baseUrl = (options === null || options === void 0 ? void 0 : options.useBackendUrl) ? backendUrl : uiConfig.fundingBaseUrl || backendUrl;
64
64
  const injected = options === null || options === void 0 ? void 0 : options.client;
65
65
  // Resolve the client, in order of preference:
66
66
  // 1. an explicitly injected client (tests / custom backends),
@@ -188,7 +188,7 @@ function useFunding(options) {
188
188
  }, [client]);
189
189
  return {
190
190
  session,
191
- status: (_c = session === null || session === void 0 ? void 0 : session.status) !== null && _c !== void 0 ? _c : 'idle',
191
+ status: (_b = session === null || session === void 0 ? void 0 : session.status) !== null && _b !== void 0 ? _b : 'idle',
192
192
  error,
193
193
  loading,
194
194
  isAvailable,
@@ -20,6 +20,12 @@ export type FundingChain = {
20
20
  };
21
21
  type UseFundingChains = {
22
22
  chains: FundingChain[];
23
+ /**
24
+ * The rail's full deliverable chain list (uncurated). Used to check whether a
25
+ * funding TARGET chain is supported, independent of the source allowlist that
26
+ * narrows {@link chains}.
27
+ */
28
+ railChains: FundingChain[];
23
29
  loading: boolean;
24
30
  error: Error | null;
25
31
  };
@@ -1,5 +1,7 @@
1
+ import { SDKConfiguration } from '@openfort/openfort-js';
1
2
  import { useState, useEffect } from 'react';
2
3
  import { useOpenfort } from '../../components/Openfort/useOpenfort.js';
4
+ import { getPublishableKeyEnvironment } from '../../utils/validation.js';
3
5
 
4
6
  /**
5
7
  * Sensible default source chains — the common funding origins. Override with
@@ -31,19 +33,24 @@ const DEFAULT_SOURCE_CURRENCIES = ['native', 'USDC', 'USDT'];
31
33
  */
32
34
  function useFundingChains() {
33
35
  var _a, _b, _c, _d, _e;
34
- const { uiConfig } = useOpenfort();
35
- const baseUrl = (_a = uiConfig.fundingBaseUrl) !== null && _a !== void 0 ? _a : '';
36
+ const { uiConfig, publishableKey } = useOpenfort();
37
+ // Defaults to the SDK backend (api.openfort.io); override for a custom funding service.
38
+ const baseUrl = uiConfig.fundingBaseUrl || ((_a = SDKConfiguration.getInstance()) === null || _a === void 0 ? void 0 : _a.backendUrl) || 'https://api.openfort.io';
36
39
  const sourceChains = (_c = (_b = uiConfig.funding) === null || _b === void 0 ? void 0 : _b.sourceChains) !== null && _c !== void 0 ? _c : DEFAULT_SOURCE_CHAINS;
37
40
  const sourceCurrencies = (_e = (_d = uiConfig.funding) === null || _d === void 0 ? void 0 : _d.sourceCurrencies) !== null && _e !== void 0 ? _e : DEFAULT_SOURCE_CURRENCIES;
38
- const [state, setState] = useState({ chains: [], loading: Boolean(baseUrl), error: null });
41
+ // Match the rail host to the key environment: test keys (`pk_test_…`) list the
42
+ // testnet rail, everything else the mainnet rail. The backend picks the same
43
+ // host from the request livemode for the authenticated session endpoints.
44
+ const livemode = getPublishableKeyEnvironment(publishableKey) !== 'test';
45
+ const [state, setState] = useState({
46
+ chains: [],
47
+ loading: true,
48
+ error: null,
49
+ });
39
50
  useEffect(() => {
40
- if (!baseUrl) {
41
- setState({ chains: [], loading: false, error: null });
42
- return;
43
- }
44
51
  let cancelled = false;
45
52
  setState((s) => ({ ...s, loading: true }));
46
- fetch(`${baseUrl}/v2/funding/chains`)
53
+ fetch(`${baseUrl}/v2/funding/chains?livemode=${livemode}`)
47
54
  .then((r) => {
48
55
  if (!r.ok)
49
56
  throw new Error(`Failed to load chains (${r.status})`);
@@ -61,9 +68,14 @@ function useFundingChains() {
61
68
  return () => {
62
69
  cancelled = true;
63
70
  };
64
- }, [baseUrl]);
71
+ }, [baseUrl, livemode]);
65
72
  // Narrow the provider dictionary to the selected subset (cheap, O(chains)).
66
- return { ...state, chains: curateChains(state.chains, sourceChains, sourceCurrencies) };
73
+ return {
74
+ chains: curateChains(state.chains, sourceChains, sourceCurrencies),
75
+ railChains: state.chains,
76
+ loading: state.loading,
77
+ error: state.error,
78
+ };
67
79
  }
68
80
  /**
69
81
  * Narrow the fetched chains to a selection. `sourceChains` is a CAIP-2 allowlist
@@ -1 +1 @@
1
- {"version":3,"file":"useFundingChains.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"useFundingChains.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -2,6 +2,19 @@ import { useState, useRef, useCallback, useEffect } from 'react';
2
2
 
3
3
  /** Module-level cache shared across hook instances, so revisiting a view paints instantly. */
4
4
  const dataCache = new Map();
5
+ /**
6
+ * Serialize a queryKey to a stable cache string.
7
+ *
8
+ * `JSON.stringify` throws `TypeError: Do not know how to serialize a BigInt`,
9
+ * and queryKeys legitimately carry bigints (token amounts, balances, gas
10
+ * values — e.g. a native ETH send keys its gas estimate on the bigint amount).
11
+ * Without this replacer such a key crashes the whole modal render. A bigint is
12
+ * encoded as its decimal digits with an `n` suffix so distinct values stay
13
+ * distinct keys.
14
+ */
15
+ function serializeQueryKey(queryKey) {
16
+ return JSON.stringify(queryKey, (_key, value) => (typeof value === 'bigint' ? `${value}n` : value));
17
+ }
5
18
  /**
6
19
  * Drop cached entries so the next mount (or refetch) hits the network instead of
7
20
  * painting stale data. Pass a substring matched against the serialized queryKey
@@ -40,8 +53,8 @@ function isEmptyResult(result) {
40
53
  */
41
54
  function useAsyncData({ queryFn, queryKey, enabled = true, refetchInterval, staleTime = 0, }) {
42
55
  // Serialize queryKey to a stable string so the effect only re-runs when values change,
43
- // not when array/object references change.
44
- const queryKeyStr = JSON.stringify(queryKey);
56
+ // not when array/object references change. Bigint-safe (see serializeQueryKey).
57
+ const queryKeyStr = serializeQueryKey(queryKey);
45
58
  const [data, setData] = useState(() => { var _a; return (_a = dataCache.get(queryKeyStr)) === null || _a === void 0 ? void 0 : _a.data; });
46
59
  const [error, setError] = useState(null);
47
60
  const [isLoading, setIsLoading] = useState(false);
@@ -1 +1 @@
1
- {"version":3,"file":"useAsyncData.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"useAsyncData.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -29,15 +29,17 @@ function appendPath(base, options, queryParams) {
29
29
  const explorerRegistry = {
30
30
  [ChainTypeEnum.EVM]: (options) => {
31
31
  var _a;
32
+ // Never fall back to an unrelated chain's explorer — a valid hash on the wrong
33
+ // explorer reads as "transaction not found". Return '' so callers hide the link.
32
34
  if (!options.chainId) {
33
- logger.warn('No chain ID provided. Configure explorerUrls in OpenfortProvider for better reliability and rate limits.');
34
- return polygonAmoy.blockExplorers.default.url;
35
+ logger.warn('No chain ID provided; cannot build an explorer URL for this transaction.');
36
+ return '';
35
37
  }
36
38
  const chain = EVM_CHAINS_BY_ID[options.chainId];
37
39
  const explorerUrl = (_a = chain === null || chain === void 0 ? void 0 : chain.blockExplorers) === null || _a === void 0 ? void 0 : _a.default.url;
38
40
  if (!explorerUrl) {
39
- logger.warn(`No explorer URL found for chain ${options.chainId}. Configure explorerUrls in OpenfortProvider for better reliability and rate limits.`);
40
- return polygonAmoy.blockExplorers.default.url;
41
+ logger.warn(`No explorer URL known for chain ${options.chainId}. Configure explorerUrls in OpenfortProvider to enable the link.`);
42
+ return '';
41
43
  }
42
44
  return appendPath(explorerUrl, options);
43
45
  },
@@ -1 +1 @@
1
- {"version":3,"file":"explorer.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"explorer.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -13,6 +13,26 @@ type SendSolParams = {
13
13
  * to sponsor it.
14
14
  */
15
15
  export declare function sendSol({ from, to, amountSol, provider, rpcUrl, commitment, }: SendSolParams): Promise<string>;
16
+ type SendSplTokenParams = {
17
+ from: string;
18
+ to: string;
19
+ /** SPL mint address (base58). */
20
+ mint: string;
21
+ /** Amount in token base units (already scaled by `decimals`). */
22
+ amount: bigint;
23
+ decimals: number;
24
+ provider: OpenfortEmbeddedSolanaWalletProvider;
25
+ rpcUrl: string;
26
+ commitment?: 'processed' | 'confirmed' | 'finalized';
27
+ };
28
+ /**
29
+ * Build, sign, and broadcast an SPL token transfer. Creates the recipient's
30
+ * associated token account if it doesn't exist yet (idempotent — a no-op when it
31
+ * already holds the token; the sender pays the small rent). The wallet pays the
32
+ * network fee — use {@link sendSplTokenGasless} to sponsor it. Returns the
33
+ * transaction signature (base58).
34
+ */
35
+ export declare function sendSplToken({ from, to, mint, amount, decimals, provider, rpcUrl, commitment, }: SendSplTokenParams): Promise<string>;
16
36
  type SendSolGaslessParams = {
17
37
  from: string;
18
38
  to: string;
@@ -22,11 +42,20 @@ type SendSolGaslessParams = {
22
42
  /** Project publishable key; sent to the Openfort Solana paymaster (Kora) as a Bearer token. */
23
43
  publishableKey: string;
24
44
  };
25
- /**
26
- * Send a native SOL transfer with fees sponsored by the Openfort Solana paymaster
27
- * (Kora): Kora is the fee payer, the user signs their part with the embedded wallet,
28
- * and Kora co-signs + broadcasts. Requires a `sponsorSolTransaction` policy on the
29
- * project. Returns the transaction signature (base58).
30
- */
45
+ /** Send a native SOL transfer with fees sponsored by the Openfort paymaster (Kora). */
31
46
  export declare function sendSolGasless({ from, to, amountSol, provider, cluster, publishableKey, }: SendSolGaslessParams): Promise<string>;
47
+ type SendSplTokenGaslessParams = {
48
+ from: string;
49
+ to: string;
50
+ /** SPL mint address (base58). */
51
+ mint: string;
52
+ /** Amount in token base units (already scaled by `decimals`). */
53
+ amount: bigint;
54
+ provider: OpenfortEmbeddedSolanaWalletProvider;
55
+ cluster: SolanaCluster;
56
+ /** Project publishable key; sent to the Openfort Solana paymaster (Kora) as a Bearer token. */
57
+ publishableKey: string;
58
+ };
59
+ /** Send an SPL token transfer with fees sponsored by the Openfort paymaster (Kora). */
60
+ export declare function sendSplTokenGasless({ from, to, mint, amount, provider, cluster, publishableKey, }: SendSplTokenGaslessParams): Promise<string>;
32
61
  export {};
@@ -20,17 +20,11 @@ function deriveWssUrl(rpcUrl) {
20
20
  return rpcUrl.replace(/^https?:\/\//, 'wss://');
21
21
  }
22
22
  /**
23
- * Build, sign, and broadcast a native SOL transfer. Returns the transaction
24
- * signature (base58). The wallet pays the network fee use {@link sendSolGasless}
25
- * to sponsor it.
23
+ * A `TransactionSigner` that signs message bytes through the embedded wallet
24
+ * provider (Ed25519). Shared by the native and SPL non-sponsored paths.
26
25
  */
27
- async function sendSol({ from, to, amountSol, provider, rpcUrl, commitment = 'confirmed', }) {
28
- const kit = await import('@solana/kit');
29
- const { getTransferSolInstruction } = await import('@solana-program/system');
30
- const fromAddress = kit.address(from);
31
- const rpc = kit.createSolanaRpc(rpcUrl);
32
- const rpcSubscriptions = kit.createSolanaRpcSubscriptions(deriveWssUrl(rpcUrl));
33
- const signer = {
26
+ function createEmbeddedSigner(kit, provider, fromAddress) {
27
+ return {
34
28
  address: fromAddress,
35
29
  signTransactions: async (transactions) => Promise.all(transactions.map(async (transaction) => {
36
30
  const { signature } = await provider.signTransaction({
@@ -40,6 +34,19 @@ async function sendSol({ from, to, amountSol, provider, rpcUrl, commitment = 'co
40
34
  return Object.freeze({ [fromAddress]: bytes });
41
35
  })),
42
36
  };
37
+ }
38
+ /**
39
+ * Build, sign, and broadcast a native SOL transfer. Returns the transaction
40
+ * signature (base58). The wallet pays the network fee — use {@link sendSolGasless}
41
+ * to sponsor it.
42
+ */
43
+ async function sendSol({ from, to, amountSol, provider, rpcUrl, commitment = 'confirmed', }) {
44
+ const kit = await import('@solana/kit');
45
+ const { getTransferSolInstruction } = await import('@solana-program/system');
46
+ const fromAddress = kit.address(from);
47
+ const rpc = kit.createSolanaRpc(rpcUrl);
48
+ const rpcSubscriptions = kit.createSolanaRpcSubscriptions(deriveWssUrl(rpcUrl));
49
+ const signer = createEmbeddedSigner(kit, provider, fromAddress);
43
50
  const { value: latestBlockhash } = await rpc.getLatestBlockhash().send();
44
51
  const message = kit.pipe(kit.createTransactionMessage({ version: 0 }), (tx) => kit.setTransactionMessageFeePayer(fromAddress, tx), (tx) => kit.setTransactionMessageLifetimeUsingBlockhash(latestBlockhash, tx), (tx) => kit.appendTransactionMessageInstruction(getTransferSolInstruction({
45
52
  source: signer,
@@ -61,28 +68,91 @@ async function sendSol({ from, to, amountSol, provider, rpcUrl, commitment = 'co
61
68
  }
62
69
  return kit.getSignatureFromTransaction(signedTransaction);
63
70
  }
71
+ /**
72
+ * Build, sign, and broadcast an SPL token transfer. Creates the recipient's
73
+ * associated token account if it doesn't exist yet (idempotent — a no-op when it
74
+ * already holds the token; the sender pays the small rent). The wallet pays the
75
+ * network fee — use {@link sendSplTokenGasless} to sponsor it. Returns the
76
+ * transaction signature (base58).
77
+ */
78
+ async function sendSplToken({ from, to, mint, amount, decimals, provider, rpcUrl, commitment = 'confirmed', }) {
79
+ const kit = await import('@solana/kit');
80
+ const token = await import('@solana-program/token');
81
+ const fromAddress = kit.address(from);
82
+ const toAddress = kit.address(to);
83
+ const mintAddress = kit.address(mint);
84
+ const rpc = kit.createSolanaRpc(rpcUrl);
85
+ const rpcSubscriptions = kit.createSolanaRpcSubscriptions(deriveWssUrl(rpcUrl));
86
+ const signer = createEmbeddedSigner(kit, provider, fromAddress);
87
+ const [sourceAta] = await token.findAssociatedTokenPda({
88
+ owner: fromAddress,
89
+ tokenProgram: token.TOKEN_PROGRAM_ADDRESS,
90
+ mint: mintAddress,
91
+ });
92
+ const [destinationAta] = await token.findAssociatedTokenPda({
93
+ owner: toAddress,
94
+ tokenProgram: token.TOKEN_PROGRAM_ADDRESS,
95
+ mint: mintAddress,
96
+ });
97
+ const { value: latestBlockhash } = await rpc.getLatestBlockhash().send();
98
+ const message = kit.pipe(kit.createTransactionMessage({ version: 0 }), (tx) => kit.setTransactionMessageFeePayer(fromAddress, tx), (tx) => kit.setTransactionMessageLifetimeUsingBlockhash(latestBlockhash, tx), (tx) => kit.appendTransactionMessageInstructions([
99
+ token.getCreateAssociatedTokenIdempotentInstruction({
100
+ payer: signer,
101
+ ata: destinationAta,
102
+ owner: toAddress,
103
+ mint: mintAddress,
104
+ }),
105
+ token.getTransferCheckedInstruction({
106
+ source: sourceAta,
107
+ mint: mintAddress,
108
+ destination: destinationAta,
109
+ authority: signer,
110
+ amount,
111
+ decimals,
112
+ }),
113
+ ], tx));
114
+ const signedTransaction = await kit.signTransactionMessageWithSigners(message);
115
+ const sendAndConfirm = kit.sendAndConfirmTransactionFactory({ rpc, rpcSubscriptions });
116
+ const abortController = new AbortController();
117
+ const timeout = setTimeout(() => abortController.abort(), SEND_TIMEOUT_MS);
118
+ try {
119
+ await sendAndConfirm(signedTransaction, {
120
+ commitment,
121
+ abortSignal: abortController.signal,
122
+ });
123
+ }
124
+ finally {
125
+ clearTimeout(timeout);
126
+ }
127
+ return kit.getSignatureFromTransaction(signedTransaction);
128
+ }
64
129
  /** The Openfort Solana paymaster (Kora) endpoint for a cluster. */
65
130
  function koraRpcUrl(cluster) {
66
131
  const segment = cluster === 'mainnet-beta' ? 'mainnet' : cluster;
67
132
  return `https://api.openfort.io/rpc/solana/${segment}`;
68
133
  }
69
134
  /**
70
- * Send a native SOL transfer with fees sponsored by the Openfort Solana paymaster
71
- * (Kora): Kora is the fee payer, the user signs their part with the embedded wallet,
72
- * and Kora co-signs + broadcasts. Requires a `sponsorSolTransaction` policy on the
135
+ * Sponsor a transfer through the Openfort Solana paymaster (Kora): Kora is the
136
+ * fee payer, the user signs their part with the embedded wallet, and Kora
137
+ * co-signs + broadcasts. Requires a `sponsorSolTransaction` policy on the
73
138
  * project. Returns the transaction signature (base58).
74
139
  */
75
- async function sendSolGasless({ from, to, amountSol, provider, cluster, publishableKey, }) {
140
+ async function sendViaKora({ from, to, amountBaseUnits, tokenMint, provider, cluster, publishableKey, }) {
141
+ // Kora's request takes a JS number; fail loudly rather than silently corrupt
142
+ // an amount that can't be represented exactly.
143
+ if (amountBaseUnits > BigInt(Number.MAX_SAFE_INTEGER)) {
144
+ throw new Error('Amount is too large to sponsor through the paymaster.');
145
+ }
76
146
  const kit = await import('@solana/kit');
77
147
  const { KoraClient } = await import('@solana/kora');
78
148
  const client = new KoraClient({ rpcUrl: koraRpcUrl(cluster), apiKey: `Bearer ${publishableKey}` });
79
149
  // 1. Kora's fee-payer signer.
80
150
  const { signer_address } = await client.getPayerSigner();
81
151
  const feePayer = kit.createNoopSigner(signer_address);
82
- // 2. A sponsored native SOL transfer, with Kora as the fee payer.
152
+ // 2. A sponsored transfer (native or SPL), with Kora as the fee payer.
83
153
  const { instructions } = await client.transferTransaction({
84
- amount: Number(solToLamports(amountSol)),
85
- token: SYSTEM_PROGRAM_ID,
154
+ amount: Number(amountBaseUnits),
155
+ token: tokenMint,
86
156
  source: from,
87
157
  destination: to,
88
158
  signer_key: signer_address,
@@ -120,6 +190,30 @@ async function sendSolGasless({ from, to, amountSol, provider, cluster, publisha
120
190
  }
121
191
  throw new Error('Failed to extract transaction signature from the Kora response');
122
192
  }
193
+ /** Send a native SOL transfer with fees sponsored by the Openfort paymaster (Kora). */
194
+ async function sendSolGasless({ from, to, amountSol, provider, cluster, publishableKey, }) {
195
+ return sendViaKora({
196
+ from,
197
+ to,
198
+ amountBaseUnits: solToLamports(amountSol),
199
+ tokenMint: SYSTEM_PROGRAM_ID,
200
+ provider,
201
+ cluster,
202
+ publishableKey,
203
+ });
204
+ }
205
+ /** Send an SPL token transfer with fees sponsored by the Openfort paymaster (Kora). */
206
+ async function sendSplTokenGasless({ from, to, mint, amount, provider, cluster, publishableKey, }) {
207
+ return sendViaKora({
208
+ from,
209
+ to,
210
+ amountBaseUnits: amount,
211
+ tokenMint: mint,
212
+ provider,
213
+ cluster,
214
+ publishableKey,
215
+ });
216
+ }
123
217
 
124
- export { sendSol, sendSolGasless };
218
+ export { sendSol, sendSolGasless, sendSplToken, sendSplTokenGasless };
125
219
  //# sourceMappingURL=transfer.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"transfer.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"transfer.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -47,6 +47,14 @@ export type SolanaConfig = {
47
47
  rpcUrls?: Partial<Record<'mainnet-beta' | 'devnet' | 'testnet', string>>;
48
48
  /** Commitment level for transactions (default: 'confirmed') */
49
49
  commitment?: SolanaCommitment;
50
+ /**
51
+ * Sponsor network fees for Solana sends through the Openfort paymaster (Kora).
52
+ * The SVM counterpart of `ethereum.ethereumFeeSponsorshipId`: when `true`, sends
53
+ * are routed gaslessly and the confirm screen marks the network fee as sponsored.
54
+ * Requires a `sponsorSolTransaction` policy on the project (resolved server-side
55
+ * from the publishable key). Defaults to `false` (user pays the fee).
56
+ */
57
+ sponsorFees?: boolean;
50
58
  /** UI options for Solana-connected screens */
51
59
  ui?: SolanaUIOptions;
52
60
  };
@@ -1 +1,10 @@
1
1
  export declare const isValidEmail: (email: string) => boolean;
2
+ type PublishableKeyEnvironment = 'test' | 'live';
3
+ /**
4
+ * Derive the environment from an Openfort publishable key.
5
+ *
6
+ * Keys are formatted `pk_test_<uuid>` or `pk_live_<uuid>`. Returns `null` when
7
+ * the prefix is unrecognized so callers can fall back to default behavior.
8
+ */
9
+ export declare const getPublishableKeyEnvironment: (publishableKey: string | undefined | null) => PublishableKeyEnvironment | null;
10
+ export {};
@@ -2,6 +2,19 @@ const isValidEmail = (email) => {
2
2
  const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
3
3
  return emailRegex.test(email);
4
4
  };
5
+ /**
6
+ * Derive the environment from an Openfort publishable key.
7
+ *
8
+ * Keys are formatted `pk_test_<uuid>` or `pk_live_<uuid>`. Returns `null` when
9
+ * the prefix is unrecognized so callers can fall back to default behavior.
10
+ */
11
+ const getPublishableKeyEnvironment = (publishableKey) => {
12
+ if (publishableKey === null || publishableKey === void 0 ? void 0 : publishableKey.startsWith('pk_test_'))
13
+ return 'test';
14
+ if (publishableKey === null || publishableKey === void 0 ? void 0 : publishableKey.startsWith('pk_live_'))
15
+ return 'live';
16
+ return null;
17
+ };
5
18
 
6
- export { isValidEmail };
19
+ export { getPublishableKeyEnvironment, isValidEmail };
7
20
  //# sourceMappingURL=validation.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"validation.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;"}
1
+ {"version":3,"file":"validation.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;"}
@@ -1 +1 @@
1
- export declare const OPENFORT_VERSION = "1.2.0";
1
+ export declare const OPENFORT_VERSION = "1.4.0";
package/build/version.js CHANGED
@@ -1,4 +1,4 @@
1
- const OPENFORT_VERSION = '1.2.0';
1
+ const OPENFORT_VERSION = '1.4.0';
2
2
 
3
3
  export { OPENFORT_VERSION };
4
4
  //# sourceMappingURL=version.js.map
@@ -2,7 +2,7 @@ import { jsx, jsxs } from 'react/jsx-runtime';
2
2
  import { motion } from 'framer-motion';
3
3
  import { useState, useEffect } from 'react';
4
4
  import { css } from 'styled-components';
5
- import { useChainId, useSwitchChain } from 'wagmi';
5
+ import { useChainId } from 'wagmi';
6
6
  import Chain from '../../../components/Common/Chain/index.js';
7
7
  import Tooltip from '../../../components/Common/Tooltip/index.js';
8
8
  import { routes } from '../../../components/Openfort/types.js';
@@ -11,6 +11,7 @@ import defaultTheme from '../../../constants/defaultTheme.js';
11
11
  import useLocales from '../../../hooks/useLocales.js';
12
12
  import styled from '../../../styles/styled/index.js';
13
13
  import { isMobile, flattenChildren } from '../../../utils/index.js';
14
+ import { useSwitchChainFiltered } from '../../useSwitchChainFiltered.js';
14
15
  import ChainSelectDropdown from '../ChainSelectDropdown/index.js';
15
16
 
16
17
  const Container = styled(motion.div) ``;
@@ -112,7 +113,7 @@ const ChainSelector = () => {
112
113
  const { open, triggerResize, setRoute } = useOpenfort();
113
114
  const [isOpen, setIsOpen] = useState(false);
114
115
  const chainId = useChainId();
115
- const { chains } = useSwitchChain();
116
+ const { chains } = useSwitchChainFiltered();
116
117
  const chain = chains.find((c) => c.id === chainId);
117
118
  const locales = useLocales({
118
119
  CHAIN: (_a = chain === null || chain === void 0 ? void 0 : chain.name) !== null && _a !== void 0 ? _a : 'UNKNOWN',
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}