@b3dotfun/sdk 0.0.49 → 0.0.50-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 (161) hide show
  1. package/dist/cjs/anyspend/constants/index.d.ts +1 -0
  2. package/dist/cjs/anyspend/constants/index.js +12 -2
  3. package/dist/cjs/anyspend/react/components/AnySpend.d.ts +2 -1
  4. package/dist/cjs/anyspend/react/components/AnySpend.js +18 -5
  5. package/dist/cjs/anyspend/react/components/AnySpendCustom.js +12 -3
  6. package/dist/cjs/anyspend/react/components/AnyspendDepositHype.js +11 -4
  7. package/dist/cjs/anyspend/react/components/common/CryptoPaySection.d.ts +3 -1
  8. package/dist/cjs/anyspend/react/components/common/CryptoPaySection.js +2 -2
  9. package/dist/cjs/anyspend/react/components/common/CryptoReceiveSection.d.ts +3 -1
  10. package/dist/cjs/anyspend/react/components/common/CryptoReceiveSection.js +17 -11
  11. package/dist/cjs/anyspend/react/components/common/FeeBreakDown.d.ts +12 -0
  12. package/dist/cjs/anyspend/react/components/common/FeeBreakDown.js +19 -0
  13. package/dist/cjs/anyspend/react/components/common/FeeDetailPanel.d.ts +8 -0
  14. package/dist/cjs/anyspend/react/components/common/FeeDetailPanel.js +116 -0
  15. package/dist/cjs/anyspend/react/components/common/OrderDetails.d.ts +1 -0
  16. package/dist/cjs/anyspend/react/components/common/OrderDetails.js +6 -6
  17. package/dist/cjs/anyspend/react/components/common/OrderDetailsCollapsible.d.ts +1 -0
  18. package/dist/cjs/anyspend/react/components/common/OrderDetailsCollapsible.js +3 -2
  19. package/dist/cjs/anyspend/react/components/common/OrderToken.js +1 -1
  20. package/dist/cjs/anyspend/react/components/common/OrderTokenAmount.js +1 -1
  21. package/dist/cjs/anyspend/react/components/common/OrderTokenAmountFiat.js +1 -1
  22. package/dist/cjs/anyspend/react/components/common/OrderTokenAmountNew.js +1 -1
  23. package/dist/cjs/anyspend/react/components/common/PanelOnramp.d.ts +2 -1
  24. package/dist/cjs/anyspend/react/components/common/PanelOnramp.js +36 -21
  25. package/dist/cjs/anyspend/react/components/common/PanelOnrampPayment.js +2 -1
  26. package/dist/cjs/anyspend/react/components/common/PointsDetailPanel.js +1 -2
  27. package/dist/cjs/anyspend/react/contexts/FeatureFlagsContext.js +1 -1
  28. package/dist/cjs/anyspend/react/hooks/useAnyspendFlow.d.ts +3 -1
  29. package/dist/cjs/anyspend/react/hooks/useAnyspendFlow.js +1 -0
  30. package/dist/cjs/anyspend/react/hooks/useAnyspendOrderHistory.d.ts +48 -12
  31. package/dist/cjs/anyspend/types/api.d.ts +133 -178
  32. package/dist/cjs/anyspend/utils/chain.js +4 -4
  33. package/dist/cjs/bondkit/bondkitToken.d.ts +3 -1
  34. package/dist/cjs/bondkit/bondkitToken.js +19 -0
  35. package/dist/cjs/bondkit/components/TradingView.d.ts +1 -1
  36. package/dist/cjs/bondkit/components/TradingView.js +14 -3
  37. package/dist/cjs/bondkit/components/index.d.ts +1 -1
  38. package/dist/cjs/bondkit/components/index.js +1 -1
  39. package/dist/cjs/bondkit/components/types.d.ts +1 -0
  40. package/dist/cjs/bondkit/config.d.ts +1 -0
  41. package/dist/cjs/bondkit/config.js +1 -0
  42. package/dist/cjs/bondkit/index.d.ts +1 -1
  43. package/dist/cjs/bondkit/index.js +2 -6
  44. package/dist/cjs/bondkit/types.d.ts +15 -0
  45. package/dist/cjs/global-account/react/components/B3Provider/B3Provider.d.ts +1 -1
  46. package/dist/cjs/global-account/react/components/B3Provider/B3Provider.js +1 -1
  47. package/dist/cjs/global-account/react/components/B3Provider/RelayKitProviderWrapper.js +2 -2
  48. package/dist/cjs/global-account/react/components/ui/tooltip.js +1 -1
  49. package/dist/cjs/global-account/react/hooks/useAuthentication.js +11 -0
  50. package/dist/cjs/global-account/react/hooks/useFirstEOA.d.ts +7663 -1
  51. package/dist/cjs/global-account/react/hooks/useFirstEOA.js +21 -1
  52. package/dist/cjs/shared/generated/chain-networks.json +40 -7
  53. package/dist/esm/anyspend/constants/index.d.ts +1 -0
  54. package/dist/esm/anyspend/constants/index.js +11 -1
  55. package/dist/esm/anyspend/react/components/AnySpend.d.ts +2 -1
  56. package/dist/esm/anyspend/react/components/AnySpend.js +18 -5
  57. package/dist/esm/anyspend/react/components/AnySpendCustom.js +14 -5
  58. package/dist/esm/anyspend/react/components/AnyspendDepositHype.js +11 -4
  59. package/dist/esm/anyspend/react/components/common/CryptoPaySection.d.ts +3 -1
  60. package/dist/esm/anyspend/react/components/common/CryptoPaySection.js +4 -4
  61. package/dist/esm/anyspend/react/components/common/CryptoReceiveSection.d.ts +3 -1
  62. package/dist/esm/anyspend/react/components/common/CryptoReceiveSection.js +19 -13
  63. package/dist/esm/anyspend/react/components/common/FeeBreakDown.d.ts +12 -0
  64. package/dist/esm/anyspend/react/components/common/FeeBreakDown.js +16 -0
  65. package/dist/esm/anyspend/react/components/common/FeeDetailPanel.d.ts +8 -0
  66. package/dist/esm/anyspend/react/components/common/FeeDetailPanel.js +113 -0
  67. package/dist/esm/anyspend/react/components/common/OrderDetails.d.ts +1 -0
  68. package/dist/esm/anyspend/react/components/common/OrderDetails.js +6 -6
  69. package/dist/esm/anyspend/react/components/common/OrderDetailsCollapsible.d.ts +1 -0
  70. package/dist/esm/anyspend/react/components/common/OrderDetailsCollapsible.js +4 -3
  71. package/dist/esm/anyspend/react/components/common/OrderToken.js +1 -1
  72. package/dist/esm/anyspend/react/components/common/OrderTokenAmount.js +1 -1
  73. package/dist/esm/anyspend/react/components/common/OrderTokenAmountFiat.js +1 -1
  74. package/dist/esm/anyspend/react/components/common/OrderTokenAmountNew.js +1 -1
  75. package/dist/esm/anyspend/react/components/common/PanelOnramp.d.ts +2 -1
  76. package/dist/esm/anyspend/react/components/common/PanelOnramp.js +38 -23
  77. package/dist/esm/anyspend/react/components/common/PanelOnrampPayment.js +2 -1
  78. package/dist/esm/anyspend/react/components/common/PointsDetailPanel.js +2 -3
  79. package/dist/esm/anyspend/react/contexts/FeatureFlagsContext.js +1 -1
  80. package/dist/esm/anyspend/react/hooks/useAnyspendFlow.d.ts +3 -1
  81. package/dist/esm/anyspend/react/hooks/useAnyspendFlow.js +1 -0
  82. package/dist/esm/anyspend/react/hooks/useAnyspendOrderHistory.d.ts +48 -12
  83. package/dist/esm/anyspend/types/api.d.ts +133 -178
  84. package/dist/esm/anyspend/utils/chain.js +4 -4
  85. package/dist/esm/bondkit/bondkitToken.d.ts +3 -1
  86. package/dist/esm/bondkit/bondkitToken.js +19 -0
  87. package/dist/esm/bondkit/components/TradingView.d.ts +1 -1
  88. package/dist/esm/bondkit/components/TradingView.js +14 -3
  89. package/dist/esm/bondkit/components/index.d.ts +1 -1
  90. package/dist/esm/bondkit/components/index.js +1 -1
  91. package/dist/esm/bondkit/components/types.d.ts +1 -0
  92. package/dist/esm/bondkit/config.d.ts +1 -0
  93. package/dist/esm/bondkit/config.js +1 -0
  94. package/dist/esm/bondkit/index.d.ts +1 -1
  95. package/dist/esm/bondkit/index.js +1 -1
  96. package/dist/esm/bondkit/types.d.ts +15 -0
  97. package/dist/esm/global-account/react/components/B3Provider/B3Provider.d.ts +1 -1
  98. package/dist/esm/global-account/react/components/B3Provider/B3Provider.js +1 -1
  99. package/dist/esm/global-account/react/components/B3Provider/RelayKitProviderWrapper.js +2 -2
  100. package/dist/esm/global-account/react/components/ui/tooltip.js +1 -1
  101. package/dist/esm/global-account/react/hooks/useAuthentication.js +11 -0
  102. package/dist/esm/global-account/react/hooks/useFirstEOA.d.ts +7663 -1
  103. package/dist/esm/global-account/react/hooks/useFirstEOA.js +22 -2
  104. package/dist/esm/shared/generated/chain-networks.json +40 -7
  105. package/dist/styles/index.css +1 -1
  106. package/dist/types/anyspend/constants/index.d.ts +1 -0
  107. package/dist/types/anyspend/react/components/AnySpend.d.ts +2 -1
  108. package/dist/types/anyspend/react/components/common/CryptoPaySection.d.ts +3 -1
  109. package/dist/types/anyspend/react/components/common/CryptoReceiveSection.d.ts +3 -1
  110. package/dist/types/anyspend/react/components/common/FeeBreakDown.d.ts +12 -0
  111. package/dist/types/anyspend/react/components/common/FeeDetailPanel.d.ts +8 -0
  112. package/dist/types/anyspend/react/components/common/OrderDetails.d.ts +1 -0
  113. package/dist/types/anyspend/react/components/common/OrderDetailsCollapsible.d.ts +1 -0
  114. package/dist/types/anyspend/react/components/common/PanelOnramp.d.ts +2 -1
  115. package/dist/types/anyspend/react/hooks/useAnyspendFlow.d.ts +3 -1
  116. package/dist/types/anyspend/react/hooks/useAnyspendOrderHistory.d.ts +48 -12
  117. package/dist/types/anyspend/types/api.d.ts +133 -178
  118. package/dist/types/bondkit/bondkitToken.d.ts +3 -1
  119. package/dist/types/bondkit/components/TradingView.d.ts +1 -1
  120. package/dist/types/bondkit/components/index.d.ts +1 -1
  121. package/dist/types/bondkit/components/types.d.ts +1 -0
  122. package/dist/types/bondkit/config.d.ts +1 -0
  123. package/dist/types/bondkit/index.d.ts +1 -1
  124. package/dist/types/bondkit/types.d.ts +15 -0
  125. package/dist/types/global-account/react/components/B3Provider/B3Provider.d.ts +1 -1
  126. package/dist/types/global-account/react/hooks/useFirstEOA.d.ts +7663 -1
  127. package/package.json +4 -4
  128. package/src/anyspend/constants/index.ts +12 -1
  129. package/src/anyspend/react/components/AnySpend.tsx +33 -0
  130. package/src/anyspend/react/components/AnySpendCustom.tsx +69 -7
  131. package/src/anyspend/react/components/AnyspendDepositHype.tsx +24 -0
  132. package/src/anyspend/react/components/common/CryptoPaySection.tsx +14 -2
  133. package/src/anyspend/react/components/common/CryptoReceiveSection.tsx +31 -11
  134. package/src/anyspend/react/components/common/FeeBreakDown.tsx +105 -0
  135. package/src/anyspend/react/components/common/FeeDetailPanel.tsx +334 -0
  136. package/src/anyspend/react/components/common/OrderDetails.tsx +7 -0
  137. package/src/anyspend/react/components/common/OrderDetailsCollapsible.tsx +16 -0
  138. package/src/anyspend/react/components/common/OrderToken.tsx +1 -1
  139. package/src/anyspend/react/components/common/OrderTokenAmount.tsx +1 -1
  140. package/src/anyspend/react/components/common/OrderTokenAmountFiat.tsx +1 -1
  141. package/src/anyspend/react/components/common/OrderTokenAmountNew.tsx +1 -1
  142. package/src/anyspend/react/components/common/PanelOnramp.tsx +58 -27
  143. package/src/anyspend/react/components/common/PanelOnrampPayment.tsx +18 -6
  144. package/src/anyspend/react/components/common/PointsDetailPanel.tsx +1 -13
  145. package/src/anyspend/react/contexts/FeatureFlagsContext.tsx +2 -2
  146. package/src/anyspend/react/hooks/useAnyspendFlow.ts +1 -0
  147. package/src/anyspend/types/api.ts +135 -178
  148. package/src/anyspend/utils/chain.ts +4 -4
  149. package/src/bondkit/bondkitToken.ts +24 -0
  150. package/src/bondkit/components/TradingView.tsx +15 -3
  151. package/src/bondkit/components/index.ts +1 -1
  152. package/src/bondkit/components/types.ts +1 -0
  153. package/src/bondkit/config.ts +2 -0
  154. package/src/bondkit/index.ts +1 -1
  155. package/src/bondkit/types.ts +19 -0
  156. package/src/global-account/react/components/B3Provider/B3Provider.tsx +1 -1
  157. package/src/global-account/react/components/B3Provider/RelayKitProviderWrapper.tsx +2 -2
  158. package/src/global-account/react/components/ui/tooltip.tsx +11 -9
  159. package/src/global-account/react/hooks/useAuthentication.ts +13 -1
  160. package/src/global-account/react/hooks/useFirstEOA.tsx +20 -2
  161. package/src/shared/generated/chain-networks.json +40 -7
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@b3dotfun/sdk",
3
- "version": "0.0.49",
3
+ "version": "0.0.50-alpha.0",
4
4
  "source": "src/index.ts",
5
5
  "main": "./dist/cjs/index.js",
6
6
  "react-native": "./dist/cjs/index.native.js",
@@ -295,8 +295,8 @@
295
295
  "@radix-ui/react-slot": "1.1.2",
296
296
  "@radix-ui/react-tabs": "1.1.3",
297
297
  "@radix-ui/react-tooltip": "1.1.8",
298
- "@reservoir0x/relay-kit-ui": "2.17.2",
299
- "@reservoir0x/relay-sdk": "2.4.0",
298
+ "@relayprotocol/relay-kit-ui": "5.0.3",
299
+ "@relayprotocol/relay-sdk": "3.0.0",
300
300
  "@solana/spl-token": "^0.4.13",
301
301
  "@solana/web3.js": "^1.98.2",
302
302
  "@stripe/react-stripe-js": "^3.7.0",
@@ -374,7 +374,7 @@
374
374
  "react": "^18.0.0 || ^19.0.0",
375
375
  "react-dom": "^18.0.0 || ^19.0.0",
376
376
  "react-native-mmkv": "^3.2.0",
377
- "thirdweb": "5.108.9",
377
+ "thirdweb": "5.108.14",
378
378
  "three": "^0.175.0",
379
379
  "viem": "^2.28.1",
380
380
  "wagmi": "^2.14.15"
@@ -12,7 +12,7 @@ export const SOLANA_ASSOCIATED_TOKEN_ACCOUNT_PROGRAM_ID = "ATokenGPvbdGVxr1b2hvZ
12
12
  export const SOLANA_TOKEN_2022_PROGRAM_ID = "TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb";
13
13
 
14
14
  export const B3_TOKEN: components["schemas"]["Token"] = {
15
- chainId: 8453,
15
+ chainId: base.id,
16
16
  address: "0xb3b32f9f8827d4634fe7d973fa1034ec9fddb3b3",
17
17
  decimals: 18,
18
18
  name: "B3",
@@ -22,6 +22,17 @@ export const B3_TOKEN: components["schemas"]["Token"] = {
22
22
  },
23
23
  };
24
24
 
25
+ export const ANYSPEND_TOKEN: components["schemas"]["Token"] = {
26
+ chainId: base.id,
27
+ address: "0xc17dda248e2d50fc006d8febb5a406dd31972712",
28
+ decimals: 18,
29
+ name: "Anyspend",
30
+ symbol: "ANY",
31
+ metadata: {
32
+ logoURI: "https://cdn.b3.fun/anyspend_64x64.png",
33
+ },
34
+ };
35
+
25
36
  export const USDC_BASE: components["schemas"]["Token"] = {
26
37
  symbol: "USDC",
27
38
  chainId: base.id,
@@ -40,6 +40,7 @@ import { OrderHistory } from "./common/OrderHistory";
40
40
  import { PanelOnramp } from "./common/PanelOnramp";
41
41
  import { PanelOnrampPayment } from "./common/PanelOnrampPayment";
42
42
  import { PointsDetailPanel } from "./common/PointsDetailPanel";
43
+ import { FeeDetailPanel } from "./common/FeeDetailPanel";
43
44
  import { RecipientSelection } from "./common/RecipientSelection";
44
45
  import { TabSection } from "./common/TabSection";
45
46
 
@@ -60,6 +61,7 @@ export enum PanelView {
60
61
  CRYPTO_PAYMENT_METHOD,
61
62
  FIAT_PAYMENT_METHOD,
62
63
  POINTS_DETAIL,
64
+ FEE_DETAIL,
63
65
  }
64
66
 
65
67
  const ANYSPEND_RECIPIENTS_KEY = "anyspend_recipients";
@@ -607,9 +609,20 @@ function AnySpendInner({
607
609
  },
608
610
  });
609
611
 
612
+ // Check if it's a same-chain same-token swap
613
+ const isSameChainSameToken = useMemo(() => {
614
+ return (
615
+ activeTab === "crypto" &&
616
+ selectedSrcChainId === selectedDstChainId &&
617
+ selectedSrcToken.address.toLowerCase() === selectedDstToken.address.toLowerCase()
618
+ );
619
+ }, [activeTab, selectedSrcChainId, selectedDstChainId, selectedSrcToken.address, selectedDstToken.address]);
620
+
610
621
  // Determine button state and text
611
622
  const btnInfo: { text: string; disable: boolean; error: boolean; loading: boolean } = useMemo(() => {
612
623
  if (activeInputAmountInWei === "0") return { text: "Enter an amount", disable: true, error: false, loading: false };
624
+ if (isSameChainSameToken)
625
+ return { text: "Select a different token or chain", disable: true, error: false, loading: false };
613
626
  if (isLoadingAnyspendQuote) return { text: "Loading quote...", disable: true, error: false, loading: true };
614
627
  if (!recipientAddress) return { text: "Select recipient", disable: false, error: false, loading: false };
615
628
  if (isCreatingOrder || isCreatingOnrampOrder)
@@ -646,6 +659,7 @@ function AnySpendInner({
646
659
  return { text: "Buy", disable: false, error: false, loading: false };
647
660
  }, [
648
661
  activeInputAmountInWei,
662
+ isSameChainSameToken,
649
663
  isLoadingAnyspendQuote,
650
664
  recipientAddress,
651
665
  isCreatingOrder,
@@ -903,6 +917,7 @@ function AnySpendInner({
903
917
  refundTxs={oat.data.refundTxs}
904
918
  selectedCryptoPaymentMethod={selectedCryptoPaymentMethod}
905
919
  onPaymentMethodChange={setSelectedCryptoPaymentMethod}
920
+ points={oat.data.points || undefined}
906
921
  onBack={() => {
907
922
  setOrderId(undefined);
908
923
  navigateBack();
@@ -953,11 +968,13 @@ function AnySpendInner({
953
968
  setSelectedSrcToken={setSelectedSrcToken}
954
969
  srcAmount={srcAmount}
955
970
  setSrcAmount={setSrcAmount}
971
+ isSrcInputDirty={isSrcInputDirty}
956
972
  setIsSrcInputDirty={setIsSrcInputDirty}
957
973
  selectedCryptoPaymentMethod={selectedCryptoPaymentMethod}
958
974
  onSelectCryptoPaymentMethod={() => navigateToPanel(PanelView.CRYPTO_PAYMENT_METHOD, "forward")}
959
975
  anyspendQuote={anyspendQuote}
960
976
  onTokenSelect={onTokenSelect}
977
+ onShowFeeDetail={() => navigateToPanel(PanelView.FEE_DETAIL, "forward")}
961
978
  />
962
979
  ) : (
963
980
  <motion.div
@@ -989,6 +1006,7 @@ function AnySpendInner({
989
1006
  hideDstToken={isBuyMode}
990
1007
  anyspendQuote={anyspendQuote}
991
1008
  onShowPointsDetail={() => navigateToPanel(PanelView.POINTS_DETAIL, "forward")}
1009
+ onShowFeeDetail={() => navigateToPanel(PanelView.FEE_DETAIL, "forward")}
992
1010
  customUsdInputValues={customUsdInputValues}
993
1011
  />
994
1012
  </motion.div>
@@ -1044,12 +1062,14 @@ function AnySpendInner({
1044
1062
  selectedDstChainId={selectedDstChainId}
1045
1063
  setSelectedDstChainId={setSelectedDstChainId}
1046
1064
  setSelectedDstToken={setSelectedDstToken}
1065
+ isSrcInputDirty={isSrcInputDirty}
1047
1066
  onChangeDstAmount={value => {
1048
1067
  setIsSrcInputDirty(false);
1049
1068
  setDstAmount(value);
1050
1069
  }}
1051
1070
  anyspendQuote={anyspendQuote}
1052
1071
  onShowPointsDetail={() => navigateToPanel(PanelView.POINTS_DETAIL, "forward")}
1072
+ onShowFeeDetail={() => navigateToPanel(PanelView.FEE_DETAIL, "forward")}
1053
1073
  />
1054
1074
  )}
1055
1075
  </div>
@@ -1166,6 +1186,16 @@ function AnySpendInner({
1166
1186
  <PointsDetailPanel pointsAmount={anyspendQuote?.data?.pointsAmount || 0} onBack={navigateBack} />
1167
1187
  );
1168
1188
 
1189
+ const feeDetailView = anyspendQuote?.data?.fee ? (
1190
+ <FeeDetailPanel
1191
+ fee={anyspendQuote.data.fee}
1192
+ transactionAmountUsd={
1193
+ activeTab === "crypto" ? Number(anyspendQuote.data.currencyIn?.amountUsd) : parseFloat(srcAmountOnRamp)
1194
+ }
1195
+ onBack={navigateBack}
1196
+ />
1197
+ ) : null;
1198
+
1169
1199
  // Add tabs to the main component when no order is loaded
1170
1200
  return (
1171
1201
  <StyleRoot>
@@ -1231,6 +1261,9 @@ function AnySpendInner({
1231
1261
  <div key="points-detail-view" className={cn(mode === "page" && "p-6")}>
1232
1262
  {pointsDetailView}
1233
1263
  </div>,
1264
+ <div key="fee-detail-view" className={cn(mode === "page" && "p-6")}>
1265
+ {feeDetailView}
1266
+ </div>,
1234
1267
  ]}
1235
1268
  </TransitionPanel>
1236
1269
  </div>
@@ -22,6 +22,7 @@ import {
22
22
  TextShimmer,
23
23
  Tooltip,
24
24
  TooltipContent,
25
+ TooltipProvider,
25
26
  TooltipTrigger,
26
27
  TransitionPanel,
27
28
  useAccountWallet,
@@ -37,7 +38,7 @@ import { shortenAddress } from "@b3dotfun/sdk/shared/utils/formatAddress";
37
38
  import { formatTokenAmount, formatUnits } from "@b3dotfun/sdk/shared/utils/number";
38
39
  import { simpleHashChainToChainName } from "@b3dotfun/sdk/shared/utils/simplehash";
39
40
  import invariant from "invariant";
40
- import { ChevronRight, ChevronRightCircle, Loader2 } from "lucide-react";
41
+ import { ChevronRight, ChevronRightCircle, Info, Loader2 } from "lucide-react";
41
42
  import { motion } from "motion/react";
42
43
  import React, { useCallback, useEffect, useMemo, useState } from "react";
43
44
  import { toast } from "sonner";
@@ -45,6 +46,7 @@ import { base } from "viem/chains";
45
46
  import { useFeatureFlags } from "../contexts/FeatureFlagsContext";
46
47
  import { AnySpendFingerprintWrapper, getFingerprintConfig } from "./AnySpendFingerprintWrapper";
47
48
  import { CryptoPaymentMethod, CryptoPaymentMethodType } from "./common/CryptoPaymentMethod";
49
+ import { FeeBreakDown } from "./common/FeeBreakDown";
48
50
  import { FiatPaymentMethod, FiatPaymentMethodComponent } from "./common/FiatPaymentMethod";
49
51
  import { OrderDetails } from "./common/OrderDetails";
50
52
  import { OrderHistory } from "./common/OrderHistory";
@@ -77,6 +79,7 @@ function generateGetRelayQuoteRequest({
77
79
  contractType,
78
80
  encodedData,
79
81
  spenderAddress,
82
+ onrampVendor,
80
83
  }: {
81
84
  orderType: components["schemas"]["Order"]["type"];
82
85
  srcChainId: number;
@@ -90,6 +93,7 @@ function generateGetRelayQuoteRequest({
90
93
  contractType?: components["schemas"]["NftContract"]["type"];
91
94
  encodedData: string;
92
95
  spenderAddress?: string;
96
+ onrampVendor?: components["schemas"]["OnrampMetadata"]["vendor"];
93
97
  }): GetQuoteRequest {
94
98
  switch (orderType) {
95
99
  case "mint_nft": {
@@ -105,6 +109,7 @@ function generateGetRelayQuoteRequest({
105
109
  contractAddress: contractAddress,
106
110
  tokenId: tokenId,
107
111
  contractType: contractType,
112
+ onrampVendor,
108
113
  };
109
114
  }
110
115
  case "join_tournament": {
@@ -117,6 +122,7 @@ function generateGetRelayQuoteRequest({
117
122
  recipientAddress,
118
123
  price: dstAmount,
119
124
  contractAddress: contractAddress,
125
+ onrampVendor,
120
126
  };
121
127
  }
122
128
  case "fund_tournament": {
@@ -129,6 +135,7 @@ function generateGetRelayQuoteRequest({
129
135
  recipientAddress,
130
136
  fundAmount: dstAmount,
131
137
  contractAddress: contractAddress,
138
+ onrampVendor,
132
139
  };
133
140
  }
134
141
  case "custom": {
@@ -145,6 +152,7 @@ function generateGetRelayQuoteRequest({
145
152
  to: contractAddress,
146
153
  spenderAddress: spenderAddress,
147
154
  },
155
+ onrampVendor,
148
156
  };
149
157
  }
150
158
  default: {
@@ -336,6 +344,7 @@ function AnySpendCustomInner({
336
344
  contractType: orderType === "mint_nft" ? metadata?.nftContract?.type : undefined,
337
345
  encodedData: encodedData,
338
346
  spenderAddress: spenderAddress,
347
+ onrampVendor: selectedFiatPaymentMethod === FiatPaymentMethod.STRIPE ? "stripe-web2" : undefined,
339
348
  });
340
349
  }, [
341
350
  activeTab,
@@ -351,6 +360,7 @@ function AnySpendCustomInner({
351
360
  spenderAddress,
352
361
  srcChainId,
353
362
  srcToken,
363
+ selectedFiatPaymentMethod,
354
364
  ]);
355
365
  const { anyspendQuote, isLoadingAnyspendQuote } = useAnyspendQuote(getRelayQuoteRequest);
356
366
 
@@ -960,14 +970,40 @@ function AnySpendCustomInner({
960
970
  className="relative flex w-full items-center justify-between"
961
971
  >
962
972
  <div className="flex items-center gap-2">
963
- <span className="text-as-tertiarry text-sm">
973
+ <span className="text-as-tertiarry flex items-center gap-1.5 text-sm">
964
974
  Total <span className="text-as-tertiarry">(with fee)</span>
975
+ {anyspendQuote?.data?.fee && (
976
+ <TooltipProvider>
977
+ <Tooltip>
978
+ <TooltipTrigger asChild>
979
+ <button className="text-as-primary/40 hover:text-as-primary/60 transition-colors">
980
+ <Info className="h-4 w-4" />
981
+ </button>
982
+ </TooltipTrigger>
983
+ <TooltipContent side="top">
984
+ <FeeBreakDown fee={anyspendQuote.data.fee} />
985
+ </TooltipContent>
986
+ </Tooltip>
987
+ </TooltipProvider>
988
+ )}
965
989
  </span>
966
990
  {renderPointsBadge()}
967
991
  </div>
968
- <span className="text-as-primary font-semibold">
969
- {formattedSrcAmount || "--"} {srcToken.symbol}
970
- </span>
992
+ <div className="flex flex-col items-end gap-0.5">
993
+ <span className="text-as-primary font-semibold">
994
+ {formattedSrcAmount || "--"} {srcToken.symbol}
995
+ </span>
996
+ {anyspendQuote?.data?.fee?.type === "standard_fee" && anyspendQuote.data.currencyIn?.amountUsd && (
997
+ <span className="text-as-secondary text-xs">
998
+ incl. $
999
+ {(
1000
+ (Number(anyspendQuote.data.currencyIn.amountUsd) * anyspendQuote.data.fee.finalFeeBps) /
1001
+ 10000
1002
+ ).toFixed(2)}{" "}
1003
+ fee
1004
+ </span>
1005
+ )}
1006
+ </div>
971
1007
  </motion.div>
972
1008
  </div>
973
1009
  </div>
@@ -1086,12 +1122,38 @@ function AnySpendCustomInner({
1086
1122
  className="relative flex w-full items-center justify-between"
1087
1123
  >
1088
1124
  <div className="flex items-center gap-2">
1089
- <span className="text-as-tertiarry text-sm">
1125
+ <span className="text-as-tertiarry flex items-center gap-1.5 text-sm">
1090
1126
  Total <span className="text-as-tertiarry">(USD)</span>
1127
+ {anyspendQuote?.data?.fee && (
1128
+ <TooltipProvider>
1129
+ <Tooltip>
1130
+ <TooltipTrigger asChild>
1131
+ <button className="text-as-primary/40 hover:text-as-primary/60 transition-colors">
1132
+ <Info className="h-4 w-4" />
1133
+ </button>
1134
+ </TooltipTrigger>
1135
+ <TooltipContent side="top">
1136
+ <FeeBreakDown fee={anyspendQuote.data.fee} />
1137
+ </TooltipContent>
1138
+ </Tooltip>
1139
+ </TooltipProvider>
1140
+ )}
1091
1141
  </span>
1092
1142
  {renderPointsBadge()}
1093
1143
  </div>
1094
- <span className="text-as-primary text-xl font-semibold">${srcFiatAmount || "0.00"}</span>
1144
+ <div className="flex flex-col items-end gap-0.5">
1145
+ <span className="text-as-primary text-xl font-semibold">${srcFiatAmount || "0.00"}</span>
1146
+ {anyspendQuote?.data?.fee?.type === "stripeweb2_fee" && anyspendQuote.data.fee.originalAmount && (
1147
+ <span className="text-as-secondary text-xs">
1148
+ incl. $
1149
+ {(
1150
+ (Number(anyspendQuote.data.fee.originalAmount) - Number(anyspendQuote.data.fee.finalAmount)) /
1151
+ 1e6
1152
+ ).toFixed(2)}{" "}
1153
+ fee
1154
+ </span>
1155
+ )}
1156
+ </div>
1095
1157
  </motion.div>
1096
1158
  </div>
1097
1159
 
@@ -12,6 +12,7 @@ import { AnySpendFingerprintWrapper, getFingerprintConfig } from "./AnySpendFing
12
12
  import { CryptoPaySection } from "./common/CryptoPaySection";
13
13
  import { CryptoPaymentMethod, CryptoPaymentMethodType } from "./common/CryptoPaymentMethod";
14
14
  import { CryptoReceiveSection } from "./common/CryptoReceiveSection";
15
+ import { FeeDetailPanel } from "./common/FeeDetailPanel";
15
16
  import { FiatPaymentMethod, FiatPaymentMethodComponent } from "./common/FiatPaymentMethod";
16
17
  import { OrderDetails } from "./common/OrderDetails";
17
18
  import { PointsDetailPanel } from "./common/PointsDetailPanel";
@@ -80,6 +81,7 @@ function AnySpendDepositHypeInner({
80
81
  srcAmount,
81
82
  setSrcAmount,
82
83
  dstAmount,
84
+ isSrcInputDirty,
83
85
  setIsSrcInputDirty,
84
86
  selectedCryptoPaymentMethod,
85
87
  setSelectedCryptoPaymentMethod,
@@ -207,6 +209,7 @@ function AnySpendDepositHypeInner({
207
209
  setSelectedSrcToken={setSelectedSrcToken}
208
210
  srcAmount={srcAmount}
209
211
  setSrcAmount={setSrcAmount}
212
+ isSrcInputDirty={isSrcInputDirty}
210
213
  setIsSrcInputDirty={setIsSrcInputDirty}
211
214
  selectedCryptoPaymentMethod={selectedCryptoPaymentMethod}
212
215
  onSelectCryptoPaymentMethod={() => setActivePanel(PanelView.CRYPTO_PAYMENT_METHOD)}
@@ -236,6 +239,7 @@ function AnySpendDepositHypeInner({
236
239
  recipientSelectionPanelIndex={PanelView.RECIPIENT_SELECTION}
237
240
  anyspendQuote={anyspendQuote}
238
241
  onShowPointsDetail={() => setActivePanel(PanelView.POINTS_DETAIL)}
242
+ onShowFeeDetail={() => setActivePanel(PanelView.FEE_DETAIL)}
239
243
  customUsdInputValues={customUsdInputValues}
240
244
  />
241
245
  </motion.div>
@@ -272,12 +276,14 @@ function AnySpendDepositHypeInner({
272
276
  selectedDstChainId={base.id}
273
277
  setSelectedDstChainId={() => {}}
274
278
  setSelectedDstToken={() => {}}
279
+ isSrcInputDirty={isSrcInputDirty}
275
280
  onChangeDstAmount={value => {
276
281
  setIsSrcInputDirty(false);
277
282
  setSrcAmount(value);
278
283
  }}
279
284
  anyspendQuote={anyspendQuote}
280
285
  onShowPointsDetail={() => setActivePanel(PanelView.POINTS_DETAIL)}
286
+ onShowFeeDetail={() => setActivePanel(PanelView.FEE_DETAIL)}
281
287
  />
282
288
  )}
283
289
  </div>
@@ -410,6 +416,7 @@ function AnySpendDepositHypeInner({
410
416
  setActivePanel(PanelView.MAIN);
411
417
  }}
412
418
  disableUrlParamManagement
419
+ points={oat.data.points || undefined}
413
420
  />
414
421
  )}
415
422
  </div>
@@ -470,6 +477,20 @@ function AnySpendDepositHypeInner({
470
477
  />
471
478
  );
472
479
 
480
+ const feeDetailView = anyspendQuote?.data?.fee ? (
481
+ <FeeDetailPanel
482
+ fee={anyspendQuote.data.fee}
483
+ transactionAmountUsd={
484
+ paymentType === "fiat"
485
+ ? parseFloat(srcAmount)
486
+ : anyspendQuote.data.currencyIn?.amountUsd
487
+ ? Number(anyspendQuote.data.currencyIn.amountUsd)
488
+ : undefined
489
+ }
490
+ onBack={() => setActivePanel(PanelView.MAIN)}
491
+ />
492
+ ) : null;
493
+
473
494
  // If showing token selection, render with panel transitions
474
495
  return (
475
496
  <StyleRoot>
@@ -522,6 +543,9 @@ function AnySpendDepositHypeInner({
522
543
  <div key="points-detail-view" className={cn(mode === "page" && "p-6")}>
523
544
  {pointsDetailView}
524
545
  </div>,
546
+ <div key="fee-detail-view" className={cn(mode === "page" && "p-6")}>
547
+ {feeDetailView}
548
+ </div>,
525
549
  ]}
526
550
  </TransitionPanel>
527
551
  </div>
@@ -2,7 +2,7 @@ import { useAccountWallet, useProfile, useTokenData } from "@b3dotfun/sdk/global
2
2
  import { formatUsername } from "@b3dotfun/sdk/shared/utils";
3
3
  import { shortenAddress } from "@b3dotfun/sdk/shared/utils/formatAddress";
4
4
  import { formatDisplayNumber } from "@b3dotfun/sdk/shared/utils/number";
5
- import { ChevronRight } from "lucide-react";
5
+ import { ChevronRight, Info } from "lucide-react";
6
6
  import { motion } from "motion/react";
7
7
  import { useEffect, useRef } from "react";
8
8
  import { components } from "../../../types/api";
@@ -18,6 +18,7 @@ interface CryptoPaySectionProps {
18
18
  setSelectedSrcToken: (token: components["schemas"]["Token"]) => void;
19
19
  srcAmount: string;
20
20
  setSrcAmount: (amount: string) => void;
21
+ isSrcInputDirty: boolean;
21
22
  setIsSrcInputDirty: (dirty: boolean) => void;
22
23
  // Payment method state
23
24
  selectedCryptoPaymentMethod: CryptoPaymentMethodType;
@@ -26,6 +27,8 @@ interface CryptoPaySectionProps {
26
27
  anyspendQuote?: any;
27
28
  // Token selection callback
28
29
  onTokenSelect?: (token: components["schemas"]["Token"], event: { preventDefault: () => void }) => void;
30
+ // Fee detail callback
31
+ onShowFeeDetail?: () => void;
29
32
  }
30
33
 
31
34
  export function CryptoPaySection({
@@ -35,11 +38,13 @@ export function CryptoPaySection({
35
38
  setSelectedSrcToken,
36
39
  srcAmount,
37
40
  setSrcAmount,
41
+ isSrcInputDirty,
38
42
  setIsSrcInputDirty,
39
43
  selectedCryptoPaymentMethod,
40
44
  onSelectCryptoPaymentMethod,
41
45
  anyspendQuote,
42
46
  onTokenSelect,
47
+ onShowFeeDetail,
43
48
  }: CryptoPaySectionProps) {
44
49
  const { connectedSmartWallet, connectedEOAWallet } = useAccountWallet();
45
50
  const { data: srcTokenMetadata } = useTokenData(selectedSrcToken?.chainId, selectedSrcToken?.address);
@@ -89,7 +94,14 @@ export function CryptoPaySection({
89
94
  className="pay-section bg-as-surface-secondary border-as-border-secondary relative flex w-full flex-col gap-2 rounded-2xl border p-4 sm:p-6"
90
95
  >
91
96
  <div className="flex items-center justify-between">
92
- <div className="text-as-primary/50 flex h-7 items-center text-sm">Pay</div>
97
+ <div className="text-as-primary/50 flex h-7 items-center gap-1.5 text-sm">
98
+ Pay
99
+ {!isSrcInputDirty && anyspendQuote?.data?.fee && onShowFeeDetail && (
100
+ <button onClick={onShowFeeDetail} className="text-as-primary/40 hover:text-as-primary/60 transition-colors">
101
+ <Info className="h-4 w-4" />
102
+ </button>
103
+ )}
104
+ </div>
93
105
  <button
94
106
  className="text-as-tertiarry flex h-7 items-center gap-2 text-sm transition-colors focus:!outline-none"
95
107
  onClick={onSelectCryptoPaymentMethod}
@@ -2,7 +2,7 @@ import { formatUsername } from "@b3dotfun/sdk/shared/utils";
2
2
  import { cn } from "@b3dotfun/sdk/shared/utils/cn";
3
3
  import { shortenAddress } from "@b3dotfun/sdk/shared/utils/formatAddress";
4
4
  import { formatDisplayNumber } from "@b3dotfun/sdk/shared/utils/number";
5
- import { ChevronRight } from "lucide-react";
5
+ import { ChevronRight, Info } from "lucide-react";
6
6
  import { motion } from "motion/react";
7
7
  import { components } from "../../../types/api";
8
8
  import { useFeatureFlags } from "../../contexts/FeatureFlagsContext";
@@ -23,6 +23,7 @@ interface CryptoReceiveSectionProps {
23
23
  selectedDstChainId?: number;
24
24
  setSelectedDstChainId?: (chainId: number) => void;
25
25
  setSelectedDstToken?: (token: components["schemas"]["Token"]) => void;
26
+ isSrcInputDirty: boolean;
26
27
  onChangeDstAmount?: (value: string) => void;
27
28
  // Quote data
28
29
  anyspendQuote?: any;
@@ -31,6 +32,8 @@ interface CryptoReceiveSectionProps {
31
32
  dstTokenLogoURI?: string;
32
33
  // Points navigation
33
34
  onShowPointsDetail?: () => void;
35
+ // Fee detail navigation
36
+ onShowFeeDetail?: () => void;
34
37
  }
35
38
 
36
39
  export function CryptoReceiveSection({
@@ -44,11 +47,13 @@ export function CryptoReceiveSection({
44
47
  selectedDstChainId,
45
48
  setSelectedDstChainId,
46
49
  setSelectedDstToken,
50
+ isSrcInputDirty,
47
51
  onChangeDstAmount,
48
52
  anyspendQuote,
49
53
  dstTokenSymbol,
50
54
  dstTokenLogoURI,
51
55
  onShowPointsDetail,
56
+ onShowFeeDetail,
52
57
  }: CryptoReceiveSectionProps) {
53
58
  const featureFlags = useFeatureFlags();
54
59
 
@@ -60,7 +65,14 @@ export function CryptoReceiveSection({
60
65
  className="receive-section bg-as-surface-secondary border-as-border-secondary relative flex w-full flex-col gap-2 rounded-2xl border p-4 sm:p-6"
61
66
  >
62
67
  <div className="flex w-full items-center justify-between">
63
- <div className="text-as-primary/50 flex h-7 items-center text-sm">{isDepositMode ? "Deposit" : "Receive"}</div>
68
+ <div className="text-as-primary/50 flex h-7 items-center gap-1.5 text-sm">
69
+ {isDepositMode ? "Deposit" : "Receive"}
70
+ {isSrcInputDirty && anyspendQuote?.data?.fee && onShowFeeDetail && (
71
+ <button onClick={onShowFeeDetail} className="text-as-primary/40 hover:text-as-primary/60 transition-colors">
72
+ <Info className="h-4 w-4" />
73
+ </button>
74
+ )}
75
+ </div>
64
76
  {selectedRecipientAddress ? (
65
77
  <button
66
78
  className={cn("text-as-tertiarry flex h-7 items-center gap-2 rounded-lg")}
@@ -118,7 +130,7 @@ export function CryptoReceiveSection({
118
130
  (() => {
119
131
  const calculatePriceImpact = (inputUsd?: string | number, outputUsd?: string | number) => {
120
132
  if (!inputUsd || !outputUsd) {
121
- return { percentage: "0.00", isNegative: false };
133
+ return { percentage: "0.00", percentageNum: 0, isNegative: false };
122
134
  }
123
135
 
124
136
  const input = Number(inputUsd);
@@ -126,38 +138,46 @@ export function CryptoReceiveSection({
126
138
 
127
139
  // Handle edge cases
128
140
  if (input === 0 || isNaN(input) || isNaN(output) || input <= output) {
129
- return { percentage: "0.00", isNegative: false };
141
+ return { percentage: "0.00", percentageNum: 0, isNegative: false };
130
142
  }
131
143
 
132
144
  const percentageValue = ((output - input) / input) * 100;
133
145
 
134
146
  // Handle the -0.00% case
135
147
  if (percentageValue > -0.005 && percentageValue < 0) {
136
- return { percentage: "0.00", isNegative: false };
148
+ return { percentage: "0.00", percentageNum: 0, isNegative: false };
137
149
  }
138
150
 
139
151
  return {
140
152
  percentage: Math.abs(percentageValue).toFixed(2),
153
+ percentageNum: Math.abs(percentageValue),
141
154
  isNegative: percentageValue < 0,
142
155
  };
143
156
  };
144
157
 
145
- const { percentage, isNegative } = calculatePriceImpact(
158
+ const { percentage, percentageNum, isNegative } = calculatePriceImpact(
146
159
  anyspendQuote.data.currencyIn.amountUsd,
147
160
  anyspendQuote.data.currencyOut.amountUsd,
148
161
  );
149
162
 
150
- // Parse the percentage as a number for comparison
151
- const percentageNum = parseFloat(percentage);
163
+ // Get the fee percentage if available
164
+ const feePercent = anyspendQuote.data.fee?.finalFeeBps ? anyspendQuote.data.fee.finalFeeBps / 100 : 0;
165
+
166
+ // Calculate actual slippage (price impact minus fee)
167
+ const actualSlippage = percentageNum - feePercent;
168
+
169
+ // Show warning based on actual slippage, not total impact
170
+ const yellowThreshold = 1; // 1% actual slippage
171
+ const redThreshold = 2; // 2% actual slippage
152
172
 
153
- // Don't show if less than 1%
154
- if (percentageNum < 1) {
173
+ // Don't show if actual slippage is less than yellow threshold
174
+ if (actualSlippage < yellowThreshold) {
155
175
  return null;
156
176
  }
157
177
 
158
178
  // Using inline style to ensure color displays
159
179
  return (
160
- <span className="ml-2" style={{ color: percentageNum >= 10 ? "red" : "#FFD700" }}>
180
+ <span className="ml-2" style={{ color: actualSlippage >= redThreshold ? "red" : "#FFD700" }}>
161
181
  ({isNegative ? "-" : ""}
162
182
  {percentage}%)
163
183
  </span>