@b3dotfun/sdk 0.1.2 → 0.1.5

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 (235) hide show
  1. package/dist/cjs/anyspend/react/components/AnySpend.d.ts +7 -1
  2. package/dist/cjs/anyspend/react/components/AnySpend.js +66 -15
  3. package/dist/cjs/anyspend/react/components/AnySpendCollectorClubPurchase.d.ts +6 -2
  4. package/dist/cjs/anyspend/react/components/AnySpendCollectorClubPurchase.js +4 -4
  5. package/dist/cjs/anyspend/react/components/AnySpendCustomExactIn.d.ts +6 -0
  6. package/dist/cjs/anyspend/react/components/AnySpendCustomExactIn.js +185 -50
  7. package/dist/cjs/anyspend/react/components/AnySpendDeposit.d.ts +6 -1
  8. package/dist/cjs/anyspend/react/components/AnySpendDeposit.js +19 -4
  9. package/dist/cjs/anyspend/react/components/AnySpendStakeUpsideExactIn.d.ts +2 -1
  10. package/dist/cjs/anyspend/react/components/AnySpendStakeUpsideExactIn.js +2 -2
  11. package/dist/cjs/anyspend/react/components/QRDeposit.d.ts +4 -1
  12. package/dist/cjs/anyspend/react/components/QRDeposit.js +12 -4
  13. package/dist/cjs/anyspend/react/components/common/CryptoPaySection.d.ts +3 -1
  14. package/dist/cjs/anyspend/react/components/common/CryptoPaySection.js +7 -5
  15. package/dist/cjs/anyspend/react/components/common/CryptoPaymentMethod.d.ts +3 -1
  16. package/dist/cjs/anyspend/react/components/common/CryptoPaymentMethod.js +4 -3
  17. package/dist/cjs/anyspend/react/components/common/CryptoReceiveSection.d.ts +3 -1
  18. package/dist/cjs/anyspend/react/components/common/CryptoReceiveSection.js +7 -6
  19. package/dist/cjs/anyspend/react/components/common/FeeDetailPanel.d.ts +3 -1
  20. package/dist/cjs/anyspend/react/components/common/FeeDetailPanel.js +15 -6
  21. package/dist/cjs/anyspend/react/components/common/FiatPaymentMethod.d.ts +3 -1
  22. package/dist/cjs/anyspend/react/components/common/FiatPaymentMethod.js +10 -6
  23. package/dist/cjs/anyspend/react/components/common/OrderDetails.d.ts +3 -0
  24. package/dist/cjs/anyspend/react/components/common/OrderDetails.js +11 -10
  25. package/dist/cjs/anyspend/react/components/common/OrderDetailsCollapsible.d.ts +2 -0
  26. package/dist/cjs/anyspend/react/components/common/OrderDetailsCollapsible.js +9 -9
  27. package/dist/cjs/anyspend/react/components/common/OrderHistory.js +2 -1
  28. package/dist/cjs/anyspend/react/components/common/PanelOnramp.d.ts +3 -1
  29. package/dist/cjs/anyspend/react/components/common/PanelOnramp.js +2 -2
  30. package/dist/cjs/anyspend/react/components/common/PanelOnrampPayment.d.ts +2 -0
  31. package/dist/cjs/anyspend/react/components/common/PanelOnrampPayment.js +20 -7
  32. package/dist/cjs/anyspend/react/components/common/PointsDetailPanel.d.ts +3 -1
  33. package/dist/cjs/anyspend/react/components/common/PointsDetailPanel.js +3 -2
  34. package/dist/cjs/anyspend/react/components/common/RecipientSelection.d.ts +6 -1
  35. package/dist/cjs/anyspend/react/components/common/RecipientSelection.js +5 -2
  36. package/dist/cjs/anyspend/react/components/common/TabSection.d.ts +3 -1
  37. package/dist/cjs/anyspend/react/components/common/TabSection.js +16 -7
  38. package/dist/cjs/anyspend/react/components/common/TransferCryptoDetails.d.ts +2 -0
  39. package/dist/cjs/anyspend/react/components/common/TransferCryptoDetails.js +3 -2
  40. package/dist/cjs/anyspend/react/components/common/WarningText.d.ts +8 -7
  41. package/dist/cjs/anyspend/react/components/common/WarningText.js +5 -6
  42. package/dist/cjs/anyspend/react/components/index.d.ts +1 -0
  43. package/dist/cjs/anyspend/react/components/types/classes.d.ts +390 -0
  44. package/dist/cjs/anyspend/react/components/types/classes.js +6 -0
  45. package/dist/cjs/anyspend/react/hooks/index.d.ts +1 -0
  46. package/dist/cjs/anyspend/react/hooks/index.js +1 -0
  47. package/dist/cjs/anyspend/react/hooks/useAnyspendFlow.d.ts +22 -2
  48. package/dist/cjs/anyspend/react/hooks/useAnyspendFlow.js +119 -15
  49. package/dist/cjs/anyspend/react/hooks/useDirectTransfer.d.ts +17 -0
  50. package/dist/cjs/anyspend/react/hooks/useDirectTransfer.js +46 -0
  51. package/dist/cjs/anyspend/react/hooks/useRecipientAddressState.js +1 -1
  52. package/dist/cjs/anyspend/utils/format.js +12 -2
  53. package/dist/cjs/global-account/react/components/B3DynamicModal.js +1 -5
  54. package/dist/cjs/global-account/react/components/B3Provider/B3ConfigProvider.d.ts +1 -3
  55. package/dist/cjs/global-account/react/components/B3Provider/B3ConfigProvider.js +1 -2
  56. package/dist/cjs/global-account/react/components/B3Provider/B3Provider.d.ts +1 -4
  57. package/dist/cjs/global-account/react/components/B3Provider/B3Provider.js +2 -2
  58. package/dist/cjs/global-account/react/components/B3Provider/B3Provider.native.d.ts +1 -1
  59. package/dist/cjs/global-account/react/components/B3Provider/B3Provider.native.js +1 -1
  60. package/dist/cjs/global-account/react/components/B3Provider/LocalSDKProvider.d.ts +1 -4
  61. package/dist/cjs/global-account/react/components/B3Provider/LocalSDKProvider.js +1 -3
  62. package/dist/cjs/global-account/react/components/B3Provider/RelayKitProviderWrapper.js +1 -3
  63. package/dist/cjs/global-account/react/components/ManageAccount/SettingsContent.js +17 -3
  64. package/dist/cjs/global-account/react/components/SignInWithB3/SignInWithB3Flow.js +19 -152
  65. package/dist/cjs/global-account/react/components/index.d.ts +0 -1
  66. package/dist/cjs/global-account/react/components/index.js +3 -6
  67. package/dist/cjs/global-account/react/hooks/index.d.ts +0 -1
  68. package/dist/cjs/global-account/react/hooks/index.js +2 -4
  69. package/dist/cjs/global-account/react/hooks/useAuth.d.ts +2 -3
  70. package/dist/cjs/global-account/react/hooks/useAuth.js +14 -31
  71. package/dist/cjs/global-account/react/hooks/useTWAuth.d.ts +1 -1
  72. package/dist/cjs/global-account/react/hooks/useTWAuth.js +3 -3
  73. package/dist/cjs/global-account/react/stores/useModalStore.d.ts +8 -19
  74. package/dist/esm/anyspend/react/components/AnySpend.d.ts +7 -1
  75. package/dist/esm/anyspend/react/components/AnySpend.js +68 -17
  76. package/dist/esm/anyspend/react/components/AnySpendCollectorClubPurchase.d.ts +6 -2
  77. package/dist/esm/anyspend/react/components/AnySpendCollectorClubPurchase.js +4 -4
  78. package/dist/esm/anyspend/react/components/AnySpendCustomExactIn.d.ts +6 -0
  79. package/dist/esm/anyspend/react/components/AnySpendCustomExactIn.js +189 -54
  80. package/dist/esm/anyspend/react/components/AnySpendDeposit.d.ts +6 -1
  81. package/dist/esm/anyspend/react/components/AnySpendDeposit.js +19 -4
  82. package/dist/esm/anyspend/react/components/AnySpendStakeUpsideExactIn.d.ts +2 -1
  83. package/dist/esm/anyspend/react/components/AnySpendStakeUpsideExactIn.js +2 -2
  84. package/dist/esm/anyspend/react/components/QRDeposit.d.ts +4 -1
  85. package/dist/esm/anyspend/react/components/QRDeposit.js +12 -4
  86. package/dist/esm/anyspend/react/components/common/CryptoPaySection.d.ts +3 -1
  87. package/dist/esm/anyspend/react/components/common/CryptoPaySection.js +7 -5
  88. package/dist/esm/anyspend/react/components/common/CryptoPaymentMethod.d.ts +3 -1
  89. package/dist/esm/anyspend/react/components/common/CryptoPaymentMethod.js +4 -3
  90. package/dist/esm/anyspend/react/components/common/CryptoReceiveSection.d.ts +3 -1
  91. package/dist/esm/anyspend/react/components/common/CryptoReceiveSection.js +7 -6
  92. package/dist/esm/anyspend/react/components/common/FeeDetailPanel.d.ts +3 -1
  93. package/dist/esm/anyspend/react/components/common/FeeDetailPanel.js +15 -6
  94. package/dist/esm/anyspend/react/components/common/FiatPaymentMethod.d.ts +3 -1
  95. package/dist/esm/anyspend/react/components/common/FiatPaymentMethod.js +10 -6
  96. package/dist/esm/anyspend/react/components/common/OrderDetails.d.ts +3 -0
  97. package/dist/esm/anyspend/react/components/common/OrderDetails.js +11 -10
  98. package/dist/esm/anyspend/react/components/common/OrderDetailsCollapsible.d.ts +2 -0
  99. package/dist/esm/anyspend/react/components/common/OrderDetailsCollapsible.js +9 -9
  100. package/dist/esm/anyspend/react/components/common/OrderHistory.js +2 -1
  101. package/dist/esm/anyspend/react/components/common/PanelOnramp.d.ts +3 -1
  102. package/dist/esm/anyspend/react/components/common/PanelOnramp.js +2 -2
  103. package/dist/esm/anyspend/react/components/common/PanelOnrampPayment.d.ts +2 -0
  104. package/dist/esm/anyspend/react/components/common/PanelOnrampPayment.js +20 -7
  105. package/dist/esm/anyspend/react/components/common/PointsDetailPanel.d.ts +3 -1
  106. package/dist/esm/anyspend/react/components/common/PointsDetailPanel.js +3 -2
  107. package/dist/esm/anyspend/react/components/common/RecipientSelection.d.ts +6 -1
  108. package/dist/esm/anyspend/react/components/common/RecipientSelection.js +5 -2
  109. package/dist/esm/anyspend/react/components/common/TabSection.d.ts +3 -1
  110. package/dist/esm/anyspend/react/components/common/TabSection.js +16 -7
  111. package/dist/esm/anyspend/react/components/common/TransferCryptoDetails.d.ts +2 -0
  112. package/dist/esm/anyspend/react/components/common/TransferCryptoDetails.js +3 -2
  113. package/dist/esm/anyspend/react/components/common/WarningText.d.ts +8 -7
  114. package/dist/esm/anyspend/react/components/common/WarningText.js +5 -6
  115. package/dist/esm/anyspend/react/components/index.d.ts +1 -0
  116. package/dist/esm/anyspend/react/components/types/classes.d.ts +390 -0
  117. package/dist/esm/anyspend/react/components/types/classes.js +5 -0
  118. package/dist/esm/anyspend/react/hooks/index.d.ts +1 -0
  119. package/dist/esm/anyspend/react/hooks/index.js +1 -0
  120. package/dist/esm/anyspend/react/hooks/useAnyspendFlow.d.ts +22 -2
  121. package/dist/esm/anyspend/react/hooks/useAnyspendFlow.js +119 -16
  122. package/dist/esm/anyspend/react/hooks/useDirectTransfer.d.ts +17 -0
  123. package/dist/esm/anyspend/react/hooks/useDirectTransfer.js +43 -0
  124. package/dist/esm/anyspend/react/hooks/useRecipientAddressState.js +1 -1
  125. package/dist/esm/anyspend/utils/format.js +12 -2
  126. package/dist/esm/global-account/react/components/B3DynamicModal.js +1 -5
  127. package/dist/esm/global-account/react/components/B3Provider/B3ConfigProvider.d.ts +1 -3
  128. package/dist/esm/global-account/react/components/B3Provider/B3ConfigProvider.js +1 -2
  129. package/dist/esm/global-account/react/components/B3Provider/B3Provider.d.ts +1 -4
  130. package/dist/esm/global-account/react/components/B3Provider/B3Provider.js +2 -2
  131. package/dist/esm/global-account/react/components/B3Provider/B3Provider.native.d.ts +1 -1
  132. package/dist/esm/global-account/react/components/B3Provider/B3Provider.native.js +1 -1
  133. package/dist/esm/global-account/react/components/B3Provider/LocalSDKProvider.d.ts +1 -4
  134. package/dist/esm/global-account/react/components/B3Provider/LocalSDKProvider.js +1 -3
  135. package/dist/esm/global-account/react/components/B3Provider/RelayKitProviderWrapper.js +1 -3
  136. package/dist/esm/global-account/react/components/ManageAccount/SettingsContent.js +16 -2
  137. package/dist/esm/global-account/react/components/SignInWithB3/SignInWithB3Flow.js +20 -153
  138. package/dist/esm/global-account/react/components/index.d.ts +0 -1
  139. package/dist/esm/global-account/react/components/index.js +0 -2
  140. package/dist/esm/global-account/react/hooks/index.d.ts +0 -1
  141. package/dist/esm/global-account/react/hooks/index.js +0 -1
  142. package/dist/esm/global-account/react/hooks/useAuth.d.ts +2 -3
  143. package/dist/esm/global-account/react/hooks/useAuth.js +14 -31
  144. package/dist/esm/global-account/react/hooks/useTWAuth.d.ts +1 -1
  145. package/dist/esm/global-account/react/hooks/useTWAuth.js +3 -3
  146. package/dist/esm/global-account/react/stores/useModalStore.d.ts +8 -19
  147. package/dist/styles/index.css +1 -1
  148. package/dist/types/anyspend/react/components/AnySpend.d.ts +7 -1
  149. package/dist/types/anyspend/react/components/AnySpendCollectorClubPurchase.d.ts +6 -2
  150. package/dist/types/anyspend/react/components/AnySpendCustomExactIn.d.ts +6 -0
  151. package/dist/types/anyspend/react/components/AnySpendDeposit.d.ts +6 -1
  152. package/dist/types/anyspend/react/components/AnySpendStakeUpsideExactIn.d.ts +2 -1
  153. package/dist/types/anyspend/react/components/QRDeposit.d.ts +4 -1
  154. package/dist/types/anyspend/react/components/common/CryptoPaySection.d.ts +3 -1
  155. package/dist/types/anyspend/react/components/common/CryptoPaymentMethod.d.ts +3 -1
  156. package/dist/types/anyspend/react/components/common/CryptoReceiveSection.d.ts +3 -1
  157. package/dist/types/anyspend/react/components/common/FeeDetailPanel.d.ts +3 -1
  158. package/dist/types/anyspend/react/components/common/FiatPaymentMethod.d.ts +3 -1
  159. package/dist/types/anyspend/react/components/common/OrderDetails.d.ts +3 -0
  160. package/dist/types/anyspend/react/components/common/OrderDetailsCollapsible.d.ts +2 -0
  161. package/dist/types/anyspend/react/components/common/PanelOnramp.d.ts +3 -1
  162. package/dist/types/anyspend/react/components/common/PanelOnrampPayment.d.ts +2 -0
  163. package/dist/types/anyspend/react/components/common/PointsDetailPanel.d.ts +3 -1
  164. package/dist/types/anyspend/react/components/common/RecipientSelection.d.ts +6 -1
  165. package/dist/types/anyspend/react/components/common/TabSection.d.ts +3 -1
  166. package/dist/types/anyspend/react/components/common/TransferCryptoDetails.d.ts +2 -0
  167. package/dist/types/anyspend/react/components/common/WarningText.d.ts +8 -7
  168. package/dist/types/anyspend/react/components/index.d.ts +1 -0
  169. package/dist/types/anyspend/react/components/types/classes.d.ts +390 -0
  170. package/dist/types/anyspend/react/hooks/index.d.ts +1 -0
  171. package/dist/types/anyspend/react/hooks/useAnyspendFlow.d.ts +22 -2
  172. package/dist/types/anyspend/react/hooks/useDirectTransfer.d.ts +17 -0
  173. package/dist/types/global-account/react/components/B3Provider/B3ConfigProvider.d.ts +1 -3
  174. package/dist/types/global-account/react/components/B3Provider/B3Provider.d.ts +1 -4
  175. package/dist/types/global-account/react/components/B3Provider/B3Provider.native.d.ts +1 -1
  176. package/dist/types/global-account/react/components/B3Provider/LocalSDKProvider.d.ts +1 -4
  177. package/dist/types/global-account/react/components/index.d.ts +0 -1
  178. package/dist/types/global-account/react/hooks/index.d.ts +0 -1
  179. package/dist/types/global-account/react/hooks/useAuth.d.ts +2 -3
  180. package/dist/types/global-account/react/hooks/useTWAuth.d.ts +1 -1
  181. package/dist/types/global-account/react/stores/useModalStore.d.ts +8 -19
  182. package/package.json +1 -1
  183. package/src/anyspend/react/components/AnySpend.tsx +164 -36
  184. package/src/anyspend/react/components/AnySpendCollectorClubPurchase.tsx +11 -6
  185. package/src/anyspend/react/components/AnySpendCustomExactIn.tsx +278 -69
  186. package/src/anyspend/react/components/AnySpendDeposit.tsx +176 -52
  187. package/src/anyspend/react/components/AnySpendStakeUpsideExactIn.tsx +3 -0
  188. package/src/anyspend/react/components/QRDeposit.tsx +91 -35
  189. package/src/anyspend/react/components/common/CryptoPaySection.tsx +31 -19
  190. package/src/anyspend/react/components/common/CryptoPaymentMethod.tsx +14 -4
  191. package/src/anyspend/react/components/common/CryptoReceiveSection.tsx +43 -23
  192. package/src/anyspend/react/components/common/FeeDetailPanel.tsx +53 -32
  193. package/src/anyspend/react/components/common/FiatPaymentMethod.tsx +26 -13
  194. package/src/anyspend/react/components/common/OrderDetails.tsx +20 -9
  195. package/src/anyspend/react/components/common/OrderDetailsCollapsible.tsx +12 -7
  196. package/src/anyspend/react/components/common/OrderHistory.tsx +2 -1
  197. package/src/anyspend/react/components/common/PanelOnramp.tsx +4 -1
  198. package/src/anyspend/react/components/common/PanelOnrampPayment.tsx +118 -40
  199. package/src/anyspend/react/components/common/PointsDetailPanel.tsx +28 -14
  200. package/src/anyspend/react/components/common/RecipientSelection.tsx +20 -5
  201. package/src/anyspend/react/components/common/TabSection.tsx +21 -12
  202. package/src/anyspend/react/components/common/TransferCryptoDetails.tsx +12 -4
  203. package/src/anyspend/react/components/common/WarningText.tsx +10 -10
  204. package/src/anyspend/react/components/index.ts +16 -0
  205. package/src/anyspend/react/components/types/classes.ts +476 -0
  206. package/src/anyspend/react/hooks/index.ts +1 -0
  207. package/src/anyspend/react/hooks/useAnyspendFlow.ts +141 -17
  208. package/src/anyspend/react/hooks/useDirectTransfer.ts +67 -0
  209. package/src/anyspend/react/hooks/useRecipientAddressState.ts +1 -1
  210. package/src/anyspend/utils/format.ts +13 -2
  211. package/src/global-account/react/components/B3DynamicModal.tsx +0 -5
  212. package/src/global-account/react/components/B3Provider/B3ConfigProvider.tsx +0 -4
  213. package/src/global-account/react/components/B3Provider/B3Provider.native.tsx +1 -1
  214. package/src/global-account/react/components/B3Provider/B3Provider.tsx +1 -11
  215. package/src/global-account/react/components/B3Provider/LocalSDKProvider.tsx +0 -6
  216. package/src/global-account/react/components/B3Provider/RelayKitProviderWrapper.tsx +1 -4
  217. package/src/global-account/react/components/ManageAccount/SettingsContent.tsx +33 -1
  218. package/src/global-account/react/components/SignInWithB3/SignInWithB3Flow.tsx +27 -184
  219. package/src/global-account/react/components/index.ts +0 -3
  220. package/src/global-account/react/hooks/index.ts +0 -1
  221. package/src/global-account/react/hooks/useAuth.ts +14 -31
  222. package/src/global-account/react/hooks/useTWAuth.tsx +3 -5
  223. package/src/global-account/react/stores/useModalStore.ts +7 -20
  224. package/dist/cjs/global-account/react/components/TurnkeyAuthModal.d.ts +0 -8
  225. package/dist/cjs/global-account/react/components/TurnkeyAuthModal.js +0 -86
  226. package/dist/cjs/global-account/react/hooks/useTurnkeyAuth.d.ts +0 -20
  227. package/dist/cjs/global-account/react/hooks/useTurnkeyAuth.js +0 -142
  228. package/dist/esm/global-account/react/components/TurnkeyAuthModal.d.ts +0 -8
  229. package/dist/esm/global-account/react/components/TurnkeyAuthModal.js +0 -83
  230. package/dist/esm/global-account/react/hooks/useTurnkeyAuth.d.ts +0 -20
  231. package/dist/esm/global-account/react/hooks/useTurnkeyAuth.js +0 -136
  232. package/dist/types/global-account/react/components/TurnkeyAuthModal.d.ts +0 -8
  233. package/dist/types/global-account/react/hooks/useTurnkeyAuth.d.ts +0 -20
  234. package/src/global-account/react/components/TurnkeyAuthModal.tsx +0 -243
  235. package/src/global-account/react/hooks/useTurnkeyAuth.ts +0 -171
@@ -7,6 +7,7 @@ import {
7
7
  useGeoOnrampOptions,
8
8
  } from "@b3dotfun/sdk/anyspend/react";
9
9
  import { anyspendService } from "@b3dotfun/sdk/anyspend/services/anyspend";
10
+ import { normalizeAddress } from "@b3dotfun/sdk/anyspend/utils";
10
11
  import {
11
12
  toast,
12
13
  useAccountWallet,
@@ -18,7 +19,7 @@ import {
18
19
  import { formatTokenAmount, formatUnits } from "@b3dotfun/sdk/shared/utils/number";
19
20
  import { useEffect, useMemo, useState } from "react";
20
21
 
21
- import { parseUnits } from "viem";
22
+ import { encodeFunctionData, parseUnits } from "viem";
22
23
  import { base, mainnet } from "viem/chains";
23
24
  import { components } from "../../types/api";
24
25
  import { GetQuoteRequest } from "../../types/api_req_res";
@@ -38,6 +39,60 @@ export enum PanelView {
38
39
  LOADING,
39
40
  POINTS_DETAIL,
40
41
  FEE_DETAIL,
42
+ DIRECT_TRANSFER_SUCCESS,
43
+ }
44
+
45
+ export type CustomExactInConfig = {
46
+ functionAbi: string;
47
+ functionName: string;
48
+ functionArgs: string[];
49
+ to: string;
50
+ spenderAddress?: string;
51
+ action?: string;
52
+ };
53
+
54
+ /**
55
+ * Generates encoded function data for custom contract calls.
56
+ * Handles amount placeholder replacement and BigInt conversion.
57
+ */
58
+ export function generateEncodedData(config: CustomExactInConfig | undefined, amountInWei: string): string | undefined {
59
+ if (!config || !config.functionAbi || !config.functionName || !config.functionArgs) {
60
+ console.warn("customExactInConfig missing required fields for encoding:", {
61
+ hasConfig: !!config,
62
+ hasFunctionAbi: !!config?.functionAbi,
63
+ hasFunctionName: !!config?.functionName,
64
+ hasFunctionArgs: !!config?.functionArgs,
65
+ });
66
+ return undefined;
67
+ }
68
+
69
+ try {
70
+ const abi = JSON.parse(config.functionAbi);
71
+ const processedArgs = config.functionArgs.map(arg => {
72
+ // Replace amount placeholders ({{dstAmount}}, {{amount_out}}, etc.)
73
+ if (arg === "{{dstAmount}}" || arg === "{{amount_out}}") {
74
+ return BigInt(amountInWei);
75
+ }
76
+ // Convert numeric strings to BigInt for uint256 args
77
+ if (/^\d+$/.test(arg)) {
78
+ return BigInt(arg);
79
+ }
80
+ return arg;
81
+ });
82
+
83
+ return encodeFunctionData({
84
+ abi,
85
+ functionName: config.functionName,
86
+ args: processedArgs,
87
+ });
88
+ } catch (e) {
89
+ console.error("Failed to encode function data:", e, {
90
+ functionAbi: config.functionAbi,
91
+ functionName: config.functionName,
92
+ functionArgs: config.functionArgs,
93
+ });
94
+ return undefined;
95
+ }
41
96
  }
42
97
 
43
98
  interface UseAnyspendFlowProps {
@@ -54,6 +109,7 @@ interface UseAnyspendFlowProps {
54
109
  slippage?: number;
55
110
  disableUrlParamManagement?: boolean;
56
111
  orderType?: "hype_duel" | "custom_exact_in" | "swap";
112
+ customExactInConfig?: CustomExactInConfig;
57
113
  }
58
114
 
59
115
  // This hook serves for order hype_duel and custom_exact_in
@@ -70,6 +126,7 @@ export function useAnyspendFlow({
70
126
  slippage = 0,
71
127
  disableUrlParamManagement = false,
72
128
  orderType = "hype_duel",
129
+ customExactInConfig,
73
130
  }: UseAnyspendFlowProps) {
74
131
  const searchParams = useSearchParamsSSR();
75
132
  const router = useRouter();
@@ -89,6 +146,8 @@ export function useAnyspendFlow({
89
146
  const [selectedDstToken, setSelectedDstToken] = useState<components["schemas"]["Token"]>(defaultDstToken);
90
147
  const [srcAmount, setSrcAmount] = useState<string>(paymentType === "fiat" ? "5" : "0");
91
148
  const [dstAmount, setDstAmount] = useState<string>("");
149
+ const [dstAmountInput, setDstAmountInput] = useState<string>(""); // User input for destination amount (EXACT_OUTPUT mode)
150
+ const [debouncedDstAmountInput, setDebouncedDstAmountInput] = useState<string>(""); // Debounced version for quote requests
92
151
  const [isSrcInputDirty, setIsSrcInputDirty] = useState(true);
93
152
 
94
153
  // Derive destination chain ID from token or prop (cannot change)
@@ -183,6 +242,20 @@ export function useAnyspendFlow({
183
242
  fetchDestinationToken();
184
243
  }, [destinationTokenAddress, destinationTokenChainId]);
185
244
 
245
+ // Check if destination token is ready (matches the expected address from props)
246
+ // This is important for EXACT_OUTPUT mode where we need correct decimals
247
+ const isDestinationTokenReady =
248
+ !destinationTokenAddress || selectedDstToken.address.toLowerCase() === destinationTokenAddress.toLowerCase();
249
+
250
+ // Debounce destination amount input for quote requests (500ms delay)
251
+ useEffect(() => {
252
+ const timer = setTimeout(() => {
253
+ setDebouncedDstAmountInput(dstAmountInput);
254
+ }, 500);
255
+
256
+ return () => clearTimeout(timer);
257
+ }, [dstAmountInput]);
258
+
186
259
  // Helper function for onramp vendor mapping
187
260
  const getOnrampVendor = (paymentMethod: FiatPaymentMethod): "coinbase" | "stripe" | "stripe-web2" | undefined => {
188
261
  switch (paymentMethod) {
@@ -197,8 +270,18 @@ export function useAnyspendFlow({
197
270
 
198
271
  // Get quote
199
272
  // For fiat payments, always use USDC decimals (6) regardless of selectedSrcToken
200
- const effectiveDecimals = paymentType === "fiat" ? USDC_BASE.decimals : selectedSrcToken.decimals;
201
- const activeInputAmountInWei = parseUnits(srcAmount.replace(/,/g, ""), effectiveDecimals).toString();
273
+ const effectiveSrcDecimals = paymentType === "fiat" ? USDC_BASE.decimals : selectedSrcToken.decimals;
274
+ const activeInputAmountInWei = parseUnits(srcAmount.replace(/,/g, ""), effectiveSrcDecimals).toString();
275
+
276
+ // Calculate output amount in wei for EXACT_OUTPUT mode
277
+ // Only calculate when destination token is ready (has correct decimals)
278
+ // Use debounced value to reduce quote API calls
279
+ const activeOutputAmountInWei = isDestinationTokenReady
280
+ ? parseUnits(debouncedDstAmountInput.replace(/,/g, "") || "0", selectedDstToken.decimals).toString()
281
+ : "0";
282
+
283
+ // Determine trade type based on which input was last edited
284
+ const tradeType = isSrcInputDirty ? "EXACT_INPUT" : "EXACT_OUTPUT";
202
285
 
203
286
  // Build quote request based on order type
204
287
  const quoteRequest: GetQuoteRequest = (() => {
@@ -215,8 +298,8 @@ export function useAnyspendFlow({
215
298
  return {
216
299
  ...baseParams,
217
300
  type: "swap" as const,
218
- tradeType: "EXACT_INPUT" as const,
219
- amount: activeInputAmountInWei,
301
+ tradeType: tradeType as "EXACT_INPUT" | "EXACT_OUTPUT",
302
+ amount: tradeType === "EXACT_INPUT" ? activeInputAmountInWei : activeOutputAmountInWei,
220
303
  };
221
304
  } else if (orderType === "hype_duel") {
222
305
  return {
@@ -225,6 +308,23 @@ export function useAnyspendFlow({
225
308
  amount: activeInputAmountInWei,
226
309
  };
227
310
  } else {
311
+ // custom_exact_in - for EXACT_OUTPUT, use custom type to get the quote
312
+ if (tradeType === "EXACT_OUTPUT") {
313
+ const encodedData = generateEncodedData(customExactInConfig, activeOutputAmountInWei);
314
+
315
+ return {
316
+ ...baseParams,
317
+ type: "custom" as const,
318
+ payload: {
319
+ amount: activeOutputAmountInWei,
320
+ data: encodedData || "",
321
+ to: customExactInConfig ? normalizeAddress(customExactInConfig.to) : "",
322
+ spenderAddress: customExactInConfig?.spenderAddress
323
+ ? normalizeAddress(customExactInConfig.spenderAddress)
324
+ : undefined,
325
+ },
326
+ };
327
+ }
228
328
  return {
229
329
  ...baseParams,
230
330
  type: "custom_exact_in" as const,
@@ -235,26 +335,45 @@ export function useAnyspendFlow({
235
335
 
236
336
  const { anyspendQuote, isLoadingAnyspendQuote, getAnyspendQuoteError } = useAnyspendQuote(quoteRequest);
237
337
 
338
+ // Combined loading state: includes debounce waiting period and actual quote fetching
339
+ // For EXACT_OUTPUT mode, also check if we're waiting for debounce
340
+ const isDebouncingDstAmount = tradeType === "EXACT_OUTPUT" && dstAmountInput !== debouncedDstAmountInput;
341
+ const isQuoteLoading = isLoadingAnyspendQuote || isDebouncingDstAmount;
342
+
238
343
  // Get geo options for fiat
239
344
  const { geoData, coinbaseAvailablePaymentMethods, stripeWeb2Support } = useGeoOnrampOptions(
240
345
  paymentType === "fiat" ? formatUnits(activeInputAmountInWei, USDC_BASE.decimals) : "0",
241
346
  );
242
347
 
243
- // Update destination amount when quote changes
348
+ // Update amounts when quote changes based on trade type
244
349
  useEffect(() => {
245
- if (anyspendQuote?.data?.currencyOut?.amount && anyspendQuote.data.currencyOut.currency?.decimals) {
246
- const amount = anyspendQuote.data.currencyOut.amount;
247
- const decimals = anyspendQuote.data.currencyOut.currency.decimals;
248
-
249
- // Apply slippage (0-100) - reduce amount by slippage percentageFixed slippage value
250
- const amountWithSlippage = (BigInt(amount) * BigInt(100 - slippage)) / BigInt(100);
251
-
252
- const formattedAmount = formatTokenAmount(amountWithSlippage, decimals, 6, false);
253
- setDstAmount(formattedAmount);
350
+ if (isSrcInputDirty) {
351
+ // EXACT_INPUT mode: update destination amount from quote
352
+ if (anyspendQuote?.data?.currencyOut?.amount && anyspendQuote.data.currencyOut.currency?.decimals) {
353
+ const amount = anyspendQuote.data.currencyOut.amount;
354
+ const decimals = anyspendQuote.data.currencyOut.currency.decimals;
355
+
356
+ // Apply slippage (0-100) - reduce amount by slippage percentage
357
+ const amountWithSlippage = (BigInt(amount) * BigInt(100 - slippage)) / BigInt(100);
358
+
359
+ const formattedAmount = formatTokenAmount(amountWithSlippage, decimals, 6, false);
360
+ setDstAmount(formattedAmount);
361
+ } else {
362
+ setDstAmount("");
363
+ }
254
364
  } else {
255
- setDstAmount("");
365
+ // EXACT_OUTPUT mode: update source amount from quote
366
+ if (anyspendQuote?.data?.currencyIn?.amount && anyspendQuote.data.currencyIn.currency?.decimals) {
367
+ const amount = anyspendQuote.data.currencyIn.amount;
368
+ const decimals = anyspendQuote.data.currencyIn.currency.decimals;
369
+
370
+ const formattedAmount = formatTokenAmount(BigInt(amount), decimals, 6, false);
371
+ setSrcAmount(formattedAmount);
372
+ }
373
+ // Also set the display destination amount from the user input
374
+ setDstAmount(dstAmountInput);
256
375
  }
257
- }, [anyspendQuote, slippage]);
376
+ }, [anyspendQuote, slippage, isSrcInputDirty, dstAmountInput]);
258
377
 
259
378
  // Update useEffect for URL parameter to not override loadOrder
260
379
  useEffect(() => {
@@ -344,8 +463,11 @@ export function useAnyspendFlow({
344
463
  setSrcAmount,
345
464
  dstAmount,
346
465
  setDstAmount,
466
+ dstAmountInput,
467
+ setDstAmountInput,
347
468
  isSrcInputDirty,
348
469
  setIsSrcInputDirty,
470
+ tradeType,
349
471
  // Payment methods
350
472
  cryptoPaymentMethod,
351
473
  setCryptoPaymentMethod,
@@ -366,8 +488,10 @@ export function useAnyspendFlow({
366
488
  // Quote data
367
489
  anyspendQuote,
368
490
  isLoadingAnyspendQuote,
491
+ isQuoteLoading, // Combined loading state (includes debounce + quote fetching)
369
492
  getAnyspendQuoteError,
370
493
  activeInputAmountInWei,
494
+ activeOutputAmountInWei, // User's destination amount input in wei (for EXACT_OUTPUT mode)
371
495
  // Geo/onramp data
372
496
  geoData,
373
497
  coinbaseAvailablePaymentMethods,
@@ -0,0 +1,67 @@
1
+ import { useUnifiedChainSwitchAndExecute } from "@b3dotfun/sdk/global-account/react";
2
+ import { isNativeToken } from "@b3dotfun/sdk/anyspend/utils/token";
3
+ import { encodeFunctionData, erc20Abi } from "viem";
4
+ import { useCallback } from "react";
5
+ import { CryptoPaymentMethodType } from "../components/common/CryptoPaymentMethod";
6
+
7
+ interface DirectTransferParams {
8
+ chainId: number;
9
+ tokenAddress: string;
10
+ recipientAddress: string;
11
+ amount: bigint;
12
+ method: CryptoPaymentMethodType;
13
+ }
14
+
15
+ /**
16
+ * Hook for executing direct token transfers (same chain, same token)
17
+ * bypassing the swap backend.
18
+ */
19
+ export function useDirectTransfer() {
20
+ const { switchChainAndExecute, switchChainAndExecuteWithEOA, isSwitchingOrExecuting } =
21
+ useUnifiedChainSwitchAndExecute();
22
+
23
+ const executeDirectTransfer = useCallback(
24
+ async ({
25
+ chainId,
26
+ tokenAddress,
27
+ recipientAddress,
28
+ amount,
29
+ method,
30
+ }: DirectTransferParams): Promise<string | undefined> => {
31
+ const isNative = isNativeToken(tokenAddress);
32
+
33
+ // Choose the correct execution function based on payment method
34
+ const execute =
35
+ method === CryptoPaymentMethodType.CONNECT_WALLET ? switchChainAndExecuteWithEOA : switchChainAndExecute;
36
+
37
+ let txHash: string | undefined;
38
+ if (isNative) {
39
+ // Native token transfer (ETH, etc.)
40
+ txHash = await execute(chainId, {
41
+ to: recipientAddress,
42
+ value: amount,
43
+ });
44
+ } else {
45
+ // ERC20 token transfer
46
+ const transferData = encodeFunctionData({
47
+ abi: erc20Abi,
48
+ functionName: "transfer",
49
+ args: [recipientAddress as `0x${string}`, amount],
50
+ });
51
+ txHash = await execute(chainId, {
52
+ to: tokenAddress,
53
+ data: transferData,
54
+ value: BigInt(0),
55
+ });
56
+ }
57
+
58
+ return txHash;
59
+ },
60
+ [switchChainAndExecute, switchChainAndExecuteWithEOA],
61
+ );
62
+
63
+ return {
64
+ executeDirectTransfer,
65
+ isTransferring: isSwitchingOrExecuting,
66
+ };
67
+ }
@@ -62,7 +62,7 @@ export function useRecipientAddressState({
62
62
 
63
63
  // The effective recipient address, derived on each render, respecting priority.
64
64
  const effectiveRecipientAddress =
65
- recipientAddressFromProps || selectedRecipientAddress || walletAddress || globalAddress;
65
+ selectedRecipientAddress || recipientAddressFromProps || walletAddress || globalAddress;
66
66
 
67
67
  // Helper function to reset user's manual selection.
68
68
  const resetRecipientAddress = () => {
@@ -7,7 +7,12 @@ export const getStatusDisplay = (
7
7
  const srcToken = order.metadata?.srcToken;
8
8
  const dstToken = order.metadata?.dstToken;
9
9
  const formattedSrcAmount = srcToken ? formatTokenAmount(BigInt(order.srcAmount), srcToken.decimals) : undefined;
10
- const actualDstAmount = order.settlement?.actualDstAmount;
10
+ // For custom orders, use payload.amount as fallback if actualDstAmount is not available
11
+ const actualDstAmount =
12
+ order.settlement?.actualDstAmount ||
13
+ (order.type === "custom" || order.type === "custom_exact_in" || order.type === "deposit_first"
14
+ ? order.payload.amount?.toString()
15
+ : undefined);
11
16
  const formattedActualDstAmount =
12
17
  actualDstAmount && dstToken ? formatTokenAmount(BigInt(actualDstAmount), dstToken.decimals) : undefined;
13
18
 
@@ -51,6 +56,7 @@ export const getStatusDisplay = (
51
56
  case "executed": {
52
57
  const receivedText =
53
58
  formattedActualDstAmount && dstToken ? `Received ${formattedActualDstAmount} ${dstToken.symbol}` : undefined;
59
+ const actionText = (order.metadata as { action?: string })?.action || "Order";
54
60
  const { text, description } =
55
61
  order.type === "swap"
56
62
  ? { text: receivedText || "Swap Complete", description: "Your swap has been completed successfully." }
@@ -60,7 +66,12 @@ export const getStatusDisplay = (
60
66
  ? { text: "Tournament Joined", description: "You have joined the tournament" }
61
67
  : order.type === "fund_tournament"
62
68
  ? { text: "Tournament Funded", description: "You have funded the tournament" }
63
- : { text: receivedText || "Order Complete", description: "Your order has been completed" };
69
+ : order.type === "custom" || order.type === "custom_exact_in"
70
+ ? {
71
+ text: receivedText || `${actionText} Complete`,
72
+ description: "Your order has been completed successfully.",
73
+ }
74
+ : { text: receivedText || "Order Complete", description: "Your order has been completed" };
64
75
  return { text, status: "success", description };
65
76
  }
66
77
 
@@ -29,7 +29,6 @@ import { RequestPermissions } from "./RequestPermissions/RequestPermissions";
29
29
  import { Send } from "./Send/Send";
30
30
  import { SignInWithB3Flow } from "./SignInWithB3/SignInWithB3Flow";
31
31
  import { ToastContainer, useToastContext } from "./Toast/index";
32
- import { TurnkeyAuthModal } from "./TurnkeyAuthModal";
33
32
  import { Dialog, DialogContent, DialogDescription, DialogTitle } from "./ui/dialog";
34
33
  import { Drawer, DrawerContent, DrawerDescription, DrawerTitle } from "./ui/drawer";
35
34
 
@@ -57,7 +56,6 @@ export function B3DynamicModal() {
57
56
  "anySpendBuySpin",
58
57
  "anySpendOrderHistory",
59
58
  "signInWithB3",
60
- "turnkeyAuth",
61
59
  "anySpendSignatureMint",
62
60
  "anySpendBondKit",
63
61
  "linkAccount",
@@ -96,7 +94,6 @@ export function B3DynamicModal() {
96
94
  fullWidthTypes.includes(contentType?.type as string) && "w-full",
97
95
  isFreestyleType && "b3-modal-freestyle",
98
96
  contentType?.type === "signInWithB3" && "p-0",
99
- contentType?.type === "turnkeyAuth" && "p-0",
100
97
  contentType?.type === "anySpend" && "md:p-0",
101
98
  contentType?.type === "send" && "p-0",
102
99
  contentType?.type === "manageAccount" && " md:p-0 md:pt-2",
@@ -113,8 +110,6 @@ export function B3DynamicModal() {
113
110
  switch (contentType.type) {
114
111
  case "signInWithB3":
115
112
  return <SignInWithB3Flow {...contentType} />;
116
- case "turnkeyAuth":
117
- return <TurnkeyAuthModal {...contentType} />;
118
113
  case "requestPermissions":
119
114
  return <RequestPermissions {...contentType} />;
120
115
  case "manageAccount":
@@ -25,7 +25,6 @@ export interface B3ConfigContextType {
25
25
  partnerId: string;
26
26
  stripePublishableKey?: string;
27
27
  createClientReferenceId?: (params: CreateOrderParams | CreateOnrampOrderParams) => Promise<string>;
28
- enableTurnkey: boolean;
29
28
  }
30
29
 
31
30
  const B3ConfigContext = createContext<B3ConfigContextType | null>(null);
@@ -41,7 +40,6 @@ export function B3ConfigProvider({
41
40
  partnerId,
42
41
  stripePublishableKey,
43
42
  createClientReferenceId,
44
- enableTurnkey = false,
45
43
  }: {
46
44
  children: React.ReactNode;
47
45
  accountOverride?: Account;
@@ -53,7 +51,6 @@ export function B3ConfigProvider({
53
51
  partnerId: string;
54
52
  stripePublishableKey?: string;
55
53
  createClientReferenceId?: (params: CreateOrderParams | CreateOnrampOrderParams) => Promise<string>;
56
- enableTurnkey?: boolean;
57
54
  }) {
58
55
  return (
59
56
  <B3ConfigContext.Provider
@@ -67,7 +64,6 @@ export function B3ConfigProvider({
67
64
  partnerId,
68
65
  stripePublishableKey,
69
66
  createClientReferenceId,
70
- enableTurnkey,
71
67
  }}
72
68
  >
73
69
  {children}
@@ -24,7 +24,7 @@ export function B3Provider({
24
24
  environment,
25
25
  clientType = "socket",
26
26
  partnerId,
27
- rpcUrls,
27
+ rpcUrls: _rpcUrls,
28
28
  onConnect,
29
29
  defaultPermissions,
30
30
  }: {
@@ -1,4 +1,3 @@
1
- import { Users } from "@b3dotfun/b3-api";
2
1
  import { CreateOnrampOrderParams } from "@b3dotfun/sdk/anyspend/react/hooks/useAnyspendCreateOnrampOrder";
3
2
  import { CreateOrderParams } from "@b3dotfun/sdk/anyspend/react/hooks/useAnyspendCreateOrder";
4
3
  import { RelayKitProviderWrapper, TooltipProvider } from "@b3dotfun/sdk/global-account/react";
@@ -42,9 +41,7 @@ export function B3Provider({
42
41
  connectors,
43
42
  overrideDefaultConnectors = false,
44
43
  createClientReferenceId,
45
- enableTurnkey = false,
46
44
  defaultPermissions,
47
- onTurnkeyConnect,
48
45
  }: {
49
46
  theme: "light" | "dark";
50
47
  children: React.ReactNode;
@@ -66,9 +63,7 @@ export function B3Provider({
66
63
  connectors?: CreateConnectorFn[];
67
64
  overrideDefaultConnectors?: boolean;
68
65
  createClientReferenceId?: (params: CreateOrderParams | CreateOnrampOrderParams) => Promise<string>;
69
- enableTurnkey?: boolean;
70
66
  defaultPermissions?: PermissionsConfig;
71
- onTurnkeyConnect?: (user: Users) => void | Promise<void>;
72
67
  }) {
73
68
  // Initialize Google Analytics on mount
74
69
  useEffect(() => {
@@ -91,11 +86,7 @@ export function B3Provider({
91
86
  <QueryClientProvider client={queryClient}>
92
87
  <TooltipProvider>
93
88
  <ToastProvider>
94
- <LocalSDKProvider
95
- onConnectCallback={onConnect}
96
- onLogoutCallback={onLogout}
97
- onTurnkeyConnect={onTurnkeyConnect}
98
- >
89
+ <LocalSDKProvider onConnectCallback={onConnect} onLogoutCallback={onLogout}>
99
90
  <B3ConfigProvider
100
91
  accountOverride={accountOverride}
101
92
  environment={environment}
@@ -105,7 +96,6 @@ export function B3Provider({
105
96
  partnerId={partnerId}
106
97
  stripePublishableKey={stripePublishableKey}
107
98
  createClientReferenceId={createClientReferenceId}
108
- enableTurnkey={enableTurnkey}
109
99
  defaultPermissions={defaultPermissions}
110
100
  >
111
101
  <ToastContextConnector />
@@ -1,4 +1,3 @@
1
- import { Users } from "@b3dotfun/b3-api";
2
1
  import { createContext } from "react";
3
2
  import { Wallet } from "thirdweb/wallets";
4
3
 
@@ -9,13 +8,11 @@ import { Wallet } from "thirdweb/wallets";
9
8
  export interface LocalSDKContextType {
10
9
  onConnectCallback?: (wallet: Wallet, b3Jwt: string) => void | Promise<void>;
11
10
  onLogoutCallback?: () => void | Promise<void>;
12
- onTurnkeyConnect?: (user: Users) => void | Promise<void>;
13
11
  }
14
12
 
15
13
  export const LocalSDKContext = createContext<LocalSDKContextType>({
16
14
  onConnectCallback: undefined,
17
15
  onLogoutCallback: undefined,
18
- onTurnkeyConnect: undefined,
19
16
  });
20
17
 
21
18
  /**
@@ -25,19 +22,16 @@ export function LocalSDKProvider({
25
22
  children,
26
23
  onConnectCallback,
27
24
  onLogoutCallback,
28
- onTurnkeyConnect,
29
25
  }: {
30
26
  children: React.ReactNode;
31
27
  onConnectCallback?: (wallet: Wallet, b3Jwt: string) => void | Promise<void>;
32
28
  onLogoutCallback?: () => void | Promise<void>;
33
- onTurnkeyConnect?: (user: Users) => void | Promise<void>;
34
29
  }) {
35
30
  return (
36
31
  <LocalSDKContext.Provider
37
32
  value={{
38
33
  onConnectCallback,
39
34
  onLogoutCallback,
40
- onTurnkeyConnect,
41
35
  }}
42
36
  >
43
37
  {children}
@@ -19,9 +19,6 @@ export function RelayKitProviderWrapper({
19
19
  fetchChains();
20
20
  }, []);
21
21
 
22
- const isTurnkeyPrimary = process.env.NEXT_PUBLIC_TURNKEY_PRIMARY === "true";
23
- const appName = isTurnkeyPrimary ? "Smart Wallet" : "AnySpend";
24
-
25
22
  return (
26
23
  <RelayKitProvider
27
24
  options={{
@@ -33,7 +30,7 @@ export function RelayKitProviderWrapper({
33
30
  },
34
31
  chains: relayChains,
35
32
  privateChainIds: undefined,
36
- appName,
33
+ appName: "AnySpend",
37
34
  useGasFeeEstimations: true,
38
35
  }}
39
36
  >
@@ -1,7 +1,10 @@
1
- import { useModalStore } from "@b3dotfun/sdk/global-account/react";
1
+ import { useAuthentication, useModalStore } from "@b3dotfun/sdk/global-account/react";
2
2
  import { client } from "@b3dotfun/sdk/shared/utils/thirdweb";
3
+ import { Loader2 } from "lucide-react";
4
+ import { useState } from "react";
3
5
  import { Chain } from "thirdweb";
4
6
  import { useProfiles } from "thirdweb/react";
7
+ import SignOutIcon from "../icons/SignOutIcon";
5
8
  import ModalHeader from "../ModalHeader/ModalHeader";
6
9
  import SettingsMenuItem from "./SettingsMenuItem";
7
10
  import SettingsProfileCard from "./SettingsProfileCard";
@@ -17,6 +20,8 @@ const SettingsContent = ({
17
20
  }) => {
18
21
  const setB3ModalContentType = useModalStore(state => state.setB3ModalContentType);
19
22
  const setB3ModalOpen = useModalStore(state => state.setB3ModalOpen);
23
+ const { logout } = useAuthentication(partnerId);
24
+ const [logoutLoading, setLogoutLoading] = useState(false);
20
25
 
21
26
  const { data: profilesRaw = [] } = useProfiles({ client });
22
27
 
@@ -59,6 +64,14 @@ const SettingsContent = ({
59
64
  setB3ModalOpen(true);
60
65
  };
61
66
 
67
+ const onLogoutEnhanced = async () => {
68
+ setLogoutLoading(true);
69
+ await logout();
70
+ onLogout?.();
71
+ setB3ModalOpen(false);
72
+ setLogoutLoading(false);
73
+ };
74
+
62
75
  return (
63
76
  <div className="flex h-[470px] flex-col">
64
77
  <ModalHeader showBackButton={false} showCloseButton={false} title="Settings" />
@@ -99,6 +112,25 @@ const SettingsContent = ({
99
112
  onClick={() => handleNavigate("notifications")}
100
113
  />
101
114
  </div>
115
+
116
+ {/* Logout Section */}
117
+ <div className="mt-auto px-5 pb-5">
118
+ <button
119
+ className="b3-modal-sign-out-button border-b3-line hover:bg-b3-line bg-b3-background dark:bg-b3-background dark:border-b3-line dark:hover:bg-b3-line/80 flex w-full items-center justify-center gap-1.5 rounded-xl border border-solid p-3 transition-colors"
120
+ onClick={onLogoutEnhanced}
121
+ disabled={logoutLoading}
122
+ style={{
123
+ boxShadow: "inset 0px 0px 0px 1px rgba(10,13,18,0.18), inset 0px -2px 0px 0px rgba(10,13,18,0.05)",
124
+ }}
125
+ >
126
+ {logoutLoading ? (
127
+ <Loader2 className="text-b3-grey animate-spin" size={20} />
128
+ ) : (
129
+ <SignOutIcon size={20} className="text-b3-grey" color="currentColor" />
130
+ )}
131
+ <p className="text-b3-grey dark:text-b3-foreground-muted font-neue-montreal-semibold text-base">Sign out</p>
132
+ </button>
133
+ </div>
102
134
  </div>
103
135
  );
104
136
  };