@b3dotfun/sdk 0.0.40-alpha.7 → 0.0.40-alpha.8

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 (41) hide show
  1. package/dist/cjs/anyspend/react/components/AnySpend.js +1 -1
  2. package/dist/cjs/anyspend/react/components/AnyspendDepositHype.js +1 -1
  3. package/dist/cjs/anyspend/react/components/common/CryptoReceiveSection.js +38 -36
  4. package/dist/cjs/anyspend/react/components/common/PanelOnramp.d.ts +3 -1
  5. package/dist/cjs/anyspend/react/components/common/PanelOnramp.js +7 -6
  6. package/dist/cjs/anyspend/react/contexts/FeatureFlagsContext.d.ts +11 -0
  7. package/dist/cjs/anyspend/react/contexts/FeatureFlagsContext.js +21 -0
  8. package/dist/cjs/anyspend/react/hooks/useAnyspendFlow.d.ts +1 -65
  9. package/dist/cjs/anyspend/react/providers/AnyspendProvider.d.ts +5 -2
  10. package/dist/cjs/anyspend/react/providers/AnyspendProvider.js +5 -3
  11. package/dist/cjs/anyspend/react/providers/index.d.ts +1 -0
  12. package/dist/cjs/anyspend/react/providers/index.js +3 -0
  13. package/dist/cjs/anyspend/types/api_req_res.d.ts +8 -1
  14. package/dist/esm/anyspend/react/components/AnySpend.js +1 -1
  15. package/dist/esm/anyspend/react/components/AnyspendDepositHype.js +1 -1
  16. package/dist/esm/anyspend/react/components/common/CryptoReceiveSection.js +38 -36
  17. package/dist/esm/anyspend/react/components/common/PanelOnramp.d.ts +3 -1
  18. package/dist/esm/anyspend/react/components/common/PanelOnramp.js +7 -6
  19. package/dist/esm/anyspend/react/contexts/FeatureFlagsContext.d.ts +11 -0
  20. package/dist/esm/anyspend/react/contexts/FeatureFlagsContext.js +17 -0
  21. package/dist/esm/anyspend/react/hooks/useAnyspendFlow.d.ts +1 -65
  22. package/dist/esm/anyspend/react/providers/AnyspendProvider.d.ts +5 -2
  23. package/dist/esm/anyspend/react/providers/AnyspendProvider.js +5 -3
  24. package/dist/esm/anyspend/react/providers/index.d.ts +1 -0
  25. package/dist/esm/anyspend/react/providers/index.js +1 -0
  26. package/dist/esm/anyspend/types/api_req_res.d.ts +8 -1
  27. package/dist/types/anyspend/react/components/common/PanelOnramp.d.ts +3 -1
  28. package/dist/types/anyspend/react/contexts/FeatureFlagsContext.d.ts +11 -0
  29. package/dist/types/anyspend/react/hooks/useAnyspendFlow.d.ts +1 -65
  30. package/dist/types/anyspend/react/providers/AnyspendProvider.d.ts +5 -2
  31. package/dist/types/anyspend/react/providers/index.d.ts +1 -0
  32. package/dist/types/anyspend/types/api_req_res.d.ts +8 -1
  33. package/package.json +1 -1
  34. package/src/anyspend/react/components/AnySpend.tsx +1 -0
  35. package/src/anyspend/react/components/AnyspendDepositHype.tsx +1 -0
  36. package/src/anyspend/react/components/common/CryptoReceiveSection.tsx +56 -45
  37. package/src/anyspend/react/components/common/PanelOnramp.tsx +22 -16
  38. package/src/anyspend/react/contexts/FeatureFlagsContext.tsx +34 -0
  39. package/src/anyspend/react/providers/AnyspendProvider.tsx +11 -6
  40. package/src/anyspend/react/providers/index.ts +1 -0
  41. package/src/anyspend/types/api_req_res.ts +10 -1
@@ -7,9 +7,11 @@ import { formatAddress } from "../../../../shared/utils/formatAddress.js";
7
7
  import { ChevronRight, Wallet } from "lucide-react";
8
8
  import { useRef } from "react";
9
9
  import { toast } from "sonner";
10
+ import { useFeatureFlags } from "../../contexts/FeatureFlagsContext.js";
10
11
  import { FiatPaymentMethod } from "./FiatPaymentMethod.js";
11
12
  import { OrderTokenAmountFiat } from "./OrderTokenAmountFiat.js";
12
- export function PanelOnramp({ srcAmountOnRamp, setSrcAmountOnRamp, selectedPaymentMethod, setActivePanel, _recipientAddress, destinationToken, destinationChainId, destinationAmount, onDestinationTokenChange, onDestinationChainChange, fiatPaymentMethodIndex, recipientSelectionPanelIndex, dstTokenSymbol, hideDstToken = false, }) {
13
+ export function PanelOnramp({ srcAmountOnRamp, setSrcAmountOnRamp, selectedPaymentMethod, setActivePanel, _recipientAddress, destinationToken, destinationChainId, destinationAmount, onDestinationTokenChange, onDestinationChainChange, fiatPaymentMethodIndex, recipientSelectionPanelIndex, dstTokenSymbol, hideDstToken = false, anyspendQuote, }) {
14
+ const featureFlags = useFeatureFlags();
13
15
  // Get geo-based onramp options to access fee information
14
16
  const { stripeWeb2Support } = useGeoOnrampOptions(srcAmountOnRamp);
15
17
  // Helper function to get fees from API data
@@ -70,9 +72,8 @@ export function PanelOnramp({ srcAmountOnRamp, setSrcAmountOnRamp, selectedPayme
70
72
  width: `${Math.max(50, srcAmountOnRamp.length * 34)}px`,
71
73
  } })] }) }), _jsx("div", { className: cn("mx-auto mb-6 inline-grid grid-cols-4 gap-2", hideDstToken && "mb-0"), children: ["5", "10", "20", "25"].map(value => (_jsxs("button", { onClick: () => handleQuickAmount(value), className: `bg-as-surface-secondary border-as-border-secondary hover:border-as-border-secondary h-7 w-14 rounded-lg border text-sm font-medium transition-all duration-200 ${srcAmountOnRamp === value
72
74
  ? "border-as-border-secondary bg-as-surface-secondary"
73
- : "bg-as-surface-secondary hover:bg-as-surface-secondary"}`, children: ["$", value] }, value))) }), destinationToken && destinationChainId && !hideDstToken && (_jsx(OrderTokenAmountFiat, { address: _recipientAddress, context: "to", inputValue: destinationAmount || "0", onChangeInput: () => { }, chainId: destinationChainId, setChainId: onDestinationChainChange || (() => { }), token: destinationToken, setToken: onDestinationTokenChange || (() => { }) }))] }), _jsxs("div", { className: "border-as-border-secondary bg-as-surface-secondary mt-4 flex w-full flex-col gap-3 rounded-xl border p-4", children: [_jsxs("div", { className: "flex w-full items-center justify-between gap-2", children: [_jsx("span", { className: "text-as-tertiarry flex items-center text-sm", children: "Recipient" }), _recipientAddress ? (_jsxs("button", { className: "text-as-tertiarry flex h-7 items-center gap-1 text-sm transition-colors hover:text-blue-700", onClick: () => setActivePanel(recipientSelectionPanelIndex), children: [_jsx("span", { className: "text-sm", children: recipientName ? formatUsername(recipientName) : formatAddress(_recipientAddress) }), _jsx(ChevronRight, { size: 16 })] })) : (_jsxs("button", { className: "text-as-tertiarry flex h-7 items-center gap-1 text-sm transition-colors hover:text-blue-700", onClick: () => setActivePanel(5), children: [_jsx(Wallet, { className: "text-as-brand", size: 16 }), "Select recipient", _jsx(ChevronRight, { size: 16 })] }))] }), _jsx("div", { className: "divider w-full" }), _jsxs("div", { className: "flex items-center justify-between", children: [_jsx("span", { className: "text-as-tertiarry text-sm", children: "Expected to receive" }), _jsxs("div", { className: "flex items-center gap-2", children: [_jsxs("span", { className: "text-as-primary font-semibold", children: [destinationAmount || "0", " ", dstTokenSymbol || destinationToken?.symbol || ""] }), _jsxs("span", { className: "text-as-tertiarry text-sm", children: ["on ", destinationChainId ? ALL_CHAINS[destinationChainId]?.name : ""] }), destinationToken && destinationChainId && destinationToken.metadata?.logoURI && (_jsx("img", { src: ALL_CHAINS[destinationChainId]?.logoUrl, alt: "Chain", className: "h-4 w-4 rounded-full" }))] })] }), _jsx("div", { className: "divider w-full" }), _jsx("div", { className: "", children: _jsx("div", { className: "flex items-center justify-between", children: (() => {
74
- const currentPaymentMethod = selectedPaymentMethod || FiatPaymentMethod.NONE;
75
- const fee = getFeeFromApi(currentPaymentMethod);
76
- return (_jsxs(_Fragment, { children: [_jsx("span", { className: "text-as-tertiarry text-sm", children: fee !== null ? `Total (included $${fee.toFixed(2)} fee)` : "Total" }), _jsxs("span", { className: "text-as-primary font-semibold", children: ["$", getTotalAmount(currentPaymentMethod).toFixed(2)] })] }));
77
- })() }) })] })] }));
75
+ : "bg-as-surface-secondary hover:bg-as-surface-secondary"}`, children: ["$", value] }, value))) }), destinationToken && destinationChainId && !hideDstToken && (_jsx(OrderTokenAmountFiat, { address: _recipientAddress, context: "to", inputValue: destinationAmount || "0", onChangeInput: () => { }, chainId: destinationChainId, setChainId: onDestinationChainChange || (() => { }), token: destinationToken, setToken: onDestinationTokenChange || (() => { }) }))] }), _jsxs("div", { className: "border-as-border-secondary bg-as-surface-secondary mt-4 flex w-full flex-col gap-3 rounded-xl border p-4", children: [_jsxs("div", { className: "flex w-full items-center justify-between gap-2", children: [_jsx("span", { className: "text-as-tertiarry flex items-center text-sm", children: "Recipient" }), _recipientAddress ? (_jsxs("button", { className: "text-as-tertiarry flex h-7 items-center gap-1 text-sm transition-colors hover:text-blue-700", onClick: () => setActivePanel(recipientSelectionPanelIndex), children: [_jsx("span", { className: "text-sm", children: recipientName ? formatUsername(recipientName) : formatAddress(_recipientAddress) }), _jsx(ChevronRight, { size: 16 })] })) : (_jsxs("button", { className: "text-as-tertiarry flex h-7 items-center gap-1 text-sm transition-colors hover:text-blue-700", onClick: () => setActivePanel(5), children: [_jsx(Wallet, { className: "text-as-brand", size: 16 }), "Select recipient", _jsx(ChevronRight, { size: 16 })] }))] }), _jsx("div", { className: "divider w-full" }), _jsxs("div", { className: "flex items-center justify-between", children: [_jsx("span", { className: "text-as-tertiarry text-sm", children: "Expected to receive" }), _jsxs("div", { className: "flex items-center gap-2", children: [_jsxs("span", { className: "text-as-primary font-semibold", children: [destinationAmount || "0", " ", dstTokenSymbol || destinationToken?.symbol || ""] }), _jsxs("span", { className: "text-as-tertiarry text-sm", children: ["on ", destinationChainId ? ALL_CHAINS[destinationChainId]?.name : ""] }), destinationToken && destinationChainId && destinationToken.metadata?.logoURI && (_jsx("img", { src: ALL_CHAINS[destinationChainId]?.logoUrl, alt: "Chain", className: "h-4 w-4 rounded-full" }))] })] }), _jsx("div", { className: "divider w-full" }), _jsx("div", { className: "", children: _jsxs("div", { className: "flex items-center justify-between", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx("span", { className: "text-as-tertiarry text-sm", children: (() => {
76
+ const fee = getFeeFromApi(selectedPaymentMethod || FiatPaymentMethod.NONE);
77
+ return fee !== null ? `Total (included $${fee.toFixed(2)} fee)` : "Total";
78
+ })() }), featureFlags.showPoints && anyspendQuote?.data?.pointsAmount && anyspendQuote.data.pointsAmount > 0 && (_jsxs("span", { className: "text-as-brand text-sm font-medium", children: ["+", anyspendQuote.data.pointsAmount.toLocaleString(), " pts"] }, `points-${anyspendQuote.data.pointsAmount}`))] }), _jsxs("span", { className: "text-as-primary font-semibold", children: ["$", getTotalAmount(selectedPaymentMethod || FiatPaymentMethod.NONE).toFixed(2)] })] }) })] })] }));
78
79
  }
@@ -0,0 +1,11 @@
1
+ import { ReactNode } from "react";
2
+ export interface FeatureFlags {
3
+ showPoints?: boolean;
4
+ }
5
+ interface FeatureFlagsProviderProps {
6
+ children: ReactNode;
7
+ featureFlags?: FeatureFlags;
8
+ }
9
+ export declare function FeatureFlagsProvider({ children, featureFlags }: FeatureFlagsProviderProps): import("react/jsx-runtime").JSX.Element;
10
+ export declare function useFeatureFlags(): FeatureFlags;
11
+ export {};
@@ -0,0 +1,17 @@
1
+ "use client";
2
+ import { jsx as _jsx } from "react/jsx-runtime";
3
+ import { createContext, useContext } from "react";
4
+ const FeatureFlagsContext = createContext(undefined);
5
+ const defaultFeatureFlags = {
6
+ showPoints: false,
7
+ };
8
+ export function FeatureFlagsProvider({ children, featureFlags = defaultFeatureFlags }) {
9
+ return _jsx(FeatureFlagsContext.Provider, { value: { featureFlags }, children: children });
10
+ }
11
+ export function useFeatureFlags() {
12
+ const context = useContext(FeatureFlagsContext);
13
+ if (!context) {
14
+ return defaultFeatureFlags;
15
+ }
16
+ return context.featureFlags;
17
+ }
@@ -78,71 +78,7 @@ export declare function useAnyspendFlow({ paymentType, recipientAddress, loadOrd
78
78
  globalAddress: string | undefined;
79
79
  hasEnoughBalance: boolean;
80
80
  isBalanceLoading: boolean;
81
- anyspendQuote: {
82
- success: boolean;
83
- message: string;
84
- data: {
85
- operation?: string;
86
- sender?: string;
87
- recipient?: string;
88
- currencyIn?: {
89
- currency?: {
90
- chainId?: number;
91
- address?: string;
92
- symbol?: string;
93
- name?: string;
94
- decimals?: number;
95
- metadata?: {
96
- logoURI?: string;
97
- };
98
- };
99
- amount?: string;
100
- amountFormatted?: string;
101
- amountUsd?: string;
102
- minimumAmount?: string;
103
- };
104
- currencyOut?: {
105
- currency?: {
106
- chainId?: number;
107
- address?: string;
108
- symbol?: string;
109
- name?: string;
110
- decimals?: number;
111
- metadata?: {
112
- logoURI?: string;
113
- };
114
- };
115
- amount?: string;
116
- amountFormatted?: string;
117
- amountUsd?: string;
118
- minimumAmount?: string;
119
- };
120
- totalImpact?: {
121
- usd?: string;
122
- percent?: string;
123
- };
124
- swapImpact?: {
125
- usd?: string;
126
- percent?: string;
127
- };
128
- rate?: string;
129
- slippageTolerance?: {
130
- origin?: {
131
- usd?: string;
132
- value?: string;
133
- percent?: string;
134
- };
135
- destination?: {
136
- usd?: string;
137
- value?: string;
138
- percent?: string;
139
- };
140
- };
141
- timeEstimate?: number;
142
- userBalance?: string;
143
- };
144
- statusCode: number;
145
- } | undefined;
81
+ anyspendQuote: import("../../types/api_req_res").GetQuoteResponse | undefined;
146
82
  isLoadingAnyspendQuote: boolean;
147
83
  getAnyspendQuoteError: Error | null;
148
84
  activeInputAmountInWei: string;
@@ -1,6 +1,8 @@
1
1
  import { ReactNode } from "react";
2
+ import { FeatureFlags } from "../contexts/FeatureFlagsContext";
2
3
  interface AnyspendProviderProps {
3
4
  children: ReactNode;
5
+ featureFlags?: FeatureFlags;
4
6
  }
5
7
  /**
6
8
  * AnyspendProvider is a top-level provider that wraps your application to provide
@@ -12,17 +14,18 @@ interface AnyspendProviderProps {
12
14
  * - Safe to use at the application root
13
15
  * - Configures sensible defaults for query caching
14
16
  * - Handles Stripe payment redirects and modal state
17
+ * - Provides feature flags configuration
15
18
  *
16
19
  * @example
17
20
  * ```tsx
18
21
  * function App() {
19
22
  * return (
20
- * <AnyspendProvider>
23
+ * <AnyspendProvider featureFlags={{ showPoints: true }}>
21
24
  * <YourApp />
22
25
  * </AnyspendProvider>
23
26
  * );
24
27
  * }
25
28
  * ```
26
29
  */
27
- export declare const AnyspendProvider: ({ children }: AnyspendProviderProps) => import("react/jsx-runtime").JSX.Element;
30
+ export declare const AnyspendProvider: ({ children, featureFlags }: AnyspendProviderProps) => import("react/jsx-runtime").JSX.Element;
28
31
  export {};
@@ -3,6 +3,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import { TooltipProvider } from "../../../global-account/react/index.js";
4
4
  import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
5
5
  import { useState } from "react";
6
+ import { FeatureFlagsProvider } from "../contexts/FeatureFlagsContext.js";
6
7
  import { StripeRedirectHandler } from "./StripeRedirectHandler.js";
7
8
  const defaultQueryClientConfig = {
8
9
  defaultOptions: {
@@ -23,19 +24,20 @@ const defaultQueryClientConfig = {
23
24
  * - Safe to use at the application root
24
25
  * - Configures sensible defaults for query caching
25
26
  * - Handles Stripe payment redirects and modal state
27
+ * - Provides feature flags configuration
26
28
  *
27
29
  * @example
28
30
  * ```tsx
29
31
  * function App() {
30
32
  * return (
31
- * <AnyspendProvider>
33
+ * <AnyspendProvider featureFlags={{ showPoints: true }}>
32
34
  * <YourApp />
33
35
  * </AnyspendProvider>
34
36
  * );
35
37
  * }
36
38
  * ```
37
39
  */
38
- export const AnyspendProvider = function AnyspendProvider({ children }) {
40
+ export const AnyspendProvider = function AnyspendProvider({ children, featureFlags }) {
39
41
  const [queryClient] = useState(() => new QueryClient(defaultQueryClientConfig));
40
- return (_jsx(QueryClientProvider, { client: queryClient, children: _jsxs(TooltipProvider, { children: [_jsx(StripeRedirectHandler, {}), children] }) }));
42
+ return (_jsx(QueryClientProvider, { client: queryClient, children: _jsx(FeatureFlagsProvider, { featureFlags: featureFlags, children: _jsxs(TooltipProvider, { children: [_jsx(StripeRedirectHandler, {}), children] }) }) }));
41
43
  };
@@ -1,2 +1,3 @@
1
1
  export * from "./AnyspendProvider";
2
2
  export * from "./StripeRedirectHandler";
3
+ export { useFeatureFlags, type FeatureFlags } from "../contexts/FeatureFlagsContext";
@@ -1,2 +1,3 @@
1
1
  export * from "./AnyspendProvider.js";
2
2
  export * from "./StripeRedirectHandler.js";
3
+ export { useFeatureFlags } from "../contexts/FeatureFlagsContext.js";
@@ -1,10 +1,17 @@
1
1
  import { paths } from "./api";
2
2
  export type GetOrderAndTxsResponse = paths["/orders/{orderId}"]["get"]["responses"]["200"]["content"]["application/json"];
3
3
  export type GetQuoteRequest = paths["/orders/quote"]["post"]["requestBody"]["content"]["application/json"];
4
- export type GetQuoteResponse = paths["/orders/quote"]["post"]["responses"]["200"]["content"]["application/json"];
4
+ type BaseGetQuoteResponse = paths["/orders/quote"]["post"]["responses"]["200"]["content"]["application/json"];
5
+ export type GetQuoteResponse = BaseGetQuoteResponse & {
6
+ data: BaseGetQuoteResponse["data"] & {
7
+ pointsAmount?: number;
8
+ pointsMultiplier?: number;
9
+ };
10
+ };
5
11
  export type GetCoinbaseOnrampOptionsResponse = paths["/onramp/coinbase/options"]["get"]["responses"]["200"]["content"]["application/json"];
6
12
  export type GetOrderHistoryResponse = paths["/orders"]["get"]["responses"]["200"]["content"]["application/json"];
7
13
  export type GetTokenListResponse = paths["/chains/{chainId}/tokens"]["get"]["responses"]["200"]["content"]["application/json"];
8
14
  export type CreateOrderResponse = paths["/orders"]["post"]["responses"]["200"]["content"]["application/json"];
9
15
  export type GetStripeSupportedResponse = paths["/onramp/stripe/supported"]["get"]["responses"]["200"]["content"]["application/json"];
10
16
  export type GetStripeClientSecret = paths["/stripe/clientSecret"]["get"]["responses"]["200"]["content"]["application/json"];
17
+ export {};
@@ -1,6 +1,7 @@
1
1
  import { components } from "@b3dotfun/sdk/anyspend/types/api";
2
+ import { GetQuoteResponse } from "@b3dotfun/sdk/anyspend/types/api_req_res";
2
3
  import { FiatPaymentMethod } from "./FiatPaymentMethod";
3
- export declare function PanelOnramp({ srcAmountOnRamp, setSrcAmountOnRamp, selectedPaymentMethod, setActivePanel, _recipientAddress, destinationToken, destinationChainId, destinationAmount, onDestinationTokenChange, onDestinationChainChange, fiatPaymentMethodIndex, recipientSelectionPanelIndex, dstTokenSymbol, hideDstToken, }: {
4
+ export declare function PanelOnramp({ srcAmountOnRamp, setSrcAmountOnRamp, selectedPaymentMethod, setActivePanel, _recipientAddress, destinationToken, destinationChainId, destinationAmount, onDestinationTokenChange, onDestinationChainChange, fiatPaymentMethodIndex, recipientSelectionPanelIndex, dstTokenSymbol, hideDstToken, anyspendQuote, }: {
4
5
  srcAmountOnRamp: string;
5
6
  setSrcAmountOnRamp: (amount: string) => void;
6
7
  selectedPaymentMethod?: FiatPaymentMethod;
@@ -15,4 +16,5 @@ export declare function PanelOnramp({ srcAmountOnRamp, setSrcAmountOnRamp, selec
15
16
  recipientSelectionPanelIndex: number;
16
17
  dstTokenSymbol?: string;
17
18
  hideDstToken?: boolean;
19
+ anyspendQuote?: GetQuoteResponse;
18
20
  }): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,11 @@
1
+ import { ReactNode } from "react";
2
+ export interface FeatureFlags {
3
+ showPoints?: boolean;
4
+ }
5
+ interface FeatureFlagsProviderProps {
6
+ children: ReactNode;
7
+ featureFlags?: FeatureFlags;
8
+ }
9
+ export declare function FeatureFlagsProvider({ children, featureFlags }: FeatureFlagsProviderProps): import("react/jsx-runtime").JSX.Element;
10
+ export declare function useFeatureFlags(): FeatureFlags;
11
+ export {};
@@ -78,71 +78,7 @@ export declare function useAnyspendFlow({ paymentType, recipientAddress, loadOrd
78
78
  globalAddress: string | undefined;
79
79
  hasEnoughBalance: boolean;
80
80
  isBalanceLoading: boolean;
81
- anyspendQuote: {
82
- success: boolean;
83
- message: string;
84
- data: {
85
- operation?: string;
86
- sender?: string;
87
- recipient?: string;
88
- currencyIn?: {
89
- currency?: {
90
- chainId?: number;
91
- address?: string;
92
- symbol?: string;
93
- name?: string;
94
- decimals?: number;
95
- metadata?: {
96
- logoURI?: string;
97
- };
98
- };
99
- amount?: string;
100
- amountFormatted?: string;
101
- amountUsd?: string;
102
- minimumAmount?: string;
103
- };
104
- currencyOut?: {
105
- currency?: {
106
- chainId?: number;
107
- address?: string;
108
- symbol?: string;
109
- name?: string;
110
- decimals?: number;
111
- metadata?: {
112
- logoURI?: string;
113
- };
114
- };
115
- amount?: string;
116
- amountFormatted?: string;
117
- amountUsd?: string;
118
- minimumAmount?: string;
119
- };
120
- totalImpact?: {
121
- usd?: string;
122
- percent?: string;
123
- };
124
- swapImpact?: {
125
- usd?: string;
126
- percent?: string;
127
- };
128
- rate?: string;
129
- slippageTolerance?: {
130
- origin?: {
131
- usd?: string;
132
- value?: string;
133
- percent?: string;
134
- };
135
- destination?: {
136
- usd?: string;
137
- value?: string;
138
- percent?: string;
139
- };
140
- };
141
- timeEstimate?: number;
142
- userBalance?: string;
143
- };
144
- statusCode: number;
145
- } | undefined;
81
+ anyspendQuote: import("../../types/api_req_res").GetQuoteResponse | undefined;
146
82
  isLoadingAnyspendQuote: boolean;
147
83
  getAnyspendQuoteError: Error | null;
148
84
  activeInputAmountInWei: string;
@@ -1,6 +1,8 @@
1
1
  import { ReactNode } from "react";
2
+ import { FeatureFlags } from "../contexts/FeatureFlagsContext";
2
3
  interface AnyspendProviderProps {
3
4
  children: ReactNode;
5
+ featureFlags?: FeatureFlags;
4
6
  }
5
7
  /**
6
8
  * AnyspendProvider is a top-level provider that wraps your application to provide
@@ -12,17 +14,18 @@ interface AnyspendProviderProps {
12
14
  * - Safe to use at the application root
13
15
  * - Configures sensible defaults for query caching
14
16
  * - Handles Stripe payment redirects and modal state
17
+ * - Provides feature flags configuration
15
18
  *
16
19
  * @example
17
20
  * ```tsx
18
21
  * function App() {
19
22
  * return (
20
- * <AnyspendProvider>
23
+ * <AnyspendProvider featureFlags={{ showPoints: true }}>
21
24
  * <YourApp />
22
25
  * </AnyspendProvider>
23
26
  * );
24
27
  * }
25
28
  * ```
26
29
  */
27
- export declare const AnyspendProvider: ({ children }: AnyspendProviderProps) => import("react/jsx-runtime").JSX.Element;
30
+ export declare const AnyspendProvider: ({ children, featureFlags }: AnyspendProviderProps) => import("react/jsx-runtime").JSX.Element;
28
31
  export {};
@@ -1,2 +1,3 @@
1
1
  export * from "./AnyspendProvider";
2
2
  export * from "./StripeRedirectHandler";
3
+ export { useFeatureFlags, type FeatureFlags } from "../contexts/FeatureFlagsContext";
@@ -1,10 +1,17 @@
1
1
  import { paths } from "./api";
2
2
  export type GetOrderAndTxsResponse = paths["/orders/{orderId}"]["get"]["responses"]["200"]["content"]["application/json"];
3
3
  export type GetQuoteRequest = paths["/orders/quote"]["post"]["requestBody"]["content"]["application/json"];
4
- export type GetQuoteResponse = paths["/orders/quote"]["post"]["responses"]["200"]["content"]["application/json"];
4
+ type BaseGetQuoteResponse = paths["/orders/quote"]["post"]["responses"]["200"]["content"]["application/json"];
5
+ export type GetQuoteResponse = BaseGetQuoteResponse & {
6
+ data: BaseGetQuoteResponse["data"] & {
7
+ pointsAmount?: number;
8
+ pointsMultiplier?: number;
9
+ };
10
+ };
5
11
  export type GetCoinbaseOnrampOptionsResponse = paths["/onramp/coinbase/options"]["get"]["responses"]["200"]["content"]["application/json"];
6
12
  export type GetOrderHistoryResponse = paths["/orders"]["get"]["responses"]["200"]["content"]["application/json"];
7
13
  export type GetTokenListResponse = paths["/chains/{chainId}/tokens"]["get"]["responses"]["200"]["content"]["application/json"];
8
14
  export type CreateOrderResponse = paths["/orders"]["post"]["responses"]["200"]["content"]["application/json"];
9
15
  export type GetStripeSupportedResponse = paths["/onramp/stripe/supported"]["get"]["responses"]["200"]["content"]["application/json"];
10
16
  export type GetStripeClientSecret = paths["/stripe/clientSecret"]["get"]["responses"]["200"]["content"]["application/json"];
17
+ export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@b3dotfun/sdk",
3
- "version": "0.0.40-alpha.7",
3
+ "version": "0.0.40-alpha.8",
4
4
  "source": "src/index.ts",
5
5
  "main": "./dist/cjs/index.js",
6
6
  "react-native": "./dist/cjs/index.native.js",
@@ -890,6 +890,7 @@ function AnySpendInner({
890
890
  fiatPaymentMethodIndex={PanelView.FIAT_PAYMENT_METHOD}
891
891
  recipientSelectionPanelIndex={PanelView.RECIPIENT_SELECTION}
892
892
  hideDstToken={isBuyMode}
893
+ anyspendQuote={anyspendQuote}
893
894
  />
894
895
  </motion.div>
895
896
  )}
@@ -223,6 +223,7 @@ function AnySpendDepositHypeInner({
223
223
  onDestinationChainChange={() => {}}
224
224
  fiatPaymentMethodIndex={PanelView.FIAT_PAYMENT_METHOD}
225
225
  recipientSelectionPanelIndex={PanelView.RECIPIENT_SELECTION}
226
+ anyspendQuote={anyspendQuote}
226
227
  />
227
228
  </motion.div>
228
229
  )}
@@ -4,7 +4,9 @@ import { shortenAddress } from "@b3dotfun/sdk/shared/utils/formatAddress";
4
4
  import { formatDisplayNumber } from "@b3dotfun/sdk/shared/utils/number";
5
5
  import { ChevronRight } from "lucide-react";
6
6
  import { motion } from "motion/react";
7
+ import { useEffect } from "react";
7
8
  import { components } from "../../../types/api";
9
+ import { useFeatureFlags } from "../../contexts/FeatureFlagsContext";
8
10
  import { OrderTokenAmount } from "./OrderTokenAmount";
9
11
 
10
12
  interface CryptoReceiveSectionProps {
@@ -45,6 +47,8 @@ export function CryptoReceiveSection({
45
47
  dstTokenSymbol,
46
48
  dstTokenLogoURI,
47
49
  }: CryptoReceiveSectionProps) {
50
+ const featureFlags = useFeatureFlags();
51
+
48
52
  return (
49
53
  <motion.div
50
54
  initial={{ opacity: 0, y: 20, filter: "blur(10px)" }}
@@ -100,61 +104,68 @@ export function CryptoReceiveSection({
100
104
  setToken={setSelectedDstToken || (() => {})}
101
105
  />
102
106
  )}
103
- <div className="text-as-primary/50 flex h-5 items-center text-sm">
104
- {formatDisplayNumber(anyspendQuote?.data?.currencyOut?.amountUsd, {
105
- style: "currency",
106
- fallback: "",
107
- })}
108
- {anyspendQuote?.data?.currencyIn?.amountUsd &&
109
- anyspendQuote?.data?.currencyOut?.amountUsd &&
110
- (() => {
111
- const calculatePriceImpact = (inputUsd?: string | number, outputUsd?: string | number) => {
112
- if (!inputUsd || !outputUsd) {
113
- return { percentage: "0.00", isNegative: false };
114
- }
107
+ <div className="text-as-primary/50 flex h-5 items-center justify-between text-sm">
108
+ <div className="flex items-center gap-2">
109
+ {formatDisplayNumber(anyspendQuote?.data?.currencyOut?.amountUsd, {
110
+ style: "currency",
111
+ fallback: "",
112
+ })}
113
+ {anyspendQuote?.data?.currencyIn?.amountUsd &&
114
+ anyspendQuote?.data?.currencyOut?.amountUsd &&
115
+ (() => {
116
+ const calculatePriceImpact = (inputUsd?: string | number, outputUsd?: string | number) => {
117
+ if (!inputUsd || !outputUsd) {
118
+ return { percentage: "0.00", isNegative: false };
119
+ }
115
120
 
116
- const input = Number(inputUsd);
117
- const output = Number(outputUsd);
121
+ const input = Number(inputUsd);
122
+ const output = Number(outputUsd);
118
123
 
119
- // Handle edge cases
120
- if (input === 0 || isNaN(input) || isNaN(output) || input <= output) {
121
- return { percentage: "0.00", isNegative: false };
122
- }
124
+ // Handle edge cases
125
+ if (input === 0 || isNaN(input) || isNaN(output) || input <= output) {
126
+ return { percentage: "0.00", isNegative: false };
127
+ }
123
128
 
124
- const percentageValue = ((output - input) / input) * 100;
129
+ const percentageValue = ((output - input) / input) * 100;
125
130
 
126
- // Handle the -0.00% case
127
- if (percentageValue > -0.005 && percentageValue < 0) {
128
- return { percentage: "0.00", isNegative: false };
129
- }
131
+ // Handle the -0.00% case
132
+ if (percentageValue > -0.005 && percentageValue < 0) {
133
+ return { percentage: "0.00", isNegative: false };
134
+ }
130
135
 
131
- return {
132
- percentage: Math.abs(percentageValue).toFixed(2),
133
- isNegative: percentageValue < 0,
136
+ return {
137
+ percentage: Math.abs(percentageValue).toFixed(2),
138
+ isNegative: percentageValue < 0,
139
+ };
134
140
  };
135
- };
136
141
 
137
- const { percentage, isNegative } = calculatePriceImpact(
138
- anyspendQuote.data.currencyIn.amountUsd,
139
- anyspendQuote.data.currencyOut.amountUsd,
140
- );
142
+ const { percentage, isNegative } = calculatePriceImpact(
143
+ anyspendQuote.data.currencyIn.amountUsd,
144
+ anyspendQuote.data.currencyOut.amountUsd,
145
+ );
141
146
 
142
- // Parse the percentage as a number for comparison
143
- const percentageNum = parseFloat(percentage);
147
+ // Parse the percentage as a number for comparison
148
+ const percentageNum = parseFloat(percentage);
144
149
 
145
- // Don't show if less than 1%
146
- if (percentageNum < 1) {
147
- return null;
148
- }
150
+ // Don't show if less than 1%
151
+ if (percentageNum < 1) {
152
+ return null;
153
+ }
149
154
 
150
- // Using inline style to ensure color displays
151
- return (
152
- <span className="ml-2" style={{ color: percentageNum >= 10 ? "red" : "#FFD700" }}>
153
- ({isNegative ? "-" : ""}
154
- {percentage}%)
155
- </span>
156
- );
157
- })()}
155
+ // Using inline style to ensure color displays
156
+ return (
157
+ <span className="ml-2" style={{ color: percentageNum >= 10 ? "red" : "#FFD700" }}>
158
+ ({isNegative ? "-" : ""}
159
+ {percentage}%)
160
+ </span>
161
+ );
162
+ })()}
163
+ </div>
164
+ {featureFlags.showPoints && anyspendQuote?.data?.pointsAmount && anyspendQuote.data.pointsAmount > 0 && (
165
+ <div key={`points-${anyspendQuote.data.pointsAmount}`} className="flex items-center gap-1">
166
+ <span className="text-as-brand font-medium">+{anyspendQuote.data.pointsAmount.toLocaleString()} pts</span>
167
+ </div>
168
+ )}
158
169
  </div>
159
170
  </motion.div>
160
171
  );
@@ -1,12 +1,14 @@
1
1
  import { useCoinbaseOnrampOptions, useGeoOnrampOptions } from "@b3dotfun/sdk/anyspend/react";
2
2
  import { components } from "@b3dotfun/sdk/anyspend/types/api";
3
+ import { GetQuoteResponse } from "@b3dotfun/sdk/anyspend/types/api_req_res";
3
4
  import { ALL_CHAINS } from "@b3dotfun/sdk/anyspend/utils/chain";
4
5
  import { Input, useGetGeo, useProfile } from "@b3dotfun/sdk/global-account/react";
5
6
  import { cn, formatUsername } from "@b3dotfun/sdk/shared/utils";
6
7
  import { formatAddress } from "@b3dotfun/sdk/shared/utils/formatAddress";
7
8
  import { ChevronRight, Wallet } from "lucide-react";
8
- import { useRef } from "react";
9
+ import { useRef, useEffect } from "react";
9
10
  import { toast } from "sonner";
11
+ import { useFeatureFlags } from "../../contexts/FeatureFlagsContext";
10
12
  import { FiatPaymentMethod } from "./FiatPaymentMethod";
11
13
  import { OrderTokenAmountFiat } from "./OrderTokenAmountFiat";
12
14
 
@@ -25,6 +27,7 @@ export function PanelOnramp({
25
27
  recipientSelectionPanelIndex,
26
28
  dstTokenSymbol,
27
29
  hideDstToken = false,
30
+ anyspendQuote,
28
31
  }: {
29
32
  srcAmountOnRamp: string;
30
33
  setSrcAmountOnRamp: (amount: string) => void;
@@ -40,7 +43,9 @@ export function PanelOnramp({
40
43
  recipientSelectionPanelIndex: number;
41
44
  dstTokenSymbol?: string;
42
45
  hideDstToken?: boolean;
46
+ anyspendQuote?: GetQuoteResponse;
43
47
  }) {
48
+ const featureFlags = useFeatureFlags();
44
49
  // Get geo-based onramp options to access fee information
45
50
  const { stripeWeb2Support } = useGeoOnrampOptions(srcAmountOnRamp);
46
51
 
@@ -245,21 +250,22 @@ export function PanelOnramp({
245
250
 
246
251
  <div className="">
247
252
  <div className="flex items-center justify-between">
248
- {(() => {
249
- const currentPaymentMethod = selectedPaymentMethod || FiatPaymentMethod.NONE;
250
- const fee = getFeeFromApi(currentPaymentMethod);
251
-
252
- return (
253
- <>
254
- <span className="text-as-tertiarry text-sm">
255
- {fee !== null ? `Total (included $${fee.toFixed(2)} fee)` : "Total"}
256
- </span>
257
- <span className="text-as-primary font-semibold">
258
- ${getTotalAmount(currentPaymentMethod).toFixed(2)}
259
- </span>
260
- </>
261
- );
262
- })()}
253
+ <div className="flex items-center gap-2">
254
+ <span className="text-as-tertiarry text-sm">
255
+ {(() => {
256
+ const fee = getFeeFromApi(selectedPaymentMethod || FiatPaymentMethod.NONE);
257
+ return fee !== null ? `Total (included $${fee.toFixed(2)} fee)` : "Total";
258
+ })()}
259
+ </span>
260
+ {featureFlags.showPoints && anyspendQuote?.data?.pointsAmount && anyspendQuote.data.pointsAmount > 0 && (
261
+ <span key={`points-${anyspendQuote.data.pointsAmount}`} className="text-as-brand text-sm font-medium">
262
+ +{anyspendQuote.data.pointsAmount.toLocaleString()} pts
263
+ </span>
264
+ )}
265
+ </div>
266
+ <span className="text-as-primary font-semibold">
267
+ ${getTotalAmount(selectedPaymentMethod || FiatPaymentMethod.NONE).toFixed(2)}
268
+ </span>
263
269
  </div>
264
270
  </div>
265
271
  </div>