@b3dotfun/sdk 0.1.70-alpha.2 → 0.1.70-alpha.21

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 (355) hide show
  1. package/README.md +3 -3
  2. package/constants/chains/b3Chain.js +3 -1
  3. package/dist/cjs/anyspend/constants/rpc.d.ts +3 -1
  4. package/dist/cjs/anyspend/constants/rpc.js +6 -2
  5. package/dist/cjs/anyspend/react/components/AnySpend.d.ts +9 -1
  6. package/dist/cjs/anyspend/react/components/AnySpend.js +123 -46
  7. package/dist/cjs/anyspend/react/components/AnySpendCustomExactIn.js +8 -10
  8. package/dist/cjs/anyspend/react/components/AnySpendDeposit.d.ts +15 -3
  9. package/dist/cjs/anyspend/react/components/AnySpendDeposit.js +78 -25
  10. package/dist/cjs/anyspend/react/components/AnySpendStakeB3.js +32 -13
  11. package/dist/cjs/anyspend/react/components/AnySpendStakeB3ExactIn.js +32 -10
  12. package/dist/cjs/anyspend/react/components/QRDeposit.d.ts +22 -3
  13. package/dist/cjs/anyspend/react/components/QRDeposit.js +25 -16
  14. package/dist/cjs/anyspend/react/components/checkout/CryptoPayPanel.js +18 -11
  15. package/dist/cjs/anyspend/react/components/common/PureTransferView.d.ts +30 -0
  16. package/dist/cjs/anyspend/react/components/common/PureTransferView.js +64 -0
  17. package/dist/cjs/anyspend/react/components/common/TokenBalance.js +4 -5
  18. package/dist/cjs/anyspend/react/hooks/useCreateDepositFirstOrder.d.ts +3 -3
  19. package/dist/cjs/anyspend/react/hooks/useSigMint.d.ts +1 -1
  20. package/dist/cjs/anyspend/utils/address.d.ts +2 -1
  21. package/dist/cjs/anyspend/utils/address.js +12 -9
  22. package/dist/cjs/anyspend/utils/chain.d.ts +84 -1
  23. package/dist/cjs/anyspend/utils/chain.js +73 -3
  24. package/dist/cjs/anyspend/utils/token.d.ts +2 -0
  25. package/dist/cjs/anyspend/utils/token.js +15 -1
  26. package/dist/cjs/app.shared.d.ts +9 -1
  27. package/dist/cjs/app.shared.js +19 -0
  28. package/dist/cjs/global-account/app.native.d.ts +1 -1
  29. package/dist/cjs/global-account/better-auth-client.d.ts +3314 -36
  30. package/dist/cjs/global-account/better-auth-client.js +28 -3
  31. package/dist/cjs/global-account/bsmnt.d.ts +2 -2
  32. package/dist/cjs/global-account/bsmnt.native.d.ts +1 -1
  33. package/dist/cjs/global-account/client-manager.d.ts +7 -5
  34. package/dist/cjs/global-account/client-manager.js +51 -4
  35. package/dist/cjs/global-account/react/components/AvatarEditor/AvatarEditor.js +6 -11
  36. package/dist/cjs/global-account/react/components/B3Provider/B3ConfigProvider.d.ts +11 -0
  37. package/dist/cjs/global-account/react/components/B3Provider/B3ConfigProvider.js +12 -0
  38. package/dist/cjs/global-account/react/components/B3Provider/B3Provider.d.ts +12 -2
  39. package/dist/cjs/global-account/react/components/B3Provider/B3Provider.js +25 -3
  40. package/dist/cjs/global-account/react/components/B3Provider/BetterAuthProvider.js +45 -4
  41. package/dist/cjs/global-account/react/components/B3Provider/RelayKitProviderWrapper.d.ts +1 -2
  42. package/dist/cjs/global-account/react/components/B3Provider/RelayKitProviderWrapper.js +11 -5
  43. package/dist/cjs/global-account/react/components/ManageAccount/ContentTokens.js +23 -15
  44. package/dist/cjs/global-account/react/components/ManageAccount/NFTContent.js +2 -2
  45. package/dist/cjs/global-account/react/components/ManageAccount/ProfileSection.js +8 -6
  46. package/dist/cjs/global-account/react/components/ManageAccount/SettingsProfileCard.js +1 -1
  47. package/dist/cjs/global-account/react/components/ManageAccount/TokenContent.js +17 -8
  48. package/dist/cjs/global-account/react/components/Send/Send.js +15 -11
  49. package/dist/cjs/global-account/react/components/SignInWithB3/BetterAuthSignIn.js +3 -1
  50. package/dist/cjs/global-account/react/components/SignInWithB3/SignInWithB3Flow.js +1 -5
  51. package/dist/cjs/global-account/react/components/SignInWithB3/components/AuthButton.js +2 -1
  52. package/dist/cjs/global-account/react/components/SignInWithB3/steps/LoginStepBetterAuth.js +1 -0
  53. package/dist/cjs/global-account/react/components/SignInWithB3/utils/signInUtils.d.ts +3 -2
  54. package/dist/cjs/global-account/react/components/SignInWithB3/utils/signInUtils.js +3 -3
  55. package/dist/cjs/global-account/react/components/index.d.ts +1 -1
  56. package/dist/cjs/global-account/react/components/index.js +3 -3
  57. package/dist/cjs/global-account/react/hooks/index.d.ts +2 -3
  58. package/dist/cjs/global-account/react/hooks/index.js +7 -10
  59. package/dist/cjs/global-account/react/hooks/useAuth.d.ts +5 -4
  60. package/dist/cjs/global-account/react/hooks/useAuth.js +1 -0
  61. package/dist/cjs/global-account/react/hooks/useAuthentication.d.ts +3 -2
  62. package/dist/cjs/global-account/react/hooks/useAuthentication.js +2 -1
  63. package/dist/cjs/global-account/react/hooks/useBetterAuth.d.ts +1657 -22
  64. package/dist/cjs/global-account/react/hooks/useBetterAuth.js +7 -7
  65. package/dist/cjs/global-account/react/hooks/useClient.d.ts +3 -3
  66. package/dist/cjs/global-account/react/hooks/useFirstEOA.d.ts +4 -7666
  67. package/dist/cjs/global-account/react/hooks/useFirstEOA.js +1 -0
  68. package/dist/cjs/global-account/react/hooks/useNativeBalance.js +2 -2
  69. package/dist/cjs/global-account/react/hooks/usePortfolioBalance.d.ts +15 -0
  70. package/dist/cjs/global-account/react/hooks/usePortfolioBalance.js +76 -0
  71. package/dist/cjs/global-account/react/hooks/usePortfolioCollectibles.d.ts +12 -0
  72. package/dist/cjs/global-account/react/hooks/usePortfolioCollectibles.js +178 -0
  73. package/dist/cjs/global-account/react/hooks/useSiwe.d.ts +1 -1
  74. package/dist/cjs/global-account/react/hooks/useSiwe.native.d.ts +1 -1
  75. package/dist/cjs/global-account/react/hooks/useTWAuth.d.ts +1 -1
  76. package/dist/cjs/global-account/react/hooks/useUnifiedChainSwitchAndExecute.d.ts +1 -0
  77. package/dist/cjs/global-account/react/hooks/useUnifiedChainSwitchAndExecute.js +37 -27
  78. package/dist/cjs/global-account/react/stores/useModalStore.d.ts +14 -2
  79. package/dist/cjs/global-account/types/b3-api.types.d.ts +5 -0
  80. package/dist/cjs/global-account/types/feature-flags.d.ts +5 -5
  81. package/dist/cjs/notifications/services/api.js +1 -0
  82. package/dist/cjs/shared/constants/chains/b3Chain.d.ts +30 -54
  83. package/dist/cjs/shared/constants/chains/b3Chain.js +5 -41
  84. package/dist/cjs/shared/constants/chains/supported.d.ts +1 -49
  85. package/dist/cjs/shared/constants/chains/supported.js +8 -36
  86. package/dist/cjs/shared/constants/index.d.ts +4 -0
  87. package/dist/cjs/shared/utils/chain-transformers.d.ts +4 -4
  88. package/dist/cjs/shared/utils/chain-transformers.js +38 -37
  89. package/dist/cjs/shared/utils/thirdweb-insights.js +2 -2
  90. package/dist/cjs/shared/utils/upload.d.ts +9 -0
  91. package/dist/cjs/shared/utils/upload.js +34 -0
  92. package/dist/cjs/shared/utils/zerionPositions.d.ts +96 -0
  93. package/dist/cjs/shared/utils/zerionPositions.js +188 -0
  94. package/dist/esm/anyspend/constants/rpc.d.ts +3 -1
  95. package/dist/esm/anyspend/constants/rpc.js +5 -1
  96. package/dist/esm/anyspend/react/components/AnySpend.d.ts +9 -1
  97. package/dist/esm/anyspend/react/components/AnySpend.js +124 -47
  98. package/dist/esm/anyspend/react/components/AnySpendCustomExactIn.js +9 -11
  99. package/dist/esm/anyspend/react/components/AnySpendDeposit.d.ts +15 -3
  100. package/dist/esm/anyspend/react/components/AnySpendDeposit.js +80 -27
  101. package/dist/esm/anyspend/react/components/AnySpendStakeB3.js +33 -14
  102. package/dist/esm/anyspend/react/components/AnySpendStakeB3ExactIn.js +33 -11
  103. package/dist/esm/anyspend/react/components/QRDeposit.d.ts +22 -3
  104. package/dist/esm/anyspend/react/components/QRDeposit.js +27 -18
  105. package/dist/esm/anyspend/react/components/checkout/CryptoPayPanel.js +21 -14
  106. package/dist/esm/anyspend/react/components/common/PureTransferView.d.ts +30 -0
  107. package/dist/esm/anyspend/react/components/common/PureTransferView.js +61 -0
  108. package/dist/esm/anyspend/react/components/common/TokenBalance.js +6 -7
  109. package/dist/esm/anyspend/react/hooks/useCreateDepositFirstOrder.d.ts +3 -3
  110. package/dist/esm/anyspend/react/hooks/useSigMint.d.ts +1 -1
  111. package/dist/esm/anyspend/utils/address.d.ts +2 -1
  112. package/dist/esm/anyspend/utils/address.js +9 -6
  113. package/dist/esm/anyspend/utils/chain.d.ts +84 -1
  114. package/dist/esm/anyspend/utils/chain.js +73 -5
  115. package/dist/esm/anyspend/utils/token.d.ts +2 -0
  116. package/dist/esm/anyspend/utils/token.js +13 -0
  117. package/dist/esm/app.shared.d.ts +9 -1
  118. package/dist/esm/app.shared.js +17 -0
  119. package/dist/esm/global-account/app.native.d.ts +1 -1
  120. package/dist/esm/global-account/better-auth-client.d.ts +3314 -36
  121. package/dist/esm/global-account/better-auth-client.js +27 -4
  122. package/dist/esm/global-account/bsmnt.d.ts +2 -2
  123. package/dist/esm/global-account/bsmnt.native.d.ts +1 -1
  124. package/dist/esm/global-account/client-manager.d.ts +7 -5
  125. package/dist/esm/global-account/client-manager.js +51 -5
  126. package/dist/esm/global-account/react/components/AvatarEditor/AvatarEditor.js +6 -11
  127. package/dist/esm/global-account/react/components/B3Provider/B3ConfigProvider.d.ts +11 -0
  128. package/dist/esm/global-account/react/components/B3Provider/B3ConfigProvider.js +11 -0
  129. package/dist/esm/global-account/react/components/B3Provider/B3Provider.d.ts +12 -2
  130. package/dist/esm/global-account/react/components/B3Provider/B3Provider.js +26 -4
  131. package/dist/esm/global-account/react/components/B3Provider/BetterAuthProvider.js +46 -5
  132. package/dist/esm/global-account/react/components/B3Provider/RelayKitProviderWrapper.d.ts +1 -2
  133. package/dist/esm/global-account/react/components/B3Provider/RelayKitProviderWrapper.js +11 -5
  134. package/dist/esm/global-account/react/components/ManageAccount/ContentTokens.js +24 -16
  135. package/dist/esm/global-account/react/components/ManageAccount/NFTContent.js +3 -3
  136. package/dist/esm/global-account/react/components/ManageAccount/ProfileSection.js +9 -7
  137. package/dist/esm/global-account/react/components/ManageAccount/SettingsProfileCard.js +1 -1
  138. package/dist/esm/global-account/react/components/ManageAccount/TokenContent.js +18 -9
  139. package/dist/esm/global-account/react/components/Send/Send.js +16 -12
  140. package/dist/esm/global-account/react/components/SignInWithB3/BetterAuthSignIn.js +3 -1
  141. package/dist/esm/global-account/react/components/SignInWithB3/SignInWithB3Flow.js +1 -5
  142. package/dist/esm/global-account/react/components/SignInWithB3/components/AuthButton.js +2 -1
  143. package/dist/esm/global-account/react/components/SignInWithB3/steps/LoginStepBetterAuth.js +1 -0
  144. package/dist/esm/global-account/react/components/SignInWithB3/utils/signInUtils.d.ts +3 -2
  145. package/dist/esm/global-account/react/components/SignInWithB3/utils/signInUtils.js +3 -3
  146. package/dist/esm/global-account/react/components/index.d.ts +1 -1
  147. package/dist/esm/global-account/react/components/index.js +1 -1
  148. package/dist/esm/global-account/react/hooks/index.d.ts +2 -3
  149. package/dist/esm/global-account/react/hooks/index.js +2 -3
  150. package/dist/esm/global-account/react/hooks/useAuth.d.ts +5 -4
  151. package/dist/esm/global-account/react/hooks/useAuth.js +1 -0
  152. package/dist/esm/global-account/react/hooks/useAuthentication.d.ts +3 -2
  153. package/dist/esm/global-account/react/hooks/useAuthentication.js +2 -1
  154. package/dist/esm/global-account/react/hooks/useBetterAuth.d.ts +1657 -22
  155. package/dist/esm/global-account/react/hooks/useBetterAuth.js +8 -8
  156. package/dist/esm/global-account/react/hooks/useClient.d.ts +3 -3
  157. package/dist/esm/global-account/react/hooks/useFirstEOA.d.ts +4 -7666
  158. package/dist/esm/global-account/react/hooks/useFirstEOA.js +1 -0
  159. package/dist/esm/global-account/react/hooks/useNativeBalance.js +1 -1
  160. package/dist/esm/global-account/react/hooks/usePortfolioBalance.d.ts +15 -0
  161. package/dist/esm/global-account/react/hooks/usePortfolioBalance.js +72 -0
  162. package/dist/esm/global-account/react/hooks/usePortfolioCollectibles.d.ts +12 -0
  163. package/dist/esm/global-account/react/hooks/usePortfolioCollectibles.js +175 -0
  164. package/dist/esm/global-account/react/hooks/useSiwe.d.ts +1 -1
  165. package/dist/esm/global-account/react/hooks/useSiwe.native.d.ts +1 -1
  166. package/dist/esm/global-account/react/hooks/useTWAuth.d.ts +1 -1
  167. package/dist/esm/global-account/react/hooks/useUnifiedChainSwitchAndExecute.d.ts +1 -0
  168. package/dist/esm/global-account/react/hooks/useUnifiedChainSwitchAndExecute.js +37 -27
  169. package/dist/esm/global-account/react/stores/useModalStore.d.ts +14 -2
  170. package/dist/esm/global-account/types/b3-api.types.d.ts +5 -0
  171. package/dist/esm/global-account/types/feature-flags.d.ts +5 -5
  172. package/dist/esm/notifications/services/api.js +1 -0
  173. package/dist/esm/shared/constants/chains/b3Chain.d.ts +30 -54
  174. package/dist/esm/shared/constants/chains/b3Chain.js +4 -38
  175. package/dist/esm/shared/constants/chains/supported.d.ts +1 -49
  176. package/dist/esm/shared/constants/chains/supported.js +7 -35
  177. package/dist/esm/shared/constants/index.d.ts +4 -0
  178. package/dist/esm/shared/utils/chain-transformers.d.ts +4 -4
  179. package/dist/esm/shared/utils/chain-transformers.js +38 -37
  180. package/dist/esm/shared/utils/thirdweb-insights.js +2 -2
  181. package/dist/esm/shared/utils/upload.d.ts +9 -0
  182. package/dist/esm/shared/utils/upload.js +31 -0
  183. package/dist/esm/shared/utils/zerionPositions.d.ts +96 -0
  184. package/dist/esm/shared/utils/zerionPositions.js +180 -0
  185. package/dist/styles/index.css +1 -1
  186. package/dist/types/anyspend/constants/rpc.d.ts +3 -1
  187. package/dist/types/anyspend/react/components/AnySpend.d.ts +9 -1
  188. package/dist/types/anyspend/react/components/AnySpendDeposit.d.ts +15 -3
  189. package/dist/types/anyspend/react/components/QRDeposit.d.ts +22 -3
  190. package/dist/types/anyspend/react/components/common/PureTransferView.d.ts +30 -0
  191. package/dist/types/anyspend/react/hooks/useCreateDepositFirstOrder.d.ts +3 -3
  192. package/dist/types/anyspend/react/hooks/useSigMint.d.ts +1 -1
  193. package/dist/types/anyspend/utils/address.d.ts +2 -1
  194. package/dist/types/anyspend/utils/chain.d.ts +84 -1
  195. package/dist/types/anyspend/utils/token.d.ts +2 -0
  196. package/dist/types/app.shared.d.ts +9 -1
  197. package/dist/types/global-account/app.native.d.ts +1 -1
  198. package/dist/types/global-account/better-auth-client.d.ts +3314 -36
  199. package/dist/types/global-account/bsmnt.d.ts +2 -2
  200. package/dist/types/global-account/bsmnt.native.d.ts +1 -1
  201. package/dist/types/global-account/client-manager.d.ts +7 -5
  202. package/dist/types/global-account/react/components/B3Provider/B3ConfigProvider.d.ts +11 -0
  203. package/dist/types/global-account/react/components/B3Provider/B3Provider.d.ts +12 -2
  204. package/dist/types/global-account/react/components/B3Provider/RelayKitProviderWrapper.d.ts +1 -2
  205. package/dist/types/global-account/react/components/SignInWithB3/utils/signInUtils.d.ts +3 -2
  206. package/dist/types/global-account/react/components/index.d.ts +1 -1
  207. package/dist/types/global-account/react/hooks/index.d.ts +2 -3
  208. package/dist/types/global-account/react/hooks/useAuth.d.ts +5 -4
  209. package/dist/types/global-account/react/hooks/useAuthentication.d.ts +3 -2
  210. package/dist/types/global-account/react/hooks/useBetterAuth.d.ts +1657 -22
  211. package/dist/types/global-account/react/hooks/useClient.d.ts +3 -3
  212. package/dist/types/global-account/react/hooks/useFirstEOA.d.ts +4 -7666
  213. package/dist/types/global-account/react/hooks/usePortfolioBalance.d.ts +15 -0
  214. package/dist/types/global-account/react/hooks/usePortfolioCollectibles.d.ts +12 -0
  215. package/dist/types/global-account/react/hooks/useSiwe.d.ts +1 -1
  216. package/dist/types/global-account/react/hooks/useSiwe.native.d.ts +1 -1
  217. package/dist/types/global-account/react/hooks/useTWAuth.d.ts +1 -1
  218. package/dist/types/global-account/react/hooks/useUnifiedChainSwitchAndExecute.d.ts +1 -0
  219. package/dist/types/global-account/react/stores/useModalStore.d.ts +14 -2
  220. package/dist/types/global-account/types/b3-api.types.d.ts +5 -0
  221. package/dist/types/global-account/types/feature-flags.d.ts +5 -5
  222. package/dist/types/shared/constants/chains/b3Chain.d.ts +30 -54
  223. package/dist/types/shared/constants/chains/supported.d.ts +1 -49
  224. package/dist/types/shared/constants/index.d.ts +4 -0
  225. package/dist/types/shared/utils/chain-transformers.d.ts +4 -4
  226. package/dist/types/shared/utils/upload.d.ts +9 -0
  227. package/dist/types/shared/utils/zerionPositions.d.ts +96 -0
  228. package/node_modules/@b3/chain-registry/chains.json +1225 -0
  229. package/node_modules/@b3/chain-registry/dist/chains.json +1225 -0
  230. package/node_modules/@b3/chain-registry/dist/index.cjs +1676 -0
  231. package/node_modules/@b3/chain-registry/dist/index.d.cts +195 -0
  232. package/node_modules/@b3/chain-registry/dist/index.d.ts +195 -0
  233. package/node_modules/@b3/chain-registry/dist/index.mjs +1604 -0
  234. package/node_modules/@b3/chain-registry/dist/src/index.d.ts +193 -0
  235. package/node_modules/@b3/chain-registry/dist/src/index.js +408 -0
  236. package/node_modules/@b3/chain-registry/package.json +66 -0
  237. package/node_modules/@b3/chain-registry/src/index.test.ts +432 -0
  238. package/node_modules/@b3/chain-registry/src/index.ts +672 -0
  239. package/package.json +81 -30
  240. package/src/anyspend/README.md +2 -2
  241. package/src/anyspend/constants/rpc.ts +5 -2
  242. package/src/anyspend/docs/components.md +6 -6
  243. package/src/anyspend/docs/contributing.md +1 -1
  244. package/src/anyspend/docs/hooks.md +3 -3
  245. package/src/anyspend/docs/installation.md +2 -2
  246. package/src/anyspend/react/components/AnySpend.tsx +163 -47
  247. package/src/anyspend/react/components/AnySpendCustomExactIn.tsx +10 -11
  248. package/src/anyspend/react/components/AnySpendDeposit.tsx +130 -31
  249. package/src/anyspend/react/components/AnySpendStakeB3.tsx +55 -14
  250. package/src/anyspend/react/components/AnySpendStakeB3ExactIn.tsx +55 -11
  251. package/src/anyspend/react/components/QRDeposit.tsx +101 -22
  252. package/src/anyspend/react/components/__tests__/QRDeposit.test.tsx +331 -0
  253. package/src/anyspend/react/components/checkout/CryptoPayPanel.tsx +38 -16
  254. package/src/anyspend/react/components/common/PureTransferView.tsx +212 -0
  255. package/src/anyspend/react/components/common/TokenBalance.tsx +10 -7
  256. package/src/anyspend/react/hooks/useAnyspendQuote.ts +13 -13
  257. package/src/anyspend/react/hooks/useCreateDepositFirstOrder.ts +4 -4
  258. package/src/anyspend/services/gas.test.ts +95 -18
  259. package/src/anyspend/types/api_req_res.ts +10 -5
  260. package/src/anyspend/utils/__tests__/address.test.ts +39 -0
  261. package/src/anyspend/utils/__tests__/deprecatedChains.test.ts +44 -0
  262. package/src/anyspend/utils/__tests__/toRegistryChainId.test.ts +17 -0
  263. package/src/anyspend/utils/address.ts +8 -6
  264. package/src/anyspend/utils/chain.ts +79 -3
  265. package/src/anyspend/utils/token.ts +14 -0
  266. package/src/app.shared.ts +21 -1
  267. package/src/global-account/app.native.ts +5 -1
  268. package/src/global-account/better-auth-client.ts +30 -4
  269. package/src/global-account/bsmnt.native.ts +5 -1
  270. package/src/global-account/bsmnt.ts +9 -2
  271. package/src/global-account/client-manager.ts +74 -9
  272. package/src/global-account/react/components/AvatarEditor/AvatarEditor.tsx +6 -11
  273. package/src/global-account/react/components/B3Provider/B3ConfigProvider.tsx +12 -0
  274. package/src/global-account/react/components/B3Provider/B3Provider.tsx +40 -4
  275. package/src/global-account/react/components/B3Provider/BetterAuthProvider.tsx +51 -5
  276. package/src/global-account/react/components/B3Provider/RelayKitProviderWrapper.tsx +11 -11
  277. package/src/global-account/react/components/ManageAccount/ContentTokens.tsx +50 -21
  278. package/src/global-account/react/components/ManageAccount/NFTContent.tsx +5 -3
  279. package/src/global-account/react/components/ManageAccount/ProfileSection.tsx +10 -6
  280. package/src/global-account/react/components/ManageAccount/SettingsProfileCard.tsx +1 -1
  281. package/src/global-account/react/components/ManageAccount/TokenContent.tsx +22 -9
  282. package/src/global-account/react/components/Send/Send.tsx +39 -15
  283. package/src/global-account/react/components/SignInWithB3/BetterAuthSignIn.tsx +12 -1
  284. package/src/global-account/react/components/SignInWithB3/SignInWithB3Flow.tsx +1 -4
  285. package/src/global-account/react/components/SignInWithB3/components/AuthButton.tsx +9 -1
  286. package/src/global-account/react/components/SignInWithB3/steps/LoginStepBetterAuth.tsx +1 -0
  287. package/src/global-account/react/components/SignInWithB3/utils/signInUtils.ts +4 -4
  288. package/src/global-account/react/components/index.ts +1 -1
  289. package/src/global-account/react/components/ui/button.tsx +1 -2
  290. package/src/global-account/react/hooks/__tests__/useUnifiedChainSwitchAndExecute.test.tsx +156 -0
  291. package/src/global-account/react/hooks/index.ts +2 -3
  292. package/src/global-account/react/hooks/useAuth.ts +5 -4
  293. package/src/global-account/react/hooks/useAuthentication.ts +5 -4
  294. package/src/global-account/react/hooks/useBetterAuth.ts +10 -10
  295. package/src/global-account/react/hooks/useClient.ts +11 -2
  296. package/src/global-account/react/hooks/useFirstEOA.tsx +9 -2
  297. package/src/global-account/react/hooks/useNativeBalance.tsx +1 -1
  298. package/src/global-account/react/hooks/usePortfolioBalance.ts +89 -0
  299. package/src/global-account/react/hooks/usePortfolioCollectibles.ts +212 -0
  300. package/src/global-account/react/hooks/useSiwe.native.tsx +1 -1
  301. package/src/global-account/react/hooks/useSiwe.tsx +1 -1
  302. package/src/global-account/react/hooks/useTWAuth.tsx +1 -1
  303. package/src/global-account/react/hooks/useUnifiedChainSwitchAndExecute.ts +47 -31
  304. package/src/global-account/react/stores/useModalStore.ts +14 -2
  305. package/src/global-account/types/b3-api.types.ts +5 -1
  306. package/src/notifications/services/api.ts +1 -0
  307. package/src/shared/constants/chains/b3Chain.ts +4 -43
  308. package/src/shared/constants/chains/supported.ts +9 -48
  309. package/src/shared/constants/index.ts +8 -0
  310. package/src/shared/react/hooks/__tests__/useCurrencyConversion.test.ts +54 -43
  311. package/src/shared/utils/__tests__/zerionPositions.test.ts +248 -0
  312. package/src/shared/utils/chain-transformers.ts +41 -39
  313. package/src/shared/utils/thirdweb-insights.ts +2 -2
  314. package/src/shared/utils/upload.ts +48 -0
  315. package/src/shared/utils/zerionPositions.ts +247 -0
  316. package/src/styles/index.css +27 -0
  317. package/dist/cjs/global-account/react/components/SignInWithB3/SignInWithB3Privy.d.ts +0 -10
  318. package/dist/cjs/global-account/react/components/SignInWithB3/SignInWithB3Privy.js +0 -46
  319. package/dist/cjs/global-account/react/hooks/useHandleConnectWithPrivy.d.ts +0 -11
  320. package/dist/cjs/global-account/react/hooks/useHandleConnectWithPrivy.js +0 -70
  321. package/dist/cjs/global-account/react/hooks/useSimBalance.d.ts +0 -59
  322. package/dist/cjs/global-account/react/hooks/useSimBalance.js +0 -98
  323. package/dist/cjs/global-account/react/hooks/useSimCollectibles.d.ts +0 -45
  324. package/dist/cjs/global-account/react/hooks/useSimCollectibles.js +0 -190
  325. package/dist/cjs/global-account/react/utils/simdune.d.ts +0 -7
  326. package/dist/cjs/global-account/react/utils/simdune.js +0 -21
  327. package/dist/cjs/global-account/types/chain-networks.d.ts +0 -44
  328. package/dist/cjs/global-account/types/chain-networks.js +0 -48
  329. package/dist/cjs/shared/generated/chain-networks.json +0 -684
  330. package/dist/esm/global-account/react/components/SignInWithB3/SignInWithB3Privy.d.ts +0 -10
  331. package/dist/esm/global-account/react/components/SignInWithB3/SignInWithB3Privy.js +0 -43
  332. package/dist/esm/global-account/react/hooks/useHandleConnectWithPrivy.d.ts +0 -11
  333. package/dist/esm/global-account/react/hooks/useHandleConnectWithPrivy.js +0 -67
  334. package/dist/esm/global-account/react/hooks/useSimBalance.d.ts +0 -59
  335. package/dist/esm/global-account/react/hooks/useSimBalance.js +0 -93
  336. package/dist/esm/global-account/react/hooks/useSimCollectibles.d.ts +0 -45
  337. package/dist/esm/global-account/react/hooks/useSimCollectibles.js +0 -187
  338. package/dist/esm/global-account/react/utils/simdune.d.ts +0 -7
  339. package/dist/esm/global-account/react/utils/simdune.js +0 -17
  340. package/dist/esm/global-account/types/chain-networks.d.ts +0 -44
  341. package/dist/esm/global-account/types/chain-networks.js +0 -45
  342. package/dist/esm/shared/generated/chain-networks.json +0 -684
  343. package/dist/types/global-account/react/components/SignInWithB3/SignInWithB3Privy.d.ts +0 -10
  344. package/dist/types/global-account/react/hooks/useHandleConnectWithPrivy.d.ts +0 -11
  345. package/dist/types/global-account/react/hooks/useSimBalance.d.ts +0 -59
  346. package/dist/types/global-account/react/hooks/useSimCollectibles.d.ts +0 -45
  347. package/dist/types/global-account/react/utils/simdune.d.ts +0 -7
  348. package/dist/types/global-account/types/chain-networks.d.ts +0 -44
  349. package/src/global-account/react/components/SignInWithB3/SignInWithB3Privy.tsx +0 -63
  350. package/src/global-account/react/hooks/useHandleConnectWithPrivy.tsx +0 -79
  351. package/src/global-account/react/hooks/useSimBalance.ts +0 -164
  352. package/src/global-account/react/hooks/useSimCollectibles.ts +0 -238
  353. package/src/global-account/react/utils/simdune.ts +0 -20
  354. package/src/global-account/types/chain-networks.ts +0 -54
  355. package/src/shared/generated/chain-networks.json +0 -684
@@ -41,6 +41,13 @@ export interface AnySpendDepositProps {
41
41
  destinationTokenAddress: string;
42
42
  /** The destination chain ID */
43
43
  destinationTokenChainId: number;
44
+ /**
45
+ * When false, the destination token is user-selectable even though a default destination token is
46
+ * provided (the provided destination is used only as the initial/default value). Used by the
47
+ * wallet-funding deposit flow so the user can change the receive token away from the default
48
+ * (Base USDC). Defaults to true (locked destination, current behavior). Does not affect the
49
+ * QR/pure-transfer path. */
50
+ lockDestinationToken?: boolean;
44
51
  /** Callback when deposit succeeds */
45
52
  onSuccess?: (amount: string) => void;
46
53
  /** Callback for opening a custom modal (e.g., for special token handling) */
@@ -77,8 +84,6 @@ export interface AnySpendDepositProps {
77
84
  showFiatOption?: boolean;
78
85
  /** Custom list of supported chains. If not provided, uses default chains */
79
86
  supportedChains?: ChainConfig[];
80
- /** Minimum pool size for filtering tokens (default: 1,000,000) */
81
- minPoolSize?: number;
82
87
  /** Custom title for chain selection step */
83
88
  chainSelectionTitle?: string;
84
89
  /** Custom description for chain selection step */
@@ -102,6 +107,13 @@ export interface AnySpendDepositProps {
102
107
  classes?: AnySpendAllClasses;
103
108
  /** When true, allows direct transfer without swap if source and destination token/chain are the same */
104
109
  allowDirectTransfer?: boolean;
110
+ /**
111
+ * When true, the QR-deposit path is a PURE TRANSFER: the destination token/chain
112
+ * mirror whatever source token the user selects, so the exact token they send lands
113
+ * in their wallet on the same chain (no swap/bridge). Forwarded to QRDeposit.
114
+ * Defaults to false.
115
+ */
116
+ pureTransferOnly?: boolean;
105
117
  /** Fixed destination token amount (in wei/smallest unit). When provided, user cannot change the amount. */
106
118
  destinationTokenAmount?: string;
107
119
  /** Opaque metadata passed to the order for callbacks (e.g., workflow form data) */
@@ -150,4 +162,4 @@ export interface AnySpendDepositProps {
150
162
  * onSuccess={(amount) => console.log(`Deposited ${amount}`)}
151
163
  * />
152
164
  */
153
- export declare function AnySpendDeposit({ loadOrder, mode, recipientAddress, paymentType: initialPaymentType, sourceTokenAddress, sourceTokenChainId: initialSourceChainId, destinationTokenAddress, destinationTokenChainId, onSuccess, onOpenCustomModal, mainFooter, onTokenSelect, customUsdInputValues, preferEoa, minDestinationAmount, header, orderType, depositContractConfig, showChainSelection, showFiatOption, supportedChains, minPoolSize, topChainsCount, onClose, returnToHomeUrl, customRecipientLabel, returnHomeLabel, isCustomDeposit, classes, allowDirectTransfer, 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;
@@ -1,9 +1,11 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { Skeleton, useAccountWallet, useSimBalance, useTokenData } from "../../../global-account/react/index.js";
2
+ import { USDC_BASE } from "../../../anyspend/index.js";
3
+ import { Skeleton, useAccountWallet, usePortfolioBalance, useTokenData } from "../../../global-account/react/index.js";
3
4
  import { cn } from "../../../shared/utils/cn.js";
5
+ import { formatTokenAmount } from "../../../shared/utils/number.js";
4
6
  import { NetworkArbitrumOne, NetworkBase, NetworkBinanceSmartChain, NetworkEthereum, NetworkOptimism, NetworkPolygonPos, } from "@web3icons/react";
5
7
  import { ChevronRight } from "lucide-react";
6
- import { useEffect, useMemo, useState } from "react";
8
+ import { useCallback, useEffect, useMemo, useState } from "react";
7
9
  import { AnySpend } from "./AnySpend.js";
8
10
  import { AnySpendCustomExactIn } from "./AnySpendCustomExactIn.js";
9
11
  import { ChainWarningText } from "./common/WarningText.js";
@@ -19,8 +21,19 @@ const DEFAULT_SUPPORTED_CHAINS = [
19
21
  { id: 137, name: "Polygon" },
20
22
  { id: 56, name: "BNB Chain" },
21
23
  ];
22
- // Minimum pool size to filter out low liquidity tokens
23
- const DEFAULT_MIN_POOL_SIZE = 1000000;
24
+ /**
25
+ * Self-described fallback metadata for the default funding token(s), keyed by
26
+ * `${chainId}:${lowercased address}`. Used when `useTokenData` misses (returns
27
+ * null) so the destination token's decimals/symbol are correct WITHOUT depending
28
+ * on the network — critical in pure-transfer mode where there's no server-side
29
+ * correction and the wrong decimals would make `useWatchTransfer` show a wrong amount.
30
+ */
31
+ const KNOWN_FUNDING_TOKENS = {
32
+ [`${USDC_BASE.chainId}:${USDC_BASE.address.toLowerCase()}`]: USDC_BASE,
33
+ };
34
+ function getKnownFundingToken(chainId, address) {
35
+ return KNOWN_FUNDING_TOKENS[`${chainId}:${address.toLowerCase()}`];
36
+ }
24
37
  function formatUsd(value) {
25
38
  return new Intl.NumberFormat("en-US", {
26
39
  style: "currency",
@@ -94,7 +107,7 @@ function ChainIcon({ chainId, className }) {
94
107
  * onSuccess={(amount) => console.log(`Deposited ${amount}`)}
95
108
  * />
96
109
  */
97
- export function AnySpendDeposit({ loadOrder, mode = "modal", recipientAddress, paymentType: initialPaymentType, sourceTokenAddress, sourceTokenChainId: initialSourceChainId, destinationTokenAddress, destinationTokenChainId, 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, destinationTokenAmount, callbackMetadata, senderAddress, slots, content, theme, }) {
110
+ export 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, }) {
98
111
  // Extract deposit-specific classes for convenience
99
112
  const depositClasses = classes?.deposit;
100
113
  const { connectedEOAWallet } = useAccountWallet();
@@ -111,25 +124,35 @@ export function AnySpendDeposit({ loadOrder, mode = "modal", recipientAddress, p
111
124
  }
112
125
  }, [showFiatOption, paymentType]);
113
126
  // Fetch destination token data
114
- const { data: destinationTokenData } = useTokenData(destinationTokenChainId, destinationTokenAddress);
115
- // Construct full destination token object
116
- const destinationToken = useMemo(() => ({
117
- address: destinationTokenAddress,
118
- chainId: destinationTokenChainId,
119
- symbol: destinationTokenData?.symbol ?? "",
120
- name: destinationTokenData?.name ?? "",
121
- decimals: destinationTokenData?.decimals ?? 18,
122
- metadata: { logoURI: destinationTokenData?.logoURI },
123
- }), [destinationTokenAddress, destinationTokenChainId, destinationTokenData]);
127
+ const { data: destinationTokenData, isLoading: isDestinationTokenLoading } = useTokenData(destinationTokenChainId, destinationTokenAddress);
128
+ // Construct full destination token object. When `useTokenData` misses (it returns
129
+ // null on an API miss, not an error), fall back to a known-token entry so the
130
+ // decimals/symbol invariant holds regardless of the fetch — e.g. Base USDC is 6
131
+ // decimals, never the generic 18 fallback.
132
+ const destinationToken = useMemo(() => {
133
+ const known = getKnownFundingToken(destinationTokenChainId, destinationTokenAddress);
134
+ return {
135
+ address: destinationTokenAddress,
136
+ chainId: destinationTokenChainId,
137
+ symbol: destinationTokenData?.symbol ?? known?.symbol ?? "",
138
+ name: destinationTokenData?.name ?? known?.name ?? "",
139
+ decimals: destinationTokenData?.decimals ?? known?.decimals ?? 18,
140
+ metadata: { logoURI: destinationTokenData?.logoURI ?? known?.metadata?.logoURI },
141
+ };
142
+ }, [destinationTokenAddress, destinationTokenChainId, destinationTokenData]);
124
143
  // Fetch balances for EOA wallet (use senderAddress as fallback for pre-filled balance display)
125
144
  const effectiveBalanceAddress = senderAddress || eoaAddress;
126
- const { data: balanceData, isLoading: isBalanceLoading } = useSimBalance(shouldShowChainSelection ? effectiveBalanceAddress : undefined, supportedChains.map(c => c.id));
127
- // Group balances by chain and calculate total USD value per chain
145
+ const { data: balances, isLoading: isBalanceLoading, isError: isBalanceError, } = usePortfolioBalance(shouldShowChainSelection ? effectiveBalanceAddress : undefined, supportedChains.map(c => c.id));
146
+ // Group balances by chain and calculate total USD value per chain.
147
+ //
148
+ // There is deliberately no liquidity threshold here. The balance provider reports no pool size,
149
+ // so a `pool_size > n` test is false for every row and quietly reduces to "native only",
150
+ // erasing every ERC-20 the user holds from the chain summary. Spam filtering belongs to the
151
+ // token-filter service, which has the data to do it.
128
152
  const chainBalances = useMemo(() => {
129
- if (!balanceData?.balances)
153
+ if (!balances)
130
154
  return {};
131
- const filteredBalances = balanceData.balances.filter(token => token.address === "native" || (token.pool_size && token.pool_size > minPoolSize));
132
- return filteredBalances.reduce((acc, token) => {
155
+ return balances.reduce((acc, token) => {
133
156
  const chainId = token.chain_id;
134
157
  if (!acc[chainId]) {
135
158
  acc[chainId] = {
@@ -143,7 +166,7 @@ export function AnySpendDeposit({ loadOrder, mode = "modal", recipientAddress, p
143
166
  acc[chainId].tokenCount += 1;
144
167
  return acc;
145
168
  }, {});
146
- }, [balanceData, minPoolSize]);
169
+ }, [balances]);
147
170
  // Sort chains by USD value (highest first)
148
171
  const sortedChains = useMemo(() => {
149
172
  return supportedChains
@@ -162,6 +185,9 @@ export function AnySpendDeposit({ loadOrder, mode = "modal", recipientAddress, p
162
185
  const totalBalance = useMemo(() => {
163
186
  return Object.values(chainBalances).reduce((sum, chain) => sum + chain.totalUsdValue, 0);
164
187
  }, [chainBalances]);
188
+ const handleQRDepositSuccess = useCallback((txHash) => {
189
+ onSuccess?.(txHash ?? "");
190
+ }, [onSuccess]);
165
191
  if (!recipientAddress)
166
192
  return null;
167
193
  const tokenSymbol = destinationToken.symbol || "TOKEN";
@@ -195,23 +221,50 @@ export function AnySpendDeposit({ loadOrder, mode = "modal", recipientAddress, p
195
221
  if (step === "select-chain") {
196
222
  return (_jsxs("div", { className: depositClasses?.chainSelection ||
197
223
  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 && (_jsx("button", { onClick: onClose, className: depositClasses?.closeButton ||
198
- "anyspend-deposit-close-button text-as-secondary hover:text-as-primary absolute right-4 top-4 z-10", children: _jsx("svg", { className: "h-6 w-6", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M6 18L18 6M6 6l12 12" }) }) })), !isBalanceLoading && totalBalance > 0 && (_jsxs("div", { className: depositClasses?.balanceContainer || "anyspend-deposit-balance border-theme-border-secondary border-b p-5", children: [_jsx("p", { className: depositClasses?.balanceLabel || "anyspend-deposit-balance-label text-as-secondary text-sm", children: "Your Balance" }), _jsxs("p", { className: depositClasses?.balanceValue || "anyspend-deposit-balance-value text-as-primary text-3xl font-semibold", children: [formatDecimal(totalBalance), " ", _jsx("span", { className: "text-sm", children: "USD" })] })] })), _jsxs("div", { className: depositClasses?.optionsContainer || "anyspend-deposit-options flex flex-col gap-2 p-6", children: [isBalanceLoading && (_jsx("div", { className: depositClasses?.chainsSkeleton || "anyspend-deposit-chains-skeleton flex flex-col gap-2", children: [1, 2].map((_, i) => (_jsxs("div", { className: depositClasses?.skeletonItem ||
199
- "border-border-primary flex items-center justify-between rounded-xl border p-4", children: [_jsxs("div", { className: "flex items-center gap-3", children: [_jsx(Skeleton, { className: "h-6 w-6 rounded-full" }), _jsxs("div", { className: "flex flex-col gap-1", children: [_jsx(Skeleton, { className: "h-4 w-32" }), _jsx(Skeleton, { className: "h-3 w-20" })] })] }), _jsx(Skeleton, { className: "h-5 w-5" })] }, i))) })), topChainsWithBalance.length > 0 && (_jsx("div", { className: depositClasses?.chainsContainer || "anyspend-deposit-chains flex flex-col gap-2", children: topChainsWithBalance.map(chain => (_jsxs("button", { onClick: () => handleSelectChain(chain.id), className: depositClasses?.chainButton ||
224
+ "anyspend-deposit-close-button text-as-secondary hover:text-as-primary absolute right-4 top-4 z-10", children: _jsx("svg", { className: "h-6 w-6", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M6 18L18 6M6 6l12 12" }) }) })), !isBalanceLoading && !isBalanceError && totalBalance > 0 && (_jsxs("div", { className: depositClasses?.balanceContainer || "anyspend-deposit-balance border-theme-border-secondary border-b p-5", children: [_jsx("p", { className: depositClasses?.balanceLabel || "anyspend-deposit-balance-label text-as-secondary text-sm", children: "Your Balance" }), _jsxs("p", { className: depositClasses?.balanceValue || "anyspend-deposit-balance-value text-as-primary text-3xl font-semibold", children: [formatDecimal(totalBalance), " ", _jsx("span", { className: "text-sm", children: "USD" })] })] })), _jsxs("div", { className: depositClasses?.optionsContainer || "anyspend-deposit-options flex flex-col gap-2 p-6", children: [isBalanceLoading && (_jsx("div", { className: depositClasses?.chainsSkeleton || "anyspend-deposit-chains-skeleton flex flex-col gap-2", children: [1, 2].map((_, i) => (_jsxs("div", { className: depositClasses?.skeletonItem ||
225
+ "border-border-primary flex items-center justify-between rounded-xl border p-4", children: [_jsxs("div", { className: "flex items-center gap-3", children: [_jsx(Skeleton, { className: "h-6 w-6 rounded-full" }), _jsxs("div", { className: "flex flex-col gap-1", children: [_jsx(Skeleton, { className: "h-4 w-32" }), _jsx(Skeleton, { className: "h-3 w-20" })] })] }), _jsx(Skeleton, { className: "h-5 w-5" })] }, i))) })), isBalanceError && !isBalanceLoading && (_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 && (_jsx("div", { className: depositClasses?.chainsContainer || "anyspend-deposit-chains flex flex-col gap-2", children: topChainsWithBalance.map(chain => (_jsxs("button", { onClick: () => handleSelectChain(chain.id), className: depositClasses?.chainButton ||
200
226
  "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: [_jsx("div", { className: depositClasses?.chainContent || "anyspend-deposit-chain-content", children: _jsxs("div", { className: depositClasses?.chainInfo || "anyspend-deposit-chain-info", children: [_jsxs("span", { className: depositClasses?.chainName ||
201
- "anyspend-deposit-chain-name text-as-primary flex items-center gap-1.5 font-medium", children: ["Deposit from ", chain.name, _jsx(ChainIcon, { chainId: chain.id, className: depositClasses?.chainIcon || "h-5 w-5" })] }), _jsxs("p", { className: depositClasses?.chainBalance || "anyspend-deposit-chain-balance text-as-secondary text-xs", children: [formatUsd(chain.balance), " available"] })] }) }), _jsx(ChevronRight, { className: depositClasses?.chainChevron || "anyspend-deposit-chain-chevron text-as-secondary h-5 w-5" })] }, chain.id))) })), _jsxs("div", { className: depositClasses?.generalOptions || "anyspend-deposit-general-options flex flex-col gap-2", children: [_jsxs("button", { onClick: handleSelectCrypto, className: depositClasses?.cryptoButton ||
227
+ "anyspend-deposit-chain-name text-as-primary flex items-center gap-1.5 font-medium", children: ["Deposit from ", chain.name, _jsx(ChainIcon, { chainId: chain.id, className: depositClasses?.chainIcon || "h-5 w-5" })] }), _jsx("p", { className: depositClasses?.chainBalance || "anyspend-deposit-chain-balance text-as-secondary text-xs", children: `${formatUsd(chain.balance)} available` })] }) }), _jsx(ChevronRight, { className: depositClasses?.chainChevron || "anyspend-deposit-chain-chevron text-as-secondary h-5 w-5" })] }, chain.id))) })), _jsxs("div", { className: depositClasses?.generalOptions || "anyspend-deposit-general-options flex flex-col gap-2", children: [_jsxs("button", { onClick: handleSelectCrypto, className: depositClasses?.cryptoButton ||
202
228
  "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: [_jsx("div", { className: depositClasses?.optionContent || "anyspend-deposit-option-content", children: _jsxs("div", { className: depositClasses?.optionInfo || "anyspend-deposit-option-info", children: [_jsx("span", { className: depositClasses?.optionTitle || "anyspend-deposit-option-title text-as-primary font-medium", children: "Deposit Crypto" }), _jsx("p", { className: depositClasses?.optionDescription ||
203
229
  "anyspend-deposit-option-description text-as-secondary text-xs", children: "Swap from any token on any chain" })] }) }), _jsx(ChevronRight, { className: depositClasses?.optionChevron || "anyspend-deposit-option-chevron text-as-secondary h-5 w-5" })] }), _jsxs("div", { className: depositClasses?.divider || "anyspend-deposit-divider flex items-center gap-3", children: [_jsx("div", { className: depositClasses?.dividerLine || "bg-as-stroke h-px flex-1" }), _jsx("span", { className: depositClasses?.dividerText || "anyspend-deposit-divider-text text-as-secondary text-sm", children: "More options" }), _jsx("div", { className: depositClasses?.dividerLine || "bg-as-stroke h-px flex-1" })] }), _jsxs("button", { onClick: handleSelectQrDeposit, className: depositClasses?.qrButton ||
204
230
  "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: [_jsxs("div", { className: depositClasses?.optionContent || "anyspend-deposit-option-content flex items-center gap-3", children: [_jsx(QrCodeIcon, { className: depositClasses?.optionIcon || "anyspend-deposit-option-icon h-10 w-10" }), _jsxs("div", { className: depositClasses?.optionInfo || "anyspend-deposit-option-info", children: [_jsx("span", { className: depositClasses?.optionTitle || "anyspend-deposit-option-title text-as-primary font-medium", children: "Deposit with QR Code" }), _jsx("p", { className: depositClasses?.optionDescription ||
205
- "anyspend-deposit-option-description text-as-secondary text-xs", children: "Send tokens directly to deposit address" })] })] }), _jsx(ChevronRight, { className: depositClasses?.optionChevron || "anyspend-deposit-option-chevron text-as-secondary h-5 w-5" })] }), showFiatOption && (_jsxs("button", { onClick: handleSelectFiat, className: depositClasses?.fiatButton ||
231
+ "anyspend-deposit-option-description text-as-secondary text-xs", children: pureTransferOnly
232
+ ? "Send tokens directly to deposit address"
233
+ : "Send any token — we'll convert it for you" })] })] }), _jsx(ChevronRight, { className: depositClasses?.optionChevron || "anyspend-deposit-option-chevron text-as-secondary h-5 w-5" })] }), showFiatOption && (_jsxs("button", { onClick: handleSelectFiat, className: depositClasses?.fiatButton ||
206
234
  "anyspend-deposit-option-button anyspend-deposit-fiat-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 transition-all", children: [_jsxs("div", { className: depositClasses?.optionContent || "anyspend-deposit-option-content flex items-center gap-3", children: [_jsx(CreditCardIcon, { className: depositClasses?.optionIcon || "anyspend-deposit-option-icon h-10 w-10" }), _jsxs("div", { className: depositClasses?.optionInfo || "anyspend-deposit-option-info", children: [_jsx("span", { className: depositClasses?.optionTitle || "anyspend-deposit-option-title text-as-primary font-medium", children: "Fund with Fiat" }), _jsx("p", { className: depositClasses?.optionDescription ||
207
235
  "anyspend-deposit-option-description text-as-secondary text-xs", children: "Pay with card or bank transfer" })] })] }), _jsx(ChevronRight, { className: depositClasses?.optionChevron || "anyspend-deposit-option-chevron text-as-secondary h-5 w-5" })] }))] }), _jsx(ChainWarningText, { chainId: destinationTokenChainId, classes: classes?.chainWarningText || { root: "mt-2" } })] })] }));
208
236
  }
209
237
  // QR Deposit view
210
238
  if (step === "qr-deposit") {
211
- return (_jsx(QRDeposit, { mode: mode, recipientAddress: recipientAddress, destinationToken: destinationToken, destinationChainId: destinationTokenChainId, depositContractConfig: depositContractConfig, onBack: handleBack, onClose: onClose ?? handleBack, classes: classes?.qrDeposit }));
239
+ // In pure-transfer mode QRDeposit captures `destinationToken` as its initial
240
+ // SOURCE token via useState, so it must be fully resolved (correct symbol +
241
+ // decimals) before QRDeposit mounts. Known funding tokens (e.g. Base USDC) are
242
+ // already fully resolved via the self-described fallback, so only show a spinner
243
+ // for unknown tokens whose metadata still has to load over the network.
244
+ const hasKnownDestination = !!getKnownFundingToken(destinationTokenChainId, destinationTokenAddress);
245
+ // NOTE: all current Fund Wallet callers derive `destinationTokenAddress` from
246
+ // `getDefaultDepositDestination`, which always returns Base USDC — exactly a
247
+ // `KNOWN_FUNDING_TOKENS` key — so `hasKnownDestination` is always true and this
248
+ // branch never fires for them. The guard is defensive for FUTURE callers that pass
249
+ // an unknown token together with `pureTransferOnly=true`.
250
+ // Only surface the fixed destination amount on the QR path when its decimals are trustworthy
251
+ // (a known funding token or a resolved API lookup) — otherwise `destinationToken.decimals`
252
+ // is the generic 18 fallback and formatting a 6-decimal token's wei against it would be off by
253
+ // 10^12. When unresolved we still show the destination token/chain, just without an amount.
254
+ const destinationDecimalsResolved = hasKnownDestination || !!destinationTokenData;
255
+ const destinationAmountDisplay = destinationTokenAmount &&
256
+ /^\d+$/.test(destinationTokenAmount) &&
257
+ BigInt(destinationTokenAmount) > 0n &&
258
+ destinationDecimalsResolved
259
+ ? formatTokenAmount(BigInt(destinationTokenAmount), destinationToken.decimals, 6, false)
260
+ : undefined;
261
+ if (pureTransferOnly && !hasKnownDestination && !destinationTokenData && isDestinationTokenLoading) {
262
+ return (_jsx("div", { className: cn("anyspend-deposit anyspend-deposit-qr-loading font-inter bg-as-surface-primary mx-auto w-full max-w-[460px] p-6", mode === "page" && "border-as-border-secondary overflow-hidden rounded-2xl border shadow-xl"), children: _jsxs("div", { className: "anyspend-deposit-qr-loading-content flex flex-col items-center justify-center gap-4 py-12", children: [_jsx(Skeleton, { className: "h-8 w-8 rounded-full" }), _jsx(Skeleton, { className: "h-4 w-40" })] }) }));
263
+ }
264
+ return (_jsx(QRDeposit, { mode: mode, recipientAddress: recipientAddress, destinationToken: destinationToken, destinationChainId: destinationTokenChainId, destinationAmountDisplay: destinationAmountDisplay, pureTransferOnly: pureTransferOnly, depositContractConfig: depositContractConfig, onBack: handleBack, onClose: onClose ?? handleBack, onSuccess: handleQRDepositSuccess, classes: classes?.qrDeposit }));
212
265
  }
213
266
  // Deposit view
214
267
  return (_jsxs("div", { className: depositClasses?.form || "anyspend-deposit anyspend-deposit-form relative", children: [shouldShowChainSelection && (_jsxs("button", { onClick: handleBack, className: depositClasses?.backButton ||
215
268
  "anyspend-deposit-back-button text-as-secondary hover:text-as-primary absolute left-4 top-4 z-10 flex items-center gap-1", children: [_jsx("svg", { className: depositClasses?.backIcon || "anyspend-deposit-back-icon h-5 w-5", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M15 19l-7-7 7-7" }) }), _jsx("span", { className: depositClasses?.backText || "anyspend-deposit-back-text text-sm", children: "Back" })] })), onClose && (_jsx("button", { onClick: onClose, className: depositClasses?.closeButton ||
216
- "anyspend-deposit-close-button text-as-secondary hover:text-as-primary absolute right-4 top-4 z-10", children: _jsx("svg", { className: "h-6 w-6", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M6 18L18 6M6 6l12 12" }) }) })), _jsx("div", { className: depositClasses?.formContent || cn("anyspend-deposit-form-content", shouldShowChainSelection && "pt-8"), children: isCustomDeposit ? (_jsx(AnySpendCustomExactIn, { loadOrder: loadOrder, mode: mode, recipientAddress: recipientAddress, paymentType: paymentType, sourceTokenAddress: sourceTokenAddress, sourceTokenChainId: selectedChainId, destinationToken: destinationToken, destinationChainId: destinationTokenChainId, orderType: effectiveOrderType, minDestinationAmount: minDestinationAmount, header: header ?? defaultHeader, onSuccess: onSuccess, onOpenCustomModal: onOpenCustomModal, mainFooter: mainFooter, onTokenSelect: onTokenSelect, customUsdInputValues: customUsdInputValues, preferEoa: preferEoa, customExactInConfig: depositContractConfig, returnToHomeUrl: returnToHomeUrl, customRecipientLabel: customRecipientLabel, returnHomeLabel: returnHomeLabel, classes: classes?.customExactIn, allowDirectTransfer: allowDirectTransfer, destinationTokenAmount: destinationTokenAmount, callbackMetadata: callbackMetadata, senderAddress: senderAddress, showFiatOption: showFiatOption, slots: slots, content: content, theme: theme }, selectedChainId)) : (_jsx(AnySpend, { loadOrder: loadOrder, mode: mode, defaultActiveTab: paymentType, recipientAddress: recipientAddress, sourceChainId: selectedChainId, destinationTokenAddress: destinationTokenAddress, destinationTokenChainId: destinationTokenChainId, onSuccess: txHash => onSuccess?.(txHash ?? ""), onTokenSelect: onTokenSelect, customUsdInputValues: customUsdInputValues, hideHeader: true, hideBottomNavigation: true, disableUrlParamManagement: true, returnToHomeUrl: returnToHomeUrl, customRecipientLabel: customRecipientLabel, returnHomeLabel: returnHomeLabel, classes: classes?.anySpend, allowDirectTransfer: allowDirectTransfer, destinationTokenAmount: destinationTokenAmount, callbackMetadata: callbackMetadata, senderAddress: senderAddress, showFiatOption: showFiatOption, slots: slots, content: content, theme: theme }, selectedChainId)) }), _jsx(ChainWarningText, { chainId: destinationTokenChainId, classes: classes?.chainWarningText || { root: "px-4 pb-4" } })] }));
269
+ "anyspend-deposit-close-button text-as-secondary hover:text-as-primary absolute right-4 top-4 z-10", children: _jsx("svg", { className: "h-6 w-6", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M6 18L18 6M6 6l12 12" }) }) })), _jsx("div", { className: depositClasses?.formContent || cn("anyspend-deposit-form-content", shouldShowChainSelection && "pt-8"), children: isCustomDeposit ? (_jsx(AnySpendCustomExactIn, { loadOrder: loadOrder, mode: mode, recipientAddress: recipientAddress, paymentType: paymentType, sourceTokenAddress: sourceTokenAddress, sourceTokenChainId: selectedChainId, destinationToken: destinationToken, destinationChainId: destinationTokenChainId, orderType: effectiveOrderType, minDestinationAmount: minDestinationAmount, header: header ?? defaultHeader, onSuccess: onSuccess, onOpenCustomModal: onOpenCustomModal, mainFooter: mainFooter, onTokenSelect: onTokenSelect, customUsdInputValues: customUsdInputValues, preferEoa: preferEoa, customExactInConfig: depositContractConfig, returnToHomeUrl: returnToHomeUrl, customRecipientLabel: customRecipientLabel, returnHomeLabel: returnHomeLabel, classes: classes?.customExactIn, allowDirectTransfer: allowDirectTransfer, destinationTokenAmount: destinationTokenAmount, callbackMetadata: callbackMetadata, senderAddress: senderAddress, showFiatOption: showFiatOption, slots: slots, content: content, theme: theme }, selectedChainId)) : (_jsx(AnySpend, { loadOrder: loadOrder, mode: mode, defaultActiveTab: paymentType, recipientAddress: recipientAddress, sourceChainId: selectedChainId, destinationTokenAddress: destinationTokenAddress, destinationTokenChainId: destinationTokenChainId, lockDestinationToken: lockDestinationToken, onSuccess: txHash => onSuccess?.(txHash ?? ""), onTokenSelect: onTokenSelect, customUsdInputValues: customUsdInputValues, hideHeader: true, hideBottomNavigation: true, disableUrlParamManagement: true, returnToHomeUrl: returnToHomeUrl, customRecipientLabel: customRecipientLabel, returnHomeLabel: returnHomeLabel, classes: classes?.anySpend, allowDirectTransfer: allowDirectTransfer, destinationTokenAmount: destinationTokenAmount, callbackMetadata: callbackMetadata, senderAddress: senderAddress, showFiatOption: showFiatOption, slots: slots, content: content, theme: theme }, selectedChainId)) }), _jsx(ChainWarningText, { chainId: destinationTokenChainId, classes: classes?.chainWarningText || { root: "px-4 pb-4" } })] }));
217
270
  }
@@ -1,6 +1,6 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
2
  import { ABI_ERC20_STAKING, B3_TOKEN, eqci, getExplorerTxUrl } from "../../../anyspend/index.js";
3
- import { Button, GlareCardRounded, Input, StyleRoot, TextLoop, toast, useHasMounted, useModalStore, useSimBalance, useUnifiedChainSwitchAndExecute, } from "../../../global-account/react/index.js";
3
+ import { Button, GlareCardRounded, Input, StyleRoot, TextLoop, toast, useHasMounted, useModalStore, usePortfolioBalance, useUnifiedChainSwitchAndExecute, } from "../../../global-account/react/index.js";
4
4
  import { PUBLIC_BASE_RPC_URL } from "../../../shared/constants/index.js";
5
5
  import { formatTokenAmount } from "../../../shared/utils/number.js";
6
6
  import invariant from "invariant";
@@ -34,11 +34,25 @@ export function AnySpendStakeB3({ loadOrder, mode = "modal", recipientAddress, s
34
34
  // Wagmi hooks for direct staking
35
35
  const { address } = useAccount();
36
36
  const { switchChainAndExecute, isSwitchingOrExecuting } = useUnifiedChainSwitchAndExecute();
37
- // Fetch B3 token balance
38
- const { data: simBalance, isLoading: isBalanceLoading } = useSimBalance(address, [base.id]);
39
- const b3RawBalanceStr = simBalance?.balances.find(b => eqci(b.address, B3_TOKEN.address))?.amount || "0";
37
+ // Fetch B3 token balance. `isBalanceUnknown` must gate every use of `b3RawBalance`: a failed read
38
+ // yields the same 0 as an empty wallet, and acting on it pushes a holder into the swap flow to
39
+ // buy a token they already have.
40
+ const { data: balances, isLoading: isBalanceLoading, isError: isBalanceError, refetch: refetchBalance, } = usePortfolioBalance(address, [base.id]);
41
+ // Guarded on `address`: with no wallet connected the query never runs, and a query that was
42
+ // never asked is not a query that failed. Without this the screen tells a visitor their
43
+ // balance is unavailable and refuses to continue, when they simply have not connected yet.
44
+ const isBalanceUnknown = Boolean(address) && (isBalanceError || (!isBalanceLoading && balances === undefined));
45
+ const b3RawBalanceStr = balances?.find(b => eqci(b.address, B3_TOKEN.address))?.amount || "0";
40
46
  const b3RawBalance = BigInt(b3RawBalanceStr);
41
47
  const b3Balance = formatTokenAmount(b3RawBalance, B3_TOKEN.decimals);
48
+ /**
49
+ * Whether the wallet demonstrably holds enough B3 to stake `amountRaw` directly.
50
+ *
51
+ * False while the balance is unknown — but callers must not read that as a shortfall. An unknown
52
+ * balance is neither enough nor short, and the two need different UI: a shortfall offers the swap
53
+ * flow, an unknown offers a retry. Check `isBalanceUnknown` first.
54
+ */
55
+ const hasEnoughB3 = (amountRaw) => !isBalanceUnknown && BigInt(amountRaw || "0") <= b3RawBalance;
42
56
  // State for direct staking flow
43
57
  const [isStaking, setIsStaking] = useState(false);
44
58
  const [stakingTxHash, setStakingTxHash] = useState("");
@@ -206,9 +220,11 @@ export function AnySpendStakeB3({ loadOrder, mode = "modal", recipientAddress, s
206
220
  toast.error("Please enter a valid amount to stake");
207
221
  return;
208
222
  }
209
- // Check if user has sufficient B3 balance for direct staking
210
- const hasEnoughBalance = b3RawBalance && BigInt(userStakeAmount) <= b3RawBalance;
211
- if (hasEnoughBalance) {
223
+ if (isBalanceUnknown) {
224
+ toast.error("Can't read your B3 balance right now. Please try again.");
225
+ return;
226
+ }
227
+ if (hasEnoughB3(userStakeAmount)) {
212
228
  // User has enough B3, proceed with direct staking
213
229
  handleDirectStaking();
214
230
  }
@@ -232,16 +248,19 @@ export function AnySpendStakeB3({ loadOrder, mode = "modal", recipientAddress, s
232
248
  opacity: hasMounted ? 1 : 0,
233
249
  y: hasMounted ? 0 : 20,
234
250
  filter: hasMounted ? "blur(0px)" : "blur(10px)",
235
- }, transition: { duration: 0.3, delay: 0.1, ease: "easeInOut" }, children: _jsx("h2", { className: "font-sf-rounded font-neue-montreal-medium mb-1 text-center text-2xl font-semibold", children: (() => {
236
- const hasEnoughBalance = b3RawBalance && BigInt(debouncedUserStakeAmount || "0") <= b3RawBalance;
237
- return hasEnoughBalance || !debouncedAmount ? "Stake B3" : "Swap & Stake B3";
238
- })() }) })] }), _jsxs(motion.div, { initial: false, animate: {
251
+ }, transition: { duration: 0.3, delay: 0.1, ease: "easeInOut" }, children: _jsx("h2", { className: "font-sf-rounded font-neue-montreal-medium mb-1 text-center text-2xl font-semibold", children: isBalanceUnknown || !debouncedAmount || hasEnoughB3(debouncedUserStakeAmount)
252
+ ? "Stake B3"
253
+ : "Swap & Stake B3" }) })] }), _jsxs(motion.div, { initial: false, animate: {
239
254
  opacity: hasMounted ? 1 : 0,
240
255
  y: hasMounted ? 0 : 20,
241
256
  filter: hasMounted ? "blur(0px)" : "blur(10px)",
242
- }, transition: { duration: 0.3, delay: 0.2, ease: "easeInOut" }, className: "bg-b3-react-background w-full p-6", children: [_jsx("div", { className: "mb-2", children: _jsxs("div", { className: "flex items-center justify-between", children: [_jsx("p", { className: "text-as-primary/70 text-sm font-medium", children: "I want to stake" }), _jsxs("span", { className: "text-as-primary/50 flex items-center gap-1 text-sm", children: ["Available: ", isBalanceLoading ? _jsx(Loader2, { className: "h-3 w-3 animate-spin" }) : `${b3Balance} B3`] })] }) }), _jsxs("div", { className: "relative", children: [_jsx(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"}` }), _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 && _jsx("p", { className: "text-as-red mt-2 text-sm", children: validationError }), _jsx("div", { className: "mt-4", children: (() => {
243
- const hasEnoughBalance = b3RawBalance && BigInt(debouncedUserStakeAmount || "0") <= b3RawBalance;
244
- if (!hasEnoughBalance || !debouncedAmount) {
257
+ }, transition: { duration: 0.3, delay: 0.2, ease: "easeInOut" }, className: "bg-b3-react-background w-full p-6", children: [_jsx("div", { className: "mb-2", children: _jsxs("div", { className: "flex items-center justify-between", children: [_jsx("p", { className: "text-as-primary/70 text-sm font-medium", children: "I want to stake" }), _jsxs("span", { className: "text-as-primary/50 flex items-center gap-1 text-sm", children: ["Available:", " ", isBalanceLoading ? (_jsx(Loader2, { className: "h-3 w-3 animate-spin" })) : isBalanceUnknown ? ("unavailable") : (`${b3Balance} B3`)] })] }) }), _jsxs("div", { className: "relative", children: [_jsx(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"}` }), _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 && _jsx("p", { className: "text-as-red mt-2 text-sm", children: validationError }), _jsx("div", { className: "mt-4", children: (() => {
258
+ // An unreadable balance is not a shortfall, so it must not open the swap upsell —
259
+ // that would sell a swap to someone who may already hold the tokens.
260
+ if (isBalanceUnknown) {
261
+ return (_jsxs("div", { className: "bg-as-brand/10 flex flex-col items-center gap-2 rounded-lg p-4 pb-5", children: [_jsx("p", { className: "text-as-primary/70 text-sm font-medium", children: "We couldn't read your B3 balance just now." }), _jsx(Button, { variant: "ghost", onClick: () => refetchBalance(), className: "text-as-primary text-sm", children: "Try again" })] }));
262
+ }
263
+ if (!hasEnoughB3(debouncedUserStakeAmount) || !debouncedAmount) {
245
264
  return (_jsxs("div", { className: "bg-as-brand/10 flex flex-col items-center gap-2 rounded-lg p-4 pb-5", children: [_jsxs("div", { className: "flex items-center justify-center gap-2", children: [_jsx("span", { className: "text-as-primary text-sm font-semibold", children: "Swap & stake from any token" }), _jsxs(TextLoop, { children: [_jsx(EthIcon, { className: "h-8 w-8" }), _jsx(SolIcon, { className: "h-8 w-8" }), _jsx(UsdcIcon, { className: "h-8 w-8" })] }), _jsx(ArrowRight, { className: "text-as-primary h-4 w-4" }), _jsx("img", { src: "https://cdn.b3.fun/b3-coin-3d.png", className: "h-7 w-7", alt: "B3 Token" })] }), _jsx("p", { className: "text-as-primary/50 text-sm font-medium", children: debouncedAmount
246
265
  ? `No problem, we'll help you swap to ${debouncedAmount} B3!`
247
266
  : "Not enough B3? We'll help you swap from other coins." })] }));
@@ -1,7 +1,7 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
2
  import { ABI_ERC20_STAKING, B3_TOKEN, eqci, getExplorerTxUrl } from "../../../anyspend/index.js";
3
3
  import { normalizeAddress } from "../../../anyspend/utils/index.js";
4
- import { Button, GlareCardRounded, Input, StyleRoot, TextLoop, toast, useHasMounted, useModalStore, useSimBalance, useUnifiedChainSwitchAndExecute, } from "../../../global-account/react/index.js";
4
+ import { Button, GlareCardRounded, Input, StyleRoot, TextLoop, toast, useHasMounted, useModalStore, usePortfolioBalance, useUnifiedChainSwitchAndExecute, } from "../../../global-account/react/index.js";
5
5
  import { PUBLIC_BASE_RPC_URL } from "../../../shared/constants/index.js";
6
6
  import { formatTokenAmount } from "../../../shared/utils/number.js";
7
7
  import { ArrowRight, Loader2 } from "lucide-react";
@@ -37,11 +37,25 @@ export function AnySpendStakeB3ExactIn({ loadOrder, mode = "modal", sourceTokenA
37
37
  // Wagmi hooks for direct staking
38
38
  const { address } = useAccount();
39
39
  const { switchChainAndExecute, isSwitchingOrExecuting } = useUnifiedChainSwitchAndExecute();
40
- // Fetch B3 token balance
41
- const { data: simBalance, isLoading: isBalanceLoading } = useSimBalance(address, [base.id]);
42
- const b3RawBalanceStr = simBalance?.balances.find(b => eqci(b.address, B3_TOKEN.address))?.amount || "0";
40
+ // Fetch B3 token balance. `isBalanceUnknown` must gate every use of `b3RawBalance`: a failed read
41
+ // yields the same 0 as an empty wallet, and acting on it pushes a holder into the swap flow to
42
+ // buy a token they already have.
43
+ const { data: balances, isLoading: isBalanceLoading, isError: isBalanceError, refetch: refetchBalance, } = usePortfolioBalance(address, [base.id]);
44
+ // Guarded on `address`: with no wallet connected the query never runs, and a query that was
45
+ // never asked is not a query that failed. Without this the screen tells a visitor their
46
+ // balance is unavailable and refuses to continue, when they simply have not connected yet.
47
+ const isBalanceUnknown = Boolean(address) && (isBalanceError || (!isBalanceLoading && balances === undefined));
48
+ const b3RawBalanceStr = balances?.find(b => eqci(b.address, B3_TOKEN.address))?.amount || "0";
43
49
  const b3RawBalance = BigInt(b3RawBalanceStr);
44
50
  const b3Balance = formatTokenAmount(b3RawBalance, B3_TOKEN.decimals);
51
+ /**
52
+ * Whether the wallet demonstrably holds enough B3 to stake `amountRaw` directly.
53
+ *
54
+ * False while the balance is unknown — but callers must not read that as a shortfall. An unknown
55
+ * balance is neither enough nor short, and the two need different UI: a shortfall offers the swap
56
+ * flow, an unknown offers a retry. Check `isBalanceUnknown` first.
57
+ */
58
+ const hasEnoughB3 = (amountRaw) => !isBalanceUnknown && BigInt(amountRaw || "0") <= b3RawBalance;
45
59
  // State for direct staking flow
46
60
  const [isStaking, setIsStaking] = useState(false);
47
61
  const [stakingTxHash, setStakingTxHash] = useState("");
@@ -212,8 +226,11 @@ export function AnySpendStakeB3ExactIn({ loadOrder, mode = "modal", sourceTokenA
212
226
  return;
213
227
  }
214
228
  // Check if user has sufficient B3 balance for direct staking
215
- const hasEnoughBalance = b3RawBalance && BigInt(userStakeAmount) <= b3RawBalance;
216
- if (hasEnoughBalance) {
229
+ if (isBalanceUnknown) {
230
+ toast.error("Can't read your B3 balance right now. Please try again.");
231
+ return;
232
+ }
233
+ if (hasEnoughB3(userStakeAmount)) {
217
234
  // User has enough B3, proceed with direct staking
218
235
  handleDirectStaking();
219
236
  }
@@ -246,15 +263,20 @@ export function AnySpendStakeB3ExactIn({ loadOrder, mode = "modal", sourceTokenA
246
263
  y: hasMounted ? 0 : 20,
247
264
  filter: hasMounted ? "blur(0px)" : "blur(10px)",
248
265
  }, transition: { duration: 0.3, delay: 0.1, ease: "easeInOut" }, children: _jsx("h2", { className: "font-sf-rounded font-neue-montreal-medium mb-1 text-center text-2xl font-semibold", children: (() => {
249
- const hasEnoughBalance = b3RawBalance && BigInt(debouncedUserStakeAmount || "0") <= b3RawBalance;
250
- return hasEnoughBalance || !debouncedAmount ? "Stake B3" : "Swap & Stake B3";
266
+ return isBalanceUnknown || !debouncedAmount || hasEnoughB3(debouncedUserStakeAmount)
267
+ ? "Stake B3"
268
+ : "Swap & Stake B3";
251
269
  })() }) })] }), _jsxs(motion.div, { initial: false, animate: {
252
270
  opacity: hasMounted ? 1 : 0,
253
271
  y: hasMounted ? 0 : 20,
254
272
  filter: hasMounted ? "blur(0px)" : "blur(10px)",
255
- }, transition: { duration: 0.3, delay: 0.2, ease: "easeInOut" }, className: "bg-b3-react-background w-full p-6", children: [_jsx("div", { className: "mb-2", children: _jsxs("div", { className: "flex items-center justify-between", children: [_jsx("p", { className: "text-as-primary/70 text-sm font-medium", children: "I want to stake" }), _jsxs("span", { className: "text-as-primary/50 flex items-center gap-1 text-sm", children: ["Available: ", isBalanceLoading ? _jsx(Loader2, { className: "h-3 w-3 animate-spin" }) : `${b3Balance} B3`] })] }) }), _jsxs("div", { className: "relative", children: [_jsx(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"}` }), _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 && _jsx("p", { className: "text-as-red mt-2 text-sm", children: validationError }), _jsx("div", { className: "mt-4", children: (() => {
256
- const hasEnoughBalance = b3RawBalance && BigInt(debouncedUserStakeAmount || "0") <= b3RawBalance;
257
- if (!hasEnoughBalance || !debouncedAmount) {
273
+ }, transition: { duration: 0.3, delay: 0.2, ease: "easeInOut" }, className: "bg-b3-react-background w-full p-6", children: [_jsx("div", { className: "mb-2", children: _jsxs("div", { className: "flex items-center justify-between", children: [_jsx("p", { className: "text-as-primary/70 text-sm font-medium", children: "I want to stake" }), _jsxs("span", { className: "text-as-primary/50 flex items-center gap-1 text-sm", children: ["Available:", " ", isBalanceLoading ? (_jsx(Loader2, { className: "h-3 w-3 animate-spin" })) : isBalanceUnknown ? ("unavailable") : (`${b3Balance} B3`)] })] }) }), _jsxs("div", { className: "relative", children: [_jsx(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"}` }), _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 && _jsx("p", { className: "text-as-red mt-2 text-sm", children: validationError }), _jsx("div", { className: "mt-4", children: (() => {
274
+ // An unreadable balance is not a shortfall, so it must not open the swap upsell —
275
+ // that would sell a swap to someone who may already hold the tokens.
276
+ if (isBalanceUnknown) {
277
+ return (_jsxs("div", { className: "bg-as-brand/10 flex flex-col items-center gap-2 rounded-lg p-4 pb-5", children: [_jsx("p", { className: "text-as-primary/70 text-sm font-medium", children: "We couldn't read your B3 balance just now." }), _jsx(Button, { variant: "ghost", onClick: () => refetchBalance(), className: "text-as-primary text-sm", children: "Try again" })] }));
278
+ }
279
+ if (!hasEnoughB3(debouncedUserStakeAmount) || !debouncedAmount) {
258
280
  return (_jsxs("div", { className: "bg-as-brand/10 flex flex-col items-center gap-2 rounded-lg p-4 pb-5", children: [_jsxs("div", { className: "flex items-center justify-center gap-2", children: [_jsx("span", { className: "text-as-primary text-sm font-semibold", children: "Swap & stake from any token" }), _jsxs(TextLoop, { children: [_jsx(EthIcon, { className: "h-8 w-8" }), _jsx(SolIcon, { className: "h-8 w-8" }), _jsx(UsdcIcon, { className: "h-8 w-8" })] }), _jsx(ArrowRight, { className: "text-as-primary h-4 w-4" }), _jsx("img", { src: "https://cdn.b3.fun/b3-coin-3d.png", className: "h-7 w-7", alt: "B3 Token" })] }), _jsx("p", { className: "text-as-primary/50 text-sm font-medium", children: debouncedAmount
259
281
  ? `No problem, we'll help you swap to ${debouncedAmount} B3!`
260
282
  : "Not enough B3? We'll help you swap from other coins." })] }));
@@ -14,6 +14,22 @@ export interface QRDepositProps {
14
14
  destinationToken: components["schemas"]["Token"];
15
15
  /** The destination chain ID */
16
16
  destinationChainId: number;
17
+ /**
18
+ * Human-formatted destination amount (e.g. "9.365547"), shown as an APPROXIMATE
19
+ * target in swap mode only. The QR deposit path accepts an arbitrary sent amount,
20
+ * so this is never a guaranteed receive figure — the UI frames it as "any amount
21
+ * works". Omitted when no fixed amount is set or the destination decimals are
22
+ * unresolved (to avoid a mis-scaled number). Ignored in pure-transfer mode.
23
+ */
24
+ destinationAmountDisplay?: string;
25
+ /**
26
+ * When true, the deposit is a PURE TRANSFER: the destination token/chain mirror
27
+ * the user's currently selected source token/chain, so the exact token the user
28
+ * sends lands in their wallet on the same chain — no swap/bridge order is created.
29
+ * The `destinationToken`/`destinationChainId` props are then used only as the
30
+ * initial source selection (they must be fully resolved before mount). Defaults to false.
31
+ */
32
+ pureTransferOnly?: boolean;
17
33
  /** Creator address (optional) */
18
34
  creatorAddress?: string;
19
35
  /** Contract config for custom execution after deposit */
@@ -24,8 +40,11 @@ export interface QRDepositProps {
24
40
  onClose?: () => void;
25
41
  /** Callback when order is created successfully */
26
42
  onOrderCreated?: (orderId: string) => void;
27
- /** Callback when deposit is completed */
28
- onSuccess?: (txHash?: string) => void;
43
+ /**
44
+ * Callback when deposit is completed. The argument carries the deposited amount string
45
+ * (e.g. "200.00") on the pure-transfer path, or the order tx hash otherwise.
46
+ */
47
+ onSuccess?: (amountOrTxHash?: string) => void;
29
48
  /** Custom classes for styling */
30
49
  classes?: QRDepositClasses;
31
50
  }
@@ -43,4 +62,4 @@ export interface QRDepositProps {
43
62
  * onSuccess={(txHash) => console.log("Deposit complete:", txHash)}
44
63
  * />
45
64
  */
46
- export declare function QRDeposit({ mode, recipientAddress, sourceToken: sourceTokenProp, sourceChainId: sourceChainIdProp, destinationToken, destinationChainId, creatorAddress, depositContractConfig, onBack, onClose, onOrderCreated, onSuccess, classes, }: QRDepositProps): import("react/jsx-runtime").JSX.Element;
65
+ export declare function QRDeposit({ mode, recipientAddress, sourceToken: sourceTokenProp, sourceChainId: sourceChainIdProp, destinationToken, destinationChainId, destinationAmountDisplay, pureTransferOnly, creatorAddress, depositContractConfig, onBack, onClose, onOrderCreated, onSuccess, classes, }: QRDepositProps): import("react/jsx-runtime").JSX.Element;
@@ -1,11 +1,11 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
2
  import { ALL_CHAINS, getAvailableChainIds, getPaymentUrl, isSameChainAndToken, ZERO_ADDRESS, } from "../../../anyspend/index.js";
3
3
  import { Button, toast } from "../../../global-account/react/index.js";
4
4
  import { cn } from "../../../shared/utils/cn.js";
5
5
  import { TokenSelector } from "@relayprotocol/relay-kit-ui";
6
6
  import { Check, ChevronsUpDown, Copy, Loader2 } from "lucide-react";
7
7
  import { QRCodeSVG } from "qrcode.react";
8
- import { useEffect, useRef, useState } from "react";
8
+ import { useCallback, useEffect, useRef, useState } from "react";
9
9
  import { useAnyspendOrderAndTransactions } from "../hooks/useAnyspendOrderAndTransactions.js";
10
10
  import { useCreateDepositFirstOrder } from "../hooks/useCreateDepositFirstOrder.js";
11
11
  import { useOnOrderSuccess } from "../hooks/useOnOrderSuccess.js";
@@ -39,28 +39,35 @@ const DEFAULT_ETH_ON_BASE = {
39
39
  * onSuccess={(txHash) => console.log("Deposit complete:", txHash)}
40
40
  * />
41
41
  */
42
- export function QRDeposit({ mode = "modal", recipientAddress, sourceToken: sourceTokenProp, sourceChainId: sourceChainIdProp, destinationToken, destinationChainId, creatorAddress, depositContractConfig, onBack, onClose, onOrderCreated, onSuccess, classes, }) {
42
+ export function QRDeposit({ mode = "modal", recipientAddress, sourceToken: sourceTokenProp, sourceChainId: sourceChainIdProp, destinationToken, destinationChainId, destinationAmountDisplay, pureTransferOnly = false, creatorAddress, depositContractConfig, onBack, onClose, onOrderCreated, onSuccess, classes, }) {
43
43
  const [copied, setCopied] = useState(false);
44
44
  const [orderId, setOrderId] = useState();
45
45
  const [globalAddress, setGlobalAddress] = useState();
46
46
  const orderCreatedRef = useRef(false);
47
47
  const [transferResult, setTransferResult] = useState(null);
48
- // Source token/chain as state (can be changed by user)
49
- const [sourceChainId, setSourceChainId] = useState(sourceChainIdProp ?? 8453);
50
- const [sourceToken, setSourceToken] = useState(sourceTokenProp ?? DEFAULT_ETH_ON_BASE);
48
+ // Source token/chain as state (can be changed by user).
49
+ // In pure-transfer mode the initial source is the passed destination (caller sets
50
+ // it to the desired default funding token), so the deposit mirrors the user's selection.
51
+ const [sourceChainId, setSourceChainId] = useState(sourceChainIdProp ?? (pureTransferOnly ? destinationChainId : 8453));
52
+ const [sourceToken, setSourceToken] = useState(sourceTokenProp ?? (pureTransferOnly ? destinationToken : DEFAULT_ETH_ON_BASE));
53
+ // In pure-transfer mode the effective destination mirrors the selected source,
54
+ // forcing isPureTransfer = true (no swap/bridge order is created).
55
+ const effectiveDestinationToken = pureTransferOnly ? sourceToken : destinationToken;
56
+ const effectiveDestinationChainId = pureTransferOnly ? sourceChainId : destinationChainId;
51
57
  // Check if this is a pure transfer (same chain and token)
52
- const isPureTransfer = isSameChainAndToken(sourceChainId, sourceToken.address, destinationChainId, destinationToken.address);
58
+ const isPureTransfer = isSameChainAndToken(sourceChainId, sourceToken.address, effectiveDestinationChainId, effectiveDestinationToken.address);
59
+ const handleTransferDetected = useCallback((result) => {
60
+ setTransferResult(result);
61
+ onSuccess?.(result.formattedAmount);
62
+ }, [onSuccess]);
53
63
  // Watch for pure transfers (same chain and token)
54
- const { isWatching: isWatchingTransfer } = useWatchTransfer({
64
+ const { isWatching: isWatchingTransfer, reset: resetWatchTransfer } = useWatchTransfer({
55
65
  address: recipientAddress,
56
66
  chainId: sourceChainId,
57
67
  tokenAddress: sourceToken.address,
58
68
  tokenDecimals: sourceToken.decimals,
59
69
  enabled: isPureTransfer && !transferResult,
60
- onTransferDetected: result => {
61
- setTransferResult(result);
62
- onSuccess?.();
63
- },
70
+ onTransferDetected: handleTransferDetected,
64
71
  });
65
72
  // Handle token selection from TokenSelector
66
73
  const handleTokenSelect = (newToken) => {
@@ -77,6 +84,8 @@ export function QRDeposit({ mode = "modal", recipientAddress, sourceToken: sourc
77
84
  setGlobalAddress(undefined);
78
85
  orderCreatedRef.current = false;
79
86
  setTransferResult(null);
87
+ // Reset the balance watcher baseline so the new token isn't compared against the old token's balance
88
+ resetWatchTransfer();
80
89
  // Update token and chain
81
90
  setSourceChainId(newToken.chainId);
82
91
  setSourceToken(token);
@@ -107,18 +116,18 @@ export function QRDeposit({ mode = "modal", recipientAddress, sourceToken: sourc
107
116
  createOrder({
108
117
  recipientAddress,
109
118
  srcChain: sourceChainId,
110
- dstChain: destinationChainId,
119
+ dstChain: effectiveDestinationChainId,
111
120
  srcToken: sourceToken,
112
- dstToken: destinationToken,
121
+ dstToken: effectiveDestinationToken,
113
122
  creatorAddress,
114
123
  contractConfig: depositContractConfig,
115
124
  });
116
125
  }, [
117
126
  recipientAddress,
118
127
  sourceChainId,
119
- destinationChainId,
128
+ effectiveDestinationChainId,
120
129
  sourceToken,
121
- destinationToken,
130
+ effectiveDestinationToken,
122
131
  creatorAddress,
123
132
  depositContractConfig,
124
133
  createOrder,
@@ -162,8 +171,8 @@ export function QRDeposit({ mode = "modal", recipientAddress, sourceToken: sourc
162
171
  }
163
172
  return (_jsx("div", { className: classes?.container ||
164
173
  cn("anyspend-container anyspend-qr-deposit font-inter bg-as-surface-primary mx-auto w-full max-w-[460px] p-6", mode === "page" && "border-as-border-secondary overflow-hidden rounded-2xl border shadow-xl"), children: _jsxs("div", { className: classes?.content || "anyspend-qr-deposit-content flex flex-col gap-4", children: [_jsxs("div", { className: classes?.header || "anyspend-qr-header flex items-center justify-between", children: [_jsx("button", { onClick: handleBack, className: classes?.backButton || "anyspend-qr-back-button text-as-secondary hover:text-as-primary", children: _jsx("svg", { className: "h-5 w-5", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M15 19l-7-7 7-7" }) }) }), _jsx("h2", { className: classes?.title || "anyspend-qr-title text-as-primary text-base font-semibold", children: "Deposit" }), onClose ? (_jsx("button", { onClick: handleClose, className: classes?.closeButton || "anyspend-qr-close-button text-as-secondary hover:text-as-primary", children: _jsx("svg", { className: "h-5 w-5", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M6 18L18 6M6 6l12 12" }) }) })) : (_jsx("div", { className: "w-5" }))] }), _jsxs("div", { className: classes?.tokenSelectorContainer || "anyspend-qr-token-selector flex flex-col gap-1.5", children: [_jsx("label", { className: classes?.tokenSelectorLabel || "anyspend-qr-token-label text-as-secondary text-sm", children: "Send" }), _jsx(TokenSelector, { chainIdsFilter: getAvailableChainIds("from"), context: "from", fromChainWalletVMSupported: true, isValidAddress: true, lockedChainIds: getAvailableChainIds("from"), multiWalletSupportEnabled: true, onAnalyticEvent: undefined, setToken: handleTokenSelect, supportedWalletVMs: ["evm"], token: undefined, trigger: _jsxs(Button, { variant: "outline", role: "combobox", className: classes?.tokenSelectorTrigger ||
165
- "anyspend-qr-token-trigger border-as-stroke bg-as-surface-secondary flex h-auto w-full items-center justify-between gap-2 rounded-xl border px-3 py-2.5", children: [_jsxs("div", { className: "flex items-center gap-2", children: [sourceToken.metadata?.logoURI ? (_jsx(ChainTokenIcon, { chainUrl: ALL_CHAINS[sourceChainId]?.logoUrl, tokenUrl: sourceToken.metadata.logoURI, className: "h-8 min-h-8 w-8 min-w-8" })) : (_jsx("div", { className: "h-8 w-8 rounded-full bg-gray-700" })), _jsxs("div", { className: "flex flex-col items-start gap-0", children: [_jsx("div", { className: "text-as-primary font-semibold", children: sourceToken.symbol }), _jsx("div", { className: "text-as-primary/70 text-xs", children: ALL_CHAINS[sourceChainId]?.name ?? "Unknown" })] })] }), _jsx(ChevronsUpDown, { className: "h-4 w-4 shrink-0 opacity-70" })] }) })] }), _jsxs("div", { className: classes?.qrContent || "anyspend-qr-content border-as-stroke flex items-start gap-4 rounded-xl border p-4", children: [_jsxs("div", { className: classes?.qrCodeContainer || "anyspend-qr-code-container flex flex-col items-center gap-2", children: [_jsx("div", { className: classes?.qrCode || "anyspend-qr-code rounded-lg bg-white p-2", children: _jsx(QRCodeSVG, { value: qrValue, size: 120, level: "M", marginSize: 0 }) }), _jsxs("span", { className: classes?.qrScanHint || "anyspend-qr-scan-hint text-as-secondary text-xs", children: ["SCAN WITH ", _jsx("span", { className: "inline-block", children: "\uD83E\uDD8A" })] })] }), _jsxs("div", { className: classes?.addressContainer || "anyspend-qr-address-container flex flex-1 flex-col gap-1", children: [_jsx("span", { className: classes?.addressLabel || "anyspend-qr-address-label text-as-secondary text-sm", children: "Deposit address:" }), _jsxs("div", { className: classes?.addressRow || "anyspend-qr-address-row flex items-start gap-1", children: [_jsx("span", { className: classes?.address || "anyspend-qr-address text-as-primary break-all font-mono text-sm leading-relaxed", children: displayAddress }), _jsx("button", { onClick: handleCopyAddress, className: classes?.addressCopyIcon ||
166
- "anyspend-qr-copy-icon text-as-secondary hover:text-as-primary mt-0.5 shrink-0", children: copied ? _jsx(Check, { className: "h-4 w-4" }) : _jsx(Copy, { className: "h-4 w-4" }) })] })] })] }), _jsx(ChainWarningText, { chainId: destinationChainId }), _jsxs(WarningText, { children: ["Only send ", sourceToken.symbol, " on ", ALL_CHAINS[sourceChainId]?.name ?? "the specified chain", ". Other tokens will not be converted."] }), isPureTransfer && isWatchingTransfer && (_jsxs("div", { className: classes?.watchingIndicator ||
174
+ "anyspend-qr-token-trigger border-as-stroke bg-as-surface-secondary flex h-auto w-full items-center justify-between gap-2 rounded-xl border px-3 py-2.5", children: [_jsxs("div", { className: "flex items-center gap-2", children: [sourceToken.metadata?.logoURI ? (_jsx(ChainTokenIcon, { chainUrl: ALL_CHAINS[sourceChainId]?.logoUrl, tokenUrl: sourceToken.metadata.logoURI, className: "h-8 min-h-8 w-8 min-w-8" })) : (_jsx("div", { className: "h-8 w-8 rounded-full bg-gray-700" })), _jsxs("div", { className: "flex flex-col items-start gap-0", children: [_jsx("div", { className: "text-as-primary font-semibold", children: sourceToken.symbol }), _jsx("div", { className: "text-as-primary/70 text-xs", children: ALL_CHAINS[sourceChainId]?.name ?? "Unknown" })] })] }), _jsx(ChevronsUpDown, { className: "h-4 w-4 shrink-0 opacity-70" })] }) })] }), !isPureTransfer && (_jsxs("div", { className: "anyspend-qr-receive flex flex-col gap-1.5", children: [_jsx("label", { className: "anyspend-qr-receive-label text-as-secondary text-sm", children: "Receive" }), _jsxs("div", { className: "anyspend-qr-receive-row border-as-stroke bg-as-surface-secondary flex w-full items-center gap-2 rounded-xl border px-3 py-2.5", children: [effectiveDestinationToken.metadata?.logoURI ? (_jsx(ChainTokenIcon, { chainUrl: ALL_CHAINS[effectiveDestinationChainId]?.logoUrl, tokenUrl: effectiveDestinationToken.metadata.logoURI, className: "h-8 min-h-8 w-8 min-w-8" })) : (_jsx("div", { className: "h-8 w-8 rounded-full bg-gray-700" })), _jsxs("div", { className: "flex flex-col items-start gap-0", children: [_jsx("div", { className: "text-as-primary font-semibold", children: effectiveDestinationToken.symbol || "Token" }), _jsx("div", { className: "text-as-primary/70 text-xs", children: ALL_CHAINS[effectiveDestinationChainId]?.name ?? "Unknown" })] })] })] })), _jsxs("div", { className: classes?.qrContent || "anyspend-qr-content border-as-stroke flex items-start gap-4 rounded-xl border p-4", children: [_jsxs("div", { className: classes?.qrCodeContainer || "anyspend-qr-code-container flex flex-col items-center gap-2", children: [_jsx("div", { className: classes?.qrCode || "anyspend-qr-code rounded-lg bg-white p-2", children: _jsx(QRCodeSVG, { value: qrValue, size: 120, level: "M", marginSize: 0 }) }), _jsxs("span", { className: classes?.qrScanHint || "anyspend-qr-scan-hint text-as-secondary text-xs", children: ["SCAN WITH ", _jsx("span", { className: "inline-block", children: "\uD83E\uDD8A" })] })] }), _jsxs("div", { className: classes?.addressContainer || "anyspend-qr-address-container flex flex-1 flex-col gap-1", children: [_jsx("span", { className: classes?.addressLabel || "anyspend-qr-address-label text-as-secondary text-sm", children: "Deposit address:" }), _jsxs("div", { className: classes?.addressRow || "anyspend-qr-address-row flex items-start gap-1", children: [_jsx("span", { className: classes?.address || "anyspend-qr-address text-as-primary break-all font-mono text-sm leading-relaxed", children: displayAddress }), _jsx("button", { onClick: handleCopyAddress, className: classes?.addressCopyIcon ||
175
+ "anyspend-qr-copy-icon text-as-secondary hover:text-as-primary mt-0.5 shrink-0", children: copied ? _jsx(Check, { className: "h-4 w-4" }) : _jsx(Copy, { className: "h-4 w-4" }) })] })] })] }), _jsx(ChainWarningText, { chainId: effectiveDestinationChainId }), isPureTransfer ? (_jsxs(WarningText, { children: ["Only send ", sourceToken.symbol, " on ", ALL_CHAINS[sourceChainId]?.name ?? "the specified chain", ". Other tokens will not be converted."] })) : (_jsxs(_Fragment, { children: [_jsxs(WarningText, { children: ["Only send ", sourceToken.symbol, " on ", ALL_CHAINS[sourceChainId]?.name ?? "the specified chain", " to this address \u2014 it will be converted to ", effectiveDestinationToken.symbol || "the destination token", " on", " ", ALL_CHAINS[effectiveDestinationChainId]?.name ?? "the destination chain", "."] }), destinationAmountDisplay && (_jsxs("p", { className: "anyspend-qr-amount-hint text-as-secondary text-xs", children: ["Target \u2248 ", destinationAmountDisplay, " ", effectiveDestinationToken.symbol || "tokens", ". Any amount of", " ", sourceToken.symbol || "tokens", " works \u2014 you'll receive whatever your deposit converts to."] }))] })), isPureTransfer && isWatchingTransfer && (_jsxs("div", { className: classes?.watchingIndicator ||
167
176
  "anyspend-qr-watching flex items-center justify-center gap-2 rounded-lg bg-blue-500/10 p-3", children: [_jsx(Loader2, { className: "h-4 w-4 animate-spin text-blue-500" }), _jsx("span", { className: "text-sm text-blue-500", children: "Watching for incoming transfer..." })] })), _jsx("button", { onClick: handleCopyAddress, className: classes?.copyButton ||
168
177
  "anyspend-qr-copy-button flex w-full items-center justify-center gap-2 rounded-xl bg-blue-500 py-3.5 font-medium text-white transition-all hover:bg-blue-600", children: "Copy deposit address" })] }) }));
169
178
  }