@b3dotfun/sdk 0.1.70-alpha.17 → 0.1.70-alpha.19

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 (162) hide show
  1. package/README.md +3 -3
  2. package/dist/cjs/anyspend/constants/rpc.d.ts +1 -0
  3. package/dist/cjs/anyspend/constants/rpc.js +3 -1
  4. package/dist/cjs/anyspend/react/components/AnySpendDeposit.d.ts +1 -3
  5. package/dist/cjs/anyspend/react/components/AnySpendDeposit.js +14 -12
  6. package/dist/cjs/anyspend/react/components/AnySpendStakeB3.js +32 -13
  7. package/dist/cjs/anyspend/react/components/AnySpendStakeB3ExactIn.js +32 -10
  8. package/dist/cjs/anyspend/react/components/checkout/CryptoPayPanel.js +16 -8
  9. package/dist/cjs/anyspend/react/components/common/TokenBalance.js +4 -5
  10. package/dist/cjs/anyspend/react/hooks/useSigMint.d.ts +1 -1
  11. package/dist/cjs/anyspend/utils/chain.d.ts +45 -0
  12. package/dist/cjs/anyspend/utils/chain.js +51 -2
  13. package/dist/cjs/global-account/react/components/B3Provider/B3Provider.d.ts +1 -2
  14. package/dist/cjs/global-account/react/components/B3Provider/B3Provider.js +2 -2
  15. package/dist/cjs/global-account/react/components/B3Provider/RelayKitProviderWrapper.d.ts +1 -2
  16. package/dist/cjs/global-account/react/components/B3Provider/RelayKitProviderWrapper.js +4 -5
  17. package/dist/cjs/global-account/react/components/ManageAccount/ContentTokens.js +23 -15
  18. package/dist/cjs/global-account/react/components/ManageAccount/NFTContent.js +2 -2
  19. package/dist/cjs/global-account/react/components/ManageAccount/ProfileSection.js +8 -6
  20. package/dist/cjs/global-account/react/components/ManageAccount/TokenContent.js +17 -8
  21. package/dist/cjs/global-account/react/components/Send/Send.js +15 -11
  22. package/dist/cjs/global-account/react/hooks/index.d.ts +2 -2
  23. package/dist/cjs/global-account/react/hooks/index.js +7 -8
  24. package/dist/cjs/global-account/react/hooks/useAuth.d.ts +2 -1
  25. package/dist/cjs/global-account/react/hooks/useAuth.js +1 -0
  26. package/dist/cjs/global-account/react/hooks/useAuthentication.d.ts +2 -1
  27. package/dist/cjs/global-account/react/hooks/useAuthentication.js +1 -0
  28. package/dist/cjs/global-account/react/hooks/useFirstEOA.d.ts +4 -7666
  29. package/dist/cjs/global-account/react/hooks/useFirstEOA.js +1 -0
  30. package/dist/cjs/global-account/react/hooks/usePortfolioBalance.d.ts +15 -0
  31. package/dist/cjs/global-account/react/hooks/usePortfolioBalance.js +76 -0
  32. package/dist/cjs/global-account/react/hooks/usePortfolioCollectibles.d.ts +12 -0
  33. package/dist/cjs/global-account/react/hooks/usePortfolioCollectibles.js +178 -0
  34. package/dist/cjs/global-account/react/hooks/useUnifiedChainSwitchAndExecute.d.ts +1 -0
  35. package/dist/cjs/global-account/react/hooks/useUnifiedChainSwitchAndExecute.js +18 -11
  36. package/dist/cjs/global-account/react/stores/useModalStore.d.ts +0 -2
  37. package/dist/cjs/global-account/react/utils/createWagmiConfig.d.ts +2 -2
  38. package/dist/cjs/shared/constants/chains/b3Chain.d.ts +24 -0
  39. package/dist/cjs/shared/constants/chains/supported.d.ts +4 -4
  40. package/dist/cjs/shared/constants/index.d.ts +4 -0
  41. package/dist/cjs/shared/utils/zerionPositions.d.ts +96 -0
  42. package/dist/cjs/shared/utils/zerionPositions.js +186 -0
  43. package/dist/cjs/wallet/utils/createWalletConfig.d.ts +2 -2
  44. package/dist/esm/anyspend/constants/rpc.d.ts +1 -0
  45. package/dist/esm/anyspend/constants/rpc.js +2 -0
  46. package/dist/esm/anyspend/react/components/AnySpendDeposit.d.ts +1 -3
  47. package/dist/esm/anyspend/react/components/AnySpendDeposit.js +15 -13
  48. package/dist/esm/anyspend/react/components/AnySpendStakeB3.js +33 -14
  49. package/dist/esm/anyspend/react/components/AnySpendStakeB3ExactIn.js +33 -11
  50. package/dist/esm/anyspend/react/components/checkout/CryptoPayPanel.js +18 -10
  51. package/dist/esm/anyspend/react/components/common/TokenBalance.js +6 -7
  52. package/dist/esm/anyspend/react/hooks/useSigMint.d.ts +1 -1
  53. package/dist/esm/anyspend/utils/chain.d.ts +45 -0
  54. package/dist/esm/anyspend/utils/chain.js +50 -3
  55. package/dist/esm/global-account/react/components/B3Provider/B3Provider.d.ts +1 -2
  56. package/dist/esm/global-account/react/components/B3Provider/B3Provider.js +2 -2
  57. package/dist/esm/global-account/react/components/B3Provider/RelayKitProviderWrapper.d.ts +1 -2
  58. package/dist/esm/global-account/react/components/B3Provider/RelayKitProviderWrapper.js +4 -5
  59. package/dist/esm/global-account/react/components/ManageAccount/ContentTokens.js +24 -16
  60. package/dist/esm/global-account/react/components/ManageAccount/NFTContent.js +3 -3
  61. package/dist/esm/global-account/react/components/ManageAccount/ProfileSection.js +9 -7
  62. package/dist/esm/global-account/react/components/ManageAccount/TokenContent.js +18 -9
  63. package/dist/esm/global-account/react/components/Send/Send.js +16 -12
  64. package/dist/esm/global-account/react/hooks/index.d.ts +2 -2
  65. package/dist/esm/global-account/react/hooks/index.js +2 -2
  66. package/dist/esm/global-account/react/hooks/useAuth.d.ts +2 -1
  67. package/dist/esm/global-account/react/hooks/useAuth.js +1 -0
  68. package/dist/esm/global-account/react/hooks/useAuthentication.d.ts +2 -1
  69. package/dist/esm/global-account/react/hooks/useAuthentication.js +1 -0
  70. package/dist/esm/global-account/react/hooks/useFirstEOA.d.ts +4 -7666
  71. package/dist/esm/global-account/react/hooks/useFirstEOA.js +1 -0
  72. package/dist/esm/global-account/react/hooks/usePortfolioBalance.d.ts +15 -0
  73. package/dist/esm/global-account/react/hooks/usePortfolioBalance.js +72 -0
  74. package/dist/esm/global-account/react/hooks/usePortfolioCollectibles.d.ts +12 -0
  75. package/dist/esm/global-account/react/hooks/usePortfolioCollectibles.js +175 -0
  76. package/dist/esm/global-account/react/hooks/useUnifiedChainSwitchAndExecute.d.ts +1 -0
  77. package/dist/esm/global-account/react/hooks/useUnifiedChainSwitchAndExecute.js +18 -11
  78. package/dist/esm/global-account/react/stores/useModalStore.d.ts +0 -2
  79. package/dist/esm/global-account/react/utils/createWagmiConfig.d.ts +2 -2
  80. package/dist/esm/shared/constants/chains/b3Chain.d.ts +24 -0
  81. package/dist/esm/shared/constants/chains/supported.d.ts +4 -4
  82. package/dist/esm/shared/constants/index.d.ts +4 -0
  83. package/dist/esm/shared/utils/zerionPositions.d.ts +96 -0
  84. package/dist/esm/shared/utils/zerionPositions.js +178 -0
  85. package/dist/esm/wallet/utils/createWalletConfig.d.ts +2 -2
  86. package/dist/types/anyspend/constants/rpc.d.ts +1 -0
  87. package/dist/types/anyspend/react/components/AnySpendDeposit.d.ts +1 -3
  88. package/dist/types/anyspend/react/hooks/useSigMint.d.ts +1 -1
  89. package/dist/types/anyspend/utils/chain.d.ts +45 -0
  90. package/dist/types/global-account/react/components/B3Provider/B3Provider.d.ts +1 -2
  91. package/dist/types/global-account/react/components/B3Provider/RelayKitProviderWrapper.d.ts +1 -2
  92. package/dist/types/global-account/react/hooks/index.d.ts +2 -2
  93. package/dist/types/global-account/react/hooks/useAuth.d.ts +2 -1
  94. package/dist/types/global-account/react/hooks/useAuthentication.d.ts +2 -1
  95. package/dist/types/global-account/react/hooks/useFirstEOA.d.ts +4 -7666
  96. package/dist/types/global-account/react/hooks/usePortfolioBalance.d.ts +15 -0
  97. package/dist/types/global-account/react/hooks/usePortfolioCollectibles.d.ts +12 -0
  98. package/dist/types/global-account/react/hooks/useUnifiedChainSwitchAndExecute.d.ts +1 -0
  99. package/dist/types/global-account/react/stores/useModalStore.d.ts +0 -2
  100. package/dist/types/global-account/react/utils/createWagmiConfig.d.ts +2 -2
  101. package/dist/types/shared/constants/chains/b3Chain.d.ts +24 -0
  102. package/dist/types/shared/constants/chains/supported.d.ts +4 -4
  103. package/dist/types/shared/constants/index.d.ts +4 -0
  104. package/dist/types/shared/utils/zerionPositions.d.ts +96 -0
  105. package/dist/types/wallet/utils/createWalletConfig.d.ts +2 -2
  106. package/node_modules/@b3/chain-registry/chains.json +29 -1
  107. package/node_modules/@b3/chain-registry/package.json +18 -2
  108. package/package.json +2 -2
  109. package/src/anyspend/README.md +2 -2
  110. package/src/anyspend/constants/rpc.ts +2 -0
  111. package/src/anyspend/docs/components.md +6 -6
  112. package/src/anyspend/docs/contributing.md +1 -1
  113. package/src/anyspend/docs/hooks.md +3 -3
  114. package/src/anyspend/docs/installation.md +2 -2
  115. package/src/anyspend/react/components/AnySpendDeposit.tsx +26 -19
  116. package/src/anyspend/react/components/AnySpendStakeB3.tsx +55 -14
  117. package/src/anyspend/react/components/AnySpendStakeB3ExactIn.tsx +55 -11
  118. package/src/anyspend/react/components/__tests__/QRDeposit.test.tsx +3 -4
  119. package/src/anyspend/react/components/checkout/CryptoPayPanel.tsx +25 -12
  120. package/src/anyspend/react/components/common/TokenBalance.tsx +10 -7
  121. package/src/anyspend/utils/__tests__/deprecatedChains.test.ts +44 -0
  122. package/src/anyspend/utils/__tests__/toRegistryChainId.test.ts +17 -0
  123. package/src/anyspend/utils/chain.ts +53 -2
  124. package/src/global-account/react/components/B3Provider/B3Provider.tsx +1 -3
  125. package/src/global-account/react/components/B3Provider/RelayKitProviderWrapper.tsx +4 -11
  126. package/src/global-account/react/components/ManageAccount/ContentTokens.tsx +50 -21
  127. package/src/global-account/react/components/ManageAccount/NFTContent.tsx +5 -3
  128. package/src/global-account/react/components/ManageAccount/ProfileSection.tsx +10 -6
  129. package/src/global-account/react/components/ManageAccount/TokenContent.tsx +22 -9
  130. package/src/global-account/react/components/Send/Send.tsx +39 -15
  131. package/src/global-account/react/hooks/__tests__/useUnifiedChainSwitchAndExecute.test.tsx +156 -0
  132. package/src/global-account/react/hooks/index.ts +2 -2
  133. package/src/global-account/react/hooks/useAuth.ts +3 -2
  134. package/src/global-account/react/hooks/useAuthentication.ts +3 -2
  135. package/src/global-account/react/hooks/useFirstEOA.tsx +9 -2
  136. package/src/global-account/react/hooks/usePortfolioBalance.ts +89 -0
  137. package/src/global-account/react/hooks/usePortfolioCollectibles.ts +212 -0
  138. package/src/global-account/react/hooks/useUnifiedChainSwitchAndExecute.ts +26 -12
  139. package/src/global-account/react/stores/useModalStore.ts +0 -2
  140. package/src/shared/constants/index.ts +8 -0
  141. package/src/shared/utils/__tests__/zerionPositions.test.ts +226 -0
  142. package/src/shared/utils/zerionPositions.ts +244 -0
  143. package/dist/cjs/global-account/react/hooks/useSimBalance.d.ts +0 -59
  144. package/dist/cjs/global-account/react/hooks/useSimBalance.js +0 -98
  145. package/dist/cjs/global-account/react/hooks/useSimCollectibles.d.ts +0 -45
  146. package/dist/cjs/global-account/react/hooks/useSimCollectibles.js +0 -190
  147. package/dist/cjs/global-account/react/utils/simdune.d.ts +0 -7
  148. package/dist/cjs/global-account/react/utils/simdune.js +0 -21
  149. package/dist/esm/global-account/react/hooks/useSimBalance.d.ts +0 -59
  150. package/dist/esm/global-account/react/hooks/useSimBalance.js +0 -93
  151. package/dist/esm/global-account/react/hooks/useSimCollectibles.d.ts +0 -45
  152. package/dist/esm/global-account/react/hooks/useSimCollectibles.js +0 -187
  153. package/dist/esm/global-account/react/utils/simdune.d.ts +0 -7
  154. package/dist/esm/global-account/react/utils/simdune.js +0 -17
  155. package/dist/types/global-account/react/hooks/useSimBalance.d.ts +0 -59
  156. package/dist/types/global-account/react/hooks/useSimCollectibles.d.ts +0 -45
  157. package/dist/types/global-account/react/utils/simdune.d.ts +0 -7
  158. package/node_modules/@b3/chain-registry/src/index.ts +0 -169
  159. package/node_modules/@b3/chain-registry/tsconfig.json +0 -16
  160. package/src/global-account/react/hooks/useSimBalance.ts +0 -164
  161. package/src/global-account/react/hooks/useSimCollectibles.ts +0 -238
  162. package/src/global-account/react/utils/simdune.ts +0 -20
package/README.md CHANGED
@@ -69,7 +69,7 @@ import { AnySpendNFTButton } from "@b3dotfun/sdk/anyspend/react";
69
69
  function NFTMinting() {
70
70
  const nftContract = {
71
71
  address: "0x9c275ff1634519E9B5449ec79cd939B5F900564d",
72
- chainId: 8333,
72
+ chainId: 8453,
73
73
  name: "Example NFT Collection",
74
74
  imageUrl: "https://example.com/nft-image.jpg",
75
75
  description: "A beautiful NFT from our collection",
@@ -127,7 +127,7 @@ import type { GetQuoteRequest } from "@b3dotfun/sdk/anyspend/types";
127
127
  // Get quote for cross-chain swap
128
128
  const quoteRequest: GetQuoteRequest = {
129
129
  srcChain: 1,
130
- dstChain: 8333,
130
+ dstChain: 8453,
131
131
  srcTokenAddress: "0xA0b86a33E6c51c7C36c654d6C9e7b8F5d4a8b5c5",
132
132
  dstTokenAddress: "0x...",
133
133
  srcAmount: "1000000", // 1 USDC
@@ -142,7 +142,7 @@ const order = await anyspendService.createOrder({
142
142
  recipientAddress: "0x...",
143
143
  type: "swap",
144
144
  srcChain: 1,
145
- dstChain: 8333,
145
+ dstChain: 8453,
146
146
  srcTokenAddress: "0x...",
147
147
  dstTokenAddress: "0x...",
148
148
  srcAmount: "1000000",
@@ -17,6 +17,7 @@ export declare const B3_PUBLIC_RPC = "https://mainnet-rpc.b3.fun";
17
17
  export declare const ABSTRACT_PUBLIC_RPC = "https://api.mainnet.abs.xyz";
18
18
  export declare const HYPEREVM_PUBLIC_RPC = "https://rpc.hyperliquid.xyz/evm";
19
19
  export declare const PLUME_PUBLIC_RPC = "https://rpc.plume.org";
20
+ export declare const ROBINHOOD_PUBLIC_RPC = "https://rpc.mainnet.chain.robinhood.com";
20
21
  /**
21
22
  * Map of chain IDs to their default public RPC URLs.
22
23
  */
@@ -8,7 +8,7 @@
8
8
  * - https://chainlist.org
9
9
  */
10
10
  Object.defineProperty(exports, "__esModule", { value: true });
11
- exports.PUBLIC_RPC_URLS = exports.PLUME_PUBLIC_RPC = exports.HYPEREVM_PUBLIC_RPC = exports.ABSTRACT_PUBLIC_RPC = exports.B3_PUBLIC_RPC = exports.BSC_PUBLIC_RPC = exports.AVALANCHE_PUBLIC_RPC = exports.POLYGON_PUBLIC_RPC = exports.OPTIMISM_PUBLIC_RPC = exports.BASE_PUBLIC_RPC = exports.ARBITRUM_PUBLIC_RPC = exports.ETHEREUM_PUBLIC_RPC = void 0;
11
+ exports.PUBLIC_RPC_URLS = exports.ROBINHOOD_PUBLIC_RPC = exports.PLUME_PUBLIC_RPC = exports.HYPEREVM_PUBLIC_RPC = exports.ABSTRACT_PUBLIC_RPC = exports.B3_PUBLIC_RPC = exports.BSC_PUBLIC_RPC = exports.AVALANCHE_PUBLIC_RPC = exports.POLYGON_PUBLIC_RPC = exports.OPTIMISM_PUBLIC_RPC = exports.BASE_PUBLIC_RPC = exports.ARBITRUM_PUBLIC_RPC = exports.ETHEREUM_PUBLIC_RPC = void 0;
12
12
  // PublicNode endpoints
13
13
  exports.ETHEREUM_PUBLIC_RPC = "https://ethereum-rpc.publicnode.com";
14
14
  exports.ARBITRUM_PUBLIC_RPC = "https://arbitrum-one-rpc.publicnode.com";
@@ -22,6 +22,7 @@ exports.B3_PUBLIC_RPC = "https://mainnet-rpc.b3.fun";
22
22
  exports.ABSTRACT_PUBLIC_RPC = "https://api.mainnet.abs.xyz";
23
23
  exports.HYPEREVM_PUBLIC_RPC = "https://rpc.hyperliquid.xyz/evm";
24
24
  exports.PLUME_PUBLIC_RPC = "https://rpc.plume.org";
25
+ exports.ROBINHOOD_PUBLIC_RPC = "https://rpc.mainnet.chain.robinhood.com";
25
26
  /**
26
27
  * Map of chain IDs to their default public RPC URLs.
27
28
  */
@@ -37,4 +38,5 @@ exports.PUBLIC_RPC_URLS = {
37
38
  2741: exports.ABSTRACT_PUBLIC_RPC, // Abstract
38
39
  999: exports.HYPEREVM_PUBLIC_RPC, // HyperEVM
39
40
  98866: exports.PLUME_PUBLIC_RPC, // Plume Network
41
+ 4663: exports.ROBINHOOD_PUBLIC_RPC, // Robinhood Chain
40
42
  };
@@ -84,8 +84,6 @@ export interface AnySpendDepositProps {
84
84
  showFiatOption?: boolean;
85
85
  /** Custom list of supported chains. If not provided, uses default chains */
86
86
  supportedChains?: ChainConfig[];
87
- /** Minimum pool size for filtering tokens (default: 1,000,000) */
88
- minPoolSize?: number;
89
87
  /** Custom title for chain selection step */
90
88
  chainSelectionTitle?: string;
91
89
  /** Custom description for chain selection step */
@@ -164,4 +162,4 @@ export interface AnySpendDepositProps {
164
162
  * onSuccess={(amount) => console.log(`Deposited ${amount}`)}
165
163
  * />
166
164
  */
167
- export declare function AnySpendDeposit({ loadOrder, mode, recipientAddress, paymentType: initialPaymentType, sourceTokenAddress, sourceTokenChainId: initialSourceChainId, destinationTokenAddress, destinationTokenChainId, lockDestinationToken, onSuccess, onOpenCustomModal, mainFooter, onTokenSelect, customUsdInputValues, preferEoa, minDestinationAmount, header, orderType, depositContractConfig, showChainSelection, showFiatOption, supportedChains, minPoolSize, topChainsCount, onClose, returnToHomeUrl, customRecipientLabel, returnHomeLabel, isCustomDeposit, classes, allowDirectTransfer, pureTransferOnly, destinationTokenAmount, callbackMetadata, senderAddress, slots, content, theme, }: AnySpendDepositProps): import("react/jsx-runtime").JSX.Element | null;
165
+ export declare function AnySpendDeposit({ loadOrder, mode, recipientAddress, paymentType: initialPaymentType, sourceTokenAddress, sourceTokenChainId: initialSourceChainId, destinationTokenAddress, destinationTokenChainId, lockDestinationToken, onSuccess, onOpenCustomModal, mainFooter, onTokenSelect, customUsdInputValues, preferEoa, minDestinationAmount, header, orderType, depositContractConfig, showChainSelection, showFiatOption, supportedChains, topChainsCount, onClose, returnToHomeUrl, customRecipientLabel, returnHomeLabel, isCustomDeposit, classes, allowDirectTransfer, pureTransferOnly, destinationTokenAmount, callbackMetadata, senderAddress, slots, content, theme, }: AnySpendDepositProps): import("react/jsx-runtime").JSX.Element | null;
@@ -24,8 +24,6 @@ const DEFAULT_SUPPORTED_CHAINS = [
24
24
  { id: 137, name: "Polygon" },
25
25
  { id: 56, name: "BNB Chain" },
26
26
  ];
27
- // Minimum pool size to filter out low liquidity tokens
28
- const DEFAULT_MIN_POOL_SIZE = 1000000;
29
27
  /**
30
28
  * Self-described fallback metadata for the default funding token(s), keyed by
31
29
  * `${chainId}:${lowercased address}`. Used when `useTokenData` misses (returns
@@ -112,7 +110,7 @@ function ChainIcon({ chainId, className }) {
112
110
  * onSuccess={(amount) => console.log(`Deposited ${amount}`)}
113
111
  * />
114
112
  */
115
- function AnySpendDeposit({ loadOrder, mode = "modal", recipientAddress, paymentType: initialPaymentType, sourceTokenAddress, sourceTokenChainId: initialSourceChainId, destinationTokenAddress, destinationTokenChainId, lockDestinationToken = true, onSuccess, onOpenCustomModal, mainFooter, onTokenSelect, customUsdInputValues, preferEoa, minDestinationAmount, header, orderType, depositContractConfig, showChainSelection, showFiatOption = true, supportedChains = DEFAULT_SUPPORTED_CHAINS, minPoolSize = DEFAULT_MIN_POOL_SIZE, topChainsCount = 3, onClose, returnToHomeUrl, customRecipientLabel, returnHomeLabel, isCustomDeposit = false, classes, allowDirectTransfer = false, pureTransferOnly = false, destinationTokenAmount, callbackMetadata, senderAddress, slots, content, theme, }) {
113
+ function AnySpendDeposit({ loadOrder, mode = "modal", recipientAddress, paymentType: initialPaymentType, sourceTokenAddress, sourceTokenChainId: initialSourceChainId, destinationTokenAddress, destinationTokenChainId, lockDestinationToken = true, onSuccess, onOpenCustomModal, mainFooter, onTokenSelect, customUsdInputValues, preferEoa, minDestinationAmount, header, orderType, depositContractConfig, showChainSelection, showFiatOption = true, supportedChains = DEFAULT_SUPPORTED_CHAINS, topChainsCount = 3, onClose, returnToHomeUrl, customRecipientLabel, returnHomeLabel, isCustomDeposit = false, classes, allowDirectTransfer = false, pureTransferOnly = false, destinationTokenAmount, callbackMetadata, senderAddress, slots, content, theme, }) {
116
114
  // Extract deposit-specific classes for convenience
117
115
  const depositClasses = classes?.deposit;
118
116
  const { connectedEOAWallet } = (0, react_1.useAccountWallet)();
@@ -147,13 +145,17 @@ function AnySpendDeposit({ loadOrder, mode = "modal", recipientAddress, paymentT
147
145
  }, [destinationTokenAddress, destinationTokenChainId, destinationTokenData]);
148
146
  // Fetch balances for EOA wallet (use senderAddress as fallback for pre-filled balance display)
149
147
  const effectiveBalanceAddress = senderAddress || eoaAddress;
150
- const { data: balanceData, isLoading: isBalanceLoading } = (0, react_1.useSimBalance)(shouldShowChainSelection ? effectiveBalanceAddress : undefined, supportedChains.map(c => c.id));
151
- // Group balances by chain and calculate total USD value per chain
148
+ const { data: balances, isLoading: isBalanceLoading, isError: isBalanceError, } = (0, react_1.usePortfolioBalance)(shouldShowChainSelection ? effectiveBalanceAddress : undefined, supportedChains.map(c => c.id));
149
+ // Group balances by chain and calculate total USD value per chain.
150
+ //
151
+ // There is deliberately no liquidity threshold here. The balance provider reports no pool size,
152
+ // so a `pool_size > n` test is false for every row and quietly reduces to "native only",
153
+ // erasing every ERC-20 the user holds from the chain summary. Spam filtering belongs to the
154
+ // token-filter service, which has the data to do it.
152
155
  const chainBalances = (0, react_3.useMemo)(() => {
153
- if (!balanceData?.balances)
156
+ if (!balances)
154
157
  return {};
155
- const filteredBalances = balanceData.balances.filter(token => token.address === "native" || (token.pool_size && token.pool_size > minPoolSize));
156
- return filteredBalances.reduce((acc, token) => {
158
+ return balances.reduce((acc, token) => {
157
159
  const chainId = token.chain_id;
158
160
  if (!acc[chainId]) {
159
161
  acc[chainId] = {
@@ -167,7 +169,7 @@ function AnySpendDeposit({ loadOrder, mode = "modal", recipientAddress, paymentT
167
169
  acc[chainId].tokenCount += 1;
168
170
  return acc;
169
171
  }, {});
170
- }, [balanceData, minPoolSize]);
172
+ }, [balances]);
171
173
  // Sort chains by USD value (highest first)
172
174
  const sortedChains = (0, react_3.useMemo)(() => {
173
175
  return supportedChains
@@ -222,10 +224,10 @@ function AnySpendDeposit({ loadOrder, mode = "modal", recipientAddress, paymentT
222
224
  if (step === "select-chain") {
223
225
  return ((0, jsx_runtime_1.jsxs)("div", { className: depositClasses?.chainSelection ||
224
226
  (0, cn_1.cn)("anyspend-deposit anyspend-deposit-chain-selection font-inter bg-as-surface-primary relative mx-auto w-full max-w-[460px]", mode === "page" && "border-as-border-secondary overflow-hidden rounded-2xl border shadow-xl"), children: [onClose && ((0, jsx_runtime_1.jsx)("button", { onClick: onClose, className: depositClasses?.closeButton ||
225
- "anyspend-deposit-close-button text-as-secondary hover:text-as-primary absolute right-4 top-4 z-10", children: (0, jsx_runtime_1.jsx)("svg", { className: "h-6 w-6", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: (0, jsx_runtime_1.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M6 18L18 6M6 6l12 12" }) }) })), !isBalanceLoading && totalBalance > 0 && ((0, jsx_runtime_1.jsxs)("div", { className: depositClasses?.balanceContainer || "anyspend-deposit-balance border-theme-border-secondary border-b p-5", children: [(0, jsx_runtime_1.jsx)("p", { className: depositClasses?.balanceLabel || "anyspend-deposit-balance-label text-as-secondary text-sm", children: "Your Balance" }), (0, jsx_runtime_1.jsxs)("p", { className: depositClasses?.balanceValue || "anyspend-deposit-balance-value text-as-primary text-3xl font-semibold", children: [formatDecimal(totalBalance), " ", (0, jsx_runtime_1.jsx)("span", { className: "text-sm", children: "USD" })] })] })), (0, jsx_runtime_1.jsxs)("div", { className: depositClasses?.optionsContainer || "anyspend-deposit-options flex flex-col gap-2 p-6", children: [isBalanceLoading && ((0, jsx_runtime_1.jsx)("div", { className: depositClasses?.chainsSkeleton || "anyspend-deposit-chains-skeleton flex flex-col gap-2", children: [1, 2].map((_, i) => ((0, jsx_runtime_1.jsxs)("div", { className: depositClasses?.skeletonItem ||
226
- "border-border-primary flex items-center justify-between rounded-xl border p-4", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-3", children: [(0, jsx_runtime_1.jsx)(react_1.Skeleton, { className: "h-6 w-6 rounded-full" }), (0, jsx_runtime_1.jsxs)("div", { className: "flex flex-col gap-1", children: [(0, jsx_runtime_1.jsx)(react_1.Skeleton, { className: "h-4 w-32" }), (0, jsx_runtime_1.jsx)(react_1.Skeleton, { className: "h-3 w-20" })] })] }), (0, jsx_runtime_1.jsx)(react_1.Skeleton, { className: "h-5 w-5" })] }, i))) })), topChainsWithBalance.length > 0 && ((0, jsx_runtime_1.jsx)("div", { className: depositClasses?.chainsContainer || "anyspend-deposit-chains flex flex-col gap-2", children: topChainsWithBalance.map(chain => ((0, jsx_runtime_1.jsxs)("button", { onClick: () => handleSelectChain(chain.id), className: depositClasses?.chainButton ||
227
+ "anyspend-deposit-close-button text-as-secondary hover:text-as-primary absolute right-4 top-4 z-10", children: (0, jsx_runtime_1.jsx)("svg", { className: "h-6 w-6", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: (0, jsx_runtime_1.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M6 18L18 6M6 6l12 12" }) }) })), !isBalanceLoading && !isBalanceError && totalBalance > 0 && ((0, jsx_runtime_1.jsxs)("div", { className: depositClasses?.balanceContainer || "anyspend-deposit-balance border-theme-border-secondary border-b p-5", children: [(0, jsx_runtime_1.jsx)("p", { className: depositClasses?.balanceLabel || "anyspend-deposit-balance-label text-as-secondary text-sm", children: "Your Balance" }), (0, jsx_runtime_1.jsxs)("p", { className: depositClasses?.balanceValue || "anyspend-deposit-balance-value text-as-primary text-3xl font-semibold", children: [formatDecimal(totalBalance), " ", (0, jsx_runtime_1.jsx)("span", { className: "text-sm", children: "USD" })] })] })), (0, jsx_runtime_1.jsxs)("div", { className: depositClasses?.optionsContainer || "anyspend-deposit-options flex flex-col gap-2 p-6", children: [isBalanceLoading && ((0, jsx_runtime_1.jsx)("div", { className: depositClasses?.chainsSkeleton || "anyspend-deposit-chains-skeleton flex flex-col gap-2", children: [1, 2].map((_, i) => ((0, jsx_runtime_1.jsxs)("div", { className: depositClasses?.skeletonItem ||
228
+ "border-border-primary flex items-center justify-between rounded-xl border p-4", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-3", children: [(0, jsx_runtime_1.jsx)(react_1.Skeleton, { className: "h-6 w-6 rounded-full" }), (0, jsx_runtime_1.jsxs)("div", { className: "flex flex-col gap-1", children: [(0, jsx_runtime_1.jsx)(react_1.Skeleton, { className: "h-4 w-32" }), (0, jsx_runtime_1.jsx)(react_1.Skeleton, { className: "h-3 w-20" })] })] }), (0, jsx_runtime_1.jsx)(react_1.Skeleton, { className: "h-5 w-5" })] }, i))) })), isBalanceError && !isBalanceLoading && ((0, jsx_runtime_1.jsx)("p", { className: "text-as-primary/50 px-1 py-2 text-sm", children: "We couldn't read your balances just now. You can still pick a chain below." })), !isBalanceError && topChainsWithBalance.length > 0 && ((0, jsx_runtime_1.jsx)("div", { className: depositClasses?.chainsContainer || "anyspend-deposit-chains flex flex-col gap-2", children: topChainsWithBalance.map(chain => ((0, jsx_runtime_1.jsxs)("button", { onClick: () => handleSelectChain(chain.id), className: depositClasses?.chainButton ||
227
229
  "anyspend-deposit-chain-button border-border-primary hover:border-as-brand hover:bg-as-surface-secondary flex w-full items-center justify-between rounded-xl border p-4 text-left shadow-sm transition-all", children: [(0, jsx_runtime_1.jsx)("div", { className: depositClasses?.chainContent || "anyspend-deposit-chain-content", children: (0, jsx_runtime_1.jsxs)("div", { className: depositClasses?.chainInfo || "anyspend-deposit-chain-info", children: [(0, jsx_runtime_1.jsxs)("span", { className: depositClasses?.chainName ||
228
- "anyspend-deposit-chain-name text-as-primary flex items-center gap-1.5 font-medium", children: ["Deposit from ", chain.name, (0, jsx_runtime_1.jsx)(ChainIcon, { chainId: chain.id, className: depositClasses?.chainIcon || "h-5 w-5" })] }), (0, jsx_runtime_1.jsxs)("p", { className: depositClasses?.chainBalance || "anyspend-deposit-chain-balance text-as-secondary text-xs", children: [formatUsd(chain.balance), " available"] })] }) }), (0, jsx_runtime_1.jsx)(lucide_react_1.ChevronRight, { className: depositClasses?.chainChevron || "anyspend-deposit-chain-chevron text-as-secondary h-5 w-5" })] }, chain.id))) })), (0, jsx_runtime_1.jsxs)("div", { className: depositClasses?.generalOptions || "anyspend-deposit-general-options flex flex-col gap-2", children: [(0, jsx_runtime_1.jsxs)("button", { onClick: handleSelectCrypto, className: depositClasses?.cryptoButton ||
230
+ "anyspend-deposit-chain-name text-as-primary flex items-center gap-1.5 font-medium", children: ["Deposit from ", chain.name, (0, jsx_runtime_1.jsx)(ChainIcon, { chainId: chain.id, className: depositClasses?.chainIcon || "h-5 w-5" })] }), (0, jsx_runtime_1.jsx)("p", { className: depositClasses?.chainBalance || "anyspend-deposit-chain-balance text-as-secondary text-xs", children: `${formatUsd(chain.balance)} available` })] }) }), (0, jsx_runtime_1.jsx)(lucide_react_1.ChevronRight, { className: depositClasses?.chainChevron || "anyspend-deposit-chain-chevron text-as-secondary h-5 w-5" })] }, chain.id))) })), (0, jsx_runtime_1.jsxs)("div", { className: depositClasses?.generalOptions || "anyspend-deposit-general-options flex flex-col gap-2", children: [(0, jsx_runtime_1.jsxs)("button", { onClick: handleSelectCrypto, className: depositClasses?.cryptoButton ||
229
231
  "anyspend-deposit-option-button anyspend-deposit-crypto-button border-border-primary hover:border-as-brand hover:bg-as-surface-secondary flex w-full items-center justify-between rounded-xl border p-4 text-left shadow-sm transition-all", children: [(0, jsx_runtime_1.jsx)("div", { className: depositClasses?.optionContent || "anyspend-deposit-option-content", children: (0, jsx_runtime_1.jsxs)("div", { className: depositClasses?.optionInfo || "anyspend-deposit-option-info", children: [(0, jsx_runtime_1.jsx)("span", { className: depositClasses?.optionTitle || "anyspend-deposit-option-title text-as-primary font-medium", children: "Deposit Crypto" }), (0, jsx_runtime_1.jsx)("p", { className: depositClasses?.optionDescription ||
230
232
  "anyspend-deposit-option-description text-as-secondary text-xs", children: "Swap from any token on any chain" })] }) }), (0, jsx_runtime_1.jsx)(lucide_react_1.ChevronRight, { className: depositClasses?.optionChevron || "anyspend-deposit-option-chevron text-as-secondary h-5 w-5" })] }), (0, jsx_runtime_1.jsxs)("div", { className: depositClasses?.divider || "anyspend-deposit-divider flex items-center gap-3", children: [(0, jsx_runtime_1.jsx)("div", { className: depositClasses?.dividerLine || "bg-as-stroke h-px flex-1" }), (0, jsx_runtime_1.jsx)("span", { className: depositClasses?.dividerText || "anyspend-deposit-divider-text text-as-secondary text-sm", children: "More options" }), (0, jsx_runtime_1.jsx)("div", { className: depositClasses?.dividerLine || "bg-as-stroke h-px flex-1" })] }), (0, jsx_runtime_1.jsxs)("button", { onClick: handleSelectQrDeposit, className: depositClasses?.qrButton ||
231
233
  "anyspend-deposit-option-button anyspend-deposit-qr-button border-border-primary hover:border-as-brand hover:bg-as-surface-secondary flex w-full items-center justify-between rounded-xl border p-4 text-left shadow-sm transition-all", children: [(0, jsx_runtime_1.jsxs)("div", { className: depositClasses?.optionContent || "anyspend-deposit-option-content flex items-center gap-3", children: [(0, jsx_runtime_1.jsx)(QrCodeIcon_1.QrCodeIcon, { className: depositClasses?.optionIcon || "anyspend-deposit-option-icon h-10 w-10" }), (0, jsx_runtime_1.jsxs)("div", { className: depositClasses?.optionInfo || "anyspend-deposit-option-info", children: [(0, jsx_runtime_1.jsx)("span", { className: depositClasses?.optionTitle || "anyspend-deposit-option-title text-as-primary font-medium", children: "Deposit with QR Code" }), (0, jsx_runtime_1.jsx)("p", { className: depositClasses?.optionDescription ||
@@ -40,11 +40,25 @@ function AnySpendStakeB3({ loadOrder, mode = "modal", recipientAddress, stakeAmo
40
40
  // Wagmi hooks for direct staking
41
41
  const { address } = (0, wagmi_1.useAccount)();
42
42
  const { switchChainAndExecute, isSwitchingOrExecuting } = (0, react_1.useUnifiedChainSwitchAndExecute)();
43
- // Fetch B3 token balance
44
- const { data: simBalance, isLoading: isBalanceLoading } = (0, react_1.useSimBalance)(address, [chains_1.base.id]);
45
- const b3RawBalanceStr = simBalance?.balances.find(b => (0, anyspend_1.eqci)(b.address, anyspend_1.B3_TOKEN.address))?.amount || "0";
43
+ // Fetch B3 token balance. `isBalanceUnknown` must gate every use of `b3RawBalance`: a failed read
44
+ // yields the same 0 as an empty wallet, and acting on it pushes a holder into the swap flow to
45
+ // buy a token they already have.
46
+ const { data: balances, isLoading: isBalanceLoading, isError: isBalanceError, refetch: refetchBalance, } = (0, react_1.usePortfolioBalance)(address, [chains_1.base.id]);
47
+ // Guarded on `address`: with no wallet connected the query never runs, and a query that was
48
+ // never asked is not a query that failed. Without this the screen tells a visitor their
49
+ // balance is unavailable and refuses to continue, when they simply have not connected yet.
50
+ const isBalanceUnknown = Boolean(address) && (isBalanceError || (!isBalanceLoading && balances === undefined));
51
+ const b3RawBalanceStr = balances?.find(b => (0, anyspend_1.eqci)(b.address, anyspend_1.B3_TOKEN.address))?.amount || "0";
46
52
  const b3RawBalance = BigInt(b3RawBalanceStr);
47
53
  const b3Balance = (0, number_1.formatTokenAmount)(b3RawBalance, anyspend_1.B3_TOKEN.decimals);
54
+ /**
55
+ * Whether the wallet demonstrably holds enough B3 to stake `amountRaw` directly.
56
+ *
57
+ * False while the balance is unknown — but callers must not read that as a shortfall. An unknown
58
+ * balance is neither enough nor short, and the two need different UI: a shortfall offers the swap
59
+ * flow, an unknown offers a retry. Check `isBalanceUnknown` first.
60
+ */
61
+ const hasEnoughB3 = (amountRaw) => !isBalanceUnknown && BigInt(amountRaw || "0") <= b3RawBalance;
48
62
  // State for direct staking flow
49
63
  const [isStaking, setIsStaking] = (0, react_3.useState)(false);
50
64
  const [stakingTxHash, setStakingTxHash] = (0, react_3.useState)("");
@@ -212,9 +226,11 @@ function AnySpendStakeB3({ loadOrder, mode = "modal", recipientAddress, stakeAmo
212
226
  react_1.toast.error("Please enter a valid amount to stake");
213
227
  return;
214
228
  }
215
- // Check if user has sufficient B3 balance for direct staking
216
- const hasEnoughBalance = b3RawBalance && BigInt(userStakeAmount) <= b3RawBalance;
217
- if (hasEnoughBalance) {
229
+ if (isBalanceUnknown) {
230
+ react_1.toast.error("Can't read your B3 balance right now. Please try again.");
231
+ return;
232
+ }
233
+ if (hasEnoughB3(userStakeAmount)) {
218
234
  // User has enough B3, proceed with direct staking
219
235
  handleDirectStaking();
220
236
  }
@@ -238,16 +254,19 @@ function AnySpendStakeB3({ loadOrder, mode = "modal", recipientAddress, stakeAmo
238
254
  opacity: hasMounted ? 1 : 0,
239
255
  y: hasMounted ? 0 : 20,
240
256
  filter: hasMounted ? "blur(0px)" : "blur(10px)",
241
- }, transition: { duration: 0.3, delay: 0.1, ease: "easeInOut" }, children: (0, jsx_runtime_1.jsx)("h2", { className: "font-sf-rounded font-neue-montreal-medium mb-1 text-center text-2xl font-semibold", children: (() => {
242
- const hasEnoughBalance = b3RawBalance && BigInt(debouncedUserStakeAmount || "0") <= b3RawBalance;
243
- return hasEnoughBalance || !debouncedAmount ? "Stake B3" : "Swap & Stake B3";
244
- })() }) })] }), (0, jsx_runtime_1.jsxs)(react_2.motion.div, { initial: false, animate: {
257
+ }, transition: { duration: 0.3, delay: 0.1, ease: "easeInOut" }, children: (0, jsx_runtime_1.jsx)("h2", { className: "font-sf-rounded font-neue-montreal-medium mb-1 text-center text-2xl font-semibold", children: isBalanceUnknown || !debouncedAmount || hasEnoughB3(debouncedUserStakeAmount)
258
+ ? "Stake B3"
259
+ : "Swap & Stake B3" }) })] }), (0, jsx_runtime_1.jsxs)(react_2.motion.div, { initial: false, animate: {
245
260
  opacity: hasMounted ? 1 : 0,
246
261
  y: hasMounted ? 0 : 20,
247
262
  filter: hasMounted ? "blur(0px)" : "blur(10px)",
248
- }, transition: { duration: 0.3, delay: 0.2, ease: "easeInOut" }, className: "bg-b3-react-background w-full p-6", children: [(0, jsx_runtime_1.jsx)("div", { className: "mb-2", children: (0, jsx_runtime_1.jsxs)("div", { className: "flex items-center justify-between", children: [(0, jsx_runtime_1.jsx)("p", { className: "text-as-primary/70 text-sm font-medium", children: "I want to stake" }), (0, jsx_runtime_1.jsxs)("span", { className: "text-as-primary/50 flex items-center gap-1 text-sm", children: ["Available: ", isBalanceLoading ? (0, jsx_runtime_1.jsx)(lucide_react_1.Loader2, { className: "h-3 w-3 animate-spin" }) : `${b3Balance} B3`] })] }) }), (0, jsx_runtime_1.jsxs)("div", { className: "relative", children: [(0, jsx_runtime_1.jsx)(react_1.Input, { onFocus: onFocusStakeAmountInput, type: "text", placeholder: "0.00", value: displayAmount, onChange: e => validateAndSetAmount(e.target.value), className: `h-14 px-4 text-lg ${!isAmountValid && displayAmount ? "border-as-red" : "border-b3-react-border"}` }), (0, jsx_runtime_1.jsx)("div", { className: "font-pack absolute right-4 top-1/2 -translate-y-1/2 text-lg font-medium text-blue-500/70", children: "B3" })] }), !isAmountValid && displayAmount && (0, jsx_runtime_1.jsx)("p", { className: "text-as-red mt-2 text-sm", children: validationError }), (0, jsx_runtime_1.jsx)("div", { className: "mt-4", children: (() => {
249
- const hasEnoughBalance = b3RawBalance && BigInt(debouncedUserStakeAmount || "0") <= b3RawBalance;
250
- if (!hasEnoughBalance || !debouncedAmount) {
263
+ }, transition: { duration: 0.3, delay: 0.2, ease: "easeInOut" }, className: "bg-b3-react-background w-full p-6", children: [(0, jsx_runtime_1.jsx)("div", { className: "mb-2", children: (0, jsx_runtime_1.jsxs)("div", { className: "flex items-center justify-between", children: [(0, jsx_runtime_1.jsx)("p", { className: "text-as-primary/70 text-sm font-medium", children: "I want to stake" }), (0, jsx_runtime_1.jsxs)("span", { className: "text-as-primary/50 flex items-center gap-1 text-sm", children: ["Available:", " ", isBalanceLoading ? ((0, jsx_runtime_1.jsx)(lucide_react_1.Loader2, { className: "h-3 w-3 animate-spin" })) : isBalanceUnknown ? ("unavailable") : (`${b3Balance} B3`)] })] }) }), (0, jsx_runtime_1.jsxs)("div", { className: "relative", children: [(0, jsx_runtime_1.jsx)(react_1.Input, { onFocus: onFocusStakeAmountInput, type: "text", placeholder: "0.00", value: displayAmount, onChange: e => validateAndSetAmount(e.target.value), className: `h-14 px-4 text-lg ${!isAmountValid && displayAmount ? "border-as-red" : "border-b3-react-border"}` }), (0, jsx_runtime_1.jsx)("div", { className: "font-pack absolute right-4 top-1/2 -translate-y-1/2 text-lg font-medium text-blue-500/70", children: "B3" })] }), !isAmountValid && displayAmount && (0, jsx_runtime_1.jsx)("p", { className: "text-as-red mt-2 text-sm", children: validationError }), (0, jsx_runtime_1.jsx)("div", { className: "mt-4", children: (() => {
264
+ // An unreadable balance is not a shortfall, so it must not open the swap upsell —
265
+ // that would sell a swap to someone who may already hold the tokens.
266
+ if (isBalanceUnknown) {
267
+ return ((0, jsx_runtime_1.jsxs)("div", { className: "bg-as-brand/10 flex flex-col items-center gap-2 rounded-lg p-4 pb-5", children: [(0, jsx_runtime_1.jsx)("p", { className: "text-as-primary/70 text-sm font-medium", children: "We couldn't read your B3 balance just now." }), (0, jsx_runtime_1.jsx)(react_1.Button, { variant: "ghost", onClick: () => refetchBalance(), className: "text-as-primary text-sm", children: "Try again" })] }));
268
+ }
269
+ if (!hasEnoughB3(debouncedUserStakeAmount) || !debouncedAmount) {
251
270
  return ((0, jsx_runtime_1.jsxs)("div", { className: "bg-as-brand/10 flex flex-col items-center gap-2 rounded-lg p-4 pb-5", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-center justify-center gap-2", children: [(0, jsx_runtime_1.jsx)("span", { className: "text-as-primary text-sm font-semibold", children: "Swap & stake from any token" }), (0, jsx_runtime_1.jsxs)(react_1.TextLoop, { children: [(0, jsx_runtime_1.jsx)(EthIcon_1.EthIcon, { className: "h-8 w-8" }), (0, jsx_runtime_1.jsx)(SolIcon_1.SolIcon, { className: "h-8 w-8" }), (0, jsx_runtime_1.jsx)(USDCIcon_1.UsdcIcon, { className: "h-8 w-8" })] }), (0, jsx_runtime_1.jsx)(lucide_react_1.ArrowRight, { className: "text-as-primary h-4 w-4" }), (0, jsx_runtime_1.jsx)("img", { src: "https://cdn.b3.fun/b3-coin-3d.png", className: "h-7 w-7", alt: "B3 Token" })] }), (0, jsx_runtime_1.jsx)("p", { className: "text-as-primary/50 text-sm font-medium", children: debouncedAmount
252
271
  ? `No problem, we'll help you swap to ${debouncedAmount} B3!`
253
272
  : "Not enough B3? We'll help you swap from other coins." })] }));
@@ -40,11 +40,25 @@ function AnySpendStakeB3ExactIn({ loadOrder, mode = "modal", sourceTokenAddress,
40
40
  // Wagmi hooks for direct staking
41
41
  const { address } = (0, wagmi_1.useAccount)();
42
42
  const { switchChainAndExecute, isSwitchingOrExecuting } = (0, react_1.useUnifiedChainSwitchAndExecute)();
43
- // Fetch B3 token balance
44
- const { data: simBalance, isLoading: isBalanceLoading } = (0, react_1.useSimBalance)(address, [chains_1.base.id]);
45
- const b3RawBalanceStr = simBalance?.balances.find(b => (0, anyspend_1.eqci)(b.address, anyspend_1.B3_TOKEN.address))?.amount || "0";
43
+ // Fetch B3 token balance. `isBalanceUnknown` must gate every use of `b3RawBalance`: a failed read
44
+ // yields the same 0 as an empty wallet, and acting on it pushes a holder into the swap flow to
45
+ // buy a token they already have.
46
+ const { data: balances, isLoading: isBalanceLoading, isError: isBalanceError, refetch: refetchBalance, } = (0, react_1.usePortfolioBalance)(address, [chains_1.base.id]);
47
+ // Guarded on `address`: with no wallet connected the query never runs, and a query that was
48
+ // never asked is not a query that failed. Without this the screen tells a visitor their
49
+ // balance is unavailable and refuses to continue, when they simply have not connected yet.
50
+ const isBalanceUnknown = Boolean(address) && (isBalanceError || (!isBalanceLoading && balances === undefined));
51
+ const b3RawBalanceStr = balances?.find(b => (0, anyspend_1.eqci)(b.address, anyspend_1.B3_TOKEN.address))?.amount || "0";
46
52
  const b3RawBalance = BigInt(b3RawBalanceStr);
47
53
  const b3Balance = (0, number_1.formatTokenAmount)(b3RawBalance, anyspend_1.B3_TOKEN.decimals);
54
+ /**
55
+ * Whether the wallet demonstrably holds enough B3 to stake `amountRaw` directly.
56
+ *
57
+ * False while the balance is unknown — but callers must not read that as a shortfall. An unknown
58
+ * balance is neither enough nor short, and the two need different UI: a shortfall offers the swap
59
+ * flow, an unknown offers a retry. Check `isBalanceUnknown` first.
60
+ */
61
+ const hasEnoughB3 = (amountRaw) => !isBalanceUnknown && BigInt(amountRaw || "0") <= b3RawBalance;
48
62
  // State for direct staking flow
49
63
  const [isStaking, setIsStaking] = (0, react_3.useState)(false);
50
64
  const [stakingTxHash, setStakingTxHash] = (0, react_3.useState)("");
@@ -215,8 +229,11 @@ function AnySpendStakeB3ExactIn({ loadOrder, mode = "modal", sourceTokenAddress,
215
229
  return;
216
230
  }
217
231
  // Check if user has sufficient B3 balance for direct staking
218
- const hasEnoughBalance = b3RawBalance && BigInt(userStakeAmount) <= b3RawBalance;
219
- if (hasEnoughBalance) {
232
+ if (isBalanceUnknown) {
233
+ react_1.toast.error("Can't read your B3 balance right now. Please try again.");
234
+ return;
235
+ }
236
+ if (hasEnoughB3(userStakeAmount)) {
220
237
  // User has enough B3, proceed with direct staking
221
238
  handleDirectStaking();
222
239
  }
@@ -249,15 +266,20 @@ function AnySpendStakeB3ExactIn({ loadOrder, mode = "modal", sourceTokenAddress,
249
266
  y: hasMounted ? 0 : 20,
250
267
  filter: hasMounted ? "blur(0px)" : "blur(10px)",
251
268
  }, transition: { duration: 0.3, delay: 0.1, ease: "easeInOut" }, children: (0, jsx_runtime_1.jsx)("h2", { className: "font-sf-rounded font-neue-montreal-medium mb-1 text-center text-2xl font-semibold", children: (() => {
252
- const hasEnoughBalance = b3RawBalance && BigInt(debouncedUserStakeAmount || "0") <= b3RawBalance;
253
- return hasEnoughBalance || !debouncedAmount ? "Stake B3" : "Swap & Stake B3";
269
+ return isBalanceUnknown || !debouncedAmount || hasEnoughB3(debouncedUserStakeAmount)
270
+ ? "Stake B3"
271
+ : "Swap & Stake B3";
254
272
  })() }) })] }), (0, jsx_runtime_1.jsxs)(react_2.motion.div, { initial: false, animate: {
255
273
  opacity: hasMounted ? 1 : 0,
256
274
  y: hasMounted ? 0 : 20,
257
275
  filter: hasMounted ? "blur(0px)" : "blur(10px)",
258
- }, transition: { duration: 0.3, delay: 0.2, ease: "easeInOut" }, className: "bg-b3-react-background w-full p-6", children: [(0, jsx_runtime_1.jsx)("div", { className: "mb-2", children: (0, jsx_runtime_1.jsxs)("div", { className: "flex items-center justify-between", children: [(0, jsx_runtime_1.jsx)("p", { className: "text-as-primary/70 text-sm font-medium", children: "I want to stake" }), (0, jsx_runtime_1.jsxs)("span", { className: "text-as-primary/50 flex items-center gap-1 text-sm", children: ["Available: ", isBalanceLoading ? (0, jsx_runtime_1.jsx)(lucide_react_1.Loader2, { className: "h-3 w-3 animate-spin" }) : `${b3Balance} B3`] })] }) }), (0, jsx_runtime_1.jsxs)("div", { className: "relative", children: [(0, jsx_runtime_1.jsx)(react_1.Input, { onFocus: onFocusStakeAmountInput, type: "text", placeholder: "0.00", value: displayAmount, onChange: e => validateAndSetAmount(e.target.value), className: `h-14 px-4 text-lg ${!isAmountValid && displayAmount ? "border-as-red" : "border-b3-react-border"}` }), (0, jsx_runtime_1.jsx)("div", { className: "font-pack absolute right-4 top-1/2 -translate-y-1/2 text-lg font-medium text-blue-500/70", children: "B3" })] }), !isAmountValid && displayAmount && (0, jsx_runtime_1.jsx)("p", { className: "text-as-red mt-2 text-sm", children: validationError }), (0, jsx_runtime_1.jsx)("div", { className: "mt-4", children: (() => {
259
- const hasEnoughBalance = b3RawBalance && BigInt(debouncedUserStakeAmount || "0") <= b3RawBalance;
260
- if (!hasEnoughBalance || !debouncedAmount) {
276
+ }, transition: { duration: 0.3, delay: 0.2, ease: "easeInOut" }, className: "bg-b3-react-background w-full p-6", children: [(0, jsx_runtime_1.jsx)("div", { className: "mb-2", children: (0, jsx_runtime_1.jsxs)("div", { className: "flex items-center justify-between", children: [(0, jsx_runtime_1.jsx)("p", { className: "text-as-primary/70 text-sm font-medium", children: "I want to stake" }), (0, jsx_runtime_1.jsxs)("span", { className: "text-as-primary/50 flex items-center gap-1 text-sm", children: ["Available:", " ", isBalanceLoading ? ((0, jsx_runtime_1.jsx)(lucide_react_1.Loader2, { className: "h-3 w-3 animate-spin" })) : isBalanceUnknown ? ("unavailable") : (`${b3Balance} B3`)] })] }) }), (0, jsx_runtime_1.jsxs)("div", { className: "relative", children: [(0, jsx_runtime_1.jsx)(react_1.Input, { onFocus: onFocusStakeAmountInput, type: "text", placeholder: "0.00", value: displayAmount, onChange: e => validateAndSetAmount(e.target.value), className: `h-14 px-4 text-lg ${!isAmountValid && displayAmount ? "border-as-red" : "border-b3-react-border"}` }), (0, jsx_runtime_1.jsx)("div", { className: "font-pack absolute right-4 top-1/2 -translate-y-1/2 text-lg font-medium text-blue-500/70", children: "B3" })] }), !isAmountValid && displayAmount && (0, jsx_runtime_1.jsx)("p", { className: "text-as-red mt-2 text-sm", children: validationError }), (0, jsx_runtime_1.jsx)("div", { className: "mt-4", children: (() => {
277
+ // An unreadable balance is not a shortfall, so it must not open the swap upsell —
278
+ // that would sell a swap to someone who may already hold the tokens.
279
+ if (isBalanceUnknown) {
280
+ return ((0, jsx_runtime_1.jsxs)("div", { className: "bg-as-brand/10 flex flex-col items-center gap-2 rounded-lg p-4 pb-5", children: [(0, jsx_runtime_1.jsx)("p", { className: "text-as-primary/70 text-sm font-medium", children: "We couldn't read your B3 balance just now." }), (0, jsx_runtime_1.jsx)(react_1.Button, { variant: "ghost", onClick: () => refetchBalance(), className: "text-as-primary text-sm", children: "Try again" })] }));
281
+ }
282
+ if (!hasEnoughB3(debouncedUserStakeAmount) || !debouncedAmount) {
261
283
  return ((0, jsx_runtime_1.jsxs)("div", { className: "bg-as-brand/10 flex flex-col items-center gap-2 rounded-lg p-4 pb-5", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-center justify-center gap-2", children: [(0, jsx_runtime_1.jsx)("span", { className: "text-as-primary text-sm font-semibold", children: "Swap & stake from any token" }), (0, jsx_runtime_1.jsxs)(react_1.TextLoop, { children: [(0, jsx_runtime_1.jsx)(EthIcon_1.EthIcon, { className: "h-8 w-8" }), (0, jsx_runtime_1.jsx)(SolIcon_1.SolIcon, { className: "h-8 w-8" }), (0, jsx_runtime_1.jsx)(USDCIcon_1.UsdcIcon, { className: "h-8 w-8" })] }), (0, jsx_runtime_1.jsx)(lucide_react_1.ArrowRight, { className: "text-as-primary h-4 w-4" }), (0, jsx_runtime_1.jsx)("img", { src: "https://cdn.b3.fun/b3-coin-3d.png", className: "h-7 w-7", alt: "B3 Token" })] }), (0, jsx_runtime_1.jsx)("p", { className: "text-as-primary/50 text-sm font-medium", children: debouncedAmount
262
284
  ? `No problem, we'll help you swap to ${debouncedAmount} B3!`
263
285
  : "Not enough B3? We'll help you swap from other coins." })] }));
@@ -71,13 +71,17 @@ function CryptoPayPanel({ recipientAddress, destinationTokenAddress, destination
71
71
  ? "native"
72
72
  : selectedSrcToken.address
73
73
  : undefined;
74
- const { data: balanceData } = (0, react_1.useSimTokenBalance)(effectiveAddress, tokenAddress, selectedSrcChainId);
74
+ // `selectedSrcChainId` is Relay-numbered; balance rows are keyed by the chain registry's id.
75
+ const { data: balanceRow, isError: isBalanceError } = (0, react_1.usePortfolioTokenBalance)(effectiveAddress, tokenAddress, (0, chain_1.toRegistryChainId)(selectedSrcChainId));
75
76
  const balance = (0, react_4.useMemo)(() => {
76
- const b = balanceData?.balances?.[0];
77
- if (!b?.amount)
77
+ if (!balanceRow?.amount)
78
78
  return { raw: BigInt(0), formatted: "0", decimals: 18 };
79
- return { raw: BigInt(b.amount), formatted: (0, number_1.formatTokenAmount)(BigInt(b.amount), b.decimals), decimals: b.decimals };
80
- }, [balanceData]);
79
+ return {
80
+ raw: BigInt(balanceRow.amount),
81
+ formatted: (0, number_1.formatTokenAmount)(BigInt(balanceRow.amount), balanceRow.decimals),
82
+ decimals: balanceRow.decimals,
83
+ };
84
+ }, [balanceRow]);
81
85
  const srcAmount = (0, react_4.useMemo)(() => {
82
86
  if (isSameToken)
83
87
  return totalAmount;
@@ -88,7 +92,9 @@ function CryptoPayPanel({ recipientAddress, destinationTokenAddress, destination
88
92
  return "0";
89
93
  return (0, number_1.formatTokenAmount)(BigInt(srcAmount || "0"), selectedSrcToken.decimals || 18);
90
94
  }, [srcAmount, selectedSrcToken]);
91
- const hasEnoughBalance = balance.raw >= BigInt(srcAmount || "0");
95
+ // A failed balance read must not masquerade as a shortfall: it would disable Pay and tell a
96
+ // funded user they are short. Unknown blocks auto-pay but leaves the manual path open.
97
+ const hasEnoughBalance = !isBalanceError && balance.raw >= BigInt(srcAmount || "0");
92
98
  /* ------------------------------------------------------------------ */
93
99
  /* Destination token object (shared by both flows) */
94
100
  /* ------------------------------------------------------------------ */
@@ -317,7 +323,7 @@ function CryptoPayPanel({ recipientAddress, destinationTokenAddress, destination
317
323
  }, [shouldAutoPay, connectedAddress, selectedSrcToken, hasEnoughBalance, isLoadingAnyspendQuote, handleWalletPay]);
318
324
  const isLoading = isLoadingAnyspendQuote;
319
325
  const isPending = isCreatingSwapOrder || isSendingDeposit || isWaitingForExecution;
320
- const canPay = connectedAddress && selectedSrcToken && hasEnoughBalance && !isLoading && !isPending;
326
+ const canPay = connectedAddress && selectedSrcToken && (hasEnoughBalance || isBalanceError) && !isLoading && !isPending;
321
327
  const chainName = anyspend_1.ALL_CHAINS[selectedSrcChainId]?.name || "the specified chain";
322
328
  const chainLogoUrl = anyspend_1.ALL_CHAINS[selectedSrcChainId]?.logoUrl;
323
329
  // Collapse QR on mobile when a wallet connector is available
@@ -336,7 +342,9 @@ function CryptoPayPanel({ recipientAddress, destinationTokenAddress, destination
336
342
  name: token.name,
337
343
  symbol: token.symbol,
338
344
  });
339
- }, supportedWalletVMs: ["evm", "svm"], token: undefined, trigger: (0, jsx_runtime_1.jsxs)("button", { className: (0, cn_1.cn)("flex w-full items-center justify-between rounded-xl border border-gray-200 bg-white px-4 py-3 transition-colors hover:border-gray-300 dark:border-neutral-700 dark:bg-neutral-800 dark:hover:border-neutral-600", classes?.tokenSelector), children: [selectedSrcToken ? ((0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-3", children: [(0, jsx_runtime_1.jsx)(ChainTokenIcon_1.ChainTokenIcon, { chainUrl: anyspend_1.ALL_CHAINS[selectedSrcToken.chainId]?.logoUrl || "", tokenUrl: selectedSrcToken.metadata?.logoURI, className: "h-8 w-8" }), (0, jsx_runtime_1.jsxs)("div", { className: "text-left", children: [(0, jsx_runtime_1.jsx)("p", { className: "text-sm font-medium text-gray-900 dark:text-gray-100", children: selectedSrcToken.symbol }), (0, jsx_runtime_1.jsxs)("p", { className: "text-xs text-gray-500 dark:text-gray-400", children: ["Balance: ", balance.formatted] })] })] })) : ((0, jsx_runtime_1.jsx)("span", { className: "text-sm text-gray-400", children: "Select token" })), (0, jsx_runtime_1.jsx)(lucide_react_1.ChevronsUpDown, { className: "h-4 w-4 text-gray-400" })] }) })] }), (0, jsx_runtime_1.jsx)(react_3.motion.div, { initial: { opacity: 0, y: 6 }, animate: { opacity: 1, y: 0 }, transition: { duration: 0.25, ease: "easeOut" }, className: (0, cn_1.cn)("rounded-xl border border-gray-200 bg-gray-50 px-4 py-3 dark:border-neutral-700 dark:bg-neutral-800/50", classes?.quoteDisplay), children: (0, jsx_runtime_1.jsxs)("div", { className: "flex items-center justify-between", children: [(0, jsx_runtime_1.jsx)("span", { className: "text-sm text-gray-500 dark:text-gray-400", children: "You pay" }), (0, jsx_runtime_1.jsx)(react_3.AnimatePresence, { mode: "wait", children: isLoadingAnyspendQuote ? ((0, jsx_runtime_1.jsx)(react_3.motion.div, { initial: { opacity: 0 }, animate: { opacity: 1 }, exit: { opacity: 0 }, transition: { duration: 0.15 }, children: (0, jsx_runtime_1.jsx)(react_2.TextShimmer, { duration: 1, className: "text-sm", children: "Fetching quote..." }) }, "quote-loading")) : ((0, jsx_runtime_1.jsxs)(react_3.motion.span, { initial: { opacity: 0 }, animate: { opacity: 1 }, exit: { opacity: 0 }, transition: { duration: 0.15 }, className: "text-sm font-medium text-gray-900 dark:text-gray-100", children: [srcAmountFormatted, " ", selectedSrcToken?.symbol || ""] }, "quote-amount")) })] }) }), (0, jsx_runtime_1.jsx)(react_3.AnimatePresence, { children: connectedAddress && selectedSrcToken && !hasEnoughBalance && !isLoading && ((0, jsx_runtime_1.jsxs)(react_3.motion.p, { initial: { opacity: 0, height: 0 }, animate: { opacity: 1, height: "auto" }, exit: { opacity: 0, height: 0 }, transition: { duration: 0.2, ease: "easeOut" }, className: "text-center text-sm text-red-500", children: ["Insufficient ", selectedSrcToken.symbol, " balance"] }, "balance-warning")) }), !connectedAddress ? ((0, jsx_runtime_1.jsx)(react_2.ShinyButton, { accentColor: themeColor || "hsl(var(--as-brand))", onClick: handleConnectWallet, className: (0, cn_1.cn)("w-full", classes?.payButton), textClassName: "text-white", children: "Connect Wallet to Pay" })) : ((0, jsx_runtime_1.jsx)(react_2.ShinyButton, { accentColor: themeColor || "hsl(var(--as-brand))", onClick: handleWalletPay, disabled: !canPay, className: (0, cn_1.cn)("w-full", classes?.payButton), textClassName: (0, cn_1.cn)(!canPay ? "text-as-secondary" : "text-white"), children: isPending ? ((0, jsx_runtime_1.jsxs)("span", { className: "flex items-center justify-center gap-2", children: [(0, jsx_runtime_1.jsx)(lucide_react_1.Loader2, { className: "h-4 w-4 animate-spin" }), isCreatingSwapOrder
345
+ }, supportedWalletVMs: ["evm", "svm"], token: undefined, trigger: (0, jsx_runtime_1.jsxs)("button", { className: (0, cn_1.cn)("flex w-full items-center justify-between rounded-xl border border-gray-200 bg-white px-4 py-3 transition-colors hover:border-gray-300 dark:border-neutral-700 dark:bg-neutral-800 dark:hover:border-neutral-600", classes?.tokenSelector), children: [selectedSrcToken ? ((0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-3", children: [(0, jsx_runtime_1.jsx)(ChainTokenIcon_1.ChainTokenIcon, { chainUrl: anyspend_1.ALL_CHAINS[selectedSrcToken.chainId]?.logoUrl || "", tokenUrl: selectedSrcToken.metadata?.logoURI, className: "h-8 w-8" }), (0, jsx_runtime_1.jsxs)("div", { className: "text-left", children: [(0, jsx_runtime_1.jsx)("p", { className: "text-sm font-medium text-gray-900 dark:text-gray-100", children: selectedSrcToken.symbol }), (0, jsx_runtime_1.jsxs)("p", { className: "text-xs text-gray-500 dark:text-gray-400", children: ["Balance: ", balance.formatted] })] })] })) : ((0, jsx_runtime_1.jsx)("span", { className: "text-sm text-gray-400", children: "Select token" })), (0, jsx_runtime_1.jsx)(lucide_react_1.ChevronsUpDown, { className: "h-4 w-4 text-gray-400" })] }) })] }), (0, jsx_runtime_1.jsx)(react_3.motion.div, { initial: { opacity: 0, y: 6 }, animate: { opacity: 1, y: 0 }, transition: { duration: 0.25, ease: "easeOut" }, className: (0, cn_1.cn)("rounded-xl border border-gray-200 bg-gray-50 px-4 py-3 dark:border-neutral-700 dark:bg-neutral-800/50", classes?.quoteDisplay), children: (0, jsx_runtime_1.jsxs)("div", { className: "flex items-center justify-between", children: [(0, jsx_runtime_1.jsx)("span", { className: "text-sm text-gray-500 dark:text-gray-400", children: "You pay" }), (0, jsx_runtime_1.jsx)(react_3.AnimatePresence, { mode: "wait", children: isLoadingAnyspendQuote ? ((0, jsx_runtime_1.jsx)(react_3.motion.div, { initial: { opacity: 0 }, animate: { opacity: 1 }, exit: { opacity: 0 }, transition: { duration: 0.15 }, children: (0, jsx_runtime_1.jsx)(react_2.TextShimmer, { duration: 1, className: "text-sm", children: "Fetching quote..." }) }, "quote-loading")) : ((0, jsx_runtime_1.jsxs)(react_3.motion.span, { initial: { opacity: 0 }, animate: { opacity: 1 }, exit: { opacity: 0 }, transition: { duration: 0.15 }, className: "text-sm font-medium text-gray-900 dark:text-gray-100", children: [srcAmountFormatted, " ", selectedSrcToken?.symbol || ""] }, "quote-amount")) })] }) }), (0, jsx_runtime_1.jsx)(react_3.AnimatePresence, { children: connectedAddress && selectedSrcToken && !hasEnoughBalance && !isLoading && ((0, jsx_runtime_1.jsx)(react_3.motion.p, { initial: { opacity: 0, height: 0 }, animate: { opacity: 1, height: "auto" }, exit: { opacity: 0, height: 0 }, transition: { duration: 0.2, ease: "easeOut" }, className: `text-center text-sm ${isBalanceError ? "text-as-primary/50" : "text-red-500"}`, children: isBalanceError
346
+ ? `Couldn't check your ${selectedSrcToken.symbol} balance`
347
+ : `Insufficient ${selectedSrcToken.symbol} balance` }, "balance-warning")) }), !connectedAddress ? ((0, jsx_runtime_1.jsx)(react_2.ShinyButton, { accentColor: themeColor || "hsl(var(--as-brand))", onClick: handleConnectWallet, className: (0, cn_1.cn)("w-full", classes?.payButton), textClassName: "text-white", children: "Connect Wallet to Pay" })) : ((0, jsx_runtime_1.jsx)(react_2.ShinyButton, { accentColor: themeColor || "hsl(var(--as-brand))", onClick: handleWalletPay, disabled: !canPay, className: (0, cn_1.cn)("w-full", classes?.payButton), textClassName: (0, cn_1.cn)(!canPay ? "text-as-secondary" : "text-white"), children: isPending ? ((0, jsx_runtime_1.jsxs)("span", { className: "flex items-center justify-center gap-2", children: [(0, jsx_runtime_1.jsx)(lucide_react_1.Loader2, { className: "h-4 w-4 animate-spin" }), isCreatingSwapOrder
340
348
  ? "Creating order..."
341
349
  : isSendingDeposit
342
350
  ? "Confirm in wallet..."
@@ -9,10 +9,9 @@ const number_1 = require("../../../../shared/utils/number");
9
9
  const react_2 = require("react");
10
10
  const viem_1 = require("viem");
11
11
  function TokenBalance({ token, walletAddress, onChangeInput, }) {
12
- const tokenAddress = (0, token_1.isNativeToken)(token.address) ? "native" : token.address;
13
- const { data, isLoading } = (0, react_1.useSimTokenBalance)(walletAddress, tokenAddress, token.chainId);
12
+ // `token.chainId` is Relay-numbered; balance rows are keyed by the chain registry's id.
13
+ const { data: balance, isLoading, isError, } = (0, react_1.usePortfolioTokenBalance)(walletAddress, token.address, (0, chain_1.toRegistryChainId)(token.chainId));
14
14
  const { rawBalance, formattedBalance } = (0, react_2.useMemo)(() => {
15
- const balance = data?.balances?.[0];
16
15
  if (!balance?.amount) {
17
16
  return { rawBalance: null, formattedBalance: "0" };
18
17
  }
@@ -21,7 +20,7 @@ function TokenBalance({ token, walletAddress, onChangeInput, }) {
21
20
  rawBalance: raw,
22
21
  formattedBalance: (0, number_1.formatTokenAmount)(raw, balance.decimals),
23
22
  };
24
- }, [data]);
23
+ }, [balance]);
25
24
  const handlePercentageClick = (percentage) => {
26
25
  if (!rawBalance)
27
26
  return;
@@ -45,5 +44,5 @@ function TokenBalance({ token, walletAddress, onChangeInput, }) {
45
44
  }
46
45
  onChangeInput((0, viem_1.formatUnits)(amount, token.decimals));
47
46
  };
48
- return ((0, jsx_runtime_1.jsx)("div", { className: "flex h-7 items-center justify-end gap-1", children: !isLoading && ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("div", { className: "text-as-primary/50 inline-flex rounded-lg text-sm", children: rawBalance ? `Balance: ${formattedBalance}` : `Balance: 0` }), !!rawBalance && ((0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: (0, jsx_runtime_1.jsx)("button", { onClick: () => handlePercentageClick(100), className: "text-as-primary/50 bg-as-on-surface-2 hover:bg-as-on-surface-3 inline-flex cursor-pointer rounded-lg px-2 py-1 text-xs transition-colors", children: "MAX" }) }))] })) }, `balance-${token.address}-${token.chainId}`));
47
+ return ((0, jsx_runtime_1.jsx)("div", { className: "flex h-7 items-center justify-end gap-1", children: !isLoading && ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("div", { className: "text-as-primary/50 inline-flex rounded-lg text-sm", children: isError ? "Balance: —" : rawBalance ? `Balance: ${formattedBalance}` : `Balance: 0` }), !!rawBalance && ((0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: (0, jsx_runtime_1.jsx)("button", { onClick: () => handlePercentageClick(100), className: "text-as-primary/50 bg-as-on-surface-2 hover:bg-as-on-surface-3 inline-flex cursor-pointer rounded-lg px-2 py-1 text-xs transition-colors", children: "MAX" }) }))] })) }, `balance-${token.address}-${token.chainId}`));
49
48
  }
@@ -10,9 +10,9 @@ export declare const useGenerateSigMintData: ({ recipientAddress, contractAddres
10
10
  description?: string | undefined;
11
11
  status?: "ACTIVE" | "INACTIVE" | "DRAFT" | undefined;
12
12
  metadata?: {} | undefined;
13
+ logoURI?: string | undefined;
13
14
  createdAt?: string | undefined;
14
15
  updatedAt?: string | undefined;
15
- logoURI?: string | undefined;
16
16
  creator?: string | undefined;
17
17
  signatureRequestBody?: {
18
18
  currency?: string | undefined;
@@ -56,11 +56,23 @@ export declare const hyperEVM: {
56
56
  };
57
57
  };
58
58
  sourceId?: number | undefined | undefined;
59
+ supportsTransactionReplacementDetection?: boolean | undefined | undefined;
59
60
  testnet?: boolean | undefined | undefined;
60
61
  custom?: Record<string, unknown> | undefined;
62
+ extendSchema?: Record<string, unknown> | undefined;
61
63
  fees?: import("viem").ChainFees<undefined> | undefined;
62
64
  formatters?: undefined;
65
+ prepareTransactionRequest?: ((args: import("viem").PrepareTransactionRequestParameters, options: {
66
+ client: import("viem").Client;
67
+ phase: "beforeFillTransaction" | "beforeFillParameters" | "afterFillParameters";
68
+ }) => Promise<import("viem").PrepareTransactionRequestParameters>) | [fn: ((args: import("viem").PrepareTransactionRequestParameters, options: {
69
+ client: import("viem").Client;
70
+ phase: "beforeFillTransaction" | "beforeFillParameters" | "afterFillParameters";
71
+ }) => Promise<import("viem").PrepareTransactionRequestParameters>) | undefined, options: {
72
+ runAt: readonly ("beforeFillTransaction" | "beforeFillParameters" | "afterFillParameters")[];
73
+ }] | undefined;
63
74
  serializers?: import("viem").ChainSerializers<undefined, import("viem").TransactionSerializable> | undefined;
75
+ verifyHash?: ((client: import("viem").Client, parameters: import("viem").VerifyHashActionParameters) => Promise<import("viem").VerifyHashActionReturnType>) | undefined;
64
76
  };
65
77
  export declare const plume: {
66
78
  blockExplorers: {
@@ -94,11 +106,23 @@ export declare const plume: {
94
106
  };
95
107
  };
96
108
  sourceId?: number | undefined | undefined;
109
+ supportsTransactionReplacementDetection?: boolean | undefined | undefined;
97
110
  testnet?: boolean | undefined | undefined;
98
111
  custom?: Record<string, unknown> | undefined;
112
+ extendSchema?: Record<string, unknown> | undefined;
99
113
  fees?: import("viem").ChainFees<undefined> | undefined;
100
114
  formatters?: undefined;
115
+ prepareTransactionRequest?: ((args: import("viem").PrepareTransactionRequestParameters, options: {
116
+ client: import("viem").Client;
117
+ phase: "beforeFillTransaction" | "beforeFillParameters" | "afterFillParameters";
118
+ }) => Promise<import("viem").PrepareTransactionRequestParameters>) | [fn: ((args: import("viem").PrepareTransactionRequestParameters, options: {
119
+ client: import("viem").Client;
120
+ phase: "beforeFillTransaction" | "beforeFillParameters" | "afterFillParameters";
121
+ }) => Promise<import("viem").PrepareTransactionRequestParameters>) | undefined, options: {
122
+ runAt: readonly ("beforeFillTransaction" | "beforeFillParameters" | "afterFillParameters")[];
123
+ }] | undefined;
101
124
  serializers?: import("viem").ChainSerializers<undefined, import("viem").TransactionSerializable> | undefined;
125
+ verifyHash?: ((client: import("viem").Client, parameters: import("viem").VerifyHashActionParameters) => Promise<import("viem").VerifyHashActionReturnType>) | undefined;
102
126
  };
103
127
  export declare const EVM_MAINNET: Record<number, IEVMChain>;
104
128
  export declare const EVM_TESTNET: Record<number, IEVMChain>;
@@ -106,6 +130,14 @@ export declare const SOLANA_MAINNET: ISolanaChain;
106
130
  export declare const HYPERLIQUID_MAINNET: IHyperliquidChain;
107
131
  export declare const EVM_CHAINS: Record<number, IEVMChain>;
108
132
  export declare const SOLANA_CHAINS: Record<number, ISolanaChain>;
133
+ /**
134
+ * Translate a Relay-numbered chain id into the id the chain registry uses.
135
+ *
136
+ * Relay numbers Solana 792703809; every other chain shares the universal EVM id. Balance rows are
137
+ * keyed by the registry's id, so handing Relay's number to a balance lookup matches nothing at all
138
+ * — and a funded Solana wallet then reads as empty rather than as unreadable.
139
+ */
140
+ export declare function toRegistryChainId(chainId: number): number;
109
141
  export declare const HYPERLIQUID_CHAINS: Record<number, IHyperliquidChain>;
110
142
  export declare const ALL_CHAINS: Record<number, IBaseChain>;
111
143
  export declare function getSolanaChains(network: "mainnet" | "testnet"): ISolanaChain;
@@ -128,6 +160,19 @@ export declare function getNativeToken(chainId: number): components["schemas"]["
128
160
  export declare function isEvmChain(chainId: number): boolean;
129
161
  export declare function isHyperliquidChain(chainId: number): boolean;
130
162
  export declare function getHyperliquidChain(chainId: number): IHyperliquidChain;
163
+ /**
164
+ * Chains AnySpend no longer accepts orders on, as either source or destination.
165
+ *
166
+ * They stay in ALL_CHAINS on purpose. That map answers "what is this chain" — name, logo, token,
167
+ * decimals — which every order that ever existed still needs in order to render; removing an entry
168
+ * would make getChainName and friends throw on historical rows. Whether new orders are accepted is
169
+ * this separate question.
170
+ *
171
+ * anyspend-service imports this list rather than keeping its own, so the API and the chain picker
172
+ * can never disagree about what is on offer.
173
+ */
174
+ export declare const DEPRECATED_CHAIN_IDS: readonly number[];
175
+ export declare function isDeprecatedChain(chainId?: number): boolean;
131
176
  /**
132
177
  * Get available chain IDs for AnySpend based on context (source or destination).
133
178
  * Filters out chains that shouldn't be available for the given context.