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

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 (29) hide show
  1. package/dist/cjs/anyspend/react/components/AnySpend.d.ts +2 -1
  2. package/dist/cjs/anyspend/react/components/AnySpend.js +81 -16
  3. package/dist/cjs/anyspend/react/components/AnySpendCustomExactIn.js +4 -1
  4. package/dist/cjs/anyspend/react/components/AnySpendDeposit.js +16 -2
  5. package/dist/cjs/anyspend/react/components/QRDeposit.d.ts +9 -1
  6. package/dist/cjs/anyspend/react/components/QRDeposit.js +3 -3
  7. package/dist/cjs/anyspend/react/components/common/PureTransferView.d.ts +30 -0
  8. package/dist/cjs/anyspend/react/components/common/PureTransferView.js +64 -0
  9. package/dist/cjs/global-account/client-manager.js +32 -0
  10. package/dist/esm/anyspend/react/components/AnySpend.d.ts +2 -1
  11. package/dist/esm/anyspend/react/components/AnySpend.js +81 -16
  12. package/dist/esm/anyspend/react/components/AnySpendCustomExactIn.js +4 -1
  13. package/dist/esm/anyspend/react/components/AnySpendDeposit.js +16 -2
  14. package/dist/esm/anyspend/react/components/QRDeposit.d.ts +9 -1
  15. package/dist/esm/anyspend/react/components/QRDeposit.js +4 -4
  16. package/dist/esm/anyspend/react/components/common/PureTransferView.d.ts +30 -0
  17. package/dist/esm/anyspend/react/components/common/PureTransferView.js +61 -0
  18. package/dist/esm/global-account/client-manager.js +32 -0
  19. package/dist/types/anyspend/react/components/AnySpend.d.ts +2 -1
  20. package/dist/types/anyspend/react/components/QRDeposit.d.ts +9 -1
  21. package/dist/types/anyspend/react/components/common/PureTransferView.d.ts +30 -0
  22. package/package.json +1 -1
  23. package/src/anyspend/react/components/AnySpend.tsx +108 -18
  24. package/src/anyspend/react/components/AnySpendCustomExactIn.tsx +5 -1
  25. package/src/anyspend/react/components/AnySpendDeposit.tsx +18 -1
  26. package/src/anyspend/react/components/QRDeposit.tsx +55 -4
  27. package/src/anyspend/react/components/__tests__/QRDeposit.test.tsx +39 -1
  28. package/src/anyspend/react/components/common/PureTransferView.tsx +212 -0
  29. package/src/global-account/client-manager.ts +33 -0
@@ -20,7 +20,8 @@ export declare enum PanelView {
20
20
  FEE_DETAIL = 9,
21
21
  DIRECT_TRANSFER_SUCCESS = 10,
22
22
  FIAT_KYC = 11,
23
- FIAT_AUTH = 12
23
+ FIAT_AUTH = 12,
24
+ PURE_TRANSFER_ADDRESS = 13
24
25
  }
25
26
  export declare function AnySpend(props: {
26
27
  mode?: "page" | "modal";
@@ -42,6 +42,7 @@ const LoginStep_1 = require("../../../global-account/react/components/SignInWith
42
42
  const PanelOnramp_1 = require("./common/PanelOnramp");
43
43
  const PanelOnrampPayment_1 = require("./common/PanelOnrampPayment");
44
44
  const PointsDetailPanel_1 = require("./common/PointsDetailPanel");
45
+ const PureTransferView_1 = require("./common/PureTransferView");
45
46
  const RecipientSelection_1 = require("./common/RecipientSelection");
46
47
  const TabSection_1 = require("./common/TabSection");
47
48
  const AnySpendCustomizationContext_1 = require("./context/AnySpendCustomizationContext");
@@ -61,6 +62,7 @@ var PanelView;
61
62
  PanelView[PanelView["DIRECT_TRANSFER_SUCCESS"] = 10] = "DIRECT_TRANSFER_SUCCESS";
62
63
  PanelView[PanelView["FIAT_KYC"] = 11] = "FIAT_KYC";
63
64
  PanelView[PanelView["FIAT_AUTH"] = 12] = "FIAT_AUTH";
65
+ PanelView[PanelView["PURE_TRANSFER_ADDRESS"] = 13] = "PURE_TRANSFER_ADDRESS";
64
66
  })(PanelView || (exports.PanelView = PanelView = {}));
65
67
  const ANYSPEND_RECIPIENTS_KEY = "anyspend_recipients";
66
68
  function AnySpend(props) {
@@ -453,7 +455,10 @@ function AnySpendInner({ sourceChainId, destinationTokenAddress, destinationToke
453
455
  walletAddress,
454
456
  globalAddress,
455
457
  });
456
- const recipientProfile = (0, react_2.useProfile)({ address: effectiveRecipientAddress, fresh: true });
458
+ const recipientProfile = (0, react_2.useProfile)({
459
+ address: effectiveRecipientAddress,
460
+ fresh: true,
461
+ });
457
462
  const recipientName = recipientProfile.data?.name;
458
463
  // Check token balance for crypto payments
459
464
  const effectiveBalanceAddress = senderAddress || connectedEOAWallet?.getAccount()?.address;
@@ -654,11 +659,26 @@ function AnySpendInner({ sourceChainId, destinationTokenAddress, destinationToke
654
659
  // For fiat tab, check srcAmountOnRamp; for crypto tab, check activeInputAmountInWei
655
660
  const hasAmount = activeTab === "fiat" ? srcAmountOnRamp && parseFloat(srcAmountOnRamp) > 0 : activeInputAmountInWei !== "0";
656
661
  if (!hasAmount)
657
- return { text: "Enter an amount", disable: true, error: false, loading: false };
662
+ return {
663
+ text: "Enter an amount",
664
+ disable: true,
665
+ error: false,
666
+ loading: false,
667
+ };
658
668
  if (isSameChainSameToken && !allowDirectTransfer)
659
- return { text: "Select a different token or chain", disable: true, error: false, loading: false };
669
+ return {
670
+ text: "Select a different token or chain",
671
+ disable: true,
672
+ error: false,
673
+ loading: false,
674
+ };
660
675
  if (isLoadingAnyspendQuote && !isSameChainSameToken)
661
- return { text: "Loading quote...", disable: true, error: false, loading: true };
676
+ return {
677
+ text: "Loading quote...",
678
+ disable: true,
679
+ error: false,
680
+ loading: true,
681
+ };
662
682
  if (isCreatingOrder || isCreatingOnrampOrder || isSwitchingOrExecuting)
663
683
  return {
664
684
  text: isSwitchingOrExecuting ? "Transferring..." : "Creating order...",
@@ -667,14 +687,29 @@ function AnySpendInner({ sourceChainId, destinationTokenAddress, destinationToke
667
687
  loading: true,
668
688
  };
669
689
  if ((!anyspendQuote || !anyspendQuote.success) && !(isSameChainSameToken && allowDirectTransfer))
670
- return { text: "No quote found", disable: true, error: false, loading: false };
690
+ return {
691
+ text: "No quote found",
692
+ disable: true,
693
+ error: false,
694
+ loading: false,
695
+ };
671
696
  if (activeTab === "fiat") {
672
697
  // For fiat: check recipient first, then payment method
673
698
  if (!effectiveRecipientAddress)
674
- return { text: "Select recipient", disable: false, error: false, loading: false };
699
+ return {
700
+ text: "Select recipient",
701
+ disable: false,
702
+ error: false,
703
+ loading: false,
704
+ };
675
705
  // If no fiat payment method selected, show "Select payment method"
676
706
  if (selectedFiatPaymentMethod === FiatPaymentMethod_1.FiatPaymentMethod.NONE) {
677
- return { text: "Select payment method", disable: false, error: false, loading: false };
707
+ return {
708
+ text: "Select payment method",
709
+ disable: false,
710
+ error: false,
711
+ loading: false,
712
+ };
678
713
  }
679
714
  // If payment method is selected, show "Continue"
680
715
  return { text: "Continue", disable: false, error: false, loading: false };
@@ -683,19 +718,40 @@ function AnySpendInner({ sourceChainId, destinationTokenAddress, destinationToke
683
718
  // For crypto: check payment method first, then recipient
684
719
  // If no payment method selected, show "Choose payment method"
685
720
  if (effectiveCryptoPaymentMethod === CryptoPaymentMethod_1.CryptoPaymentMethodType.NONE) {
686
- return { text: "Choose payment method", disable: false, error: false, loading: false };
721
+ return {
722
+ text: "Choose payment method",
723
+ disable: false,
724
+ error: false,
725
+ loading: false,
726
+ };
687
727
  }
688
728
  // Check recipient after payment method
689
729
  if (!effectiveRecipientAddress)
690
- return { text: "Select recipient", disable: false, error: false, loading: false };
730
+ return {
731
+ text: "Select recipient",
732
+ disable: false,
733
+ error: false,
734
+ loading: false,
735
+ };
691
736
  // If payment method selected, show appropriate action
692
737
  if (effectiveCryptoPaymentMethod === CryptoPaymentMethod_1.CryptoPaymentMethodType.CONNECT_WALLET ||
693
738
  effectiveCryptoPaymentMethod === CryptoPaymentMethod_1.CryptoPaymentMethodType.GLOBAL_WALLET) {
694
739
  const buttonText = isSameChainSameToken && allowDirectTransfer ? "Transfer" : "Swap";
695
- return { text: buttonText, disable: false, error: false, loading: false };
740
+ return {
741
+ text: buttonText,
742
+ disable: false,
743
+ error: false,
744
+ loading: false,
745
+ };
696
746
  }
697
747
  if (effectiveCryptoPaymentMethod === CryptoPaymentMethod_1.CryptoPaymentMethodType.TRANSFER_CRYPTO) {
698
- return { text: "Continue to payment", disable: false, error: false, loading: false };
748
+ const transferText = isSameChainSameToken && allowDirectTransfer ? "Show deposit address" : "Continue to payment";
749
+ return {
750
+ text: transferText,
751
+ disable: false,
752
+ error: false,
753
+ loading: false,
754
+ };
699
755
  }
700
756
  }
701
757
  return { text: "Continue", disable: false, error: false, loading: false };
@@ -787,8 +843,14 @@ function AnySpendInner({ sourceChainId, destinationTokenAddress, destinationToke
787
843
  // Handle crypto swap creation
788
844
  const handleCryptoSwap = async (method) => {
789
845
  try {
790
- const isDirectTransfer = isSameChainSameToken && allowDirectTransfer;
846
+ // TRANSFER_CRYPTO is the manual deposit-address flow — no connected wallet to send from.
847
+ const isDirectTransfer = isSameChainSameToken && allowDirectTransfer && method !== CryptoPaymentMethod_1.CryptoPaymentMethodType.TRANSFER_CRYPTO;
791
848
  (0, invariant_1.default)(effectiveRecipientAddress, "Recipient address is not found");
849
+ // Same-token manual deposit → show recipient address + watch, no relayer order, no fee
850
+ if (isSameChainSameToken && allowDirectTransfer && method === CryptoPaymentMethod_1.CryptoPaymentMethodType.TRANSFER_CRYPTO) {
851
+ navigateToPanel(PanelView.PURE_TRANSFER_ADDRESS, "forward");
852
+ return;
853
+ }
792
854
  const srcAmountBigInt = (0, viem_1.parseUnits)(srcAmount.replace(/,/g, ""), selectedSrcToken.decimals);
793
855
  // Handle direct transfer (same chain/token) - bypass backend, transfer directly
794
856
  if (isDirectTransfer) {
@@ -807,9 +869,6 @@ function AnySpendInner({ sourceChainId, destinationTokenAddress, destinationToke
807
869
  }
808
870
  // Regular swap flow - use backend
809
871
  (0, invariant_1.default)(anyspendQuote, "Relay price is not found");
810
- // Debug: Check payment method values
811
- console.log("handleCryptoSwap - method parameter:", method);
812
- console.log("handleCryptoSwap - selectedCryptoPaymentMethod state:", selectedCryptoPaymentMethod);
813
872
  createOrder({
814
873
  recipientAddress: effectiveRecipientAddress,
815
874
  orderType: "swap",
@@ -817,7 +876,11 @@ function AnySpendInner({ sourceChainId, destinationTokenAddress, destinationToke
817
876
  dstChain: isBuyMode ? destinationTokenChainId : selectedDstChainId,
818
877
  srcToken: selectedSrcToken,
819
878
  dstToken: isBuyMode
820
- ? { ...selectedDstToken, chainId: destinationTokenChainId, address: destinationTokenAddress }
879
+ ? {
880
+ ...selectedDstToken,
881
+ chainId: destinationTokenChainId,
882
+ address: destinationTokenAddress,
883
+ }
821
884
  : selectedDstToken,
822
885
  srcAmount: srcAmountBigInt.toString(),
823
886
  expectedDstAmount: anyspendQuote?.data?.currencyOut?.amount || "0",
@@ -1134,6 +1197,7 @@ function AnySpendInner({ sourceChainId, destinationTokenAddress, destinationToke
1134
1197
  const authView = ((0, jsx_runtime_1.jsx)("div", { className: "mx-auto w-full max-w-[460px]", children: (0, jsx_runtime_1.jsx)(LoginStep_1.LoginStep, { chain: baseChain, onSuccess: async () => {
1135
1198
  // isAuthenticated will be true at this point — the useEffect below handles navigation
1136
1199
  } }) }));
1200
+ const pureTransferAddressView = ((0, jsx_runtime_1.jsx)(PureTransferView_1.PureTransferView, { mode: mode, recipientAddress: effectiveRecipientAddress ?? "", chainId: selectedSrcChainId, token: selectedSrcToken, displayAmount: srcAmount && srcAmount !== "0" ? `${srcAmount} ${selectedSrcToken.symbol}` : undefined, isActive: activePanel === PanelView.PURE_TRANSFER_ADDRESS, onBack: navigateBack, onClose: () => setB3ModalOpen(false), onTransferDetected: () => onSuccess?.() }));
1137
1201
  // Add tabs to the main component when no order is loaded
1138
1202
  return ((0, jsx_runtime_1.jsx)(react_2.StyleRoot, { children: (0, jsx_runtime_1.jsx)("div", { className: classes?.container ||
1139
1203
  (0, cn_1.cn)("anyspend-container font-inter mx-auto w-full max-w-[460px]", mode === "page" &&
@@ -1169,5 +1233,6 @@ function AnySpendInner({ sourceChainId, destinationTokenAddress, destinationToke
1169
1233
  (0, jsx_runtime_1.jsx)("div", { className: (0, cn_1.cn)(mode === "page" && "p-6"), children: directTransferSuccessView }, "direct-transfer-success-view"),
1170
1234
  (0, jsx_runtime_1.jsx)("div", { className: (0, cn_1.cn)(mode === "page" && "p-6"), children: kycView }, "fiat-kyc-view"),
1171
1235
  (0, jsx_runtime_1.jsx)("div", { className: (0, cn_1.cn)(mode === "page" && "p-6"), children: authView }, "fiat-auth-view"),
1236
+ (0, jsx_runtime_1.jsx)("div", { className: (0, cn_1.cn)(mode === "page" && "p-6"), children: pureTransferAddressView }, "pure-transfer-address-view"),
1172
1237
  ] }) }) }));
1173
1238
  }
@@ -254,7 +254,10 @@ function AnySpendCustomExactInInner({ loadOrder, mode = "modal", recipientAddres
254
254
  (0, cn_1.cn)("as-main-button relative w-full", btnInfo.error ? "!bg-as-red" : btnInfo.disable ? "!bg-as-on-surface-2" : "!bg-as-brand"), textClassName: (0, cn_1.cn)(btnInfo.error ? "text-white" : btnInfo.disable ? "text-as-secondary" : "text-white"), children: (0, jsx_runtime_1.jsxs)("div", { className: "flex items-center justify-center gap-2", children: [btnInfo.loading && (0, jsx_runtime_1.jsx)(lucide_react_1.Loader2, { className: "h-4 w-4 animate-spin" }), btnInfo.text] }) })) }), gasPriceData && !isLoadingGas && effectivePaymentType === "crypto" && !isDirectTransfer && ((0, jsx_runtime_1.jsx)(GasIndicator_1.GasIndicator, { gasPrice: gasPriceData, className: classes?.gasIndicator || "mt-2 w-full" })), mainFooter ? mainFooter : null] }));
255
255
  const handleCryptoOrder = async () => {
256
256
  try {
257
- const isDirectTransfer = isSameChainSameToken && allowDirectTransfer;
257
+ // TRANSFER_CRYPTO is the manual deposit-address flow — no connected wallet to send from.
258
+ const isDirectTransfer = isSameChainSameToken &&
259
+ allowDirectTransfer &&
260
+ effectiveCryptoPaymentMethod !== CryptoPaymentMethod_1.CryptoPaymentMethodType.TRANSFER_CRYPTO;
258
261
  if (!isDirectTransfer) {
259
262
  (0, invariant_1.default)(anyspendQuote, "Relay price is not found");
260
263
  }
@@ -5,6 +5,7 @@ const jsx_runtime_1 = require("react/jsx-runtime");
5
5
  const anyspend_1 = require("../../../anyspend");
6
6
  const react_1 = require("../../../global-account/react");
7
7
  const cn_1 = require("../../../shared/utils/cn");
8
+ const number_1 = require("../../../shared/utils/number");
8
9
  const react_2 = require("@web3icons/react");
9
10
  const lucide_react_1 = require("lucide-react");
10
11
  const react_3 = require("react");
@@ -228,7 +229,9 @@ function AnySpendDeposit({ loadOrder, mode = "modal", recipientAddress, paymentT
228
229
  "anyspend-deposit-option-button anyspend-deposit-crypto-button border-border-primary hover:border-as-brand hover:bg-as-surface-secondary flex w-full items-center justify-between rounded-xl border p-4 text-left shadow-sm transition-all", children: [(0, jsx_runtime_1.jsx)("div", { className: depositClasses?.optionContent || "anyspend-deposit-option-content", children: (0, jsx_runtime_1.jsxs)("div", { className: depositClasses?.optionInfo || "anyspend-deposit-option-info", children: [(0, jsx_runtime_1.jsx)("span", { className: depositClasses?.optionTitle || "anyspend-deposit-option-title text-as-primary font-medium", children: "Deposit Crypto" }), (0, jsx_runtime_1.jsx)("p", { className: depositClasses?.optionDescription ||
229
230
  "anyspend-deposit-option-description text-as-secondary text-xs", children: "Swap from any token on any chain" })] }) }), (0, jsx_runtime_1.jsx)(lucide_react_1.ChevronRight, { className: depositClasses?.optionChevron || "anyspend-deposit-option-chevron text-as-secondary h-5 w-5" })] }), (0, jsx_runtime_1.jsxs)("div", { className: depositClasses?.divider || "anyspend-deposit-divider flex items-center gap-3", children: [(0, jsx_runtime_1.jsx)("div", { className: depositClasses?.dividerLine || "bg-as-stroke h-px flex-1" }), (0, jsx_runtime_1.jsx)("span", { className: depositClasses?.dividerText || "anyspend-deposit-divider-text text-as-secondary text-sm", children: "More options" }), (0, jsx_runtime_1.jsx)("div", { className: depositClasses?.dividerLine || "bg-as-stroke h-px flex-1" })] }), (0, jsx_runtime_1.jsxs)("button", { onClick: handleSelectQrDeposit, className: depositClasses?.qrButton ||
230
231
  "anyspend-deposit-option-button anyspend-deposit-qr-button border-border-primary hover:border-as-brand hover:bg-as-surface-secondary flex w-full items-center justify-between rounded-xl border p-4 text-left shadow-sm transition-all", children: [(0, jsx_runtime_1.jsxs)("div", { className: depositClasses?.optionContent || "anyspend-deposit-option-content flex items-center gap-3", children: [(0, jsx_runtime_1.jsx)(QrCodeIcon_1.QrCodeIcon, { className: depositClasses?.optionIcon || "anyspend-deposit-option-icon h-10 w-10" }), (0, jsx_runtime_1.jsxs)("div", { className: depositClasses?.optionInfo || "anyspend-deposit-option-info", children: [(0, jsx_runtime_1.jsx)("span", { className: depositClasses?.optionTitle || "anyspend-deposit-option-title text-as-primary font-medium", children: "Deposit with QR Code" }), (0, jsx_runtime_1.jsx)("p", { className: depositClasses?.optionDescription ||
231
- "anyspend-deposit-option-description text-as-secondary text-xs", children: "Send tokens directly to deposit address" })] })] }), (0, jsx_runtime_1.jsx)(lucide_react_1.ChevronRight, { className: depositClasses?.optionChevron || "anyspend-deposit-option-chevron text-as-secondary h-5 w-5" })] }), showFiatOption && ((0, jsx_runtime_1.jsxs)("button", { onClick: handleSelectFiat, className: depositClasses?.fiatButton ||
232
+ "anyspend-deposit-option-description text-as-secondary text-xs", children: pureTransferOnly
233
+ ? "Send tokens directly to deposit address"
234
+ : "Send any token — we'll convert it for you" })] })] }), (0, jsx_runtime_1.jsx)(lucide_react_1.ChevronRight, { className: depositClasses?.optionChevron || "anyspend-deposit-option-chevron text-as-secondary h-5 w-5" })] }), showFiatOption && ((0, jsx_runtime_1.jsxs)("button", { onClick: handleSelectFiat, className: depositClasses?.fiatButton ||
232
235
  "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: [(0, jsx_runtime_1.jsxs)("div", { className: depositClasses?.optionContent || "anyspend-deposit-option-content flex items-center gap-3", children: [(0, jsx_runtime_1.jsx)(CreditCardIcon_1.CreditCardIcon, { className: depositClasses?.optionIcon || "anyspend-deposit-option-icon h-10 w-10" }), (0, jsx_runtime_1.jsxs)("div", { className: depositClasses?.optionInfo || "anyspend-deposit-option-info", children: [(0, jsx_runtime_1.jsx)("span", { className: depositClasses?.optionTitle || "anyspend-deposit-option-title text-as-primary font-medium", children: "Fund with Fiat" }), (0, jsx_runtime_1.jsx)("p", { className: depositClasses?.optionDescription ||
233
236
  "anyspend-deposit-option-description text-as-secondary text-xs", children: "Pay with card or bank transfer" })] })] }), (0, jsx_runtime_1.jsx)(lucide_react_1.ChevronRight, { className: depositClasses?.optionChevron || "anyspend-deposit-option-chevron text-as-secondary h-5 w-5" })] }))] }), (0, jsx_runtime_1.jsx)(WarningText_1.ChainWarningText, { chainId: destinationTokenChainId, classes: classes?.chainWarningText || { root: "mt-2" } })] })] }));
234
237
  }
@@ -245,10 +248,21 @@ function AnySpendDeposit({ loadOrder, mode = "modal", recipientAddress, paymentT
245
248
  // `KNOWN_FUNDING_TOKENS` key — so `hasKnownDestination` is always true and this
246
249
  // branch never fires for them. The guard is defensive for FUTURE callers that pass
247
250
  // an unknown token together with `pureTransferOnly=true`.
251
+ // Only surface the fixed destination amount on the QR path when its decimals are trustworthy
252
+ // (a known funding token or a resolved API lookup) — otherwise `destinationToken.decimals`
253
+ // is the generic 18 fallback and formatting a 6-decimal token's wei against it would be off by
254
+ // 10^12. When unresolved we still show the destination token/chain, just without an amount.
255
+ const destinationDecimalsResolved = hasKnownDestination || !!destinationTokenData;
256
+ const destinationAmountDisplay = destinationTokenAmount &&
257
+ /^\d+$/.test(destinationTokenAmount) &&
258
+ BigInt(destinationTokenAmount) > 0n &&
259
+ destinationDecimalsResolved
260
+ ? (0, number_1.formatTokenAmount)(BigInt(destinationTokenAmount), destinationToken.decimals, 6, false)
261
+ : undefined;
248
262
  if (pureTransferOnly && !hasKnownDestination && !destinationTokenData && isDestinationTokenLoading) {
249
263
  return ((0, jsx_runtime_1.jsx)("div", { className: (0, cn_1.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: (0, jsx_runtime_1.jsxs)("div", { className: "anyspend-deposit-qr-loading-content flex flex-col items-center justify-center gap-4 py-12", children: [(0, jsx_runtime_1.jsx)(react_1.Skeleton, { className: "h-8 w-8 rounded-full" }), (0, jsx_runtime_1.jsx)(react_1.Skeleton, { className: "h-4 w-40" })] }) }));
250
264
  }
251
- return ((0, jsx_runtime_1.jsx)(QRDeposit_1.QRDeposit, { mode: mode, recipientAddress: recipientAddress, destinationToken: destinationToken, destinationChainId: destinationTokenChainId, pureTransferOnly: pureTransferOnly, depositContractConfig: depositContractConfig, onBack: handleBack, onClose: onClose ?? handleBack, onSuccess: handleQRDepositSuccess, classes: classes?.qrDeposit }));
265
+ return ((0, jsx_runtime_1.jsx)(QRDeposit_1.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 }));
252
266
  }
253
267
  // Deposit view
254
268
  return ((0, jsx_runtime_1.jsxs)("div", { className: depositClasses?.form || "anyspend-deposit anyspend-deposit-form relative", children: [shouldShowChainSelection && ((0, jsx_runtime_1.jsxs)("button", { onClick: handleBack, className: depositClasses?.backButton ||
@@ -14,6 +14,14 @@ 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;
17
25
  /**
18
26
  * When true, the deposit is a PURE TRANSFER: the destination token/chain mirror
19
27
  * the user's currently selected source token/chain, so the exact token the user
@@ -54,4 +62,4 @@ export interface QRDepositProps {
54
62
  * onSuccess={(txHash) => console.log("Deposit complete:", txHash)}
55
63
  * />
56
64
  */
57
- export declare function QRDeposit({ mode, recipientAddress, sourceToken: sourceTokenProp, sourceChainId: sourceChainIdProp, destinationToken, destinationChainId, pureTransferOnly, 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;
@@ -42,7 +42,7 @@ const DEFAULT_ETH_ON_BASE = {
42
42
  * onSuccess={(txHash) => console.log("Deposit complete:", txHash)}
43
43
  * />
44
44
  */
45
- function QRDeposit({ mode = "modal", recipientAddress, sourceToken: sourceTokenProp, sourceChainId: sourceChainIdProp, destinationToken, destinationChainId, pureTransferOnly = false, creatorAddress, depositContractConfig, onBack, onClose, onOrderCreated, onSuccess, classes, }) {
45
+ function QRDeposit({ mode = "modal", recipientAddress, sourceToken: sourceTokenProp, sourceChainId: sourceChainIdProp, destinationToken, destinationChainId, destinationAmountDisplay, pureTransferOnly = false, creatorAddress, depositContractConfig, onBack, onClose, onOrderCreated, onSuccess, classes, }) {
46
46
  const [copied, setCopied] = (0, react_2.useState)(false);
47
47
  const [orderId, setOrderId] = (0, react_2.useState)();
48
48
  const [globalAddress, setGlobalAddress] = (0, react_2.useState)();
@@ -174,8 +174,8 @@ function QRDeposit({ mode = "modal", recipientAddress, sourceToken: sourceTokenP
174
174
  }
175
175
  return ((0, jsx_runtime_1.jsx)("div", { className: classes?.container ||
176
176
  (0, cn_1.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: (0, jsx_runtime_1.jsxs)("div", { className: classes?.content || "anyspend-qr-deposit-content flex flex-col gap-4", children: [(0, jsx_runtime_1.jsxs)("div", { className: classes?.header || "anyspend-qr-header flex items-center justify-between", children: [(0, jsx_runtime_1.jsx)("button", { onClick: handleBack, className: classes?.backButton || "anyspend-qr-back-button text-as-secondary hover:text-as-primary", children: (0, jsx_runtime_1.jsx)("svg", { className: "h-5 w-5", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: (0, jsx_runtime_1.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M15 19l-7-7 7-7" }) }) }), (0, jsx_runtime_1.jsx)("h2", { className: classes?.title || "anyspend-qr-title text-as-primary text-base font-semibold", children: "Deposit" }), onClose ? ((0, jsx_runtime_1.jsx)("button", { onClick: handleClose, className: classes?.closeButton || "anyspend-qr-close-button text-as-secondary hover:text-as-primary", children: (0, jsx_runtime_1.jsx)("svg", { className: "h-5 w-5", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: (0, jsx_runtime_1.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M6 18L18 6M6 6l12 12" }) }) })) : ((0, jsx_runtime_1.jsx)("div", { className: "w-5" }))] }), (0, jsx_runtime_1.jsxs)("div", { className: classes?.tokenSelectorContainer || "anyspend-qr-token-selector flex flex-col gap-1.5", children: [(0, jsx_runtime_1.jsx)("label", { className: classes?.tokenSelectorLabel || "anyspend-qr-token-label text-as-secondary text-sm", children: "Send" }), (0, jsx_runtime_1.jsx)(relay_kit_ui_1.TokenSelector, { chainIdsFilter: (0, anyspend_1.getAvailableChainIds)("from"), context: "from", fromChainWalletVMSupported: true, isValidAddress: true, lockedChainIds: (0, anyspend_1.getAvailableChainIds)("from"), multiWalletSupportEnabled: true, onAnalyticEvent: undefined, setToken: handleTokenSelect, supportedWalletVMs: ["evm"], token: undefined, trigger: (0, jsx_runtime_1.jsxs)(react_1.Button, { variant: "outline", role: "combobox", className: classes?.tokenSelectorTrigger ||
177
- "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: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-2", children: [sourceToken.metadata?.logoURI ? ((0, jsx_runtime_1.jsx)(ChainTokenIcon_1.ChainTokenIcon, { chainUrl: anyspend_1.ALL_CHAINS[sourceChainId]?.logoUrl, tokenUrl: sourceToken.metadata.logoURI, className: "h-8 min-h-8 w-8 min-w-8" })) : ((0, jsx_runtime_1.jsx)("div", { className: "h-8 w-8 rounded-full bg-gray-700" })), (0, jsx_runtime_1.jsxs)("div", { className: "flex flex-col items-start gap-0", children: [(0, jsx_runtime_1.jsx)("div", { className: "text-as-primary font-semibold", children: sourceToken.symbol }), (0, jsx_runtime_1.jsx)("div", { className: "text-as-primary/70 text-xs", children: anyspend_1.ALL_CHAINS[sourceChainId]?.name ?? "Unknown" })] })] }), (0, jsx_runtime_1.jsx)(lucide_react_1.ChevronsUpDown, { className: "h-4 w-4 shrink-0 opacity-70" })] }) })] }), (0, jsx_runtime_1.jsxs)("div", { className: classes?.qrContent || "anyspend-qr-content border-as-stroke flex items-start gap-4 rounded-xl border p-4", children: [(0, jsx_runtime_1.jsxs)("div", { className: classes?.qrCodeContainer || "anyspend-qr-code-container flex flex-col items-center gap-2", children: [(0, jsx_runtime_1.jsx)("div", { className: classes?.qrCode || "anyspend-qr-code rounded-lg bg-white p-2", children: (0, jsx_runtime_1.jsx)(qrcode_react_1.QRCodeSVG, { value: qrValue, size: 120, level: "M", marginSize: 0 }) }), (0, jsx_runtime_1.jsxs)("span", { className: classes?.qrScanHint || "anyspend-qr-scan-hint text-as-secondary text-xs", children: ["SCAN WITH ", (0, jsx_runtime_1.jsx)("span", { className: "inline-block", children: "\uD83E\uDD8A" })] })] }), (0, jsx_runtime_1.jsxs)("div", { className: classes?.addressContainer || "anyspend-qr-address-container flex flex-1 flex-col gap-1", children: [(0, jsx_runtime_1.jsx)("span", { className: classes?.addressLabel || "anyspend-qr-address-label text-as-secondary text-sm", children: "Deposit address:" }), (0, jsx_runtime_1.jsxs)("div", { className: classes?.addressRow || "anyspend-qr-address-row flex items-start gap-1", children: [(0, jsx_runtime_1.jsx)("span", { className: classes?.address || "anyspend-qr-address text-as-primary break-all font-mono text-sm leading-relaxed", children: displayAddress }), (0, jsx_runtime_1.jsx)("button", { onClick: handleCopyAddress, className: classes?.addressCopyIcon ||
178
- "anyspend-qr-copy-icon text-as-secondary hover:text-as-primary mt-0.5 shrink-0", children: copied ? (0, jsx_runtime_1.jsx)(lucide_react_1.Check, { className: "h-4 w-4" }) : (0, jsx_runtime_1.jsx)(lucide_react_1.Copy, { className: "h-4 w-4" }) })] })] })] }), (0, jsx_runtime_1.jsx)(WarningText_1.ChainWarningText, { chainId: effectiveDestinationChainId }), (0, jsx_runtime_1.jsxs)(WarningText_1.WarningText, { children: ["Only send ", sourceToken.symbol, " on ", anyspend_1.ALL_CHAINS[sourceChainId]?.name ?? "the specified chain", ". Other tokens will not be converted."] }), isPureTransfer && isWatchingTransfer && ((0, jsx_runtime_1.jsxs)("div", { className: classes?.watchingIndicator ||
177
+ "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: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-2", children: [sourceToken.metadata?.logoURI ? ((0, jsx_runtime_1.jsx)(ChainTokenIcon_1.ChainTokenIcon, { chainUrl: anyspend_1.ALL_CHAINS[sourceChainId]?.logoUrl, tokenUrl: sourceToken.metadata.logoURI, className: "h-8 min-h-8 w-8 min-w-8" })) : ((0, jsx_runtime_1.jsx)("div", { className: "h-8 w-8 rounded-full bg-gray-700" })), (0, jsx_runtime_1.jsxs)("div", { className: "flex flex-col items-start gap-0", children: [(0, jsx_runtime_1.jsx)("div", { className: "text-as-primary font-semibold", children: sourceToken.symbol }), (0, jsx_runtime_1.jsx)("div", { className: "text-as-primary/70 text-xs", children: anyspend_1.ALL_CHAINS[sourceChainId]?.name ?? "Unknown" })] })] }), (0, jsx_runtime_1.jsx)(lucide_react_1.ChevronsUpDown, { className: "h-4 w-4 shrink-0 opacity-70" })] }) })] }), !isPureTransfer && ((0, jsx_runtime_1.jsxs)("div", { className: "anyspend-qr-receive flex flex-col gap-1.5", children: [(0, jsx_runtime_1.jsx)("label", { className: "anyspend-qr-receive-label text-as-secondary text-sm", children: "Receive" }), (0, jsx_runtime_1.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 ? ((0, jsx_runtime_1.jsx)(ChainTokenIcon_1.ChainTokenIcon, { chainUrl: anyspend_1.ALL_CHAINS[effectiveDestinationChainId]?.logoUrl, tokenUrl: effectiveDestinationToken.metadata.logoURI, className: "h-8 min-h-8 w-8 min-w-8" })) : ((0, jsx_runtime_1.jsx)("div", { className: "h-8 w-8 rounded-full bg-gray-700" })), (0, jsx_runtime_1.jsxs)("div", { className: "flex flex-col items-start gap-0", children: [(0, jsx_runtime_1.jsx)("div", { className: "text-as-primary font-semibold", children: effectiveDestinationToken.symbol || "Token" }), (0, jsx_runtime_1.jsx)("div", { className: "text-as-primary/70 text-xs", children: anyspend_1.ALL_CHAINS[effectiveDestinationChainId]?.name ?? "Unknown" })] })] })] })), (0, jsx_runtime_1.jsxs)("div", { className: classes?.qrContent || "anyspend-qr-content border-as-stroke flex items-start gap-4 rounded-xl border p-4", children: [(0, jsx_runtime_1.jsxs)("div", { className: classes?.qrCodeContainer || "anyspend-qr-code-container flex flex-col items-center gap-2", children: [(0, jsx_runtime_1.jsx)("div", { className: classes?.qrCode || "anyspend-qr-code rounded-lg bg-white p-2", children: (0, jsx_runtime_1.jsx)(qrcode_react_1.QRCodeSVG, { value: qrValue, size: 120, level: "M", marginSize: 0 }) }), (0, jsx_runtime_1.jsxs)("span", { className: classes?.qrScanHint || "anyspend-qr-scan-hint text-as-secondary text-xs", children: ["SCAN WITH ", (0, jsx_runtime_1.jsx)("span", { className: "inline-block", children: "\uD83E\uDD8A" })] })] }), (0, jsx_runtime_1.jsxs)("div", { className: classes?.addressContainer || "anyspend-qr-address-container flex flex-1 flex-col gap-1", children: [(0, jsx_runtime_1.jsx)("span", { className: classes?.addressLabel || "anyspend-qr-address-label text-as-secondary text-sm", children: "Deposit address:" }), (0, jsx_runtime_1.jsxs)("div", { className: classes?.addressRow || "anyspend-qr-address-row flex items-start gap-1", children: [(0, jsx_runtime_1.jsx)("span", { className: classes?.address || "anyspend-qr-address text-as-primary break-all font-mono text-sm leading-relaxed", children: displayAddress }), (0, jsx_runtime_1.jsx)("button", { onClick: handleCopyAddress, className: classes?.addressCopyIcon ||
178
+ "anyspend-qr-copy-icon text-as-secondary hover:text-as-primary mt-0.5 shrink-0", children: copied ? (0, jsx_runtime_1.jsx)(lucide_react_1.Check, { className: "h-4 w-4" }) : (0, jsx_runtime_1.jsx)(lucide_react_1.Copy, { className: "h-4 w-4" }) })] })] })] }), (0, jsx_runtime_1.jsx)(WarningText_1.ChainWarningText, { chainId: effectiveDestinationChainId }), isPureTransfer ? ((0, jsx_runtime_1.jsxs)(WarningText_1.WarningText, { children: ["Only send ", sourceToken.symbol, " on ", anyspend_1.ALL_CHAINS[sourceChainId]?.name ?? "the specified chain", ". Other tokens will not be converted."] })) : ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsxs)(WarningText_1.WarningText, { children: ["Only send ", sourceToken.symbol, " on ", anyspend_1.ALL_CHAINS[sourceChainId]?.name ?? "the specified chain", " to this address \u2014 it will be converted to ", effectiveDestinationToken.symbol || "the destination token", " on", " ", anyspend_1.ALL_CHAINS[effectiveDestinationChainId]?.name ?? "the destination chain", "."] }), destinationAmountDisplay && ((0, jsx_runtime_1.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 && ((0, jsx_runtime_1.jsxs)("div", { className: classes?.watchingIndicator ||
179
179
  "anyspend-qr-watching flex items-center justify-center gap-2 rounded-lg bg-blue-500/10 p-3", children: [(0, jsx_runtime_1.jsx)(lucide_react_1.Loader2, { className: "h-4 w-4 animate-spin text-blue-500" }), (0, jsx_runtime_1.jsx)("span", { className: "text-sm text-blue-500", children: "Watching for incoming transfer..." })] })), (0, jsx_runtime_1.jsx)("button", { onClick: handleCopyAddress, className: classes?.copyButton ||
180
180
  "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" })] }) }));
181
181
  }
@@ -0,0 +1,30 @@
1
+ import type { components } from "../../../../anyspend/types/api";
2
+ import type { TransferResult } from "../../hooks/useWatchTransfer";
3
+ export interface PureTransferViewProps {
4
+ mode?: "modal" | "page";
5
+ /** The recipient address where funds will land (the user's own wallet) */
6
+ recipientAddress: string;
7
+ /** Chain ID to watch on */
8
+ chainId: number;
9
+ /** Token the user sends — drives the QR code and balance watcher */
10
+ token: components["schemas"]["Token"];
11
+ /** Human-readable amount to display (display-only; skip row if empty or "0") */
12
+ displayAmount?: string;
13
+ /** Whether this panel is the currently active panel; gates the balance watcher */
14
+ isActive?: boolean;
15
+ /** Callback when back chevron is clicked */
16
+ onBack?: () => void;
17
+ /** Callback when X close button is clicked */
18
+ onClose?: () => void;
19
+ /** Callback when an incoming transfer is detected */
20
+ onTransferDetected?: (result: TransferResult) => void;
21
+ }
22
+ /**
23
+ * A self-contained view that shows the recipient address as a QR code + copy button and
24
+ * watches for an incoming same-chain/same-token transfer via `useWatchTransfer`. When a
25
+ * transfer is detected it renders `TransferResultScreen`.
26
+ *
27
+ * This is the "TRANSFER_CRYPTO" path for same-token AnySpend deposits — no relayer order,
28
+ * no fee; the user simply sends the token directly to their own address.
29
+ */
30
+ export declare function PureTransferView({ mode, recipientAddress, chainId, token, displayAmount, isActive, onBack, onClose, onTransferDetected, }: PureTransferViewProps): import("react/jsx-runtime").JSX.Element | null;
@@ -0,0 +1,64 @@
1
+ "use strict";
2
+ "use client";
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.PureTransferView = PureTransferView;
5
+ const jsx_runtime_1 = require("react/jsx-runtime");
6
+ const anyspend_1 = require("../../../../anyspend");
7
+ const react_1 = require("../../../../global-account/react");
8
+ const cn_1 = require("../../../../shared/utils/cn");
9
+ const lucide_react_1 = require("lucide-react");
10
+ const qrcode_react_1 = require("qrcode.react");
11
+ const react_2 = require("react");
12
+ const useWatchTransfer_1 = require("../../hooks/useWatchTransfer");
13
+ const WarningText_1 = require("./WarningText");
14
+ const TransferResultScreen_1 = require("./TransferResultScreen");
15
+ /**
16
+ * A self-contained view that shows the recipient address as a QR code + copy button and
17
+ * watches for an incoming same-chain/same-token transfer via `useWatchTransfer`. When a
18
+ * transfer is detected it renders `TransferResultScreen`.
19
+ *
20
+ * This is the "TRANSFER_CRYPTO" path for same-token AnySpend deposits — no relayer order,
21
+ * no fee; the user simply sends the token directly to their own address.
22
+ */
23
+ function PureTransferView({ mode = "modal", recipientAddress, chainId, token, displayAmount, isActive, onBack, onClose, onTransferDetected, }) {
24
+ const [transferResult, setTransferResult] = (0, react_2.useState)(null);
25
+ // Fix 4: reset transferResult when the panel becomes active again
26
+ (0, react_2.useEffect)(() => {
27
+ if (isActive)
28
+ setTransferResult(null);
29
+ }, [isActive]);
30
+ // Fix 3: stabilize the callback so it doesn't re-run the watcher effect every render
31
+ const handleTransferDetected = (0, react_2.useCallback)((result) => {
32
+ setTransferResult(result);
33
+ onTransferDetected?.(result);
34
+ }, [onTransferDetected]);
35
+ const { isWatching } = (0, useWatchTransfer_1.useWatchTransfer)({
36
+ address: recipientAddress,
37
+ chainId,
38
+ tokenAddress: token.address,
39
+ tokenDecimals: token.decimals,
40
+ // Fix 1: also require a non-empty recipient before enabling the watcher
41
+ enabled: !!recipientAddress && !transferResult && isActive,
42
+ onTransferDetected: handleTransferDetected,
43
+ });
44
+ // Fix 2: guard qrValue when recipientAddress is empty
45
+ const qrValue = (0, react_2.useMemo)(() => recipientAddress
46
+ ? (0, anyspend_1.getPaymentUrl)(recipientAddress, undefined, token.address === anyspend_1.ZERO_ADDRESS ? "ETH" : token.address, chainId, token.decimals)
47
+ : "", [recipientAddress, token.address, token.decimals, chainId]);
48
+ const chainName = (0, react_2.useMemo)(() => {
49
+ try {
50
+ return (0, anyspend_1.getChainName)(chainId);
51
+ }
52
+ catch {
53
+ return "the specified chain";
54
+ }
55
+ }, [chainId]);
56
+ // Guard: if no address yet, render nothing
57
+ if (!recipientAddress)
58
+ return null;
59
+ // Once a transfer is detected, hand off to the shared success screen
60
+ if (transferResult) {
61
+ return ((0, jsx_runtime_1.jsx)(TransferResultScreen_1.TransferResultScreen, { mode: mode, transferResult: transferResult, token: token, chainId: chainId, recipientAddress: recipientAddress, onBack: onBack, onClose: onClose }));
62
+ }
63
+ return ((0, jsx_runtime_1.jsx)("div", { className: (0, cn_1.cn)("anyspend-container anyspend-pure-transfer font-inter bg-as-surface-primary mx-auto w-full max-w-[460px] p-6"), children: (0, jsx_runtime_1.jsxs)("div", { className: "anyspend-pure-transfer-content flex flex-col gap-4", children: [(0, jsx_runtime_1.jsxs)("div", { className: "anyspend-pure-transfer-header flex items-center justify-between", children: [onBack ? ((0, jsx_runtime_1.jsx)("button", { onClick: onBack, className: "anyspend-pure-transfer-back text-as-secondary hover:text-as-primary", "aria-label": "Go back", children: (0, jsx_runtime_1.jsx)(lucide_react_1.ChevronLeft, { className: "h-5 w-5" }) })) : ((0, jsx_runtime_1.jsx)("div", { className: "w-5" })), (0, jsx_runtime_1.jsxs)("h2", { className: "anyspend-pure-transfer-title text-as-primary text-base font-semibold", children: ["Send ", token.symbol] }), onClose ? ((0, jsx_runtime_1.jsx)("button", { onClick: onClose, className: "anyspend-pure-transfer-close text-as-secondary hover:text-as-primary", "aria-label": "Close", children: (0, jsx_runtime_1.jsx)(lucide_react_1.X, { className: "h-5 w-5" }) })) : ((0, jsx_runtime_1.jsx)("div", { className: "w-5" }))] }), displayAmount && ((0, jsx_runtime_1.jsx)("div", { className: "anyspend-pure-transfer-amount-badge border-as-border-secondary bg-as-surface-secondary flex items-center justify-center rounded-xl border px-4 py-2", children: (0, jsx_runtime_1.jsx)("span", { className: "text-as-primary text-sm font-medium", children: displayAmount }) })), (0, jsx_runtime_1.jsxs)("div", { className: "anyspend-pure-transfer-qr-content border-as-stroke flex items-start gap-4 rounded-xl border p-4", children: [(0, jsx_runtime_1.jsxs)("div", { className: "anyspend-pure-transfer-qr-code-container flex flex-col items-center gap-2", children: [(0, jsx_runtime_1.jsx)("div", { className: "anyspend-pure-transfer-qr-code rounded-lg bg-white p-2", children: (0, jsx_runtime_1.jsx)(qrcode_react_1.QRCodeSVG, { value: qrValue, size: 120, level: "M", marginSize: 0 }) }), (0, jsx_runtime_1.jsxs)("span", { className: "anyspend-pure-transfer-qr-scan-hint text-as-secondary text-xs", children: ["SCAN WITH ", (0, jsx_runtime_1.jsx)("span", { className: "inline-block", children: "\uD83E\uDD8A" })] })] }), (0, jsx_runtime_1.jsxs)("div", { className: "anyspend-pure-transfer-address-container flex flex-1 flex-col gap-1", children: [(0, jsx_runtime_1.jsx)("span", { className: "anyspend-pure-transfer-address-label text-as-secondary text-sm", children: "Deposit address:" }), (0, jsx_runtime_1.jsxs)("div", { className: "anyspend-pure-transfer-address-row flex items-start gap-1", children: [(0, jsx_runtime_1.jsx)("span", { className: "anyspend-pure-transfer-address text-as-primary break-all font-mono text-sm leading-relaxed", children: recipientAddress }), (0, jsx_runtime_1.jsx)(react_1.CopyToClipboard, { text: recipientAddress, className: "anyspend-pure-transfer-copy-icon text-as-secondary hover:text-as-primary mt-0.5 shrink-0" })] })] })] }), (0, jsx_runtime_1.jsx)(WarningText_1.ChainWarningText, { chainId: chainId }), (0, jsx_runtime_1.jsxs)(WarningText_1.WarningText, { children: ["Only send ", token.symbol, " on ", chainName, ". Other tokens will not be converted."] }), isWatching && ((0, jsx_runtime_1.jsxs)("div", { className: "anyspend-pure-transfer-watching bg-as-brand/10 flex items-center justify-center gap-2 rounded-lg p-3", children: [(0, jsx_runtime_1.jsx)(lucide_react_1.Loader2, { className: "text-as-brand h-4 w-4 animate-spin" }), (0, jsx_runtime_1.jsx)("span", { className: "text-as-brand text-sm", children: "Watching for incoming transfer..." })] })), (0, jsx_runtime_1.jsx)(react_1.CopyToClipboard, { text: recipientAddress, children: (0, jsx_runtime_1.jsx)("button", { className: "anyspend-pure-transfer-copy-button bg-as-brand hover:bg-as-brand/90 flex w-full items-center justify-center gap-2 rounded-xl py-3.5 font-medium text-white transition-all", children: "Copy deposit address" }) })] }) }));
64
+ }
@@ -26,6 +26,36 @@ let socketClientUrl = null;
26
26
  // REST client instance
27
27
  let restClient = null;
28
28
  let restClientUrl = null;
29
+ // The pinned @b3dotfun/b3-api client's generated usersMethods predates `setBio`,
30
+ // so `users.setBio(...)` throws "setBio is not a function". Re-register the users
31
+ // service with the full list (mirrors users.shared.ts). Remove once the
32
+ // @b3dotfun/b3-api pin includes setBio.
33
+ const USERS_METHODS = [
34
+ "find",
35
+ "get",
36
+ "create",
37
+ "patch",
38
+ "remove",
39
+ "setReferralCode",
40
+ "syncTwProfiles",
41
+ "setAvatar",
42
+ "setBio",
43
+ "registerUsername",
44
+ "getMe",
45
+ ];
46
+ // Re-register on every client the manager builds — the active transport
47
+ // (REST/socket) switches at runtime.
48
+ function ensureUsersCustomMethods(client) {
49
+ try {
50
+ const connection = client.get("connection");
51
+ if (connection?.service) {
52
+ client.use("users", connection.service("users"), { methods: USERS_METHODS });
53
+ }
54
+ }
55
+ catch {
56
+ // Non-fatal: keep whatever methods the generated client already exposes.
57
+ }
58
+ }
29
59
  /**
30
60
  * Creates a socket client
31
61
  */
@@ -34,6 +64,7 @@ function createSocketClient() {
34
64
  if (!socketClient || socketClientUrl !== url) {
35
65
  socketInstance = (0, socket_io_client_1.default)(url, { transports: ["websocket"] });
36
66
  socketClient = (0, b3_api_1.createClient)((0, socketio_client_1.default)(socketInstance), app_shared_1.clientOptions);
67
+ ensureUsersCustomMethods(socketClient);
37
68
  socketClientUrl = url;
38
69
  }
39
70
  return socketClient;
@@ -54,6 +85,7 @@ function createRestClient() {
54
85
  if (!restClient || restClientUrl !== url) {
55
86
  const connection = (0, rest_client_1.default)(url).fetch(resolveFetch());
56
87
  restClient = (0, b3_api_1.createClient)(connection, app_shared_1.clientOptions);
88
+ ensureUsersCustomMethods(restClient);
57
89
  restClientUrl = url;
58
90
  }
59
91
  return restClient;
@@ -20,7 +20,8 @@ export declare enum PanelView {
20
20
  FEE_DETAIL = 9,
21
21
  DIRECT_TRANSFER_SUCCESS = 10,
22
22
  FIAT_KYC = 11,
23
- FIAT_AUTH = 12
23
+ FIAT_AUTH = 12,
24
+ PURE_TRANSFER_ADDRESS = 13
24
25
  }
25
26
  export declare function AnySpend(props: {
26
27
  mode?: "page" | "modal";