@b3dotfun/sdk 0.0.62 → 0.0.63-alpha.1

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 (171) hide show
  1. package/dist/cjs/anyspend/react/components/AnySpend.js +61 -23
  2. package/dist/cjs/anyspend/react/components/AnySpendCustom.js +3 -0
  3. package/dist/cjs/anyspend/react/components/AnySpendCustomExactIn.d.ts +34 -0
  4. package/dist/cjs/anyspend/react/components/AnySpendCustomExactIn.js +275 -0
  5. package/dist/cjs/anyspend/react/components/AnySpendStakeB3.js +5 -4
  6. package/dist/cjs/anyspend/react/components/AnySpendStakeB3ExactIn.d.ts +9 -0
  7. package/dist/cjs/anyspend/react/components/AnySpendStakeB3ExactIn.js +288 -0
  8. package/dist/cjs/anyspend/react/components/AnySpendStakeUpsideExactIn.d.ts +11 -0
  9. package/dist/cjs/anyspend/react/components/AnySpendStakeUpsideExactIn.js +33 -0
  10. package/dist/cjs/anyspend/react/components/AnyspendDepositHype.js +4 -4
  11. package/dist/cjs/anyspend/react/components/common/CryptoPaySection.js +4 -6
  12. package/dist/cjs/anyspend/react/components/common/CryptoPaymentMethod.js +9 -17
  13. package/dist/cjs/anyspend/react/components/common/CryptoReceiveSection.d.ts +6 -1
  14. package/dist/cjs/anyspend/react/components/common/CryptoReceiveSection.js +11 -1
  15. package/dist/cjs/anyspend/react/components/common/OrderDetails.js +66 -147
  16. package/dist/cjs/anyspend/react/components/common/OrderDetailsCollapsible.js +2 -3
  17. package/dist/cjs/anyspend/react/components/common/OrderTokenAmount.d.ts +2 -1
  18. package/dist/cjs/anyspend/react/components/common/OrderTokenAmount.js +39 -15
  19. package/dist/cjs/anyspend/react/components/common/PaySection.js +1 -1
  20. package/dist/cjs/anyspend/react/components/common/TokenBalance.js +1 -1
  21. package/dist/cjs/anyspend/react/components/index.d.ts +5 -1
  22. package/dist/cjs/anyspend/react/components/index.js +11 -3
  23. package/dist/cjs/anyspend/react/hooks/useAnyspendFlow.d.ts +25 -3
  24. package/dist/cjs/anyspend/react/hooks/useAnyspendFlow.js +42 -19
  25. package/dist/cjs/anyspend/react/hooks/useAnyspendOrderHistory.d.ts +116 -0
  26. package/dist/cjs/anyspend/react/hooks/useAnyspendQuote.js +1 -1
  27. package/dist/cjs/anyspend/react/hooks/useAutoSelectCryptoPaymentMethod.d.ts +26 -0
  28. package/dist/cjs/anyspend/react/hooks/useAutoSelectCryptoPaymentMethod.js +56 -0
  29. package/dist/cjs/anyspend/react/hooks/useAutoSetActiveWalletFromWagmi.d.ts +10 -0
  30. package/dist/cjs/anyspend/react/hooks/useAutoSetActiveWalletFromWagmi.js +73 -0
  31. package/dist/cjs/anyspend/react/hooks/useConnectedWalletDisplay.d.ts +14 -0
  32. package/dist/cjs/anyspend/react/hooks/useConnectedWalletDisplay.js +57 -0
  33. package/dist/cjs/anyspend/react/hooks/usePhantomTransfer.d.ts +36 -0
  34. package/dist/cjs/anyspend/react/hooks/usePhantomTransfer.js +211 -0
  35. package/dist/cjs/anyspend/types/api.d.ts +665 -3
  36. package/dist/cjs/anyspend/utils/orderPayload.js +4 -0
  37. package/dist/cjs/global-account/react/components/B3DynamicModal.js +17 -4
  38. package/dist/cjs/global-account/react/components/ManageAccount/BalanceContent.js +3 -3
  39. package/dist/cjs/global-account/react/components/ProfileEditor/ProfileEditor.d.ts +6 -0
  40. package/dist/cjs/global-account/react/components/ProfileEditor/ProfileEditor.js +141 -0
  41. package/dist/cjs/global-account/react/components/SignInWithB3/SignInWithB3Flow.js +3 -1
  42. package/dist/cjs/global-account/react/components/SignInWithB3/steps/LoginStep.js +2 -2
  43. package/dist/cjs/global-account/react/components/index.d.ts +2 -0
  44. package/dist/cjs/global-account/react/components/index.js +7 -2
  45. package/dist/cjs/global-account/react/hooks/index.d.ts +2 -1
  46. package/dist/cjs/global-account/react/hooks/index.js +5 -3
  47. package/dist/cjs/global-account/react/hooks/useAuthentication.d.ts +2 -2
  48. package/dist/cjs/global-account/react/hooks/useAuthentication.js +7 -2
  49. package/dist/cjs/global-account/react/hooks/useSimBalance.d.ts +1 -1
  50. package/dist/cjs/global-account/react/hooks/useSimBalance.js +6 -5
  51. package/dist/cjs/global-account/react/hooks/useTokenBalanceDirect.d.ts +12 -0
  52. package/dist/cjs/global-account/react/hooks/useTokenBalanceDirect.js +62 -0
  53. package/dist/cjs/global-account/react/hooks/useTokenFromUrl.js +4 -3
  54. package/dist/cjs/global-account/react/stores/useModalStore.d.ts +37 -1
  55. package/dist/cjs/global-account/react/utils/profileDisplay.d.ts +6 -0
  56. package/dist/cjs/global-account/react/utils/profileDisplay.js +60 -4
  57. package/dist/esm/anyspend/react/components/AnySpend.js +62 -24
  58. package/dist/esm/anyspend/react/components/AnySpendCustom.js +3 -0
  59. package/dist/esm/anyspend/react/components/AnySpendCustomExactIn.d.ts +34 -0
  60. package/dist/esm/anyspend/react/components/AnySpendCustomExactIn.js +269 -0
  61. package/dist/esm/anyspend/react/components/AnySpendStakeB3.js +7 -6
  62. package/dist/esm/anyspend/react/components/AnySpendStakeB3ExactIn.d.ts +9 -0
  63. package/dist/esm/anyspend/react/components/AnySpendStakeB3ExactIn.js +285 -0
  64. package/dist/esm/anyspend/react/components/AnySpendStakeUpsideExactIn.d.ts +11 -0
  65. package/dist/esm/anyspend/react/components/AnySpendStakeUpsideExactIn.js +30 -0
  66. package/dist/esm/anyspend/react/components/AnyspendDepositHype.js +4 -4
  67. package/dist/esm/anyspend/react/components/common/CryptoPaySection.js +5 -7
  68. package/dist/esm/anyspend/react/components/common/CryptoPaymentMethod.js +9 -17
  69. package/dist/esm/anyspend/react/components/common/CryptoReceiveSection.d.ts +6 -1
  70. package/dist/esm/anyspend/react/components/common/CryptoReceiveSection.js +11 -1
  71. package/dist/esm/anyspend/react/components/common/OrderDetails.js +67 -148
  72. package/dist/esm/anyspend/react/components/common/OrderDetailsCollapsible.js +2 -3
  73. package/dist/esm/anyspend/react/components/common/OrderTokenAmount.d.ts +2 -1
  74. package/dist/esm/anyspend/react/components/common/OrderTokenAmount.js +40 -16
  75. package/dist/esm/anyspend/react/components/common/PaySection.js +1 -1
  76. package/dist/esm/anyspend/react/components/common/TokenBalance.js +2 -2
  77. package/dist/esm/anyspend/react/components/index.d.ts +5 -1
  78. package/dist/esm/anyspend/react/components/index.js +5 -1
  79. package/dist/esm/anyspend/react/hooks/useAnyspendFlow.d.ts +25 -3
  80. package/dist/esm/anyspend/react/hooks/useAnyspendFlow.js +42 -19
  81. package/dist/esm/anyspend/react/hooks/useAnyspendOrderHistory.d.ts +116 -0
  82. package/dist/esm/anyspend/react/hooks/useAnyspendQuote.js +1 -1
  83. package/dist/esm/anyspend/react/hooks/useAutoSelectCryptoPaymentMethod.d.ts +26 -0
  84. package/dist/esm/anyspend/react/hooks/useAutoSelectCryptoPaymentMethod.js +53 -0
  85. package/dist/esm/anyspend/react/hooks/useAutoSetActiveWalletFromWagmi.d.ts +10 -0
  86. package/dist/esm/anyspend/react/hooks/useAutoSetActiveWalletFromWagmi.js +70 -0
  87. package/dist/esm/anyspend/react/hooks/useConnectedWalletDisplay.d.ts +14 -0
  88. package/dist/esm/anyspend/react/hooks/useConnectedWalletDisplay.js +54 -0
  89. package/dist/esm/anyspend/react/hooks/usePhantomTransfer.d.ts +36 -0
  90. package/dist/esm/anyspend/react/hooks/usePhantomTransfer.js +208 -0
  91. package/dist/esm/anyspend/types/api.d.ts +665 -3
  92. package/dist/esm/anyspend/utils/orderPayload.js +4 -0
  93. package/dist/esm/global-account/react/components/B3DynamicModal.js +18 -5
  94. package/dist/esm/global-account/react/components/ManageAccount/BalanceContent.js +3 -3
  95. package/dist/esm/global-account/react/components/ProfileEditor/ProfileEditor.d.ts +6 -0
  96. package/dist/esm/global-account/react/components/ProfileEditor/ProfileEditor.js +135 -0
  97. package/dist/esm/global-account/react/components/SignInWithB3/SignInWithB3Flow.js +3 -1
  98. package/dist/esm/global-account/react/components/SignInWithB3/steps/LoginStep.js +2 -2
  99. package/dist/esm/global-account/react/components/index.d.ts +2 -0
  100. package/dist/esm/global-account/react/components/index.js +3 -0
  101. package/dist/esm/global-account/react/hooks/index.d.ts +2 -1
  102. package/dist/esm/global-account/react/hooks/index.js +2 -1
  103. package/dist/esm/global-account/react/hooks/useAuthentication.d.ts +2 -2
  104. package/dist/esm/global-account/react/hooks/useAuthentication.js +7 -2
  105. package/dist/esm/global-account/react/hooks/useSimBalance.d.ts +1 -1
  106. package/dist/esm/global-account/react/hooks/useSimBalance.js +6 -5
  107. package/dist/esm/global-account/react/hooks/useTokenBalanceDirect.d.ts +12 -0
  108. package/dist/esm/global-account/react/hooks/useTokenBalanceDirect.js +59 -0
  109. package/dist/esm/global-account/react/hooks/useTokenFromUrl.js +4 -3
  110. package/dist/esm/global-account/react/stores/useModalStore.d.ts +37 -1
  111. package/dist/esm/global-account/react/utils/profileDisplay.d.ts +6 -0
  112. package/dist/esm/global-account/react/utils/profileDisplay.js +59 -4
  113. package/dist/types/anyspend/react/components/AnySpendCustomExactIn.d.ts +34 -0
  114. package/dist/types/anyspend/react/components/AnySpendStakeB3ExactIn.d.ts +9 -0
  115. package/dist/types/anyspend/react/components/AnySpendStakeUpsideExactIn.d.ts +11 -0
  116. package/dist/types/anyspend/react/components/common/CryptoReceiveSection.d.ts +6 -1
  117. package/dist/types/anyspend/react/components/common/OrderTokenAmount.d.ts +2 -1
  118. package/dist/types/anyspend/react/components/index.d.ts +5 -1
  119. package/dist/types/anyspend/react/hooks/useAnyspendFlow.d.ts +25 -3
  120. package/dist/types/anyspend/react/hooks/useAnyspendOrderHistory.d.ts +116 -0
  121. package/dist/types/anyspend/react/hooks/useAutoSelectCryptoPaymentMethod.d.ts +26 -0
  122. package/dist/types/anyspend/react/hooks/useAutoSetActiveWalletFromWagmi.d.ts +10 -0
  123. package/dist/types/anyspend/react/hooks/useConnectedWalletDisplay.d.ts +14 -0
  124. package/dist/types/anyspend/react/hooks/usePhantomTransfer.d.ts +36 -0
  125. package/dist/types/anyspend/types/api.d.ts +665 -3
  126. package/dist/types/global-account/react/components/ProfileEditor/ProfileEditor.d.ts +6 -0
  127. package/dist/types/global-account/react/components/index.d.ts +2 -0
  128. package/dist/types/global-account/react/hooks/index.d.ts +2 -1
  129. package/dist/types/global-account/react/hooks/useAuthentication.d.ts +2 -2
  130. package/dist/types/global-account/react/hooks/useSimBalance.d.ts +1 -1
  131. package/dist/types/global-account/react/hooks/useTokenBalanceDirect.d.ts +12 -0
  132. package/dist/types/global-account/react/stores/useModalStore.d.ts +37 -1
  133. package/dist/types/global-account/react/utils/profileDisplay.d.ts +6 -0
  134. package/package.json +4 -3
  135. package/src/anyspend/react/components/AnySpend.tsx +73 -22
  136. package/src/anyspend/react/components/AnySpendCustom.tsx +4 -0
  137. package/src/anyspend/react/components/AnySpendCustomExactIn.tsx +595 -0
  138. package/src/anyspend/react/components/AnySpendStakeB3.tsx +8 -11
  139. package/src/anyspend/react/components/AnySpendStakeB3ExactIn.tsx +522 -0
  140. package/src/anyspend/react/components/AnySpendStakeUpsideExactIn.tsx +73 -0
  141. package/src/anyspend/react/components/AnyspendDepositHype.tsx +7 -3
  142. package/src/anyspend/react/components/common/CryptoPaySection.tsx +5 -7
  143. package/src/anyspend/react/components/common/CryptoPaymentMethod.tsx +9 -18
  144. package/src/anyspend/react/components/common/CryptoReceiveSection.tsx +22 -0
  145. package/src/anyspend/react/components/common/OrderDetails.tsx +76 -190
  146. package/src/anyspend/react/components/common/OrderDetailsCollapsible.tsx +2 -3
  147. package/src/anyspend/react/components/common/OrderTokenAmount.tsx +48 -17
  148. package/src/anyspend/react/components/common/PaySection.tsx +1 -0
  149. package/src/anyspend/react/components/common/TokenBalance.tsx +2 -2
  150. package/src/anyspend/react/components/index.ts +5 -1
  151. package/src/anyspend/react/hooks/useAnyspendFlow.ts +51 -18
  152. package/src/anyspend/react/hooks/useAnyspendQuote.ts +1 -1
  153. package/src/anyspend/react/hooks/useAutoSelectCryptoPaymentMethod.ts +72 -0
  154. package/src/anyspend/react/hooks/useAutoSetActiveWalletFromWagmi.ts +80 -0
  155. package/src/anyspend/react/hooks/useConnectedWalletDisplay.ts +69 -0
  156. package/src/anyspend/react/hooks/usePhantomTransfer.ts +301 -0
  157. package/src/anyspend/types/api.ts +669 -1
  158. package/src/anyspend/utils/orderPayload.ts +5 -1
  159. package/src/global-account/react/components/B3DynamicModal.tsx +18 -4
  160. package/src/global-account/react/components/ManageAccount/BalanceContent.tsx +4 -4
  161. package/src/global-account/react/components/ProfileEditor/ProfileEditor.tsx +265 -0
  162. package/src/global-account/react/components/SignInWithB3/SignInWithB3Flow.tsx +3 -1
  163. package/src/global-account/react/components/SignInWithB3/steps/LoginStep.tsx +2 -2
  164. package/src/global-account/react/components/index.ts +4 -0
  165. package/src/global-account/react/hooks/index.ts +2 -1
  166. package/src/global-account/react/hooks/useAuthentication.ts +10 -2
  167. package/src/global-account/react/hooks/useSimBalance.ts +6 -5
  168. package/src/global-account/react/hooks/useTokenBalanceDirect.tsx +84 -0
  169. package/src/global-account/react/hooks/useTokenFromUrl.tsx +6 -5
  170. package/src/global-account/react/stores/useModalStore.ts +43 -1
  171. package/src/global-account/react/utils/profileDisplay.ts +67 -4
@@ -0,0 +1,595 @@
1
+ import { components } from "@b3dotfun/sdk/anyspend/types/api";
2
+ import { GetQuoteResponse } from "@b3dotfun/sdk/anyspend/types/api_req_res";
3
+ import { normalizeAddress } from "@b3dotfun/sdk/anyspend/utils";
4
+ import { Button, ShinyButton, StyleRoot, TransitionPanel, useAccountWallet } from "@b3dotfun/sdk/global-account/react";
5
+ import { cn } from "@b3dotfun/sdk/shared/utils/cn";
6
+ import invariant from "invariant";
7
+ import { ArrowDown, Loader2 } from "lucide-react";
8
+ import { motion } from "motion/react";
9
+ import { useEffect, useMemo, useRef } from "react";
10
+ import { toast } from "sonner";
11
+ import { useActiveWallet, useSetActiveWallet } from "thirdweb/react";
12
+ import { useGlobalWalletState } from "../../utils";
13
+ import { PanelView, useAnyspendFlow } from "../hooks/useAnyspendFlow";
14
+ import { AnySpendFingerprintWrapper, getFingerprintConfig } from "./AnySpendFingerprintWrapper";
15
+ import { CryptoPaySection } from "./common/CryptoPaySection";
16
+ import { CryptoPaymentMethod, CryptoPaymentMethodType } from "./common/CryptoPaymentMethod";
17
+ import { CryptoReceiveSection } from "./common/CryptoReceiveSection";
18
+ import { FeeDetailPanel } from "./common/FeeDetailPanel";
19
+ import { FiatPaymentMethod, FiatPaymentMethodComponent } from "./common/FiatPaymentMethod";
20
+ import { OrderDetails } from "./common/OrderDetails";
21
+ import { PanelOnramp } from "./common/PanelOnramp";
22
+ import { PointsDetailPanel } from "./common/PointsDetailPanel";
23
+ import { RecipientSelection } from "./common/RecipientSelection";
24
+
25
+ const SLIPPAGE_PERCENT = 3;
26
+
27
+ type CustomExactInConfig = {
28
+ functionAbi: string;
29
+ functionName: string;
30
+ functionArgs: string[];
31
+ to: string;
32
+ spenderAddress?: string;
33
+ action?: string;
34
+ };
35
+
36
+ export interface AnySpendCustomExactInProps {
37
+ loadOrder?: string;
38
+ mode?: "modal" | "page";
39
+ recipientAddress: string;
40
+ paymentType?: "crypto" | "fiat";
41
+ sourceTokenAddress?: string;
42
+ sourceTokenChainId?: number;
43
+ destinationToken: components["schemas"]["Token"];
44
+ destinationChainId: number;
45
+ onSuccess?: (amount: string) => void;
46
+ mainFooter?: React.ReactNode;
47
+ onTokenSelect?: (token: components["schemas"]["Token"], event: { preventDefault: () => void }) => void;
48
+ customUsdInputValues?: string[];
49
+ preferEoa?: boolean;
50
+ customExactInConfig: CustomExactInConfig;
51
+ header?: ({
52
+ anyspendPrice,
53
+ isLoadingAnyspendPrice,
54
+ }: {
55
+ anyspendPrice: GetQuoteResponse | undefined;
56
+ isLoadingAnyspendPrice: boolean;
57
+ }) => React.JSX.Element;
58
+ }
59
+
60
+ export function AnySpendCustomExactIn(props: AnySpendCustomExactInProps) {
61
+ const fingerprintConfig = getFingerprintConfig();
62
+
63
+ return (
64
+ <AnySpendFingerprintWrapper fingerprint={fingerprintConfig}>
65
+ <AnySpendCustomExactInInner {...props} />
66
+ </AnySpendFingerprintWrapper>
67
+ );
68
+ }
69
+
70
+ function AnySpendCustomExactInInner({
71
+ loadOrder,
72
+ mode = "modal",
73
+ recipientAddress,
74
+ paymentType = "crypto",
75
+ sourceTokenAddress,
76
+ sourceTokenChainId,
77
+ destinationToken,
78
+ destinationChainId,
79
+ onSuccess,
80
+ mainFooter,
81
+ onTokenSelect,
82
+ customUsdInputValues,
83
+ preferEoa,
84
+ customExactInConfig,
85
+ header,
86
+ }: AnySpendCustomExactInProps) {
87
+ const actionLabel = customExactInConfig.action ?? "Custom Execution";
88
+
89
+ const DESTINATION_TOKEN_DETAILS = {
90
+ SYMBOL: destinationToken.symbol ?? "TOKEN",
91
+ LOGO_URI: destinationToken.metadata?.logoURI ?? "",
92
+ };
93
+
94
+ const {
95
+ activePanel,
96
+ setActivePanel,
97
+ orderId,
98
+ setOrderId,
99
+ oat,
100
+ selectedSrcChainId,
101
+ setSelectedSrcChainId,
102
+ selectedSrcToken,
103
+ setSelectedSrcToken,
104
+ selectedDstToken,
105
+ selectedDstChainId,
106
+ srcAmount,
107
+ setSrcAmount,
108
+ dstAmount,
109
+ isSrcInputDirty,
110
+ setIsSrcInputDirty,
111
+ selectedCryptoPaymentMethod,
112
+ setSelectedCryptoPaymentMethod,
113
+ selectedFiatPaymentMethod,
114
+ setSelectedFiatPaymentMethod,
115
+ selectedRecipientAddress,
116
+ setSelectedRecipientAddress,
117
+ recipientName,
118
+ globalAddress,
119
+ hasEnoughBalance,
120
+ isBalanceLoading,
121
+ anyspendQuote,
122
+ isLoadingAnyspendQuote,
123
+ activeInputAmountInWei,
124
+ geoData,
125
+ coinbaseAvailablePaymentMethods,
126
+ stripeWeb2Support,
127
+ createOrder,
128
+ isCreatingOrder,
129
+ createOnrampOrder,
130
+ isCreatingOnrampOrder,
131
+ } = useAnyspendFlow({
132
+ paymentType,
133
+ recipientAddress,
134
+ loadOrder,
135
+ isDepositMode: true,
136
+ onTransactionSuccess: onSuccess,
137
+ sourceTokenAddress,
138
+ sourceTokenChainId,
139
+ destinationTokenAddress: destinationToken.address,
140
+ destinationTokenChainId: destinationChainId,
141
+ slippage: SLIPPAGE_PERCENT,
142
+ disableUrlParamManagement: true,
143
+ orderType: "custom_exact_in",
144
+ });
145
+
146
+ const { connectedEOAWallet } = useAccountWallet();
147
+ const setActiveWallet = useSetActiveWallet();
148
+ const activeWallet = useActiveWallet();
149
+ const setGlobalAccountWallet = useGlobalWalletState(state => state.setGlobalAccountWallet);
150
+ const appliedPreferEoa = useRef(false);
151
+
152
+ useEffect(() => {
153
+ if (preferEoa && !appliedPreferEoa.current) {
154
+ if (connectedEOAWallet) {
155
+ appliedPreferEoa.current = true;
156
+ setGlobalAccountWallet(activeWallet);
157
+ setActiveWallet(connectedEOAWallet);
158
+ }
159
+ }
160
+ }, [preferEoa, connectedEOAWallet, setActiveWallet, activeWallet, setGlobalAccountWallet]);
161
+
162
+ const selectedRecipientOrDefault = selectedRecipientAddress ?? recipientAddress;
163
+
164
+ const expectedDstAmountRaw = anyspendQuote?.data?.currencyOut?.amount ?? "0";
165
+
166
+ const buildCustomPayload = (_recipient: string | undefined) => {
167
+ return {
168
+ amount: expectedDstAmountRaw,
169
+ expectedDstAmount: expectedDstAmountRaw,
170
+ functionAbi: customExactInConfig.functionAbi,
171
+ functionName: customExactInConfig.functionName,
172
+ functionArgs: customExactInConfig.functionArgs,
173
+ to: normalizeAddress(customExactInConfig.to),
174
+ spenderAddress: customExactInConfig.spenderAddress
175
+ ? normalizeAddress(customExactInConfig.spenderAddress)
176
+ : undefined,
177
+ action: customExactInConfig.action,
178
+ };
179
+ };
180
+
181
+ const btnInfo: { text: string; disable: boolean; error: boolean; loading: boolean } = useMemo(() => {
182
+ if (activeInputAmountInWei === "0") return { text: "Enter an amount", disable: true, error: false, loading: false };
183
+ if (isLoadingAnyspendQuote) return { text: "Loading quote...", disable: true, error: false, loading: true };
184
+ if (isCreatingOrder || isCreatingOnrampOrder)
185
+ return { text: "Creating order...", disable: true, error: false, loading: true };
186
+ if (!selectedRecipientOrDefault) return { text: "Select recipient", disable: false, error: false, loading: false };
187
+ if (!anyspendQuote || !anyspendQuote.success)
188
+ return { text: "Get quote error", disable: true, error: true, loading: false };
189
+
190
+ if (paymentType === "crypto") {
191
+ if (selectedCryptoPaymentMethod === CryptoPaymentMethodType.NONE) {
192
+ return { text: "Choose payment method", disable: false, error: false, loading: false };
193
+ }
194
+ if (
195
+ !hasEnoughBalance &&
196
+ !isBalanceLoading &&
197
+ selectedCryptoPaymentMethod === CryptoPaymentMethodType.CONNECT_WALLET
198
+ ) {
199
+ return { text: "Insufficient balance", disable: true, error: true, loading: false };
200
+ }
201
+ return { text: `Execute ${actionLabel}`, disable: false, error: false, loading: false };
202
+ }
203
+
204
+ if (paymentType === "fiat") {
205
+ if (selectedFiatPaymentMethod === FiatPaymentMethod.NONE) {
206
+ return { text: "Select payment method", disable: false, error: false, loading: false };
207
+ }
208
+ return { text: "Buy", disable: false, error: false, loading: false };
209
+ }
210
+
211
+ return { text: "Continue", disable: false, error: false, loading: false };
212
+ }, [
213
+ activeInputAmountInWei,
214
+ isLoadingAnyspendQuote,
215
+ isCreatingOrder,
216
+ isCreatingOnrampOrder,
217
+ selectedRecipientOrDefault,
218
+ anyspendQuote,
219
+ paymentType,
220
+ selectedCryptoPaymentMethod,
221
+ selectedFiatPaymentMethod,
222
+ hasEnoughBalance,
223
+ isBalanceLoading,
224
+ actionLabel,
225
+ ]);
226
+
227
+ const onMainButtonClick = async () => {
228
+ if (btnInfo.disable) return;
229
+
230
+ if (!selectedRecipientOrDefault) {
231
+ setActivePanel(PanelView.RECIPIENT_SELECTION);
232
+ return;
233
+ }
234
+
235
+ if (paymentType === "crypto") {
236
+ if (selectedCryptoPaymentMethod === CryptoPaymentMethodType.NONE) {
237
+ setActivePanel(PanelView.CRYPTO_PAYMENT_METHOD);
238
+ return;
239
+ }
240
+ await handleCryptoOrder();
241
+ } else if (paymentType === "fiat") {
242
+ if (selectedFiatPaymentMethod === FiatPaymentMethod.NONE) {
243
+ setActivePanel(PanelView.FIAT_PAYMENT_METHOD);
244
+ return;
245
+ }
246
+ await handleFiatOrder();
247
+ }
248
+ };
249
+
250
+ const headerContent = header ? (
251
+ header({ anyspendPrice: anyspendQuote, isLoadingAnyspendPrice: isLoadingAnyspendQuote })
252
+ ) : (
253
+ <div className="mb-4 flex flex-col items-center gap-3 text-center">
254
+ <div>
255
+ <h1 className="text-as-primary text-xl font-bold">{actionLabel}</h1>
256
+ <p className="text-as-secondary text-sm">Pay from any token to execute a custom exact-in transaction.</p>
257
+ </div>
258
+ </div>
259
+ );
260
+
261
+ const mainView = (
262
+ <div className="mx-auto flex w-[460px] max-w-full flex-col items-center gap-2">
263
+ {headerContent}
264
+
265
+ <div className="relative flex w-full max-w-[calc(100vw-32px)] flex-col gap-2">
266
+ <div className="relative flex w-full max-w-[calc(100vw-32px)] flex-col gap-2">
267
+ {paymentType === "crypto" ? (
268
+ <CryptoPaySection
269
+ selectedSrcChainId={selectedSrcChainId}
270
+ setSelectedSrcChainId={setSelectedSrcChainId}
271
+ selectedSrcToken={selectedSrcToken}
272
+ setSelectedSrcToken={setSelectedSrcToken}
273
+ srcAmount={srcAmount}
274
+ setSrcAmount={setSrcAmount}
275
+ isSrcInputDirty={isSrcInputDirty}
276
+ setIsSrcInputDirty={setIsSrcInputDirty}
277
+ selectedCryptoPaymentMethod={selectedCryptoPaymentMethod}
278
+ onSelectCryptoPaymentMethod={() => setActivePanel(PanelView.CRYPTO_PAYMENT_METHOD)}
279
+ anyspendQuote={anyspendQuote}
280
+ onTokenSelect={onTokenSelect}
281
+ />
282
+ ) : (
283
+ <motion.div
284
+ initial={{ opacity: 0, y: 20, filter: "blur(10px)" }}
285
+ animate={{ opacity: 1, y: 0, filter: "blur(0px)" }}
286
+ transition={{ duration: 0.3, delay: 0, ease: "easeInOut" }}
287
+ >
288
+ <PanelOnramp
289
+ srcAmountOnRamp={srcAmount}
290
+ setSrcAmountOnRamp={setSrcAmount}
291
+ selectedPaymentMethod={selectedFiatPaymentMethod}
292
+ setActivePanel={setActivePanel}
293
+ _recipientAddress={selectedRecipientOrDefault}
294
+ destinationToken={selectedDstToken}
295
+ destinationChainId={selectedDstChainId}
296
+ dstTokenSymbol={DESTINATION_TOKEN_DETAILS.SYMBOL}
297
+ hideDstToken
298
+ destinationAmount={dstAmount}
299
+ onDestinationTokenChange={() => {}}
300
+ onDestinationChainChange={() => {}}
301
+ fiatPaymentMethodIndex={PanelView.FIAT_PAYMENT_METHOD}
302
+ recipientSelectionPanelIndex={PanelView.RECIPIENT_SELECTION}
303
+ anyspendQuote={anyspendQuote}
304
+ onShowPointsDetail={() => setActivePanel(PanelView.POINTS_DETAIL)}
305
+ onShowFeeDetail={() => setActivePanel(PanelView.FEE_DETAIL)}
306
+ customUsdInputValues={customUsdInputValues}
307
+ />
308
+ </motion.div>
309
+ )}
310
+
311
+ <div
312
+ className={cn("relative -my-1 flex h-0 items-center justify-center", paymentType === "fiat" && "hidden")}
313
+ >
314
+ <Button
315
+ variant="ghost"
316
+ className={cn(
317
+ "swap-direction-button border-as-stroke bg-as-surface-primary z-10 h-10 w-10 cursor-default rounded-xl border-2 sm:h-8 sm:w-8 sm:rounded-xl",
318
+ )}
319
+ >
320
+ <div className="relative flex items-center justify-center transition-opacity">
321
+ <ArrowDown className="text-as-primary/50 h-5 w-5" />
322
+ </div>
323
+ </Button>
324
+ </div>
325
+
326
+ {paymentType === "crypto" && (
327
+ <CryptoReceiveSection
328
+ isDepositMode={false}
329
+ isBuyMode={true}
330
+ selectedRecipientAddress={selectedRecipientOrDefault}
331
+ recipientName={recipientName || undefined}
332
+ onSelectRecipient={() => setActivePanel(PanelView.RECIPIENT_SELECTION)}
333
+ dstAmount={dstAmount}
334
+ dstToken={selectedDstToken}
335
+ dstTokenSymbol={DESTINATION_TOKEN_DETAILS.SYMBOL}
336
+ dstTokenLogoURI={DESTINATION_TOKEN_DETAILS.LOGO_URI}
337
+ selectedDstChainId={selectedDstChainId}
338
+ setSelectedDstChainId={() => {}}
339
+ setSelectedDstToken={() => {}}
340
+ isSrcInputDirty={isSrcInputDirty}
341
+ onChangeDstAmount={value => {
342
+ setIsSrcInputDirty(false);
343
+ setSrcAmount(value);
344
+ }}
345
+ anyspendQuote={anyspendQuote}
346
+ onShowPointsDetail={() => setActivePanel(PanelView.POINTS_DETAIL)}
347
+ onShowFeeDetail={() => setActivePanel(PanelView.FEE_DETAIL)}
348
+ />
349
+ )}
350
+ </div>
351
+ </div>
352
+
353
+ <motion.div
354
+ initial={{ opacity: 0, y: 20, filter: "blur(10px)" }}
355
+ animate={{ opacity: 1, y: 0, filter: "blur(0px)" }}
356
+ transition={{ duration: 0.3, delay: 0.2, ease: "easeInOut" }}
357
+ className={cn("mt-4 flex w-full max-w-[460px] flex-col gap-2")}
358
+ >
359
+ <ShinyButton
360
+ accentColor={"hsl(var(--as-brand))"}
361
+ disabled={btnInfo.disable}
362
+ onClick={onMainButtonClick}
363
+ className={cn(
364
+ "as-main-button relative w-full",
365
+ btnInfo.error ? "!bg-as-red" : btnInfo.disable ? "!bg-as-on-surface-2" : "!bg-as-brand",
366
+ )}
367
+ textClassName={cn(btnInfo.error ? "text-white" : btnInfo.disable ? "text-as-secondary" : "text-white")}
368
+ >
369
+ <div className="flex items-center justify-center gap-2">
370
+ {btnInfo.loading && <Loader2 className="h-4 w-4 animate-spin" />}
371
+ {btnInfo.text}
372
+ </div>
373
+ </ShinyButton>
374
+ </motion.div>
375
+
376
+ {mainFooter ? mainFooter : null}
377
+ </div>
378
+ );
379
+
380
+ const handleCryptoOrder = async () => {
381
+ try {
382
+ invariant(anyspendQuote, "Relay price is not found");
383
+ invariant(selectedRecipientOrDefault, "Recipient address is not found");
384
+
385
+ const srcAmountBigInt = BigInt(activeInputAmountInWei);
386
+ const payload = buildCustomPayload(selectedRecipientOrDefault);
387
+
388
+ createOrder({
389
+ recipientAddress: selectedRecipientOrDefault,
390
+ orderType: "custom_exact_in",
391
+ srcChain: selectedSrcChainId,
392
+ dstChain: selectedDstChainId,
393
+ srcToken: selectedSrcToken,
394
+ dstToken: selectedDstToken,
395
+ srcAmount: srcAmountBigInt.toString(),
396
+ expectedDstAmount: expectedDstAmountRaw,
397
+ creatorAddress: globalAddress,
398
+ payload,
399
+ });
400
+ } catch (err: any) {
401
+ console.error(err);
402
+ toast.error("Failed to create order: " + err.message);
403
+ }
404
+ };
405
+
406
+ const handleFiatOrder = async () => {
407
+ try {
408
+ invariant(anyspendQuote, "Relay price is not found");
409
+ invariant(selectedRecipientOrDefault, "Recipient address is not found");
410
+
411
+ if (!srcAmount || parseFloat(srcAmount) <= 0) {
412
+ toast.error("Please enter a valid amount");
413
+ return;
414
+ }
415
+
416
+ let vendor: "coinbase" | "stripe" | "stripe-web2";
417
+ let paymentMethodString = "";
418
+
419
+ if (selectedFiatPaymentMethod === FiatPaymentMethod.COINBASE_PAY) {
420
+ if (coinbaseAvailablePaymentMethods.length === 0) {
421
+ toast.error("Coinbase Pay not available");
422
+ return;
423
+ }
424
+ vendor = "coinbase";
425
+ paymentMethodString = coinbaseAvailablePaymentMethods[0]?.id || "";
426
+ } else if (selectedFiatPaymentMethod === FiatPaymentMethod.STRIPE) {
427
+ if (!stripeWeb2Support || !stripeWeb2Support.isSupport) {
428
+ toast.error("Stripe not available");
429
+ return;
430
+ }
431
+ vendor = "stripe-web2";
432
+ } else {
433
+ toast.error("Please select a payment method");
434
+ return;
435
+ }
436
+
437
+ const payload = buildCustomPayload(selectedRecipientOrDefault);
438
+
439
+ createOnrampOrder({
440
+ recipientAddress: selectedRecipientOrDefault,
441
+ orderType: "custom_exact_in",
442
+ dstChain: selectedDstChainId,
443
+ dstToken: selectedDstToken,
444
+ srcFiatAmount: srcAmount,
445
+ onramp: {
446
+ vendor,
447
+ paymentMethod: paymentMethodString,
448
+ country: geoData?.country || "US",
449
+ redirectUrl: window.location.origin,
450
+ },
451
+ expectedDstAmount: expectedDstAmountRaw,
452
+ creatorAddress: globalAddress,
453
+ payload,
454
+ });
455
+ } catch (err: any) {
456
+ console.error(err);
457
+ toast.error("Failed to create order: " + err.message);
458
+ }
459
+ };
460
+
461
+ const orderDetailsView = (
462
+ <div className={"mx-auto w-[460px] max-w-full"}>
463
+ <div className="relative flex flex-col gap-4">
464
+ {oat && (
465
+ <OrderDetails
466
+ mode={mode}
467
+ order={oat.data.order}
468
+ depositTxs={oat.data.depositTxs}
469
+ relayTxs={oat.data.relayTxs}
470
+ executeTx={oat.data.executeTx}
471
+ refundTxs={oat.data.refundTxs}
472
+ cryptoPaymentMethod={paymentType === "fiat" ? CryptoPaymentMethodType.NONE : selectedCryptoPaymentMethod}
473
+ selectedCryptoPaymentMethod={selectedCryptoPaymentMethod}
474
+ onPaymentMethodChange={setSelectedCryptoPaymentMethod}
475
+ onBack={() => {
476
+ setOrderId(undefined);
477
+ setActivePanel(PanelView.MAIN);
478
+ }}
479
+ disableUrlParamManagement
480
+ points={oat.data.points || undefined}
481
+ />
482
+ )}
483
+ </div>
484
+ </div>
485
+ );
486
+
487
+ const loadingView = (
488
+ <div className="mx-auto flex w-full flex-col items-center gap-4 p-5">
489
+ <div className="text-as-primary">Loading order details...</div>
490
+ </div>
491
+ );
492
+
493
+ const recipientSelectionView = (
494
+ <RecipientSelection
495
+ initialValue={selectedRecipientOrDefault || ""}
496
+ onBack={() => setActivePanel(PanelView.MAIN)}
497
+ onConfirm={address => {
498
+ setSelectedRecipientAddress(address);
499
+ setActivePanel(PanelView.MAIN);
500
+ }}
501
+ />
502
+ );
503
+
504
+ const cryptoPaymentMethodView = (
505
+ <CryptoPaymentMethod
506
+ globalAddress={globalAddress}
507
+ globalWallet={undefined}
508
+ selectedPaymentMethod={selectedCryptoPaymentMethod}
509
+ setSelectedPaymentMethod={setSelectedCryptoPaymentMethod}
510
+ isCreatingOrder={isCreatingOrder}
511
+ onBack={() => setActivePanel(PanelView.MAIN)}
512
+ onSelectPaymentMethod={(method: CryptoPaymentMethodType) => {
513
+ setSelectedCryptoPaymentMethod(method);
514
+ setActivePanel(PanelView.MAIN);
515
+ }}
516
+ />
517
+ );
518
+
519
+ const fiatPaymentMethodView = (
520
+ <FiatPaymentMethodComponent
521
+ selectedPaymentMethod={selectedFiatPaymentMethod}
522
+ setSelectedPaymentMethod={setSelectedFiatPaymentMethod}
523
+ onBack={() => setActivePanel(PanelView.MAIN)}
524
+ onSelectPaymentMethod={(method: FiatPaymentMethod) => {
525
+ setSelectedFiatPaymentMethod(method);
526
+ setActivePanel(PanelView.MAIN);
527
+ }}
528
+ srcAmountOnRamp={srcAmount}
529
+ />
530
+ );
531
+
532
+ const pointsDetailView = (
533
+ <PointsDetailPanel
534
+ pointsAmount={anyspendQuote?.data?.pointsAmount || 0}
535
+ onBack={() => setActivePanel(PanelView.MAIN)}
536
+ />
537
+ );
538
+
539
+ const feeDetailView = anyspendQuote?.data?.fee ? (
540
+ <FeeDetailPanel
541
+ fee={anyspendQuote.data.fee}
542
+ transactionAmountUsd={
543
+ paymentType === "fiat"
544
+ ? parseFloat(srcAmount)
545
+ : anyspendQuote.data.currencyIn?.amountUsd
546
+ ? Number(anyspendQuote.data.currencyIn.amountUsd)
547
+ : undefined
548
+ }
549
+ onBack={() => setActivePanel(PanelView.MAIN)}
550
+ />
551
+ ) : null;
552
+
553
+ return (
554
+ <StyleRoot>
555
+ <div
556
+ className={cn(
557
+ "anyspend-container font-inter bg-as-surface-primary mx-auto w-full max-w-[460px] p-6",
558
+ mode === "page" && "border-as-border-secondary overflow-hidden rounded-2xl border shadow-xl",
559
+ )}
560
+ >
561
+ <TransitionPanel
562
+ activeIndex={
563
+ orderId
564
+ ? oat
565
+ ? PanelView.ORDER_DETAILS
566
+ : PanelView.LOADING
567
+ : activePanel === PanelView.ORDER_DETAILS
568
+ ? PanelView.MAIN
569
+ : activePanel
570
+ }
571
+ className={cn("rounded-2xl", {
572
+ "mt-0": mode === "modal",
573
+ })}
574
+ variants={{
575
+ enter: { x: 300, opacity: 0 },
576
+ center: { x: 0, opacity: 1 },
577
+ exit: { x: -300, opacity: 0 },
578
+ }}
579
+ transition={{ type: "spring", stiffness: 300, damping: 30 }}
580
+ >
581
+ {[
582
+ <div key="main-view">{mainView}</div>,
583
+ <div key="crypto-payment-method-view">{cryptoPaymentMethodView}</div>,
584
+ <div key="fiat-payment-method-view">{fiatPaymentMethodView}</div>,
585
+ <div key="recipient-selection-view">{recipientSelectionView}</div>,
586
+ <div key="order-details-view">{orderDetailsView}</div>,
587
+ <div key="loading-view">{loadingView}</div>,
588
+ <div key="points-detail-view">{pointsDetailView}</div>,
589
+ <div key="fee-detail-view">{feeDetailView}</div>,
590
+ ]}
591
+ </TransitionPanel>
592
+ </div>
593
+ </StyleRoot>
594
+ );
595
+ }
@@ -1,4 +1,4 @@
1
- import { ABI_ERC20_STAKING, B3_TOKEN } from "@b3dotfun/sdk/anyspend";
1
+ import { ABI_ERC20_STAKING, B3_TOKEN, eqci } from "@b3dotfun/sdk/anyspend";
2
2
  import {
3
3
  Button,
4
4
  GlareCardRounded,
@@ -7,7 +7,7 @@ import {
7
7
  TextLoop,
8
8
  useHasMounted,
9
9
  useModalStore,
10
- useTokenBalance,
10
+ useSimBalance,
11
11
  useUnifiedChainSwitchAndExecute,
12
12
  } from "@b3dotfun/sdk/global-account/react";
13
13
  import { PUBLIC_BASE_RPC_URL } from "@b3dotfun/sdk/shared/constants";
@@ -58,19 +58,16 @@ export function AnySpendStakeB3({
58
58
  const hasMounted = useHasMounted();
59
59
  const { setB3ModalOpen } = useModalStore();
60
60
 
61
- // Fetch B3 token balance
62
- const {
63
- formattedBalance: b3Balance,
64
- isLoading: isBalanceLoading,
65
- rawBalance: b3RawBalance,
66
- } = useTokenBalance({
67
- token: B3_TOKEN,
68
- });
69
-
70
61
  // Wagmi hooks for direct staking
71
62
  const { address } = useAccount();
72
63
  const { switchChainAndExecute, isSwitchingOrExecuting } = useUnifiedChainSwitchAndExecute();
73
64
 
65
+ // Fetch B3 token balance
66
+ const { data: simBalance, isLoading: isBalanceLoading } = useSimBalance(address, [base.id]);
67
+ const b3RawBalanceStr = simBalance?.balances.find(b => eqci(b.address, B3_TOKEN.address))?.amount || "0";
68
+ const b3RawBalance = BigInt(b3RawBalanceStr);
69
+ const b3Balance = formatTokenAmount(b3RawBalance, B3_TOKEN.decimals);
70
+
74
71
  // State for direct staking flow
75
72
  const [isStaking, setIsStaking] = useState(false);
76
73
  const [stakingTxHash, setStakingTxHash] = useState<string>("");