@b3dotfun/sdk 0.0.20 → 0.0.21-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (136) hide show
  1. package/dist/cjs/anyspend/index.native.d.ts +0 -2
  2. package/dist/cjs/anyspend/index.native.js +0 -4
  3. package/dist/cjs/anyspend/react/components/AnySpend.d.ts +3 -3
  4. package/dist/cjs/anyspend/react/components/AnySpend.js +43 -55
  5. package/dist/cjs/anyspend/react/components/AnySpendCustom.d.ts +1 -1
  6. package/dist/cjs/anyspend/react/components/AnySpendCustom.js +159 -84
  7. package/dist/cjs/anyspend/react/components/AnySpendFingerprintWrapper.d.ts +1 -1
  8. package/dist/cjs/anyspend/react/components/AnySpendFingerprintWrapper.js +2 -5
  9. package/dist/cjs/anyspend/react/components/AnySpendNFT.js +1 -1
  10. package/dist/cjs/anyspend/react/components/common/ConnectWalletPayment.js +1 -1
  11. package/dist/cjs/anyspend/react/components/common/CryptoPaymentMethod.d.ts +4 -4
  12. package/dist/cjs/anyspend/react/components/common/CryptoPaymentMethod.js +50 -102
  13. package/dist/cjs/anyspend/react/components/common/FiatPaymentMethod.js +1 -1
  14. package/dist/cjs/anyspend/react/components/common/OrderDetails.d.ts +2 -2
  15. package/dist/cjs/anyspend/react/components/common/OrderDetails.js +7 -9
  16. package/dist/cjs/anyspend/react/components/common/OrderStatus.js +2 -2
  17. package/dist/cjs/anyspend/react/components/common/PaymentStripeWeb2.js +1 -3
  18. package/dist/cjs/anyspend/react/components/common/RecipientSelection.d.ts +42 -0
  19. package/dist/cjs/anyspend/react/components/common/RecipientSelection.example.d.ts +7 -0
  20. package/dist/cjs/anyspend/react/components/common/RecipientSelection.example.js +27 -0
  21. package/dist/cjs/anyspend/react/components/common/RecipientSelection.js +36 -0
  22. package/dist/cjs/anyspend/react/components/common/TransferCryptoDetails.js +1 -1
  23. package/dist/cjs/anyspend/react/components/index.d.ts +1 -0
  24. package/dist/cjs/anyspend/react/components/index.js +3 -1
  25. package/dist/cjs/anyspend/react/hooks/index.d.ts +1 -0
  26. package/dist/cjs/anyspend/react/hooks/index.js +1 -0
  27. package/dist/cjs/anyspend/react/hooks/useConnectedUserProfile.d.ts +12 -0
  28. package/dist/cjs/anyspend/react/hooks/useConnectedUserProfile.js +25 -0
  29. package/dist/cjs/anyspend/react/hooks/useSigMint.d.ts +5 -5
  30. package/dist/cjs/anyspend/react/index.d.ts +1 -1
  31. package/dist/cjs/anyspend/react/index.js +1 -1
  32. package/dist/cjs/anyspend/react/providers/index.d.ts +2 -0
  33. package/dist/cjs/anyspend/react/providers/index.js +18 -0
  34. package/dist/cjs/anyspend/types/api.d.ts +35 -56
  35. package/dist/cjs/anyspend/utils/chain.d.ts +1 -1
  36. package/dist/cjs/anyspend/utils/chain.js +122 -15
  37. package/dist/cjs/global-account/react/components/B3Provider/B3Provider.d.ts +5 -1
  38. package/dist/cjs/global-account/react/components/B3Provider/B3Provider.js +2 -2
  39. package/dist/cjs/global-account/react/hooks/index.d.ts +1 -1
  40. package/dist/cjs/global-account/react/hooks/useProfile.d.ts +2 -1
  41. package/dist/cjs/global-account/react/hooks/useProfile.js +9 -7
  42. package/dist/cjs/shared/constants/index.js +5 -3
  43. package/dist/cjs/shared/utils/formatUsername.d.ts +1 -1
  44. package/dist/cjs/shared/utils/formatUsername.js +3 -1
  45. package/dist/esm/anyspend/index.native.d.ts +0 -2
  46. package/dist/esm/anyspend/index.native.js +0 -4
  47. package/dist/esm/anyspend/react/components/AnySpend.d.ts +3 -3
  48. package/dist/esm/anyspend/react/components/AnySpend.js +46 -58
  49. package/dist/esm/anyspend/react/components/AnySpendCustom.d.ts +1 -1
  50. package/dist/esm/anyspend/react/components/AnySpendCustom.js +163 -88
  51. package/dist/esm/anyspend/react/components/AnySpendFingerprintWrapper.d.ts +1 -1
  52. package/dist/esm/anyspend/react/components/AnySpendFingerprintWrapper.js +2 -5
  53. package/dist/esm/anyspend/react/components/AnySpendNFT.js +1 -1
  54. package/dist/esm/anyspend/react/components/common/ConnectWalletPayment.js +1 -1
  55. package/dist/esm/anyspend/react/components/common/CryptoPaymentMethod.d.ts +4 -4
  56. package/dist/esm/anyspend/react/components/common/CryptoPaymentMethod.js +52 -104
  57. package/dist/esm/anyspend/react/components/common/FiatPaymentMethod.js +1 -1
  58. package/dist/esm/anyspend/react/components/common/OrderDetails.d.ts +2 -2
  59. package/dist/esm/anyspend/react/components/common/OrderDetails.js +8 -10
  60. package/dist/esm/anyspend/react/components/common/OrderStatus.js +2 -2
  61. package/dist/esm/anyspend/react/components/common/PaymentStripeWeb2.js +1 -3
  62. package/dist/esm/anyspend/react/components/common/RecipientSelection.d.ts +42 -0
  63. package/dist/esm/anyspend/react/components/common/RecipientSelection.example.d.ts +7 -0
  64. package/dist/esm/anyspend/react/components/common/RecipientSelection.example.js +22 -0
  65. package/dist/esm/anyspend/react/components/common/RecipientSelection.js +33 -0
  66. package/dist/esm/anyspend/react/components/common/TransferCryptoDetails.js +1 -1
  67. package/dist/esm/anyspend/react/components/index.d.ts +1 -0
  68. package/dist/esm/anyspend/react/components/index.js +1 -0
  69. package/dist/esm/anyspend/react/hooks/index.d.ts +1 -0
  70. package/dist/esm/anyspend/react/hooks/index.js +1 -0
  71. package/dist/esm/anyspend/react/hooks/useConnectedUserProfile.d.ts +12 -0
  72. package/dist/esm/anyspend/react/hooks/useConnectedUserProfile.js +22 -0
  73. package/dist/esm/anyspend/react/hooks/useSigMint.d.ts +5 -5
  74. package/dist/esm/anyspend/react/index.d.ts +1 -1
  75. package/dist/esm/anyspend/react/index.js +1 -1
  76. package/dist/esm/anyspend/react/providers/index.d.ts +2 -0
  77. package/dist/esm/anyspend/react/providers/index.js +2 -0
  78. package/dist/esm/anyspend/types/api.d.ts +35 -56
  79. package/dist/esm/anyspend/utils/chain.d.ts +1 -1
  80. package/dist/esm/anyspend/utils/chain.js +122 -15
  81. package/dist/esm/global-account/react/components/B3Provider/B3Provider.d.ts +5 -1
  82. package/dist/esm/global-account/react/components/B3Provider/B3Provider.js +2 -2
  83. package/dist/esm/global-account/react/hooks/index.d.ts +1 -1
  84. package/dist/esm/global-account/react/hooks/useProfile.d.ts +2 -1
  85. package/dist/esm/global-account/react/hooks/useProfile.js +9 -7
  86. package/dist/esm/shared/constants/index.js +5 -3
  87. package/dist/esm/shared/utils/formatUsername.d.ts +1 -1
  88. package/dist/esm/shared/utils/formatUsername.js +3 -1
  89. package/dist/styles/index.css +1 -1
  90. package/dist/types/anyspend/index.native.d.ts +0 -2
  91. package/dist/types/anyspend/react/components/AnySpend.d.ts +3 -3
  92. package/dist/types/anyspend/react/components/AnySpendCustom.d.ts +1 -1
  93. package/dist/types/anyspend/react/components/AnySpendFingerprintWrapper.d.ts +1 -1
  94. package/dist/types/anyspend/react/components/common/CryptoPaymentMethod.d.ts +4 -4
  95. package/dist/types/anyspend/react/components/common/OrderDetails.d.ts +2 -2
  96. package/dist/types/anyspend/react/components/common/RecipientSelection.d.ts +42 -0
  97. package/dist/types/anyspend/react/components/common/RecipientSelection.example.d.ts +7 -0
  98. package/dist/types/anyspend/react/components/index.d.ts +1 -0
  99. package/dist/types/anyspend/react/hooks/index.d.ts +1 -0
  100. package/dist/types/anyspend/react/hooks/useConnectedUserProfile.d.ts +12 -0
  101. package/dist/types/anyspend/react/hooks/useSigMint.d.ts +5 -5
  102. package/dist/types/anyspend/react/index.d.ts +1 -1
  103. package/dist/types/anyspend/react/providers/index.d.ts +2 -0
  104. package/dist/types/anyspend/types/api.d.ts +35 -56
  105. package/dist/types/anyspend/utils/chain.d.ts +1 -1
  106. package/dist/types/global-account/react/components/B3Provider/B3Provider.d.ts +5 -1
  107. package/dist/types/global-account/react/hooks/index.d.ts +1 -1
  108. package/dist/types/global-account/react/hooks/useProfile.d.ts +2 -1
  109. package/dist/types/shared/utils/formatUsername.d.ts +1 -1
  110. package/package.json +2 -2
  111. package/src/anyspend/index.native.ts +0 -6
  112. package/src/anyspend/react/components/AnySpend.tsx +110 -134
  113. package/src/anyspend/react/components/AnySpendCustom.tsx +488 -196
  114. package/src/anyspend/react/components/AnySpendFingerprintWrapper.tsx +4 -8
  115. package/src/anyspend/react/components/AnySpendNFT.tsx +1 -1
  116. package/src/anyspend/react/components/common/ConnectWalletPayment.tsx +1 -1
  117. package/src/anyspend/react/components/common/CryptoPaymentMethod.tsx +76 -108
  118. package/src/anyspend/react/components/common/FiatPaymentMethod.tsx +1 -1
  119. package/src/anyspend/react/components/common/OrderDetails.tsx +12 -13
  120. package/src/anyspend/react/components/common/OrderStatus.tsx +2 -2
  121. package/src/anyspend/react/components/common/PaymentStripeWeb2.tsx +1 -3
  122. package/src/anyspend/react/components/common/RecipientSelection.example.tsx +52 -0
  123. package/src/anyspend/react/components/common/RecipientSelection.tsx +146 -0
  124. package/src/anyspend/react/components/common/TransferCryptoDetails.tsx +1 -0
  125. package/src/anyspend/react/components/index.ts +1 -0
  126. package/src/anyspend/react/hooks/index.ts +1 -0
  127. package/src/anyspend/react/hooks/useConnectedUserProfile.ts +26 -0
  128. package/src/anyspend/react/index.ts +1 -1
  129. package/src/anyspend/react/providers/index.ts +2 -0
  130. package/src/anyspend/types/api.ts +37 -58
  131. package/src/anyspend/utils/chain.ts +126 -18
  132. package/src/global-account/react/components/B3Provider/B3Provider.tsx +6 -1
  133. package/src/global-account/react/hooks/index.ts +1 -1
  134. package/src/global-account/react/hooks/useProfile.ts +10 -5
  135. package/src/shared/constants/index.ts +5 -3
  136. package/src/shared/utils/formatUsername.ts +3 -2
@@ -7,23 +7,18 @@ import {
7
7
  useAnyspendOrderAndTransactions,
8
8
  useAnyspendQuote,
9
9
  useAnyspendTokenList,
10
+ useConnectedUserProfile,
10
11
  useGeoOnrampOptions,
11
12
  } from "@b3dotfun/sdk/anyspend/react";
12
13
  import { components } from "@b3dotfun/sdk/anyspend/types/api";
13
14
  import { GetQuoteRequest, GetQuoteResponse } from "@b3dotfun/sdk/anyspend/types/api_req_res";
14
15
  import {
15
16
  Badge,
16
- Button,
17
- Dialog,
18
- DialogContent,
19
- Input,
20
17
  ShinyButton,
21
18
  Skeleton,
22
19
  StyleRoot,
23
20
  Tabs,
24
21
  TabsContent,
25
- TabsList,
26
- TabTrigger,
27
22
  TextShimmer,
28
23
  Tooltip,
29
24
  TooltipContent,
@@ -36,27 +31,34 @@ import {
36
31
  useSearchParamsSSR,
37
32
  useTokenBalancesByChain,
38
33
  } from "@b3dotfun/sdk/global-account/react";
39
- import { cn } from "@b3dotfun/sdk/shared/utils";
40
- import centerTruncate from "@b3dotfun/sdk/shared/utils/centerTruncate";
34
+ import { cn, formatUsername } from "@b3dotfun/sdk/shared/utils";
35
+
36
+ import { shortenAddress } from "@b3dotfun/sdk/shared/utils/formatAddress";
41
37
  import { formatTokenAmount, formatUnits } from "@b3dotfun/sdk/shared/utils/number";
42
38
  import { simpleHashChainToChainName } from "@b3dotfun/sdk/shared/utils/simplehash";
43
39
  import invariant from "invariant";
44
- import { ChevronRightCircle, Loader2 } from "lucide-react";
40
+ import { ChevronRight, ChevronRightCircle, Loader2 } from "lucide-react";
45
41
  import { motion } from "motion/react";
46
42
  import React, { useCallback, useEffect, useMemo, useState } from "react";
47
43
  import { toast } from "sonner";
48
44
  import { base, baseSepolia } from "viem/chains";
45
+ import { AnySpendFingerprintWrapper, getFingerprintConfig } from "./AnySpendFingerprintWrapper";
46
+ import { CryptoPaymentMethod, CryptoPaymentMethodType } from "./common/CryptoPaymentMethod";
47
+ import { FiatPaymentMethod, FiatPaymentMethodComponent } from "./common/FiatPaymentMethod";
49
48
  import { OrderDetails } from "./common/OrderDetails";
50
49
  import { OrderHistory } from "./common/OrderHistory";
51
50
  import { OrderStatus as OrderStatusDisplay } from "./common/OrderStatus";
52
51
  import { OrderToken } from "./common/OrderToken";
53
- import { PanelOnrampPayment } from "./common/PanelOnrampPayment";
52
+ import { RecipientSelection } from "./common/RecipientSelection";
54
53
 
55
54
  enum PanelView {
56
55
  CONFIRM_ORDER,
57
56
  HISTORY,
58
57
  ORDER_DETAILS,
59
58
  LOADING,
59
+ RECIPIENT_SELECTION,
60
+ CRYPTO_PAYMENT_METHOD,
61
+ FIAT_PAYMENT_METHOD,
60
62
  }
61
63
 
62
64
  function generateGetRelayQuoteRequest({
@@ -141,7 +143,39 @@ function generateGetRelayQuoteRequest({
141
143
  }
142
144
  }
143
145
 
144
- export function AnySpendCustom({
146
+ export function AnySpendCustom(props: {
147
+ isMainnet?: boolean;
148
+ loadOrder?: string;
149
+ mode?: "modal" | "page";
150
+ recipientAddress?: string;
151
+ spenderAddress?: string;
152
+ orderType: components["schemas"]["Order"]["type"];
153
+ dstChainId: number;
154
+ dstToken: components["schemas"]["Token"];
155
+ dstAmount: string;
156
+ contractAddress: string;
157
+ encodedData: string;
158
+ metadata: any;
159
+ header: ({
160
+ anyspendPrice,
161
+ isLoadingAnyspendPrice,
162
+ }: {
163
+ anyspendPrice: GetQuoteResponse | undefined;
164
+ isLoadingAnyspendPrice: boolean;
165
+ }) => React.JSX.Element;
166
+ onSuccess?: (txHash?: string) => void;
167
+ showRecipient?: boolean;
168
+ }) {
169
+ const fingerprintConfig = getFingerprintConfig();
170
+
171
+ return (
172
+ <AnySpendFingerprintWrapper fingerprint={fingerprintConfig}>
173
+ <AnySpendCustomInner {...props} />
174
+ </AnySpendFingerprintWrapper>
175
+ );
176
+ }
177
+
178
+ function AnySpendCustomInner({
145
179
  isMainnet = true,
146
180
  loadOrder,
147
181
  mode = "modal",
@@ -190,20 +224,20 @@ export function AnySpendCustom({
190
224
  );
191
225
  const [activeTab, setActiveTab] = useState<"crypto" | "fiat">("crypto");
192
226
 
227
+ // Add state for selected payment methods
228
+ const [selectedCryptoPaymentMethod, setSelectedCryptoPaymentMethod] = useState<CryptoPaymentMethodType>(
229
+ CryptoPaymentMethodType.NONE,
230
+ );
231
+ const [selectedFiatPaymentMethod, setSelectedFiatPaymentMethod] = useState<FiatPaymentMethod>(FiatPaymentMethod.NONE);
232
+
193
233
  // Get current user's wallet
194
234
  const currentWallet = useAccountWallet();
195
235
 
196
- // Add state for recipient modal
197
- const [isRecipientModalOpen, setIsRecipientModalOpen] = useState(false);
198
-
199
236
  // Add state for custom recipient
200
237
  const [customRecipientAddress, setCustomRecipientAddress] = useState<string | undefined>(recipientAddressProps);
201
238
 
202
239
  // Update recipient logic to use custom recipient
203
240
  const recipientAddress = customRecipientAddress || currentWallet.address;
204
- const recipientPropsProfile = useProfile({ address: recipientAddress });
205
- const recipientEnsName = recipientPropsProfile.data?.name?.replace(/\.b3\.fun/g, "");
206
- const recipientImageUrl = recipientPropsProfile.data?.avatar || currentWallet.wallet.meta?.icon;
207
241
 
208
242
  const [orderId, setOrderId] = useState<string | undefined>(loadOrder);
209
243
 
@@ -337,7 +371,8 @@ export function AnySpendCustom({
337
371
  );
338
372
 
339
373
  // Get geo data and onramp options (after quote is available)
340
- const { geoData, isOnrampSupported } = useGeoOnrampOptions(isMainnet, srcFiatAmount);
374
+ const { geoData, isOnrampSupported, coinbaseAvailablePaymentMethods, isStripeOnrampSupported, stripeWeb2Support } =
375
+ useGeoOnrampOptions(isMainnet, srcFiatAmount);
341
376
 
342
377
  useEffect(() => {
343
378
  if (oat?.data?.order.status === "executed") {
@@ -369,6 +404,10 @@ export function AnySpendCustom({
369
404
 
370
405
  const isCreatingOrder = isCreatingRegularOrder || isCreatingOnrampOrder;
371
406
 
407
+ const { address: connectedAddress, name: connectedName, profile: connectedProfile } = useConnectedUserProfile();
408
+ const recipientProfile = useProfile({ address: recipientAddress });
409
+ const recipientName = recipientProfile.data?.name;
410
+
372
411
  const handleCreateOrder = async (
373
412
  recipientAddress: string,
374
413
  onramp?: { paymentMethod: string; vendor: components["schemas"]["OnrampMetadata"]["vendor"] },
@@ -393,7 +432,7 @@ export function AnySpendCustom({
393
432
  ? {
394
433
  type: "erc1155",
395
434
  contractAddress: metadata.nftContract.contractAddress,
396
- tokenId: metadata.nftContract.tokenId!,
435
+ tokenId: metadata.nftContract.tokenId ?? 0,
397
436
  name: metadata.nftContract.name,
398
437
  description: metadata.nftContract.description,
399
438
  imageUrl: metadata.nftContract.imageUrl,
@@ -431,15 +470,20 @@ export function AnySpendCustom({
431
470
  } as CreateOrderParams;
432
471
 
433
472
  if (onramp) {
434
- invariant(srcToken.address === USDC_BASE.address, "Selected src token is not USDC");
435
- invariant(srcChainId === base.id, "Selected src chain is not base");
473
+ const effectiveSrcToken = activeTab === "fiat" ? USDC_BASE : srcToken;
474
+ invariant(effectiveSrcToken.address === USDC_BASE.address, "Selected src token is not USDC");
475
+ invariant((activeTab === "fiat" ? base.id : srcChainId) === base.id, "Selected src chain is not base");
476
+
477
+ // Get the current geo data from the hook
478
+ const currentGeoData = geoData;
479
+
436
480
  void createOnrampOrder({
437
481
  ...createOrderParams,
438
482
  srcFiatAmount: srcFiatAmount,
439
483
  onramp: {
440
484
  vendor: onramp.vendor,
441
485
  paymentMethod: onramp.paymentMethod,
442
- country: geoData?.country || "US",
486
+ country: currentGeoData?.country || "US",
443
487
  redirectUrl:
444
488
  window.location.origin === "https://basement.fun"
445
489
  ? "https://basement.fun/deposit"
@@ -461,22 +505,23 @@ export function AnySpendCustom({
461
505
  paymentMethod: string;
462
506
  vendor: components["schemas"]["OnrampMetadata"]["vendor"];
463
507
  }) => {
464
- // if (!isAuthenticated) {
465
- // // Copied from https://github.com/b3-fun/b3-mono/blob/main/apps/anyspend-web/components/User/index.tsx#L85
466
- // setB3ModalContentType({
467
- // chain: {
468
- // ...b3,
469
- // rpc: "https://mainnet-rpc.b3.fun",
470
- // blockExplorers: [{ name: "B3 Explorer", url: "https://explorer.b3.fun/" }],
471
- // testnet: undefined,
472
- // },
473
- // partnerId: String(process.env.NEXT_PUBLIC_THIRDWEB_PARTNER_ID),
474
- // type: "signInWithB3",
475
- // showBackButton: false,
476
- // });
477
- // setB3ModalOpen(true);
478
- // return;
479
- // }
508
+ // Check if recipient is selected
509
+ if (!recipientAddress) {
510
+ setActivePanel(PanelView.RECIPIENT_SELECTION);
511
+ return;
512
+ }
513
+
514
+ // Check payment method selection for crypto tab
515
+ if (activeTab === "crypto" && selectedCryptoPaymentMethod === CryptoPaymentMethodType.NONE) {
516
+ setActivePanel(PanelView.CRYPTO_PAYMENT_METHOD);
517
+ return;
518
+ }
519
+
520
+ // Check payment method selection for fiat tab
521
+ if (activeTab === "fiat" && selectedFiatPaymentMethod === FiatPaymentMethod.NONE) {
522
+ setActivePanel(PanelView.FIAT_PAYMENT_METHOD);
523
+ return;
524
+ }
480
525
 
481
526
  if (recipientAddress) {
482
527
  try {
@@ -488,6 +533,50 @@ export function AnySpendCustom({
488
533
  }
489
534
  };
490
535
 
536
+ // Handle fiat order creation
537
+ const handleFiatOrder = async (paymentMethod: FiatPaymentMethod) => {
538
+ try {
539
+ invariant(anyspendQuote, "Relay price is not found");
540
+ invariant(recipientAddress, "Recipient address is not found");
541
+
542
+ if (!srcFiatAmount || parseFloat(srcFiatAmount) <= 0) {
543
+ toast.error("Please enter a valid amount");
544
+ return;
545
+ }
546
+
547
+ // Determine vendor and payment method string based on selected payment method
548
+ let vendor: components["schemas"]["OnrampMetadata"]["vendor"];
549
+ let paymentMethodString = "";
550
+
551
+ if (paymentMethod === FiatPaymentMethod.COINBASE_PAY) {
552
+ if (coinbaseAvailablePaymentMethods.length === 0) {
553
+ toast.error("Coinbase Pay not available");
554
+ return;
555
+ }
556
+ vendor = "coinbase";
557
+ paymentMethodString = coinbaseAvailablePaymentMethods[0]?.id || "";
558
+ } else if (paymentMethod === FiatPaymentMethod.STRIPE) {
559
+ if (!isStripeOnrampSupported && (!stripeWeb2Support || !stripeWeb2Support.isSupport)) {
560
+ toast.error("Stripe not available");
561
+ return;
562
+ }
563
+ vendor = stripeWeb2Support && stripeWeb2Support.isSupport ? "stripe-web2" : "stripe";
564
+ paymentMethodString = "";
565
+ } else {
566
+ toast.error("Please select a payment method");
567
+ return;
568
+ }
569
+
570
+ await handleCreateOrder(recipientAddress, {
571
+ paymentMethod: paymentMethodString,
572
+ vendor: vendor,
573
+ });
574
+ } catch (err: any) {
575
+ console.error(err);
576
+ toast.error("Failed to create order: " + err.message);
577
+ }
578
+ };
579
+
491
580
  const recipientSection = showRecipient ? (
492
581
  <motion.div
493
582
  initial={false}
@@ -500,7 +589,7 @@ export function AnySpendCustom({
500
589
  transition={{ duration: 0.3, delay: 0.2, ease: "easeInOut" }}
501
590
  className="flex w-full items-center justify-between gap-4"
502
591
  >
503
- <div className="text-b3-react-foreground">
592
+ <div className="text-as-tertiarry text-sm">
504
593
  {orderType === "swap"
505
594
  ? "Recipient"
506
595
  : orderType === "mint_nft"
@@ -509,33 +598,35 @@ export function AnySpendCustom({
509
598
  ? "Join for"
510
599
  : "Recipient"}
511
600
  </div>
512
- <div>
513
- <Button
514
- variant="outline"
515
- className="w-full justify-between border-none p-0"
516
- onClick={() => setIsRecipientModalOpen(true)}
517
- >
518
- {recipientAddress ? (
519
- <div className="flex items-center gap-2">
520
- {recipientImageUrl && (
601
+ <div className="flex items-center gap-2">
602
+ {recipientAddress ? (
603
+ <button
604
+ className={cn("text-as-tertiarry flex h-7 items-center gap-2 rounded-lg")}
605
+ onClick={() => setActivePanel(PanelView.RECIPIENT_SELECTION)}
606
+ >
607
+ <>
608
+ {recipientProfile && (
521
609
  <img
522
- src={recipientImageUrl}
523
- alt={recipientImageUrl}
524
- className="bg-b3-react-foreground size-7 rounded-full object-cover opacity-100"
610
+ src={recipientProfile.data?.avatar || ""}
611
+ alt={recipientProfile.data?.name || ""}
612
+ className="bg-b3-react-foreground size-6 rounded-full object-cover opacity-100"
525
613
  />
526
614
  )}
527
- <div className="flex flex-col items-start gap-1">
528
- {recipientEnsName && <span>@{recipientEnsName}</span>}
529
- <span>{centerTruncate(recipientAddress)}</span>
615
+ <div className="text-as-tertiarry flex items-center gap-1 text-sm">
616
+ {recipientName && <span>{formatUsername(recipientName)}</span>}
617
+ <span>{shortenAddress(recipientAddress)}</span>
530
618
  </div>
531
- </div>
532
- ) : (
533
- <div className="text-b3-react-foreground/60 flex items-center gap-2">
534
- <span>Select address</span>
535
- </div>
536
- )}
537
- <ChevronRightCircle className="ml-2 size-4 shrink-0 opacity-50" />
538
- </Button>
619
+ </>
620
+ </button>
621
+ ) : (
622
+ <button
623
+ className="text-as-primary/70 flex items-center gap-1 rounded-lg"
624
+ onClick={() => setActivePanel(PanelView.RECIPIENT_SELECTION)}
625
+ >
626
+ <div className="text-sm font-medium">Select recipient</div>
627
+ </button>
628
+ )}
629
+ <ChevronRight className="h-4 w-4" />
539
630
  </div>
540
631
  </motion.div>
541
632
  ) : null;
@@ -561,7 +652,7 @@ export function AnySpendCustom({
561
652
  <div
562
653
  className={cn(
563
654
  "mx-auto flex w-full flex-col items-center gap-4 p-5",
564
- mode === "modal" && "bg-b3-react-background",
655
+ mode === "modal" && "bg-b3-react-background rounded-xl",
565
656
  )}
566
657
  >
567
658
  {oat && (
@@ -575,6 +666,7 @@ export function AnySpendCustom({
575
666
  relayTx={oat.data.relayTx}
576
667
  executeTx={oat.data.executeTx}
577
668
  refundTxs={oat.data.refundTxs}
669
+ cryptoPaymentMethod={activeTab === "fiat" ? CryptoPaymentMethodType.NONE : selectedCryptoPaymentMethod}
578
670
  onBack={() => {
579
671
  setOrderId(undefined);
580
672
  setActivePanel(PanelView.CONFIRM_ORDER);
@@ -673,34 +765,68 @@ export function AnySpendCustom({
673
765
  <div className={"relative mx-auto flex w-full flex-col items-center"}>
674
766
  {header({ anyspendPrice: anyspendQuote, isLoadingAnyspendPrice: isLoadingAnyspendQuote })}
675
767
 
676
- <div className="divider w-full" />
677
-
678
768
  <Tabs
679
769
  value={activeTab}
680
770
  onValueChange={value => setActiveTab(value as "crypto" | "fiat")}
681
771
  className="bg-b3-react-background max-h-[60dvh] w-full overflow-y-auto p-5"
682
772
  >
683
- <TabsList hideGradient className="justify-center">
684
- <TabTrigger value="crypto">
685
- <span className="text-as-primary w-[140px]">Pay with crypto</span>
686
- </TabTrigger>
687
- {isOnrampSupported ? (
688
- <TabTrigger value="fiat">
689
- <span className="text-as-primary w-[140px]">Pay with fiat</span>
690
- </TabTrigger>
691
- ) : (
692
- <Tooltip>
693
- <TooltipTrigger asChild>
694
- <TabTrigger value="fiat" disabled>
695
- <span className="text-as-primary w-[140px]">Pay with fiat</span>
696
- </TabTrigger>
697
- </TooltipTrigger>
698
- <TooltipContent>
699
- <span className="text-as-primary w-[140px]">Fiat payments are not supported for this amount</span>
700
- </TooltipContent>
701
- </Tooltip>
702
- )}
703
- </TabsList>
773
+ <div className="w-full">
774
+ <div className="bg-as-surface-secondary relative mb-4 grid h-10 grid-cols-2 rounded-xl">
775
+ <div
776
+ className={cn(
777
+ "bg-as-brand absolute bottom-0 left-0 top-0 z-0 rounded-xl transition-transform duration-100",
778
+ "h-full w-1/2",
779
+ activeTab === "fiat" ? "translate-x-full" : "translate-x-0",
780
+ )}
781
+ style={{ willChange: "transform" }}
782
+ />
783
+ <button
784
+ className={cn(
785
+ "relative z-10 h-full w-full rounded-xl px-3 text-sm font-medium transition-colors duration-100",
786
+ activeTab === "crypto" ? "text-white" : "text-as-primary/70 hover:bg-as-on-surface-2 bg-transparent",
787
+ )}
788
+ onClick={() => {
789
+ setActiveTab("crypto");
790
+ setSelectedCryptoPaymentMethod(CryptoPaymentMethodType.NONE);
791
+ setSelectedFiatPaymentMethod(FiatPaymentMethod.NONE);
792
+ }}
793
+ >
794
+ Pay with crypto
795
+ </button>
796
+ {isOnrampSupported ? (
797
+ <button
798
+ className={cn(
799
+ "relative z-10 h-full w-full rounded-xl px-3 text-sm font-medium transition-colors duration-100",
800
+ activeTab === "fiat" ? "text-white" : "text-as-primary/70 hover:bg-as-on-surface-2 bg-transparent",
801
+ )}
802
+ onClick={() => {
803
+ setActiveTab("fiat");
804
+ setSelectedCryptoPaymentMethod(CryptoPaymentMethodType.NONE);
805
+ setSelectedFiatPaymentMethod(FiatPaymentMethod.NONE);
806
+ }}
807
+ >
808
+ Pay with fiat
809
+ </button>
810
+ ) : (
811
+ <Tooltip>
812
+ <TooltipTrigger asChild>
813
+ <button
814
+ className={cn(
815
+ "relative z-10 h-full w-full rounded-xl px-3 text-sm font-medium transition-colors duration-100",
816
+ "text-as-primary/50 cursor-not-allowed bg-transparent",
817
+ )}
818
+ disabled
819
+ >
820
+ Pay with fiat
821
+ </button>
822
+ </TooltipTrigger>
823
+ <TooltipContent>
824
+ <span className="text-as-primary w-[140px]">Fiat payments are not supported for this amount</span>
825
+ </TooltipContent>
826
+ </Tooltip>
827
+ )}
828
+ </div>
829
+ </div>
704
830
 
705
831
  {/* Warning */}
706
832
  {/* {srcChainId === base.id || dstChainId === base.id || activeTab === "fiat" ? (
@@ -713,8 +839,9 @@ export function AnySpendCustom({
713
839
 
714
840
  {/* Crypto tab */}
715
841
  <TabsContent value="crypto">
716
- <div className="mt-2 flex flex-col gap-4">
717
- <div className="flex flex-col gap-4">
842
+ <div className="mt-2 flex flex-col gap-6">
843
+ <div className="border-as-border-secondary bg-as-surface-secondary flex w-full flex-col gap-4 rounded-xl border p-4">
844
+ {/* Payment Method Selection */}
718
845
  <motion.div
719
846
  initial={false}
720
847
  animate={{
@@ -725,21 +852,203 @@ export function AnySpendCustom({
725
852
  transition={{ duration: 0.3, delay: 0, ease: "easeInOut" }}
726
853
  className="relative flex w-full items-center justify-between"
727
854
  >
728
- <div className="font-medium">Pay with</div>
729
- <OrderToken
730
- address={currentWallet?.wallet?.address}
731
- context="from"
732
- chainId={srcChainId}
733
- setChainId={setSrcChainId}
734
- token={srcToken}
735
- setToken={token => {
736
- setDirtySelectSrcToken(true);
737
- setSrcToken(token);
855
+ <div className="text-as-tertiarry flex h-7 items-center text-sm">Pay</div>
856
+ <button
857
+ className="text-as-tertiarry flex h-7 items-center gap-2 text-sm transition-colors hover:text-blue-700"
858
+ onClick={() => setActivePanel(PanelView.CRYPTO_PAYMENT_METHOD)}
859
+ >
860
+ {selectedCryptoPaymentMethod === CryptoPaymentMethodType.CONNECT_WALLET ? (
861
+ <>
862
+ {connectedAddress ? (
863
+ <>
864
+ {connectedProfile?.data?.avatar && (
865
+ <img
866
+ src={connectedProfile.data?.avatar || ""}
867
+ alt="Connected Wallet"
868
+ className="bg-as-primary h-6 w-6 rounded-full"
869
+ />
870
+ )}
871
+ <span className="text-as-tertiarry flex items-center gap-1">
872
+ {connectedName && <span>{formatUsername(connectedName)}</span>}
873
+ <span>{shortenAddress(connectedAddress || "")}</span>
874
+ </span>
875
+ </>
876
+ ) : (
877
+ "Connect wallet"
878
+ )}
879
+ <ChevronRight className="h-4 w-4" />
880
+ </>
881
+ ) : selectedCryptoPaymentMethod === CryptoPaymentMethodType.TRANSFER_CRYPTO ? (
882
+ <>
883
+ Transfer crypto
884
+ <ChevronRight className="h-4 w-4" />
885
+ </>
886
+ ) : (
887
+ <>
888
+ Select payment method
889
+ <ChevronRight className="h-4 w-4" />
890
+ </>
891
+ )}
892
+ </button>
893
+ </motion.div>
894
+
895
+ <div className="divider w-full" />
896
+
897
+ {recipientSection}
898
+
899
+ <div className="divider w-full" />
900
+
901
+ <div className="flex flex-col gap-4">
902
+ <motion.div
903
+ initial={false}
904
+ animate={{
905
+ opacity: hasMounted ? 1 : 0,
906
+ y: hasMounted ? 0 : 20,
907
+ filter: hasMounted ? "blur(0px)" : "blur(10px)",
738
908
  }}
739
- requiredAmount={srcAmount || undefined}
740
- />
909
+ transition={{ duration: 0.3, delay: 0, ease: "easeInOut" }}
910
+ className="relative flex w-full items-center justify-between"
911
+ >
912
+ <div className="text-as-tertiarry text-sm">Pay with</div>
913
+ <OrderToken
914
+ address={currentWallet?.wallet?.address}
915
+ context="from"
916
+ chainId={srcChainId}
917
+ setChainId={setSrcChainId}
918
+ token={srcToken}
919
+ setToken={token => {
920
+ setDirtySelectSrcToken(true);
921
+ setSrcToken(token);
922
+ }}
923
+ requiredAmount={srcAmount || undefined}
924
+ />
925
+ </motion.div>
926
+
927
+ <div className="divider w-full" />
928
+
929
+ <motion.div
930
+ initial={false}
931
+ animate={{
932
+ opacity: hasMounted ? 1 : 0,
933
+ y: hasMounted ? 0 : 20,
934
+ filter: hasMounted ? "blur(0px)" : "blur(10px)",
935
+ }}
936
+ transition={{ duration: 0.3, delay: 0.1, ease: "easeInOut" }}
937
+ className="relative flex w-full items-center justify-between"
938
+ >
939
+ <span className="text-as-tertiarry text-sm">
940
+ Total <span className="text-as-tertiarry">(with fee)</span>
941
+ </span>
942
+ <span className="text-as-primary font-semibold">
943
+ {formattedSrcAmount || "--"} {srcToken.symbol}
944
+ </span>
945
+ </motion.div>
946
+ </div>
947
+ </div>
948
+
949
+ {/* Action Buttons */}
950
+ <div className={cn("flex w-full flex-col items-center justify-between gap-2")}>
951
+ <motion.div
952
+ initial={false}
953
+ animate={{
954
+ opacity: hasMounted ? 1 : 0,
955
+ y: hasMounted ? 0 : 20,
956
+ filter: hasMounted ? "blur(0px)" : "blur(10px)",
957
+ }}
958
+ transition={{ duration: 0.3, delay: 0.3, ease: "easeInOut" }}
959
+ className="flex w-full flex-col gap-2"
960
+ >
961
+ <ShinyButton
962
+ accentColor={"hsl(var(--as-brand))"}
963
+ textColor="text-white"
964
+ disabled={isCreatingOrder || isLoadingAnyspendQuote || !anyspendQuote}
965
+ onClick={() => handleConfirmOrder()}
966
+ className="relative w-full"
967
+ >
968
+ {isCreatingOrder ? (
969
+ <div className="flex items-center gap-2">
970
+ <Loader2 className="size-4 animate-spin" />
971
+ <span>Creating order...</span>
972
+ </div>
973
+ ) : isLoadingAnyspendQuote ? (
974
+ <div className="flex items-center gap-2">
975
+ <Loader2 className="size-4 animate-spin" />
976
+ <span>Loading quote...</span>
977
+ </div>
978
+ ) : !recipientAddress ? (
979
+ "Select recipient"
980
+ ) : selectedCryptoPaymentMethod === CryptoPaymentMethodType.NONE ? (
981
+ "Choose payment method"
982
+ ) : anyspendQuote ? (
983
+ <>
984
+ <span>Checkout</span>
985
+ <ChevronRightCircle className="absolute right-0 top-1/2 size-6 -translate-y-1/2 opacity-70" />
986
+ </>
987
+ ) : (
988
+ "No quote found"
989
+ )}
990
+ </ShinyButton>
991
+ </motion.div>
992
+ </div>
993
+ </div>
994
+ </TabsContent>
995
+
996
+ {/* Fiat tab */}
997
+ <TabsContent value="fiat">
998
+ <div className="mt-2 flex flex-col gap-6">
999
+ <div className="border-as-border-secondary bg-as-surface-secondary flex w-full flex-col gap-4 rounded-xl border p-4">
1000
+ {/* Fiat Payment Method Selection */}
1001
+ <motion.div
1002
+ initial={false}
1003
+ animate={{
1004
+ opacity: hasMounted ? 1 : 0,
1005
+ y: hasMounted ? 0 : 20,
1006
+ filter: hasMounted ? "blur(0px)" : "blur(10px)",
1007
+ }}
1008
+ transition={{ duration: 0.3, delay: 0, ease: "easeInOut" }}
1009
+ className="relative flex w-full items-center justify-between"
1010
+ >
1011
+ <div className="text-as-tertiarry flex h-7 items-center text-sm">Pay with</div>
1012
+ <button
1013
+ className="text-as-tertiarry flex h-7 items-center gap-1 text-sm transition-colors hover:text-blue-700"
1014
+ onClick={() => setActivePanel(PanelView.FIAT_PAYMENT_METHOD)}
1015
+ >
1016
+ {selectedFiatPaymentMethod === FiatPaymentMethod.COINBASE_PAY ? (
1017
+ <>
1018
+ <div className="flex items-center gap-2">
1019
+ <div className="flex h-5 w-5 items-center justify-center rounded-full bg-blue-600">
1020
+ <span className="text-xs font-bold text-white">C</span>
1021
+ </div>
1022
+ Coinbase Pay
1023
+ </div>
1024
+ <ChevronRight className="h-4 w-4" />
1025
+ </>
1026
+ ) : selectedFiatPaymentMethod === FiatPaymentMethod.STRIPE ? (
1027
+ <>
1028
+ <div className="flex items-center gap-2">
1029
+ <div className="flex h-5 w-5 items-center justify-center rounded-full bg-blue-600">
1030
+ <span className="text-xs font-bold text-white">S</span>
1031
+ </div>
1032
+ Credit/Debit Card
1033
+ </div>
1034
+ <ChevronRight className="h-4 w-4" />
1035
+ </>
1036
+ ) : (
1037
+ <>
1038
+ Select payment method
1039
+ <ChevronRight className="h-4 w-4" />
1040
+ </>
1041
+ )}
1042
+ </button>
741
1043
  </motion.div>
742
1044
 
1045
+ <div className="divider w-full" />
1046
+
1047
+ {recipientSection}
1048
+
1049
+ <div className="divider w-full" />
1050
+
1051
+ {/* Fiat Amount Display */}
743
1052
  <motion.div
744
1053
  initial={false}
745
1054
  animate={{
@@ -750,17 +1059,13 @@ export function AnySpendCustom({
750
1059
  transition={{ duration: 0.3, delay: 0.1, ease: "easeInOut" }}
751
1060
  className="relative flex w-full items-center justify-between"
752
1061
  >
753
- <span className="font-medium">
754
- Total <span className="text-sm text-gray-500">(with fee)</span>
1062
+ <span className="text-as-tertiarry text-sm">
1063
+ Total <span className="text-as-tertiarry">(USD)</span>
755
1064
  </span>
756
- <h2 className={cn("text-as-primary text-2xl font-semibold")}>
757
- {formattedSrcAmount || "--"} {srcToken.symbol}
758
- </h2>
1065
+ <span className="text-as-primary text-xl font-semibold">${srcFiatAmount || "0.00"}</span>
759
1066
  </motion.div>
760
1067
  </div>
761
1068
 
762
- {recipientSection}
763
-
764
1069
  {/* Action Buttons */}
765
1070
  <div className={cn("flex w-full flex-col items-center justify-between gap-2")}>
766
1071
  <motion.div
@@ -776,8 +1081,14 @@ export function AnySpendCustom({
776
1081
  <ShinyButton
777
1082
  accentColor={"hsl(var(--as-brand))"}
778
1083
  textColor="text-white"
779
- disabled={isCreatingOrder || isLoadingAnyspendQuote || !anyspendQuote || !recipientAddress}
780
- onClick={() => handleConfirmOrder()}
1084
+ disabled={isCreatingOrder || isLoadingAnyspendQuote || !anyspendQuote}
1085
+ onClick={() => {
1086
+ if (selectedFiatPaymentMethod !== FiatPaymentMethod.NONE) {
1087
+ handleFiatOrder(selectedFiatPaymentMethod);
1088
+ } else {
1089
+ handleConfirmOrder();
1090
+ }
1091
+ }}
781
1092
  className="relative w-full"
782
1093
  >
783
1094
  {isCreatingOrder ? (
@@ -790,80 +1101,78 @@ export function AnySpendCustom({
790
1101
  <Loader2 className="size-4 animate-spin" />
791
1102
  <span>Loading quote...</span>
792
1103
  </div>
793
- ) : anyspendQuote && recipientAddress ? (
1104
+ ) : !recipientAddress ? (
1105
+ "Select recipient"
1106
+ ) : selectedFiatPaymentMethod === FiatPaymentMethod.NONE ? (
1107
+ "Select payment method"
1108
+ ) : anyspendQuote ? (
794
1109
  <>
795
- <span>Checkout</span>
1110
+ <span>Buy</span>
796
1111
  <ChevronRightCircle className="absolute right-0 top-1/2 size-6 -translate-y-1/2 opacity-70" />
797
1112
  </>
798
- ) : recipientAddress ? (
799
- "No quote found"
800
1113
  ) : (
801
- "Please select a recipient"
1114
+ "No quote found"
802
1115
  )}
803
1116
  </ShinyButton>
804
1117
  </motion.div>
805
1118
  </div>
806
1119
  </div>
807
1120
  </TabsContent>
808
-
809
- {/* Fiat tab */}
810
- <TabsContent value="fiat">
811
- <div className="mt-6 flex w-full flex-col gap-6">
812
- <PanelOnrampPayment
813
- srcAmountOnRamp={srcAmount ? formatUnits(srcAmount.toString(), USDC_BASE.decimals) : "0"}
814
- recipientName={recipientEnsName}
815
- recipientAddress={recipientAddress}
816
- isMainnet={isMainnet}
817
- isBuyMode={false}
818
- selectedDstChainId={dstChainId}
819
- selectedDstToken={dstToken}
820
- anyspendQuote={anyspendQuote}
821
- globalAddress={currentWallet?.wallet?.address}
822
- onOrderCreated={(orderId: string) => setOrderId(orderId)}
823
- onBack={() => setActiveTab("crypto")}
824
- orderType={orderType}
825
- nft={
826
- metadata.type === "mint_nft"
827
- ? metadata.nftContract.type === "erc1155"
828
- ? {
829
- type: "erc1155",
830
- contractAddress: metadata.nftContract.contractAddress,
831
- tokenId: metadata.nftContract.tokenId!,
832
- imageUrl: metadata.nftContract.imageUrl,
833
- name: metadata.nftContract.name,
834
- description: metadata.nftContract.description,
835
- price: dstAmount,
836
- }
837
- : {
838
- type: "erc721",
839
- contractAddress: metadata.nftContract.contractAddress,
840
- name: metadata.nftContract.name,
841
- description: metadata.nftContract.description,
842
- imageUrl: metadata.nftContract.imageUrl,
843
- price: dstAmount,
844
- }
845
- : undefined
846
- }
847
- payload={
848
- metadata.type === "custom"
849
- ? {
850
- ...metadata,
851
- amount: dstAmount,
852
- data: encodedData,
853
- to: contractAddress,
854
- spenderAddress: spenderAddress,
855
- }
856
- : undefined
857
- }
858
- recipientEnsName={recipientEnsName}
859
- recipientImageUrl={recipientImageUrl}
860
- />
861
- </div>
862
- </TabsContent>
863
1121
  </Tabs>
864
1122
  </div>
865
1123
  );
866
1124
 
1125
+ // Recipient selection view
1126
+ const recipientSelectionView = (
1127
+ <div className={cn("bg-as-surface-primary mx-auto w-[460px] max-w-full rounded-xl p-4")}>
1128
+ <RecipientSelection
1129
+ initialValue={customRecipientAddress || ""}
1130
+ title="Add recipient address or ENS"
1131
+ description="Send tokens to another address"
1132
+ onBack={() => setActivePanel(PanelView.CONFIRM_ORDER)}
1133
+ onConfirm={address => {
1134
+ setCustomRecipientAddress(address);
1135
+ setActivePanel(PanelView.CONFIRM_ORDER);
1136
+ }}
1137
+ />
1138
+ </div>
1139
+ );
1140
+
1141
+ // Crypto payment method view
1142
+ const cryptoPaymentMethodView = (
1143
+ <div className={cn("bg-as-surface-primary mx-auto w-[460px] max-w-full rounded-xl p-4")}>
1144
+ <CryptoPaymentMethod
1145
+ globalAddress={currentWallet?.wallet?.address}
1146
+ globalWallet={currentWallet?.wallet}
1147
+ selectedPaymentMethod={selectedCryptoPaymentMethod}
1148
+ setSelectedPaymentMethod={setSelectedCryptoPaymentMethod}
1149
+ isCreatingOrder={isCreatingOrder}
1150
+ onBack={() => setActivePanel(PanelView.CONFIRM_ORDER)}
1151
+ onSelectPaymentMethod={(method: CryptoPaymentMethodType) => {
1152
+ setSelectedCryptoPaymentMethod(method);
1153
+ setActivePanel(PanelView.CONFIRM_ORDER);
1154
+ }}
1155
+ />
1156
+ </div>
1157
+ );
1158
+
1159
+ // Fiat payment method view
1160
+ const fiatPaymentMethodView = (
1161
+ <div className={cn("bg-as-surface-primary mx-auto w-[460px] max-w-full rounded-xl p-4")}>
1162
+ <FiatPaymentMethodComponent
1163
+ selectedPaymentMethod={selectedFiatPaymentMethod}
1164
+ setSelectedPaymentMethod={setSelectedFiatPaymentMethod}
1165
+ onBack={() => setActivePanel(PanelView.CONFIRM_ORDER)}
1166
+ onSelectPaymentMethod={(method: FiatPaymentMethod) => {
1167
+ setSelectedFiatPaymentMethod(method);
1168
+ setActivePanel(PanelView.CONFIRM_ORDER);
1169
+ }}
1170
+ srcAmountOnRamp={srcFiatAmount}
1171
+ isMainnet={isMainnet}
1172
+ />
1173
+ </div>
1174
+ );
1175
+
867
1176
  // Return the TransitionPanel with all views
868
1177
  return (
869
1178
  <StyleRoot>
@@ -886,7 +1195,7 @@ export function AnySpendCustom({
886
1195
  transition={{ type: "spring", stiffness: 300, damping: 30 }}
887
1196
  >
888
1197
  {[
889
- <div key="edit-recipient-view" className="w-full">
1198
+ <div key="confirm-order-view" className="w-full">
890
1199
  {confirmOrderView}
891
1200
  </div>,
892
1201
  <div key="history-view" className="w-full">
@@ -898,34 +1207,17 @@ export function AnySpendCustom({
898
1207
  <div key="loading-view" className="w-full">
899
1208
  {loadingView}
900
1209
  </div>,
1210
+ <div key="recipient-selection-view" className="w-full">
1211
+ {recipientSelectionView}
1212
+ </div>,
1213
+ <div key="crypto-payment-method-view" className="w-full">
1214
+ {cryptoPaymentMethodView}
1215
+ </div>,
1216
+ <div key="fiat-payment-method-view" className="w-full">
1217
+ {fiatPaymentMethodView}
1218
+ </div>,
901
1219
  ]}
902
1220
  </TransitionPanel>
903
-
904
- {/* Add EnterRecipientModal */}
905
- <Dialog open={isRecipientModalOpen} onOpenChange={setIsRecipientModalOpen}>
906
- <DialogContent className="w-[420px] max-w-[calc(100vw-32px)] rounded-2xl p-3.5">
907
- <div className="flex flex-col gap-3">
908
- <div className="text-as-primary font-semibold">To address</div>
909
- <Input
910
- value={customRecipientAddress || ""}
911
- onChange={e => setCustomRecipientAddress(e.target.value)}
912
- placeholder="Enter address"
913
- className="h-12 rounded-lg"
914
- spellCheck={false}
915
- />
916
- <ShinyButton
917
- accentColor={"hsl(var(--as-brand))"}
918
- textColor="text-white"
919
- className="w-full rounded-lg"
920
- onClick={() => {
921
- setIsRecipientModalOpen(false);
922
- }}
923
- >
924
- Save
925
- </ShinyButton>
926
- </div>
927
- </DialogContent>
928
- </Dialog>
929
1221
  </StyleRoot>
930
1222
  );
931
1223
  }