@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.
- package/README.md +3 -3
- package/constants/chains/b3Chain.js +3 -1
- package/dist/cjs/anyspend/constants/rpc.d.ts +3 -1
- package/dist/cjs/anyspend/constants/rpc.js +6 -2
- package/dist/cjs/anyspend/react/components/AnySpend.d.ts +9 -1
- package/dist/cjs/anyspend/react/components/AnySpend.js +123 -46
- package/dist/cjs/anyspend/react/components/AnySpendCustomExactIn.js +8 -10
- package/dist/cjs/anyspend/react/components/AnySpendDeposit.d.ts +15 -3
- package/dist/cjs/anyspend/react/components/AnySpendDeposit.js +78 -25
- package/dist/cjs/anyspend/react/components/AnySpendStakeB3.js +32 -13
- package/dist/cjs/anyspend/react/components/AnySpendStakeB3ExactIn.js +32 -10
- package/dist/cjs/anyspend/react/components/QRDeposit.d.ts +22 -3
- package/dist/cjs/anyspend/react/components/QRDeposit.js +25 -16
- package/dist/cjs/anyspend/react/components/checkout/CryptoPayPanel.js +18 -11
- package/dist/cjs/anyspend/react/components/common/PureTransferView.d.ts +30 -0
- package/dist/cjs/anyspend/react/components/common/PureTransferView.js +64 -0
- package/dist/cjs/anyspend/react/components/common/TokenBalance.js +4 -5
- package/dist/cjs/anyspend/react/hooks/useCreateDepositFirstOrder.d.ts +3 -3
- package/dist/cjs/anyspend/react/hooks/useSigMint.d.ts +1 -1
- package/dist/cjs/anyspend/utils/address.d.ts +2 -1
- package/dist/cjs/anyspend/utils/address.js +12 -9
- package/dist/cjs/anyspend/utils/chain.d.ts +84 -1
- package/dist/cjs/anyspend/utils/chain.js +73 -3
- package/dist/cjs/anyspend/utils/token.d.ts +2 -0
- package/dist/cjs/anyspend/utils/token.js +15 -1
- package/dist/cjs/app.shared.d.ts +9 -1
- package/dist/cjs/app.shared.js +19 -0
- package/dist/cjs/global-account/app.native.d.ts +1 -1
- package/dist/cjs/global-account/better-auth-client.d.ts +3314 -36
- package/dist/cjs/global-account/better-auth-client.js +28 -3
- package/dist/cjs/global-account/bsmnt.d.ts +2 -2
- package/dist/cjs/global-account/bsmnt.native.d.ts +1 -1
- package/dist/cjs/global-account/client-manager.d.ts +7 -5
- package/dist/cjs/global-account/client-manager.js +51 -4
- package/dist/cjs/global-account/react/components/AvatarEditor/AvatarEditor.js +6 -11
- package/dist/cjs/global-account/react/components/B3Provider/B3ConfigProvider.d.ts +11 -0
- package/dist/cjs/global-account/react/components/B3Provider/B3ConfigProvider.js +12 -0
- package/dist/cjs/global-account/react/components/B3Provider/B3Provider.d.ts +12 -2
- package/dist/cjs/global-account/react/components/B3Provider/B3Provider.js +25 -3
- package/dist/cjs/global-account/react/components/B3Provider/BetterAuthProvider.js +45 -4
- package/dist/cjs/global-account/react/components/B3Provider/RelayKitProviderWrapper.d.ts +1 -2
- package/dist/cjs/global-account/react/components/B3Provider/RelayKitProviderWrapper.js +11 -5
- package/dist/cjs/global-account/react/components/ManageAccount/ContentTokens.js +23 -15
- package/dist/cjs/global-account/react/components/ManageAccount/NFTContent.js +2 -2
- package/dist/cjs/global-account/react/components/ManageAccount/ProfileSection.js +8 -6
- package/dist/cjs/global-account/react/components/ManageAccount/SettingsProfileCard.js +1 -1
- package/dist/cjs/global-account/react/components/ManageAccount/TokenContent.js +17 -8
- package/dist/cjs/global-account/react/components/Send/Send.js +15 -11
- package/dist/cjs/global-account/react/components/SignInWithB3/BetterAuthSignIn.js +3 -1
- package/dist/cjs/global-account/react/components/SignInWithB3/SignInWithB3Flow.js +1 -5
- package/dist/cjs/global-account/react/components/SignInWithB3/components/AuthButton.js +2 -1
- package/dist/cjs/global-account/react/components/SignInWithB3/steps/LoginStepBetterAuth.js +1 -0
- package/dist/cjs/global-account/react/components/SignInWithB3/utils/signInUtils.d.ts +3 -2
- package/dist/cjs/global-account/react/components/SignInWithB3/utils/signInUtils.js +3 -3
- package/dist/cjs/global-account/react/components/index.d.ts +1 -1
- package/dist/cjs/global-account/react/components/index.js +3 -3
- package/dist/cjs/global-account/react/hooks/index.d.ts +2 -3
- package/dist/cjs/global-account/react/hooks/index.js +7 -10
- package/dist/cjs/global-account/react/hooks/useAuth.d.ts +5 -4
- package/dist/cjs/global-account/react/hooks/useAuth.js +1 -0
- package/dist/cjs/global-account/react/hooks/useAuthentication.d.ts +3 -2
- package/dist/cjs/global-account/react/hooks/useAuthentication.js +2 -1
- package/dist/cjs/global-account/react/hooks/useBetterAuth.d.ts +1657 -22
- package/dist/cjs/global-account/react/hooks/useBetterAuth.js +7 -7
- package/dist/cjs/global-account/react/hooks/useClient.d.ts +3 -3
- package/dist/cjs/global-account/react/hooks/useFirstEOA.d.ts +4 -7666
- package/dist/cjs/global-account/react/hooks/useFirstEOA.js +1 -0
- package/dist/cjs/global-account/react/hooks/useNativeBalance.js +2 -2
- package/dist/cjs/global-account/react/hooks/usePortfolioBalance.d.ts +15 -0
- package/dist/cjs/global-account/react/hooks/usePortfolioBalance.js +76 -0
- package/dist/cjs/global-account/react/hooks/usePortfolioCollectibles.d.ts +12 -0
- package/dist/cjs/global-account/react/hooks/usePortfolioCollectibles.js +178 -0
- package/dist/cjs/global-account/react/hooks/useSiwe.d.ts +1 -1
- package/dist/cjs/global-account/react/hooks/useSiwe.native.d.ts +1 -1
- package/dist/cjs/global-account/react/hooks/useTWAuth.d.ts +1 -1
- package/dist/cjs/global-account/react/hooks/useUnifiedChainSwitchAndExecute.d.ts +1 -0
- package/dist/cjs/global-account/react/hooks/useUnifiedChainSwitchAndExecute.js +37 -27
- package/dist/cjs/global-account/react/stores/useModalStore.d.ts +14 -2
- package/dist/cjs/global-account/types/b3-api.types.d.ts +5 -0
- package/dist/cjs/global-account/types/feature-flags.d.ts +5 -5
- package/dist/cjs/notifications/services/api.js +1 -0
- package/dist/cjs/shared/constants/chains/b3Chain.d.ts +30 -54
- package/dist/cjs/shared/constants/chains/b3Chain.js +5 -41
- package/dist/cjs/shared/constants/chains/supported.d.ts +1 -49
- package/dist/cjs/shared/constants/chains/supported.js +8 -36
- package/dist/cjs/shared/constants/index.d.ts +4 -0
- package/dist/cjs/shared/utils/chain-transformers.d.ts +4 -4
- package/dist/cjs/shared/utils/chain-transformers.js +38 -37
- package/dist/cjs/shared/utils/thirdweb-insights.js +2 -2
- package/dist/cjs/shared/utils/upload.d.ts +9 -0
- package/dist/cjs/shared/utils/upload.js +34 -0
- package/dist/cjs/shared/utils/zerionPositions.d.ts +96 -0
- package/dist/cjs/shared/utils/zerionPositions.js +188 -0
- package/dist/esm/anyspend/constants/rpc.d.ts +3 -1
- package/dist/esm/anyspend/constants/rpc.js +5 -1
- package/dist/esm/anyspend/react/components/AnySpend.d.ts +9 -1
- package/dist/esm/anyspend/react/components/AnySpend.js +124 -47
- package/dist/esm/anyspend/react/components/AnySpendCustomExactIn.js +9 -11
- package/dist/esm/anyspend/react/components/AnySpendDeposit.d.ts +15 -3
- package/dist/esm/anyspend/react/components/AnySpendDeposit.js +80 -27
- package/dist/esm/anyspend/react/components/AnySpendStakeB3.js +33 -14
- package/dist/esm/anyspend/react/components/AnySpendStakeB3ExactIn.js +33 -11
- package/dist/esm/anyspend/react/components/QRDeposit.d.ts +22 -3
- package/dist/esm/anyspend/react/components/QRDeposit.js +27 -18
- package/dist/esm/anyspend/react/components/checkout/CryptoPayPanel.js +21 -14
- package/dist/esm/anyspend/react/components/common/PureTransferView.d.ts +30 -0
- package/dist/esm/anyspend/react/components/common/PureTransferView.js +61 -0
- package/dist/esm/anyspend/react/components/common/TokenBalance.js +6 -7
- package/dist/esm/anyspend/react/hooks/useCreateDepositFirstOrder.d.ts +3 -3
- package/dist/esm/anyspend/react/hooks/useSigMint.d.ts +1 -1
- package/dist/esm/anyspend/utils/address.d.ts +2 -1
- package/dist/esm/anyspend/utils/address.js +9 -6
- package/dist/esm/anyspend/utils/chain.d.ts +84 -1
- package/dist/esm/anyspend/utils/chain.js +73 -5
- package/dist/esm/anyspend/utils/token.d.ts +2 -0
- package/dist/esm/anyspend/utils/token.js +13 -0
- package/dist/esm/app.shared.d.ts +9 -1
- package/dist/esm/app.shared.js +17 -0
- package/dist/esm/global-account/app.native.d.ts +1 -1
- package/dist/esm/global-account/better-auth-client.d.ts +3314 -36
- package/dist/esm/global-account/better-auth-client.js +27 -4
- package/dist/esm/global-account/bsmnt.d.ts +2 -2
- package/dist/esm/global-account/bsmnt.native.d.ts +1 -1
- package/dist/esm/global-account/client-manager.d.ts +7 -5
- package/dist/esm/global-account/client-manager.js +51 -5
- package/dist/esm/global-account/react/components/AvatarEditor/AvatarEditor.js +6 -11
- package/dist/esm/global-account/react/components/B3Provider/B3ConfigProvider.d.ts +11 -0
- package/dist/esm/global-account/react/components/B3Provider/B3ConfigProvider.js +11 -0
- package/dist/esm/global-account/react/components/B3Provider/B3Provider.d.ts +12 -2
- package/dist/esm/global-account/react/components/B3Provider/B3Provider.js +26 -4
- package/dist/esm/global-account/react/components/B3Provider/BetterAuthProvider.js +46 -5
- package/dist/esm/global-account/react/components/B3Provider/RelayKitProviderWrapper.d.ts +1 -2
- package/dist/esm/global-account/react/components/B3Provider/RelayKitProviderWrapper.js +11 -5
- package/dist/esm/global-account/react/components/ManageAccount/ContentTokens.js +24 -16
- package/dist/esm/global-account/react/components/ManageAccount/NFTContent.js +3 -3
- package/dist/esm/global-account/react/components/ManageAccount/ProfileSection.js +9 -7
- package/dist/esm/global-account/react/components/ManageAccount/SettingsProfileCard.js +1 -1
- package/dist/esm/global-account/react/components/ManageAccount/TokenContent.js +18 -9
- package/dist/esm/global-account/react/components/Send/Send.js +16 -12
- package/dist/esm/global-account/react/components/SignInWithB3/BetterAuthSignIn.js +3 -1
- package/dist/esm/global-account/react/components/SignInWithB3/SignInWithB3Flow.js +1 -5
- package/dist/esm/global-account/react/components/SignInWithB3/components/AuthButton.js +2 -1
- package/dist/esm/global-account/react/components/SignInWithB3/steps/LoginStepBetterAuth.js +1 -0
- package/dist/esm/global-account/react/components/SignInWithB3/utils/signInUtils.d.ts +3 -2
- package/dist/esm/global-account/react/components/SignInWithB3/utils/signInUtils.js +3 -3
- package/dist/esm/global-account/react/components/index.d.ts +1 -1
- package/dist/esm/global-account/react/components/index.js +1 -1
- package/dist/esm/global-account/react/hooks/index.d.ts +2 -3
- package/dist/esm/global-account/react/hooks/index.js +2 -3
- package/dist/esm/global-account/react/hooks/useAuth.d.ts +5 -4
- package/dist/esm/global-account/react/hooks/useAuth.js +1 -0
- package/dist/esm/global-account/react/hooks/useAuthentication.d.ts +3 -2
- package/dist/esm/global-account/react/hooks/useAuthentication.js +2 -1
- package/dist/esm/global-account/react/hooks/useBetterAuth.d.ts +1657 -22
- package/dist/esm/global-account/react/hooks/useBetterAuth.js +8 -8
- package/dist/esm/global-account/react/hooks/useClient.d.ts +3 -3
- package/dist/esm/global-account/react/hooks/useFirstEOA.d.ts +4 -7666
- package/dist/esm/global-account/react/hooks/useFirstEOA.js +1 -0
- package/dist/esm/global-account/react/hooks/useNativeBalance.js +1 -1
- package/dist/esm/global-account/react/hooks/usePortfolioBalance.d.ts +15 -0
- package/dist/esm/global-account/react/hooks/usePortfolioBalance.js +72 -0
- package/dist/esm/global-account/react/hooks/usePortfolioCollectibles.d.ts +12 -0
- package/dist/esm/global-account/react/hooks/usePortfolioCollectibles.js +175 -0
- package/dist/esm/global-account/react/hooks/useSiwe.d.ts +1 -1
- package/dist/esm/global-account/react/hooks/useSiwe.native.d.ts +1 -1
- package/dist/esm/global-account/react/hooks/useTWAuth.d.ts +1 -1
- package/dist/esm/global-account/react/hooks/useUnifiedChainSwitchAndExecute.d.ts +1 -0
- package/dist/esm/global-account/react/hooks/useUnifiedChainSwitchAndExecute.js +37 -27
- package/dist/esm/global-account/react/stores/useModalStore.d.ts +14 -2
- package/dist/esm/global-account/types/b3-api.types.d.ts +5 -0
- package/dist/esm/global-account/types/feature-flags.d.ts +5 -5
- package/dist/esm/notifications/services/api.js +1 -0
- package/dist/esm/shared/constants/chains/b3Chain.d.ts +30 -54
- package/dist/esm/shared/constants/chains/b3Chain.js +4 -38
- package/dist/esm/shared/constants/chains/supported.d.ts +1 -49
- package/dist/esm/shared/constants/chains/supported.js +7 -35
- package/dist/esm/shared/constants/index.d.ts +4 -0
- package/dist/esm/shared/utils/chain-transformers.d.ts +4 -4
- package/dist/esm/shared/utils/chain-transformers.js +38 -37
- package/dist/esm/shared/utils/thirdweb-insights.js +2 -2
- package/dist/esm/shared/utils/upload.d.ts +9 -0
- package/dist/esm/shared/utils/upload.js +31 -0
- package/dist/esm/shared/utils/zerionPositions.d.ts +96 -0
- package/dist/esm/shared/utils/zerionPositions.js +180 -0
- package/dist/styles/index.css +1 -1
- package/dist/types/anyspend/constants/rpc.d.ts +3 -1
- package/dist/types/anyspend/react/components/AnySpend.d.ts +9 -1
- package/dist/types/anyspend/react/components/AnySpendDeposit.d.ts +15 -3
- package/dist/types/anyspend/react/components/QRDeposit.d.ts +22 -3
- package/dist/types/anyspend/react/components/common/PureTransferView.d.ts +30 -0
- package/dist/types/anyspend/react/hooks/useCreateDepositFirstOrder.d.ts +3 -3
- package/dist/types/anyspend/react/hooks/useSigMint.d.ts +1 -1
- package/dist/types/anyspend/utils/address.d.ts +2 -1
- package/dist/types/anyspend/utils/chain.d.ts +84 -1
- package/dist/types/anyspend/utils/token.d.ts +2 -0
- package/dist/types/app.shared.d.ts +9 -1
- package/dist/types/global-account/app.native.d.ts +1 -1
- package/dist/types/global-account/better-auth-client.d.ts +3314 -36
- package/dist/types/global-account/bsmnt.d.ts +2 -2
- package/dist/types/global-account/bsmnt.native.d.ts +1 -1
- package/dist/types/global-account/client-manager.d.ts +7 -5
- package/dist/types/global-account/react/components/B3Provider/B3ConfigProvider.d.ts +11 -0
- package/dist/types/global-account/react/components/B3Provider/B3Provider.d.ts +12 -2
- package/dist/types/global-account/react/components/B3Provider/RelayKitProviderWrapper.d.ts +1 -2
- package/dist/types/global-account/react/components/SignInWithB3/utils/signInUtils.d.ts +3 -2
- package/dist/types/global-account/react/components/index.d.ts +1 -1
- package/dist/types/global-account/react/hooks/index.d.ts +2 -3
- package/dist/types/global-account/react/hooks/useAuth.d.ts +5 -4
- package/dist/types/global-account/react/hooks/useAuthentication.d.ts +3 -2
- package/dist/types/global-account/react/hooks/useBetterAuth.d.ts +1657 -22
- package/dist/types/global-account/react/hooks/useClient.d.ts +3 -3
- package/dist/types/global-account/react/hooks/useFirstEOA.d.ts +4 -7666
- package/dist/types/global-account/react/hooks/usePortfolioBalance.d.ts +15 -0
- package/dist/types/global-account/react/hooks/usePortfolioCollectibles.d.ts +12 -0
- package/dist/types/global-account/react/hooks/useSiwe.d.ts +1 -1
- package/dist/types/global-account/react/hooks/useSiwe.native.d.ts +1 -1
- package/dist/types/global-account/react/hooks/useTWAuth.d.ts +1 -1
- package/dist/types/global-account/react/hooks/useUnifiedChainSwitchAndExecute.d.ts +1 -0
- package/dist/types/global-account/react/stores/useModalStore.d.ts +14 -2
- package/dist/types/global-account/types/b3-api.types.d.ts +5 -0
- package/dist/types/global-account/types/feature-flags.d.ts +5 -5
- package/dist/types/shared/constants/chains/b3Chain.d.ts +30 -54
- package/dist/types/shared/constants/chains/supported.d.ts +1 -49
- package/dist/types/shared/constants/index.d.ts +4 -0
- package/dist/types/shared/utils/chain-transformers.d.ts +4 -4
- package/dist/types/shared/utils/upload.d.ts +9 -0
- package/dist/types/shared/utils/zerionPositions.d.ts +96 -0
- package/node_modules/@b3/chain-registry/chains.json +1225 -0
- package/node_modules/@b3/chain-registry/dist/chains.json +1225 -0
- package/node_modules/@b3/chain-registry/dist/index.cjs +1676 -0
- package/node_modules/@b3/chain-registry/dist/index.d.cts +195 -0
- package/node_modules/@b3/chain-registry/dist/index.d.ts +195 -0
- package/node_modules/@b3/chain-registry/dist/index.mjs +1604 -0
- package/node_modules/@b3/chain-registry/dist/src/index.d.ts +193 -0
- package/node_modules/@b3/chain-registry/dist/src/index.js +408 -0
- package/node_modules/@b3/chain-registry/package.json +66 -0
- package/node_modules/@b3/chain-registry/src/index.test.ts +432 -0
- package/node_modules/@b3/chain-registry/src/index.ts +672 -0
- package/package.json +81 -30
- package/src/anyspend/README.md +2 -2
- package/src/anyspend/constants/rpc.ts +5 -2
- package/src/anyspend/docs/components.md +6 -6
- package/src/anyspend/docs/contributing.md +1 -1
- package/src/anyspend/docs/hooks.md +3 -3
- package/src/anyspend/docs/installation.md +2 -2
- package/src/anyspend/react/components/AnySpend.tsx +163 -47
- package/src/anyspend/react/components/AnySpendCustomExactIn.tsx +10 -11
- package/src/anyspend/react/components/AnySpendDeposit.tsx +130 -31
- package/src/anyspend/react/components/AnySpendStakeB3.tsx +55 -14
- package/src/anyspend/react/components/AnySpendStakeB3ExactIn.tsx +55 -11
- package/src/anyspend/react/components/QRDeposit.tsx +101 -22
- package/src/anyspend/react/components/__tests__/QRDeposit.test.tsx +331 -0
- package/src/anyspend/react/components/checkout/CryptoPayPanel.tsx +38 -16
- package/src/anyspend/react/components/common/PureTransferView.tsx +212 -0
- package/src/anyspend/react/components/common/TokenBalance.tsx +10 -7
- package/src/anyspend/react/hooks/useAnyspendQuote.ts +13 -13
- package/src/anyspend/react/hooks/useCreateDepositFirstOrder.ts +4 -4
- package/src/anyspend/services/gas.test.ts +95 -18
- package/src/anyspend/types/api_req_res.ts +10 -5
- package/src/anyspend/utils/__tests__/address.test.ts +39 -0
- package/src/anyspend/utils/__tests__/deprecatedChains.test.ts +44 -0
- package/src/anyspend/utils/__tests__/toRegistryChainId.test.ts +17 -0
- package/src/anyspend/utils/address.ts +8 -6
- package/src/anyspend/utils/chain.ts +79 -3
- package/src/anyspend/utils/token.ts +14 -0
- package/src/app.shared.ts +21 -1
- package/src/global-account/app.native.ts +5 -1
- package/src/global-account/better-auth-client.ts +30 -4
- package/src/global-account/bsmnt.native.ts +5 -1
- package/src/global-account/bsmnt.ts +9 -2
- package/src/global-account/client-manager.ts +74 -9
- package/src/global-account/react/components/AvatarEditor/AvatarEditor.tsx +6 -11
- package/src/global-account/react/components/B3Provider/B3ConfigProvider.tsx +12 -0
- package/src/global-account/react/components/B3Provider/B3Provider.tsx +40 -4
- package/src/global-account/react/components/B3Provider/BetterAuthProvider.tsx +51 -5
- package/src/global-account/react/components/B3Provider/RelayKitProviderWrapper.tsx +11 -11
- package/src/global-account/react/components/ManageAccount/ContentTokens.tsx +50 -21
- package/src/global-account/react/components/ManageAccount/NFTContent.tsx +5 -3
- package/src/global-account/react/components/ManageAccount/ProfileSection.tsx +10 -6
- package/src/global-account/react/components/ManageAccount/SettingsProfileCard.tsx +1 -1
- package/src/global-account/react/components/ManageAccount/TokenContent.tsx +22 -9
- package/src/global-account/react/components/Send/Send.tsx +39 -15
- package/src/global-account/react/components/SignInWithB3/BetterAuthSignIn.tsx +12 -1
- package/src/global-account/react/components/SignInWithB3/SignInWithB3Flow.tsx +1 -4
- package/src/global-account/react/components/SignInWithB3/components/AuthButton.tsx +9 -1
- package/src/global-account/react/components/SignInWithB3/steps/LoginStepBetterAuth.tsx +1 -0
- package/src/global-account/react/components/SignInWithB3/utils/signInUtils.ts +4 -4
- package/src/global-account/react/components/index.ts +1 -1
- package/src/global-account/react/components/ui/button.tsx +1 -2
- package/src/global-account/react/hooks/__tests__/useUnifiedChainSwitchAndExecute.test.tsx +156 -0
- package/src/global-account/react/hooks/index.ts +2 -3
- package/src/global-account/react/hooks/useAuth.ts +5 -4
- package/src/global-account/react/hooks/useAuthentication.ts +5 -4
- package/src/global-account/react/hooks/useBetterAuth.ts +10 -10
- package/src/global-account/react/hooks/useClient.ts +11 -2
- package/src/global-account/react/hooks/useFirstEOA.tsx +9 -2
- package/src/global-account/react/hooks/useNativeBalance.tsx +1 -1
- package/src/global-account/react/hooks/usePortfolioBalance.ts +89 -0
- package/src/global-account/react/hooks/usePortfolioCollectibles.ts +212 -0
- package/src/global-account/react/hooks/useSiwe.native.tsx +1 -1
- package/src/global-account/react/hooks/useSiwe.tsx +1 -1
- package/src/global-account/react/hooks/useTWAuth.tsx +1 -1
- package/src/global-account/react/hooks/useUnifiedChainSwitchAndExecute.ts +47 -31
- package/src/global-account/react/stores/useModalStore.ts +14 -2
- package/src/global-account/types/b3-api.types.ts +5 -1
- package/src/notifications/services/api.ts +1 -0
- package/src/shared/constants/chains/b3Chain.ts +4 -43
- package/src/shared/constants/chains/supported.ts +9 -48
- package/src/shared/constants/index.ts +8 -0
- package/src/shared/react/hooks/__tests__/useCurrencyConversion.test.ts +54 -43
- package/src/shared/utils/__tests__/zerionPositions.test.ts +248 -0
- package/src/shared/utils/chain-transformers.ts +41 -39
- package/src/shared/utils/thirdweb-insights.ts +2 -2
- package/src/shared/utils/upload.ts +48 -0
- package/src/shared/utils/zerionPositions.ts +247 -0
- package/src/styles/index.css +27 -0
- package/dist/cjs/global-account/react/components/SignInWithB3/SignInWithB3Privy.d.ts +0 -10
- package/dist/cjs/global-account/react/components/SignInWithB3/SignInWithB3Privy.js +0 -46
- package/dist/cjs/global-account/react/hooks/useHandleConnectWithPrivy.d.ts +0 -11
- package/dist/cjs/global-account/react/hooks/useHandleConnectWithPrivy.js +0 -70
- package/dist/cjs/global-account/react/hooks/useSimBalance.d.ts +0 -59
- package/dist/cjs/global-account/react/hooks/useSimBalance.js +0 -98
- package/dist/cjs/global-account/react/hooks/useSimCollectibles.d.ts +0 -45
- package/dist/cjs/global-account/react/hooks/useSimCollectibles.js +0 -190
- package/dist/cjs/global-account/react/utils/simdune.d.ts +0 -7
- package/dist/cjs/global-account/react/utils/simdune.js +0 -21
- package/dist/cjs/global-account/types/chain-networks.d.ts +0 -44
- package/dist/cjs/global-account/types/chain-networks.js +0 -48
- package/dist/cjs/shared/generated/chain-networks.json +0 -684
- package/dist/esm/global-account/react/components/SignInWithB3/SignInWithB3Privy.d.ts +0 -10
- package/dist/esm/global-account/react/components/SignInWithB3/SignInWithB3Privy.js +0 -43
- package/dist/esm/global-account/react/hooks/useHandleConnectWithPrivy.d.ts +0 -11
- package/dist/esm/global-account/react/hooks/useHandleConnectWithPrivy.js +0 -67
- package/dist/esm/global-account/react/hooks/useSimBalance.d.ts +0 -59
- package/dist/esm/global-account/react/hooks/useSimBalance.js +0 -93
- package/dist/esm/global-account/react/hooks/useSimCollectibles.d.ts +0 -45
- package/dist/esm/global-account/react/hooks/useSimCollectibles.js +0 -187
- package/dist/esm/global-account/react/utils/simdune.d.ts +0 -7
- package/dist/esm/global-account/react/utils/simdune.js +0 -17
- package/dist/esm/global-account/types/chain-networks.d.ts +0 -44
- package/dist/esm/global-account/types/chain-networks.js +0 -45
- package/dist/esm/shared/generated/chain-networks.json +0 -684
- package/dist/types/global-account/react/components/SignInWithB3/SignInWithB3Privy.d.ts +0 -10
- package/dist/types/global-account/react/hooks/useHandleConnectWithPrivy.d.ts +0 -11
- package/dist/types/global-account/react/hooks/useSimBalance.d.ts +0 -59
- package/dist/types/global-account/react/hooks/useSimCollectibles.d.ts +0 -45
- package/dist/types/global-account/react/utils/simdune.d.ts +0 -7
- package/dist/types/global-account/types/chain-networks.d.ts +0 -44
- package/src/global-account/react/components/SignInWithB3/SignInWithB3Privy.tsx +0 -63
- package/src/global-account/react/hooks/useHandleConnectWithPrivy.tsx +0 -79
- package/src/global-account/react/hooks/useSimBalance.ts +0 -164
- package/src/global-account/react/hooks/useSimCollectibles.ts +0 -238
- package/src/global-account/react/utils/simdune.ts +0 -20
- package/src/global-account/types/chain-networks.ts +0 -54
- package/src/shared/generated/chain-networks.json +0 -684
|
@@ -11,7 +11,7 @@ import { cn } from "@b3dotfun/sdk/shared/utils/cn";
|
|
|
11
11
|
import { TokenSelector } from "@relayprotocol/relay-kit-ui";
|
|
12
12
|
import { Check, ChevronsUpDown, Copy, Loader2 } from "lucide-react";
|
|
13
13
|
import { QRCodeSVG } from "qrcode.react";
|
|
14
|
-
import { useEffect, useRef, useState } from "react";
|
|
14
|
+
import { useCallback, useEffect, useRef, useState } from "react";
|
|
15
15
|
import { useAnyspendOrderAndTransactions } from "../hooks/useAnyspendOrderAndTransactions";
|
|
16
16
|
import { useCreateDepositFirstOrder } from "../hooks/useCreateDepositFirstOrder";
|
|
17
17
|
import { useOnOrderSuccess } from "../hooks/useOnOrderSuccess";
|
|
@@ -36,6 +36,22 @@ export interface QRDepositProps {
|
|
|
36
36
|
destinationToken: components["schemas"]["Token"];
|
|
37
37
|
/** The destination chain ID */
|
|
38
38
|
destinationChainId: number;
|
|
39
|
+
/**
|
|
40
|
+
* Human-formatted destination amount (e.g. "9.365547"), shown as an APPROXIMATE
|
|
41
|
+
* target in swap mode only. The QR deposit path accepts an arbitrary sent amount,
|
|
42
|
+
* so this is never a guaranteed receive figure — the UI frames it as "any amount
|
|
43
|
+
* works". Omitted when no fixed amount is set or the destination decimals are
|
|
44
|
+
* unresolved (to avoid a mis-scaled number). Ignored in pure-transfer mode.
|
|
45
|
+
*/
|
|
46
|
+
destinationAmountDisplay?: string;
|
|
47
|
+
/**
|
|
48
|
+
* When true, the deposit is a PURE TRANSFER: the destination token/chain mirror
|
|
49
|
+
* the user's currently selected source token/chain, so the exact token the user
|
|
50
|
+
* sends lands in their wallet on the same chain — no swap/bridge order is created.
|
|
51
|
+
* The `destinationToken`/`destinationChainId` props are then used only as the
|
|
52
|
+
* initial source selection (they must be fully resolved before mount). Defaults to false.
|
|
53
|
+
*/
|
|
54
|
+
pureTransferOnly?: boolean;
|
|
39
55
|
/** Creator address (optional) */
|
|
40
56
|
creatorAddress?: string;
|
|
41
57
|
/** Contract config for custom execution after deposit */
|
|
@@ -46,8 +62,11 @@ export interface QRDepositProps {
|
|
|
46
62
|
onClose?: () => void;
|
|
47
63
|
/** Callback when order is created successfully */
|
|
48
64
|
onOrderCreated?: (orderId: string) => void;
|
|
49
|
-
/**
|
|
50
|
-
|
|
65
|
+
/**
|
|
66
|
+
* Callback when deposit is completed. The argument carries the deposited amount string
|
|
67
|
+
* (e.g. "200.00") on the pure-transfer path, or the order tx hash otherwise.
|
|
68
|
+
*/
|
|
69
|
+
onSuccess?: (amountOrTxHash?: string) => void;
|
|
51
70
|
/** Custom classes for styling */
|
|
52
71
|
classes?: QRDepositClasses;
|
|
53
72
|
}
|
|
@@ -85,6 +104,8 @@ export function QRDeposit({
|
|
|
85
104
|
sourceChainId: sourceChainIdProp,
|
|
86
105
|
destinationToken,
|
|
87
106
|
destinationChainId,
|
|
107
|
+
destinationAmountDisplay,
|
|
108
|
+
pureTransferOnly = false,
|
|
88
109
|
creatorAddress,
|
|
89
110
|
depositContractConfig,
|
|
90
111
|
onBack,
|
|
@@ -99,31 +120,45 @@ export function QRDeposit({
|
|
|
99
120
|
const orderCreatedRef = useRef(false);
|
|
100
121
|
const [transferResult, setTransferResult] = useState<TransferResult | null>(null);
|
|
101
122
|
|
|
102
|
-
// Source token/chain as state (can be changed by user)
|
|
103
|
-
|
|
123
|
+
// Source token/chain as state (can be changed by user).
|
|
124
|
+
// In pure-transfer mode the initial source is the passed destination (caller sets
|
|
125
|
+
// it to the desired default funding token), so the deposit mirrors the user's selection.
|
|
126
|
+
const [sourceChainId, setSourceChainId] = useState(
|
|
127
|
+
sourceChainIdProp ?? (pureTransferOnly ? destinationChainId : 8453),
|
|
128
|
+
);
|
|
104
129
|
const [sourceToken, setSourceToken] = useState<components["schemas"]["Token"]>(
|
|
105
|
-
sourceTokenProp ?? DEFAULT_ETH_ON_BASE,
|
|
130
|
+
sourceTokenProp ?? (pureTransferOnly ? destinationToken : DEFAULT_ETH_ON_BASE),
|
|
106
131
|
);
|
|
107
132
|
|
|
133
|
+
// In pure-transfer mode the effective destination mirrors the selected source,
|
|
134
|
+
// forcing isPureTransfer = true (no swap/bridge order is created).
|
|
135
|
+
const effectiveDestinationToken = pureTransferOnly ? sourceToken : destinationToken;
|
|
136
|
+
const effectiveDestinationChainId = pureTransferOnly ? sourceChainId : destinationChainId;
|
|
137
|
+
|
|
108
138
|
// Check if this is a pure transfer (same chain and token)
|
|
109
139
|
const isPureTransfer = isSameChainAndToken(
|
|
110
140
|
sourceChainId,
|
|
111
141
|
sourceToken.address,
|
|
112
|
-
|
|
113
|
-
|
|
142
|
+
effectiveDestinationChainId,
|
|
143
|
+
effectiveDestinationToken.address,
|
|
144
|
+
);
|
|
145
|
+
|
|
146
|
+
const handleTransferDetected = useCallback(
|
|
147
|
+
(result: TransferResult) => {
|
|
148
|
+
setTransferResult(result);
|
|
149
|
+
onSuccess?.(result.formattedAmount);
|
|
150
|
+
},
|
|
151
|
+
[onSuccess],
|
|
114
152
|
);
|
|
115
153
|
|
|
116
154
|
// Watch for pure transfers (same chain and token)
|
|
117
|
-
const { isWatching: isWatchingTransfer } = useWatchTransfer({
|
|
155
|
+
const { isWatching: isWatchingTransfer, reset: resetWatchTransfer } = useWatchTransfer({
|
|
118
156
|
address: recipientAddress,
|
|
119
157
|
chainId: sourceChainId,
|
|
120
158
|
tokenAddress: sourceToken.address,
|
|
121
159
|
tokenDecimals: sourceToken.decimals,
|
|
122
160
|
enabled: isPureTransfer && !transferResult,
|
|
123
|
-
onTransferDetected:
|
|
124
|
-
setTransferResult(result);
|
|
125
|
-
onSuccess?.();
|
|
126
|
-
},
|
|
161
|
+
onTransferDetected: handleTransferDetected,
|
|
127
162
|
});
|
|
128
163
|
|
|
129
164
|
// Handle token selection from TokenSelector
|
|
@@ -142,6 +177,8 @@ export function QRDeposit({
|
|
|
142
177
|
setGlobalAddress(undefined);
|
|
143
178
|
orderCreatedRef.current = false;
|
|
144
179
|
setTransferResult(null);
|
|
180
|
+
// Reset the balance watcher baseline so the new token isn't compared against the old token's balance
|
|
181
|
+
resetWatchTransfer();
|
|
145
182
|
|
|
146
183
|
// Update token and chain
|
|
147
184
|
setSourceChainId(newToken.chainId);
|
|
@@ -176,18 +213,18 @@ export function QRDeposit({
|
|
|
176
213
|
createOrder({
|
|
177
214
|
recipientAddress,
|
|
178
215
|
srcChain: sourceChainId,
|
|
179
|
-
dstChain:
|
|
216
|
+
dstChain: effectiveDestinationChainId,
|
|
180
217
|
srcToken: sourceToken,
|
|
181
|
-
dstToken:
|
|
218
|
+
dstToken: effectiveDestinationToken,
|
|
182
219
|
creatorAddress,
|
|
183
220
|
contractConfig: depositContractConfig,
|
|
184
221
|
});
|
|
185
222
|
}, [
|
|
186
223
|
recipientAddress,
|
|
187
224
|
sourceChainId,
|
|
188
|
-
|
|
225
|
+
effectiveDestinationChainId,
|
|
189
226
|
sourceToken,
|
|
190
|
-
|
|
227
|
+
effectiveDestinationToken,
|
|
191
228
|
creatorAddress,
|
|
192
229
|
depositContractConfig,
|
|
193
230
|
createOrder,
|
|
@@ -382,6 +419,32 @@ export function QRDeposit({
|
|
|
382
419
|
/>
|
|
383
420
|
</div>
|
|
384
421
|
|
|
422
|
+
{/* Receive (swap mode only) — makes the conversion explicit: what the sent token
|
|
423
|
+
becomes and on which chain. Gated on the computed isPureTransfer (not the static
|
|
424
|
+
prop) so a runtime source change back to the same token correctly hides it. */}
|
|
425
|
+
{!isPureTransfer && (
|
|
426
|
+
<div className="anyspend-qr-receive flex flex-col gap-1.5">
|
|
427
|
+
<label className="anyspend-qr-receive-label text-as-secondary text-sm">Receive</label>
|
|
428
|
+
<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">
|
|
429
|
+
{effectiveDestinationToken.metadata?.logoURI ? (
|
|
430
|
+
<ChainTokenIcon
|
|
431
|
+
chainUrl={ALL_CHAINS[effectiveDestinationChainId]?.logoUrl}
|
|
432
|
+
tokenUrl={effectiveDestinationToken.metadata.logoURI}
|
|
433
|
+
className="h-8 min-h-8 w-8 min-w-8"
|
|
434
|
+
/>
|
|
435
|
+
) : (
|
|
436
|
+
<div className="h-8 w-8 rounded-full bg-gray-700" />
|
|
437
|
+
)}
|
|
438
|
+
<div className="flex flex-col items-start gap-0">
|
|
439
|
+
<div className="text-as-primary font-semibold">{effectiveDestinationToken.symbol || "Token"}</div>
|
|
440
|
+
<div className="text-as-primary/70 text-xs">
|
|
441
|
+
{ALL_CHAINS[effectiveDestinationChainId]?.name ?? "Unknown"}
|
|
442
|
+
</div>
|
|
443
|
+
</div>
|
|
444
|
+
</div>
|
|
445
|
+
</div>
|
|
446
|
+
)}
|
|
447
|
+
|
|
385
448
|
{/* QR Code and Address - horizontal layout */}
|
|
386
449
|
<div
|
|
387
450
|
className={
|
|
@@ -425,11 +488,27 @@ export function QRDeposit({
|
|
|
425
488
|
</div>
|
|
426
489
|
|
|
427
490
|
{/* Warnings */}
|
|
428
|
-
<ChainWarningText chainId={
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
491
|
+
<ChainWarningText chainId={effectiveDestinationChainId} />
|
|
492
|
+
{isPureTransfer ? (
|
|
493
|
+
<WarningText>
|
|
494
|
+
Only send {sourceToken.symbol} on {ALL_CHAINS[sourceChainId]?.name ?? "the specified chain"}. Other tokens
|
|
495
|
+
will not be converted.
|
|
496
|
+
</WarningText>
|
|
497
|
+
) : (
|
|
498
|
+
<>
|
|
499
|
+
<WarningText>
|
|
500
|
+
Only send {sourceToken.symbol} on {ALL_CHAINS[sourceChainId]?.name ?? "the specified chain"} to this
|
|
501
|
+
address — it will be converted to {effectiveDestinationToken.symbol || "the destination token"} on{" "}
|
|
502
|
+
{ALL_CHAINS[effectiveDestinationChainId]?.name ?? "the destination chain"}.
|
|
503
|
+
</WarningText>
|
|
504
|
+
{destinationAmountDisplay && (
|
|
505
|
+
<p className="anyspend-qr-amount-hint text-as-secondary text-xs">
|
|
506
|
+
Target ≈ {destinationAmountDisplay} {effectiveDestinationToken.symbol || "tokens"}. Any amount of{" "}
|
|
507
|
+
{sourceToken.symbol || "tokens"} works — you'll receive whatever your deposit converts to.
|
|
508
|
+
</p>
|
|
509
|
+
)}
|
|
510
|
+
</>
|
|
511
|
+
)}
|
|
433
512
|
|
|
434
513
|
{/* Watching indicator for pure transfers */}
|
|
435
514
|
{isPureTransfer && isWatchingTransfer && (
|
|
@@ -0,0 +1,331 @@
|
|
|
1
|
+
import { RELAY_SOLANA_MAINNET_CHAIN_ID, USDC_BASE } from "@b3dotfun/sdk/anyspend";
|
|
2
|
+
import { fireEvent, render, screen } from "@testing-library/react";
|
|
3
|
+
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Deterministic component test for the `pureTransferOnly` "Fund Wallet" behavior.
|
|
7
|
+
*
|
|
8
|
+
* When `pureTransferOnly` is true, the destination token MIRRORS the user-selected
|
|
9
|
+
* source token, so funding is always a same-chain/same-token PURE TRANSFER:
|
|
10
|
+
* - NO `deposit_first` swap order is created (the order-creation effect early-returns
|
|
11
|
+
* on `isPureTransfer`), so `createOrder` is never called.
|
|
12
|
+
* - The QR/deposit address is the recipient's OWN wallet address (not a global/order
|
|
13
|
+
* address minted by AnySpend).
|
|
14
|
+
* - `useWatchTransfer` watches the user's wallet for the EXACT token they selected.
|
|
15
|
+
*
|
|
16
|
+
* This guards the bug where "Fund Wallet" with USDC delivered ETH instead.
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
// --- Spies / captured args observable across the test file ---
|
|
20
|
+
|
|
21
|
+
// createOrder spy returned by useCreateDepositFirstOrder.
|
|
22
|
+
const createOrderSpy = vi.fn();
|
|
23
|
+
|
|
24
|
+
// reset spy returned by useWatchTransfer — QRDeposit calls reset() on token switch to
|
|
25
|
+
// clear the stale balance baseline (see Test B).
|
|
26
|
+
const resetSpy = vi.fn();
|
|
27
|
+
|
|
28
|
+
// Captures the most recent props passed to useWatchTransfer so we can assert which
|
|
29
|
+
// token/decimals/address the pure-transfer path is watching.
|
|
30
|
+
let watchTransferArgs: any;
|
|
31
|
+
|
|
32
|
+
// Holds the `setToken` callback handed to the mocked Relay TokenSelector so a test
|
|
33
|
+
// can simulate the user switching the source token.
|
|
34
|
+
let capturedSetToken: ((token: any) => void) | undefined;
|
|
35
|
+
|
|
36
|
+
// Allows Test D to flip useTokenData's return (null = API miss) for the
|
|
37
|
+
// AnySpendDeposit-level decimals-invariant assertion.
|
|
38
|
+
const tokenDataState: { data: any; isLoading: boolean } = { data: null, isLoading: false };
|
|
39
|
+
|
|
40
|
+
// --- Mocks ---
|
|
41
|
+
|
|
42
|
+
// Mock the four hooks QRDeposit imports (relative paths from the component file).
|
|
43
|
+
vi.mock("../../hooks/useCreateDepositFirstOrder", () => ({
|
|
44
|
+
useCreateDepositFirstOrder: () => ({ createOrder: createOrderSpy, isCreatingOrder: false }),
|
|
45
|
+
}));
|
|
46
|
+
|
|
47
|
+
vi.mock("../../hooks/useAnyspendOrderAndTransactions", () => ({
|
|
48
|
+
useAnyspendOrderAndTransactions: () => ({ orderAndTransactions: undefined }),
|
|
49
|
+
}));
|
|
50
|
+
|
|
51
|
+
vi.mock("../../hooks/useWatchTransfer", () => ({
|
|
52
|
+
useWatchTransfer: (props: any) => {
|
|
53
|
+
watchTransferArgs = props;
|
|
54
|
+
return { isWatching: true, reset: resetSpy };
|
|
55
|
+
},
|
|
56
|
+
}));
|
|
57
|
+
|
|
58
|
+
vi.mock("../../hooks/useOnOrderSuccess", () => ({
|
|
59
|
+
useOnOrderSuccess: () => undefined,
|
|
60
|
+
}));
|
|
61
|
+
|
|
62
|
+
// Mock the Relay TokenSelector: render a button that, when clicked, invokes the passed
|
|
63
|
+
// `setToken` with a chosen token, simulating the user switching the source token. Also
|
|
64
|
+
// render the provided `trigger` so the rest of the component tree still mounts.
|
|
65
|
+
vi.mock("@relayprotocol/relay-kit-ui", () => ({
|
|
66
|
+
TokenSelector: ({ setToken, trigger }: any) => {
|
|
67
|
+
capturedSetToken = setToken;
|
|
68
|
+
return (
|
|
69
|
+
<div data-testid="token-selector">
|
|
70
|
+
{trigger}
|
|
71
|
+
<button data-testid="switch-token" onClick={() => setToken(SWITCHED_ETH_ON_BASE)} />
|
|
72
|
+
</div>
|
|
73
|
+
);
|
|
74
|
+
},
|
|
75
|
+
}));
|
|
76
|
+
|
|
77
|
+
vi.mock("@stripe/stripe-js", () => ({
|
|
78
|
+
loadStripe: vi.fn(() => Promise.resolve(null)),
|
|
79
|
+
}));
|
|
80
|
+
|
|
81
|
+
// Spread the real global-account/react (Button, Badge, etc. are needed by transitively
|
|
82
|
+
// imported sub-components and render fine under happy-dom). Override only `toast` so the
|
|
83
|
+
// error path doesn't depend on a toast provider.
|
|
84
|
+
vi.mock("@b3dotfun/sdk/global-account/react", async importOriginal => {
|
|
85
|
+
const actual = await importOriginal<any>();
|
|
86
|
+
return { ...actual, toast: { error: vi.fn(), success: vi.fn() } };
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
// Mock the wallet/balance/token hooks at their SOURCE modules (the barrel re-exports
|
|
90
|
+
// these, so the override binds reliably). This lets AnySpendDeposit (Test D) render
|
|
91
|
+
// without a ThirdwebProvider / wallet context and keeps the token-data fetch deterministic.
|
|
92
|
+
vi.mock("@b3dotfun/sdk/global-account/react/hooks/useAccountWallet", () => ({
|
|
93
|
+
useAccountWallet: () => ({ connectedEOAWallet: undefined }),
|
|
94
|
+
}));
|
|
95
|
+
|
|
96
|
+
vi.mock("@b3dotfun/sdk/global-account/react/hooks/usePortfolioBalance", () => ({
|
|
97
|
+
usePortfolioBalance: () => ({ data: undefined, isLoading: false, isError: false }),
|
|
98
|
+
usePortfolioTokenBalance: () => ({ data: undefined, isLoading: false, isError: false }),
|
|
99
|
+
}));
|
|
100
|
+
|
|
101
|
+
vi.mock("@b3dotfun/sdk/global-account/react/hooks/useTokenData", () => ({
|
|
102
|
+
useTokenData: () => tokenDataState,
|
|
103
|
+
}));
|
|
104
|
+
|
|
105
|
+
// --- Fixtures ---
|
|
106
|
+
|
|
107
|
+
const RECIPIENT = "0x1111111111111111111111111111111111111111";
|
|
108
|
+
|
|
109
|
+
// A DIFFERENT token than USDC for the "switch source token" test: native ETH on Base.
|
|
110
|
+
const SWITCHED_ETH_ON_BASE = {
|
|
111
|
+
chainId: 8453,
|
|
112
|
+
address: "0x0000000000000000000000000000000000000000",
|
|
113
|
+
symbol: "ETH",
|
|
114
|
+
name: "Ethereum",
|
|
115
|
+
decimals: 18,
|
|
116
|
+
logoURI: "https://assets.relay.link/icons/1/light.png",
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
// Imported lazily so module-level mocks are registered before the component graph loads.
|
|
120
|
+
async function loadQRDeposit() {
|
|
121
|
+
const mod = await import("../QRDeposit");
|
|
122
|
+
return mod.QRDeposit;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
async function loadAnySpendDeposit() {
|
|
126
|
+
const mod = await import("../AnySpendDeposit");
|
|
127
|
+
return mod.AnySpendDeposit;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
beforeEach(() => {
|
|
131
|
+
watchTransferArgs = undefined;
|
|
132
|
+
capturedSetToken = undefined;
|
|
133
|
+
tokenDataState.data = null;
|
|
134
|
+
tokenDataState.isLoading = false;
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
afterEach(() => {
|
|
138
|
+
vi.clearAllMocks();
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
describe("QRDeposit pureTransferOnly (Fund Wallet)", () => {
|
|
142
|
+
it("Test A — pure transfer creates NO order and uses the wallet's own address", async () => {
|
|
143
|
+
const QRDeposit = await loadQRDeposit();
|
|
144
|
+
|
|
145
|
+
render(
|
|
146
|
+
<QRDeposit
|
|
147
|
+
pureTransferOnly
|
|
148
|
+
recipientAddress={RECIPIENT}
|
|
149
|
+
destinationToken={USDC_BASE}
|
|
150
|
+
destinationChainId={8453}
|
|
151
|
+
/>,
|
|
152
|
+
);
|
|
153
|
+
|
|
154
|
+
// The whole point: no swap/bridge order is created in pure-transfer mode.
|
|
155
|
+
expect(createOrderSpy).not.toHaveBeenCalled();
|
|
156
|
+
|
|
157
|
+
// It watches the recipient's OWN wallet for a direct incoming transfer, and is enabled.
|
|
158
|
+
expect(watchTransferArgs).toBeDefined();
|
|
159
|
+
expect(watchTransferArgs.address).toBe(RECIPIENT);
|
|
160
|
+
expect(watchTransferArgs.enabled).toBe(true);
|
|
161
|
+
|
|
162
|
+
// The mirror followed the initial selection: it watches for the EXACT funding token
|
|
163
|
+
// (Base USDC, 6 decimals) — NOT a generic 18-decimal fallback.
|
|
164
|
+
expect(watchTransferArgs.chainId).toBe(USDC_BASE.chainId);
|
|
165
|
+
expect(watchTransferArgs.tokenAddress).toBe(USDC_BASE.address);
|
|
166
|
+
expect(watchTransferArgs.tokenDecimals).toBe(6);
|
|
167
|
+
|
|
168
|
+
// The displayed deposit address is the recipient's own address, NOT a global/order address.
|
|
169
|
+
expect(screen.getByText(RECIPIENT)).toBeTruthy();
|
|
170
|
+
|
|
171
|
+
// Pure-transfer UI is unchanged: NO "Receive" row (there is no distinct destination),
|
|
172
|
+
// and the accurate "will not be converted" warning is kept verbatim.
|
|
173
|
+
expect(screen.queryByText("Receive")).toBeNull();
|
|
174
|
+
expect(screen.getByText(/Other tokens will not be converted/)).toBeTruthy();
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
it("Test B — switching the source token stays a pure transfer (no order; mirror follows selection)", async () => {
|
|
178
|
+
const QRDeposit = await loadQRDeposit();
|
|
179
|
+
|
|
180
|
+
render(
|
|
181
|
+
<QRDeposit
|
|
182
|
+
pureTransferOnly
|
|
183
|
+
recipientAddress={RECIPIENT}
|
|
184
|
+
destinationToken={USDC_BASE}
|
|
185
|
+
destinationChainId={8453}
|
|
186
|
+
/>,
|
|
187
|
+
);
|
|
188
|
+
|
|
189
|
+
// Sanity: still USDC before the switch.
|
|
190
|
+
expect(watchTransferArgs.tokenAddress).toBe(USDC_BASE.address);
|
|
191
|
+
expect(watchTransferArgs.tokenDecimals).toBe(6);
|
|
192
|
+
|
|
193
|
+
// User switches the source token to native ETH on Base via the (mocked) TokenSelector.
|
|
194
|
+
expect(capturedSetToken).toBeDefined();
|
|
195
|
+
fireEvent.click(screen.getByTestId("switch-token"));
|
|
196
|
+
|
|
197
|
+
// The balance watcher baseline is reset on token switch, so the new token isn't
|
|
198
|
+
// compared against the old token's (differently-scaled) balance.
|
|
199
|
+
expect(resetSpy).toHaveBeenCalled();
|
|
200
|
+
|
|
201
|
+
// Still a pure transfer: no order is ever created, even after switching tokens.
|
|
202
|
+
expect(createOrderSpy).not.toHaveBeenCalled();
|
|
203
|
+
|
|
204
|
+
// The mirror followed the new selection: now watching native ETH (18 decimals) on Base.
|
|
205
|
+
expect(watchTransferArgs.address).toBe(RECIPIENT);
|
|
206
|
+
expect(watchTransferArgs.enabled).toBe(true);
|
|
207
|
+
expect(watchTransferArgs.chainId).toBe(SWITCHED_ETH_ON_BASE.chainId);
|
|
208
|
+
expect(watchTransferArgs.tokenAddress).toBe(SWITCHED_ETH_ON_BASE.address);
|
|
209
|
+
expect(watchTransferArgs.tokenDecimals).toBe(18);
|
|
210
|
+
});
|
|
211
|
+
|
|
212
|
+
it("Test C — control: pureTransferOnly=false with source != destination DOES create an order", async () => {
|
|
213
|
+
const QRDeposit = await loadQRDeposit();
|
|
214
|
+
|
|
215
|
+
// No pureTransferOnly: source defaults to ETH-on-Base, which differs from the USDC dest,
|
|
216
|
+
// so this is a real swap and the normal deposit_first order path must run.
|
|
217
|
+
const { container } = render(
|
|
218
|
+
<QRDeposit
|
|
219
|
+
recipientAddress={RECIPIENT}
|
|
220
|
+
destinationToken={USDC_BASE}
|
|
221
|
+
destinationChainId={8453}
|
|
222
|
+
destinationAmountDisplay="9.365547"
|
|
223
|
+
/>,
|
|
224
|
+
);
|
|
225
|
+
|
|
226
|
+
// The flag is what gates the pure-transfer behavior: without it, an order IS created once.
|
|
227
|
+
expect(createOrderSpy).toHaveBeenCalledTimes(1);
|
|
228
|
+
|
|
229
|
+
// And it's created with the USDC destination token (the swap path is intact).
|
|
230
|
+
const orderArgs = createOrderSpy.mock.calls[0][0];
|
|
231
|
+
expect(orderArgs.recipientAddress).toBe(RECIPIENT);
|
|
232
|
+
expect(orderArgs.dstToken.address).toBe(USDC_BASE.address);
|
|
233
|
+
expect(orderArgs.dstToken.decimals).toBe(6);
|
|
234
|
+
// Source defaulted to native ETH on Base (the differing token that forces a swap).
|
|
235
|
+
expect(orderArgs.srcToken.address).toBe("0x0000000000000000000000000000000000000000");
|
|
236
|
+
|
|
237
|
+
// Swap-mode UX clarity: a read-only "Receive" row now discloses the destination token…
|
|
238
|
+
expect(screen.getByText("Receive")).toBeTruthy();
|
|
239
|
+
// …the misleading "will not be converted" copy is gone…
|
|
240
|
+
expect(screen.queryByText(/will not be converted/)).toBeNull();
|
|
241
|
+
// …the warning states the conversion explicitly, and the fixed amount shows as an
|
|
242
|
+
// approximate target (never a guaranteed receive figure).
|
|
243
|
+
expect(container.textContent).toContain("it will be converted to USDC on Base");
|
|
244
|
+
expect(container.textContent).toContain("Target ≈ 9.365547 USDC");
|
|
245
|
+
});
|
|
246
|
+
|
|
247
|
+
it("Test C3 — case-mutated Solana mints require a swap order", async () => {
|
|
248
|
+
const QRDeposit = await loadQRDeposit();
|
|
249
|
+
const wrappedSol = "So11111111111111111111111111111111111111112";
|
|
250
|
+
const sourceToken = {
|
|
251
|
+
chainId: RELAY_SOLANA_MAINNET_CHAIN_ID,
|
|
252
|
+
address: wrappedSol,
|
|
253
|
+
symbol: "wSOL",
|
|
254
|
+
name: "Wrapped SOL",
|
|
255
|
+
decimals: 9,
|
|
256
|
+
metadata: {},
|
|
257
|
+
};
|
|
258
|
+
const destinationToken = {
|
|
259
|
+
...sourceToken,
|
|
260
|
+
address: `s${wrappedSol.slice(1)}`,
|
|
261
|
+
symbol: "OTHER",
|
|
262
|
+
name: "Distinct Solana Mint",
|
|
263
|
+
};
|
|
264
|
+
|
|
265
|
+
render(
|
|
266
|
+
<QRDeposit
|
|
267
|
+
recipientAddress={RECIPIENT}
|
|
268
|
+
sourceToken={sourceToken}
|
|
269
|
+
sourceChainId={RELAY_SOLANA_MAINNET_CHAIN_ID}
|
|
270
|
+
destinationToken={destinationToken}
|
|
271
|
+
destinationChainId={RELAY_SOLANA_MAINNET_CHAIN_ID}
|
|
272
|
+
destinationAmountDisplay="1"
|
|
273
|
+
/>,
|
|
274
|
+
);
|
|
275
|
+
|
|
276
|
+
expect(createOrderSpy).toHaveBeenCalledTimes(1);
|
|
277
|
+
expect(createOrderSpy.mock.calls[0][0].dstToken.address).toBe(destinationToken.address);
|
|
278
|
+
expect(watchTransferArgs.enabled).toBe(false);
|
|
279
|
+
});
|
|
280
|
+
|
|
281
|
+
it("Test C2 — swap mode without a fixed amount shows the Receive row but no target hint", async () => {
|
|
282
|
+
const QRDeposit = await loadQRDeposit();
|
|
283
|
+
|
|
284
|
+
// Swap mode (source ETH-on-Base != USDC dest) but NO destinationAmountDisplay — the common
|
|
285
|
+
// open-ended funding case. The destination must still be disclosed, but there must be no
|
|
286
|
+
// dangling "Target ≈" line (and no blank amount).
|
|
287
|
+
const { container } = render(
|
|
288
|
+
<QRDeposit recipientAddress={RECIPIENT} destinationToken={USDC_BASE} destinationChainId={8453} />,
|
|
289
|
+
);
|
|
290
|
+
|
|
291
|
+
// Destination is still disclosed…
|
|
292
|
+
expect(screen.getByText("Receive")).toBeTruthy();
|
|
293
|
+
expect(container.textContent).toContain("it will be converted to USDC on Base");
|
|
294
|
+
// …but no amount hint is rendered when no amount is provided.
|
|
295
|
+
expect(container.textContent).not.toContain("Target ≈");
|
|
296
|
+
});
|
|
297
|
+
});
|
|
298
|
+
|
|
299
|
+
describe("AnySpendDeposit decimals invariant (KNOWN_FUNDING_TOKENS fallback)", () => {
|
|
300
|
+
it("Test D — Base USDC keeps decimals: 6 even when useTokenData returns null", async () => {
|
|
301
|
+
const AnySpendDeposit = await loadAnySpendDeposit();
|
|
302
|
+
|
|
303
|
+
// Simulate the API miss: useTokenData returns null. The KNOWN_FUNDING_TOKENS fallback
|
|
304
|
+
// in AnySpendDeposit must still resolve Base USDC to decimals: 6 (never the generic 18),
|
|
305
|
+
// and that fully-resolved token is forwarded to QRDeposit as the pure-transfer source.
|
|
306
|
+
tokenDataState.data = null;
|
|
307
|
+
tokenDataState.isLoading = false;
|
|
308
|
+
|
|
309
|
+
render(
|
|
310
|
+
<AnySpendDeposit
|
|
311
|
+
pureTransferOnly
|
|
312
|
+
recipientAddress={RECIPIENT}
|
|
313
|
+
destinationTokenAddress={USDC_BASE.address}
|
|
314
|
+
destinationTokenChainId={USDC_BASE.chainId}
|
|
315
|
+
/>,
|
|
316
|
+
);
|
|
317
|
+
|
|
318
|
+
// pureTransferOnly no longer auto-opens QR — AnySpendDeposit lands on the chooser
|
|
319
|
+
// (select-chain) screen first. Navigate into QR exactly like the user would, by
|
|
320
|
+
// clicking the "Deposit with QR Code" option.
|
|
321
|
+
fireEvent.click(screen.getByText("Deposit with QR Code"));
|
|
322
|
+
|
|
323
|
+
// Verified end-to-end through the REAL AnySpendDeposit -> REAL QRDeposit: the pure-transfer
|
|
324
|
+
// source mirrors the destination, so useWatchTransfer is called with USDC's 6 decimals.
|
|
325
|
+
expect(watchTransferArgs).toBeDefined();
|
|
326
|
+
expect(watchTransferArgs.tokenAddress).toBe(USDC_BASE.address);
|
|
327
|
+
expect(watchTransferArgs.tokenDecimals).toBe(6);
|
|
328
|
+
// No swap order in pure-transfer mode.
|
|
329
|
+
expect(createOrderSpy).not.toHaveBeenCalled();
|
|
330
|
+
});
|
|
331
|
+
});
|
|
@@ -6,13 +6,18 @@ import { useAnyspendCreateOrder } from "@b3dotfun/sdk/anyspend/react/hooks/useAn
|
|
|
6
6
|
import { useAnyspendOrderAndTransactions } from "@b3dotfun/sdk/anyspend/react/hooks/useAnyspendOrderAndTransactions";
|
|
7
7
|
import { useCreateDepositFirstOrder } from "@b3dotfun/sdk/anyspend/react/hooks/useCreateDepositFirstOrder";
|
|
8
8
|
import { useOnOrderSuccess } from "@b3dotfun/sdk/anyspend/react/hooks/useOnOrderSuccess";
|
|
9
|
-
import {
|
|
10
|
-
|
|
9
|
+
import {
|
|
10
|
+
ALL_CHAINS,
|
|
11
|
+
RELAY_SOLANA_MAINNET_CHAIN_ID,
|
|
12
|
+
getAvailableChainIds,
|
|
13
|
+
isSameChainAndToken,
|
|
14
|
+
} from "@b3dotfun/sdk/anyspend";
|
|
15
|
+
import { getPaymentUrl, toRegistryChainId } from "@b3dotfun/sdk/anyspend/utils/chain";
|
|
11
16
|
import { isNativeToken } from "@b3dotfun/sdk/anyspend/utils/token";
|
|
12
17
|
import {
|
|
13
18
|
useAccountWallet,
|
|
14
19
|
useIsMobile,
|
|
15
|
-
|
|
20
|
+
usePortfolioTokenBalance,
|
|
16
21
|
useTokenData,
|
|
17
22
|
useUnifiedChainSwitchAndExecute,
|
|
18
23
|
} from "@b3dotfun/sdk/global-account/react";
|
|
@@ -97,9 +102,13 @@ export function CryptoPayPanel({
|
|
|
97
102
|
}, [selectedSrcToken, dstTokenData, destinationTokenAddress, destinationTokenChainId]);
|
|
98
103
|
|
|
99
104
|
const isSameToken =
|
|
100
|
-
selectedSrcToken &&
|
|
101
|
-
|
|
102
|
-
|
|
105
|
+
selectedSrcToken !== null &&
|
|
106
|
+
isSameChainAndToken(
|
|
107
|
+
selectedSrcToken.chainId,
|
|
108
|
+
selectedSrcToken.address,
|
|
109
|
+
destinationTokenChainId,
|
|
110
|
+
destinationTokenAddress,
|
|
111
|
+
);
|
|
103
112
|
|
|
104
113
|
const { anyspendQuote, isLoadingAnyspendQuote } = useAnyspendQuote({
|
|
105
114
|
type: "swap",
|
|
@@ -116,13 +125,21 @@ export function CryptoPayPanel({
|
|
|
116
125
|
? "native"
|
|
117
126
|
: selectedSrcToken.address
|
|
118
127
|
: undefined;
|
|
119
|
-
|
|
128
|
+
// `selectedSrcChainId` is Relay-numbered; balance rows are keyed by the chain registry's id.
|
|
129
|
+
const { data: balanceRow, isError: isBalanceError } = usePortfolioTokenBalance(
|
|
130
|
+
effectiveAddress,
|
|
131
|
+
tokenAddress,
|
|
132
|
+
toRegistryChainId(selectedSrcChainId),
|
|
133
|
+
);
|
|
120
134
|
|
|
121
135
|
const balance = useMemo(() => {
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
136
|
+
if (!balanceRow?.amount) return { raw: BigInt(0), formatted: "0", decimals: 18 };
|
|
137
|
+
return {
|
|
138
|
+
raw: BigInt(balanceRow.amount),
|
|
139
|
+
formatted: formatTokenAmount(BigInt(balanceRow.amount), balanceRow.decimals),
|
|
140
|
+
decimals: balanceRow.decimals,
|
|
141
|
+
};
|
|
142
|
+
}, [balanceRow]);
|
|
126
143
|
|
|
127
144
|
const srcAmount = useMemo(() => {
|
|
128
145
|
if (isSameToken) return totalAmount;
|
|
@@ -134,7 +151,9 @@ export function CryptoPayPanel({
|
|
|
134
151
|
return formatTokenAmount(BigInt(srcAmount || "0"), selectedSrcToken.decimals || 18);
|
|
135
152
|
}, [srcAmount, selectedSrcToken]);
|
|
136
153
|
|
|
137
|
-
|
|
154
|
+
// A failed balance read must not masquerade as a shortfall: it would disable Pay and tell a
|
|
155
|
+
// funded user they are short. Unknown blocks auto-pay but leaves the manual path open.
|
|
156
|
+
const hasEnoughBalance = !isBalanceError && balance.raw >= BigInt(srcAmount || "0");
|
|
138
157
|
|
|
139
158
|
/* ------------------------------------------------------------------ */
|
|
140
159
|
/* Destination token object (shared by both flows) */
|
|
@@ -385,7 +404,8 @@ export function CryptoPayPanel({
|
|
|
385
404
|
|
|
386
405
|
const isLoading = isLoadingAnyspendQuote;
|
|
387
406
|
const isPending = isCreatingSwapOrder || isSendingDeposit || isWaitingForExecution;
|
|
388
|
-
const canPay =
|
|
407
|
+
const canPay =
|
|
408
|
+
connectedAddress && selectedSrcToken && (hasEnoughBalance || isBalanceError) && !isLoading && !isPending;
|
|
389
409
|
|
|
390
410
|
const chainName = ALL_CHAINS[selectedSrcChainId]?.name || "the specified chain";
|
|
391
411
|
const chainLogoUrl = ALL_CHAINS[selectedSrcChainId]?.logoUrl;
|
|
@@ -494,7 +514,7 @@ export function CryptoPayPanel({
|
|
|
494
514
|
</div>
|
|
495
515
|
</motion.div>
|
|
496
516
|
|
|
497
|
-
{/* ----
|
|
517
|
+
{/* ---- Balance warning ---- */}
|
|
498
518
|
<AnimatePresence>
|
|
499
519
|
{connectedAddress && selectedSrcToken && !hasEnoughBalance && !isLoading && (
|
|
500
520
|
<motion.p
|
|
@@ -503,9 +523,11 @@ export function CryptoPayPanel({
|
|
|
503
523
|
animate={{ opacity: 1, height: "auto" }}
|
|
504
524
|
exit={{ opacity: 0, height: 0 }}
|
|
505
525
|
transition={{ duration: 0.2, ease: "easeOut" }}
|
|
506
|
-
className=
|
|
526
|
+
className={`text-center text-sm ${isBalanceError ? "text-as-primary/50" : "text-red-500"}`}
|
|
507
527
|
>
|
|
508
|
-
|
|
528
|
+
{isBalanceError
|
|
529
|
+
? `Couldn't check your ${selectedSrcToken.symbol} balance`
|
|
530
|
+
: `Insufficient ${selectedSrcToken.symbol} balance`}
|
|
509
531
|
</motion.p>
|
|
510
532
|
)}
|
|
511
533
|
</AnimatePresence>
|