@b3dotfun/sdk 0.0.31 → 0.0.32-alpha.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/anyspend/react/components/AnyspendDepositHype.js +2 -2
- package/dist/cjs/anyspend/react/components/common/OrderDetails.d.ts +1 -0
- package/dist/cjs/anyspend/react/components/common/OrderDetails.js +7 -3
- package/dist/cjs/anyspend/react/hooks/useAnyspendFlow.d.ts +4 -1
- package/dist/cjs/anyspend/react/hooks/useAnyspendFlow.js +47 -17
- package/dist/cjs/anyspend/react/hooks/useSigMint.d.ts +1 -1
- package/dist/cjs/global-account/react/components/B3Provider/types.d.ts +4 -5
- package/dist/cjs/global-account/react/components/ManageAccount/ManageAccount.js +53 -1
- package/dist/cjs/global-account/react/hooks/useSiwe.js +5 -5
- package/dist/esm/anyspend/react/components/AnyspendDepositHype.js +2 -2
- package/dist/esm/anyspend/react/components/common/OrderDetails.d.ts +1 -0
- package/dist/esm/anyspend/react/components/common/OrderDetails.js +7 -3
- package/dist/esm/anyspend/react/hooks/useAnyspendFlow.d.ts +4 -1
- package/dist/esm/anyspend/react/hooks/useAnyspendFlow.js +49 -19
- package/dist/esm/anyspend/react/hooks/useSigMint.d.ts +1 -1
- package/dist/esm/global-account/react/components/B3Provider/types.d.ts +4 -5
- package/dist/esm/global-account/react/components/ManageAccount/ManageAccount.js +54 -5
- package/dist/esm/global-account/react/hooks/useSiwe.js +5 -5
- package/dist/types/anyspend/react/components/common/OrderDetails.d.ts +1 -0
- package/dist/types/anyspend/react/hooks/useAnyspendFlow.d.ts +4 -1
- package/dist/types/anyspend/react/hooks/useSigMint.d.ts +1 -1
- package/dist/types/global-account/react/components/B3Provider/types.d.ts +4 -5
- package/package.json +2 -2
- package/src/anyspend/react/components/AnyspendDepositHype.tsx +2 -1
- package/src/anyspend/react/components/common/OrderDetails.tsx +6 -2
- package/src/anyspend/react/hooks/useAnyspendFlow.ts +53 -16
- package/src/global-account/react/components/B3Provider/B3Provider.native.tsx +2 -2
- package/src/global-account/react/components/B3Provider/B3Provider.tsx +2 -2
- package/src/global-account/react/components/B3Provider/types.ts +4 -5
- package/src/global-account/react/components/ManageAccount/ManageAccount.tsx +147 -3
- package/src/global-account/react/hooks/useSiwe.tsx +5 -5
|
@@ -1,17 +1,16 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { User } from "../../../../global-account/types/b3-api.types";
|
|
3
|
-
import { Wallet } from "thirdweb/wallets";
|
|
1
|
+
import { Users } from "@b3dotfun/b3-api";
|
|
4
2
|
import { PermissionsConfig } from "../../../../global-account/types/permissions";
|
|
3
|
+
import { Account, Wallet } from "thirdweb/wallets";
|
|
5
4
|
/**
|
|
6
5
|
* Context type for B3Provider
|
|
7
6
|
*/
|
|
8
7
|
export interface B3ContextType {
|
|
9
8
|
account?: Account;
|
|
10
9
|
automaticallySetFirstEoa: boolean;
|
|
11
|
-
user?:
|
|
10
|
+
user?: Users;
|
|
12
11
|
setWallet: (wallet: Wallet) => void;
|
|
13
12
|
wallet?: Wallet;
|
|
14
|
-
setUser: (user?:
|
|
13
|
+
setUser: (user?: Users) => void;
|
|
15
14
|
initialized: boolean;
|
|
16
15
|
ready: boolean;
|
|
17
16
|
environment?: "development" | "production";
|
|
@@ -1,10 +1,12 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
import app from "../../../../global-account/app.js";
|
|
3
|
+
import { Button, TabsContentPrimitive, TabsListPrimitive, TabsPrimitive, TabTriggerPrimitive, useAccountAssets, useAuthentication, useB3, useGetAllTWSigners, useModalStore, useQueryB3, useRemoveSessionKey, } from "../../../../global-account/react/index.js";
|
|
3
4
|
import { SignOutIcon } from "../../../../global-account/react/components/icons/SignOutIcon.js";
|
|
4
5
|
import { formatNumber } from "../../../../shared/utils/formatNumber.js";
|
|
5
6
|
import { client } from "../../../../shared/utils/thirdweb.js";
|
|
6
|
-
import { BarChart3, Coins, Image, LinkIcon, Loader2, Settings, UnlinkIcon } from "lucide-react";
|
|
7
|
-
import { useState } from "react";
|
|
7
|
+
import { BarChart3, Coins, Copy, Image, LinkIcon, Loader2, Pencil, Settings, UnlinkIcon } from "lucide-react";
|
|
8
|
+
import { useRef, useState } from "react";
|
|
9
|
+
import { toast } from "sonner";
|
|
8
10
|
import { useActiveAccount, useProfiles, useUnlinkProfile } from "thirdweb/react";
|
|
9
11
|
import { formatUnits } from "viem";
|
|
10
12
|
import { getProfileDisplayInfo } from "../../utils/profileDisplay.js";
|
|
@@ -52,6 +54,45 @@ export function ManageAccount({ onLogout, onSwap: _onSwap, onDeposit: _onDeposit
|
|
|
52
54
|
const { data: profilesRaw = [], isLoading: isLoadingProfiles } = useProfiles({ client });
|
|
53
55
|
const { mutate: unlinkProfile, isPending: isUnlinking } = useUnlinkProfile();
|
|
54
56
|
const { setB3ModalOpen, setB3ModalContentType, isLinking } = useModalStore();
|
|
57
|
+
const { user, setUser } = useB3();
|
|
58
|
+
const [isUpdatingCode, setIsUpdatingCode] = useState(false);
|
|
59
|
+
const [newReferralCode, setNewReferralCode] = useState("");
|
|
60
|
+
const [isEditingCode, setIsEditingCode] = useState(false);
|
|
61
|
+
const referallCodeRef = useRef(null);
|
|
62
|
+
const { data: referrals, isLoading: isLoadingReferrals } = useQueryB3("referrals", "find", { query: { referrerId: user?.userId } }, !!user?.userId);
|
|
63
|
+
// Fetch referred users
|
|
64
|
+
const currentReferralCode = user?.referralCode || user?.userId || "";
|
|
65
|
+
const handleCopyCode = async () => {
|
|
66
|
+
try {
|
|
67
|
+
await navigator.clipboard.writeText(currentReferralCode);
|
|
68
|
+
toast.success("Referral code copied to clipboard!");
|
|
69
|
+
}
|
|
70
|
+
catch (error) {
|
|
71
|
+
toast.error("Failed to copy referral code");
|
|
72
|
+
}
|
|
73
|
+
};
|
|
74
|
+
const handleUpdateReferralCode = async () => {
|
|
75
|
+
if (!newReferralCode)
|
|
76
|
+
return;
|
|
77
|
+
setIsUpdatingCode(true);
|
|
78
|
+
try {
|
|
79
|
+
// @ts-expect-error - setReferralCode is not typed for some reason
|
|
80
|
+
const newUser = await app.service("users").setReferralCode({
|
|
81
|
+
userId: user?.userId,
|
|
82
|
+
referralCode: newReferralCode,
|
|
83
|
+
});
|
|
84
|
+
setUser(newUser);
|
|
85
|
+
toast.success("Referral code updated successfully!");
|
|
86
|
+
setIsEditingCode(false);
|
|
87
|
+
setNewReferralCode("");
|
|
88
|
+
}
|
|
89
|
+
catch (error) {
|
|
90
|
+
toast.error("Failed to update referral code");
|
|
91
|
+
}
|
|
92
|
+
finally {
|
|
93
|
+
setIsUpdatingCode(false);
|
|
94
|
+
}
|
|
95
|
+
};
|
|
55
96
|
const profiles = profilesRaw
|
|
56
97
|
.filter((profile) => !["custom_auth_endpoint", "siwe"].includes(profile.type))
|
|
57
98
|
.map((profile) => ({
|
|
@@ -88,7 +129,15 @@ export function ManageAccount({ onLogout, onSwap: _onSwap, onDeposit: _onDeposit
|
|
|
88
129
|
},
|
|
89
130
|
});
|
|
90
131
|
};
|
|
91
|
-
return (_jsxs("div", { className: "space-y-8", children: [_jsxs("div", { className: "space-y-4", children: [_jsxs("div", { className: "flex items-center justify-between", children: [_jsx("h3", { className: "text-b3-grey font-neue-montreal-semibold text-xl", children: "Linked Accounts" }), _jsxs(Button, { className: "bg-b3-primary-wash hover:bg-b3-primary-wash/70 flex items-center gap-2 rounded-full px-4 py-2", onClick: handleOpenLinkModal, disabled: isLinking, children: [isLinking ? (_jsx(Loader2, { className: "text-b3-primary-blue animate-spin", size: 16 })) : (_jsx(LinkIcon, { size: 16, className: "text-b3-primary-blue" })), _jsx("span", { className: "text-b3-grey font-neue-montreal-semibold", children: isLinking ? "Linking..." : "Link New Account" })] })] }), isLoadingProfiles ? (_jsx("div", { className: "flex justify-center py-8", children: _jsx(Loader2, { className: "text-b3-grey animate-spin" }) })) : profiles.length > 0 ? (_jsx("div", { className: "space-y-4", children: profiles.map(profile => (_jsxs("div", { className: "bg-b3-line flex items-center justify-between rounded-xl p-4", children: [_jsxs("div", { className: "flex items-center gap-3", children: [profile.imageUrl ? (_jsx("img", { src: profile.imageUrl, alt: profile.title, className: "size-10 rounded-full" })) : (_jsx("div", { className: "bg-b3-primary-wash flex h-10 w-10 items-center justify-center rounded-full", children: _jsx("span", { className: "text-b3-grey font-neue-montreal-semibold text-sm uppercase", children: profile.initial }) })), _jsxs("div", { children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx("span", { className: "text-b3-grey font-neue-montreal-semibold", children: profile.title }), _jsx("span", { className: "text-b3-foreground-muted font-neue-montreal-medium bg-b3-primary-wash rounded px-2 py-0.5 text-xs", children: profile.type.toUpperCase() })] }), _jsx("div", { className: "text-b3-foreground-muted font-neue-montreal-medium text-sm", children: profile.subtitle })] })] }), _jsx(Button, { variant: "ghost", size: "icon", className: "text-b3-grey hover:text-b3-negative", onClick: () => handleUnlink(profile), disabled: unlinkingAccountId === profile.title || isUnlinking, children: unlinkingAccountId === profile.title || isUnlinking ? (_jsx(Loader2, { className: "animate-spin" })) : (_jsx(UnlinkIcon, { size: 16 })) })] }, profile.title))) })) : (_jsx("div", { className: "text-b3-foreground-muted py-8 text-center", children: "No linked accounts found" }))] }), _jsxs("div", { className: "space-y-4", children: [_jsx("h3", { className: "text-b3-grey font-neue-montreal-semibold text-xl", children: "
|
|
132
|
+
return (_jsxs("div", { className: "space-y-8", children: [_jsxs("div", { className: "space-y-4", children: [_jsxs("div", { className: "flex items-center justify-between", children: [_jsx("h3", { className: "text-b3-grey font-neue-montreal-semibold text-xl", children: "Linked Accounts" }), _jsxs(Button, { className: "bg-b3-primary-wash hover:bg-b3-primary-wash/70 flex items-center gap-2 rounded-full px-4 py-2", onClick: handleOpenLinkModal, disabled: isLinking, children: [isLinking ? (_jsx(Loader2, { className: "text-b3-primary-blue animate-spin", size: 16 })) : (_jsx(LinkIcon, { size: 16, className: "text-b3-primary-blue" })), _jsx("span", { className: "text-b3-grey font-neue-montreal-semibold", children: isLinking ? "Linking..." : "Link New Account" })] })] }), isLoadingProfiles ? (_jsx("div", { className: "flex justify-center py-8", children: _jsx(Loader2, { className: "text-b3-grey animate-spin" }) })) : profiles.length > 0 ? (_jsx("div", { className: "space-y-4", children: profiles.map(profile => (_jsxs("div", { className: "bg-b3-line flex items-center justify-between rounded-xl p-4", children: [_jsxs("div", { className: "flex items-center gap-3", children: [profile.imageUrl ? (_jsx("img", { src: profile.imageUrl, alt: profile.title, className: "size-10 rounded-full" })) : (_jsx("div", { className: "bg-b3-primary-wash flex h-10 w-10 items-center justify-center rounded-full", children: _jsx("span", { className: "text-b3-grey font-neue-montreal-semibold text-sm uppercase", children: profile.initial }) })), _jsxs("div", { children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx("span", { className: "text-b3-grey font-neue-montreal-semibold", children: profile.title }), _jsx("span", { className: "text-b3-foreground-muted font-neue-montreal-medium bg-b3-primary-wash rounded px-2 py-0.5 text-xs", children: profile.type.toUpperCase() })] }), _jsx("div", { className: "text-b3-foreground-muted font-neue-montreal-medium text-sm", children: profile.subtitle })] })] }), _jsx(Button, { variant: "ghost", size: "icon", className: "text-b3-grey hover:text-b3-negative", onClick: () => handleUnlink(profile), disabled: unlinkingAccountId === profile.title || isUnlinking, children: unlinkingAccountId === profile.title || isUnlinking ? (_jsx(Loader2, { className: "animate-spin" })) : (_jsx(UnlinkIcon, { size: 16 })) })] }, profile.title))) })) : (_jsx("div", { className: "text-b3-foreground-muted py-8 text-center", children: "No linked accounts found" }))] }), _jsxs("div", { className: "space-y-4", children: [_jsx("h3", { className: "text-b3-grey font-neue-montreal-semibold text-xl", children: "Referrals" }), _jsxs("div", { className: "bg-b3-line rounded-xl p-4", children: [isEditingCode && (_jsxs("div", { children: [_jsx("div", { className: "text-b3-grey font-neue-montreal-semibold", children: "Your Referral Code" }), _jsx("div", { className: "text-b3-foreground-muted font-neue-montreal-medium text-sm", children: "Share this code with friends to earn rewards" })] })), _jsxs("div", { className: "flex items-center justify-between", children: [!isEditingCode && (_jsxs("div", { children: [_jsx("div", { className: "text-b3-grey font-neue-montreal-semibold", children: "Your Referral Code" }), _jsx("div", { className: "text-b3-foreground-muted font-neue-montreal-medium text-sm", children: "Share this code with friends to earn rewards" })] })), _jsx("div", { className: "flex items-center gap-2", children: isEditingCode ? (_jsxs("div", { className: "flex items-center gap-2", children: [_jsx("input", { type: "text", value: newReferralCode, onChange: e => setNewReferralCode(e.target.value), className: "rounded-lg border border-gray-200 bg-white px-3 py-1.5 text-sm", placeholder: "Enter new code", ref: referallCodeRef }), _jsx(Button, { size: "sm", onClick: handleUpdateReferralCode, disabled: isUpdatingCode || !newReferralCode, children: isUpdatingCode ? _jsx(Loader2, { className: "h-4 w-4 animate-spin" }) : "Save" }), _jsx(Button, { size: "sm", variant: "ghost", onClick: () => {
|
|
133
|
+
setIsEditingCode(false);
|
|
134
|
+
setNewReferralCode("");
|
|
135
|
+
}, children: "Cancel" })] })) : (_jsxs(_Fragment, { children: [_jsx("div", { className: "rounded-lg border border-gray-200 bg-white px-3 py-1.5 text-sm", children: currentReferralCode }), _jsx(Button, { size: "icon", variant: "ghost", onClick: handleCopyCode, children: _jsx(Copy, { className: "h-4 w-4" }) }), _jsx(Button, { size: "icon", variant: "ghost", onClick: () => {
|
|
136
|
+
setIsEditingCode(true);
|
|
137
|
+
setTimeout(() => {
|
|
138
|
+
referallCodeRef.current?.focus();
|
|
139
|
+
}, 100);
|
|
140
|
+
}, children: _jsx(Pencil, { className: "h-4 w-4" }) })] })) })] })] }), _jsxs("div", { className: "bg-b3-line rounded-xl p-4", children: [_jsx("div", { className: "text-b3-grey font-neue-montreal-semibold mb-4", children: "Referred Users" }), isLoadingReferrals ? (_jsx("div", { className: "flex justify-center py-4", children: _jsx(Loader2, { className: "h-6 w-6 animate-spin text-gray-400" }) })) : referrals?.data?.length ? (_jsx("div", { className: "space-y-3", children: referrals.data.map((referral) => (_jsxs("div", { className: "flex items-center justify-between rounded-lg bg-white p-3", children: [_jsx("div", { className: "text-sm font-medium", children: referral.referreeId }), _jsx("div", { className: "text-sm text-gray-500", children: new Date(referral.createdAt).toLocaleDateString() })] }, String(referral._id)))) })) : (_jsx("div", { className: "py-4 text-center text-gray-500", children: "No referred users yet" }))] })] }), _jsxs("div", { className: "space-y-4", children: [_jsx("h3", { className: "text-b3-grey font-neue-montreal-semibold text-xl", children: "Account Preferences" }), _jsx("div", { className: "bg-b3-line rounded-xl p-4", children: _jsxs("div", { className: "flex items-center justify-between", children: [_jsxs("div", { children: [_jsx("div", { className: "text-b3-grey font-neue-montreal-semibold", children: "Dark Mode" }), _jsx("div", { className: "text-b3-foreground-muted font-neue-montreal-medium text-sm", children: "Switch between light and dark theme" })] }), _jsx("div", { className: "bg-b3-primary-wash h-6 w-12 rounded-full" })] }) })] }), _jsxs("div", { className: "border-b3-line flex items-center justify-between rounded-2xl border p-4", children: [_jsxs("div", { children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx("img", { src: "https://cdn.b3.fun/b3_logo.svg", alt: "B3", className: "h-4" }), _jsx("h3", { className: "font-neue-montreal-semibold text-b3-grey", children: "Global Account" })] }), _jsx("p", { className: "text-b3-foreground-muted font-neue-montreal-medium mt-2 text-sm", children: "Your universal account for all B3 apps" })] }), _jsx("button", { className: "text-b3-grey hover:text-b3-grey/80 hover:bg-b3-line border-b3-line flex size-12 items-center justify-center rounded-full border", onClick: onLogoutEnhanced, children: logoutLoading ? _jsx(Loader2, { className: "animate-spin" }) : _jsx(SignOutIcon, { size: 16, className: "text-b3-grey" }) })] })] }));
|
|
92
141
|
};
|
|
93
142
|
return (_jsx("div", { className: "b3-manage-account bg-b3-background flex flex-col rounded-xl", children: _jsx("div", { className: "flex-1", children: _jsxs(TabsPrimitive, { defaultValue: activeTab, onValueChange: value => {
|
|
94
143
|
const tab = value;
|
|
@@ -3,11 +3,11 @@ import debug from "../../../shared/utils/debug.js";
|
|
|
3
3
|
import { useCallback } from "react";
|
|
4
4
|
import { useSearchParam } from "./useSearchParamsSSR.js";
|
|
5
5
|
export function useSiwe() {
|
|
6
|
-
const
|
|
6
|
+
const referralCode = useSearchParam("referralCode");
|
|
7
7
|
const authenticate = useCallback(async (account, partnerId) => {
|
|
8
8
|
if (!account || !account.signMessage)
|
|
9
9
|
throw new Error("Account not found");
|
|
10
|
-
console.log("@@useAuthenticate:
|
|
10
|
+
console.log("@@useAuthenticate:referralCode", referralCode);
|
|
11
11
|
// generate challenge
|
|
12
12
|
const challenge = await app.service("global-accounts-challenge").create({
|
|
13
13
|
address: account.address,
|
|
@@ -25,13 +25,13 @@ export function useSiwe() {
|
|
|
25
25
|
signature,
|
|
26
26
|
serverSignature: challenge.serverSignature,
|
|
27
27
|
nonce: challenge.nonce,
|
|
28
|
-
// http://localhost:5173/?
|
|
29
|
-
|
|
28
|
+
// http://localhost:5173/?referralCode=GIO2
|
|
29
|
+
referralCode,
|
|
30
30
|
partnerId: partnerId,
|
|
31
31
|
});
|
|
32
32
|
debug("@@useAuthenticate:response", response);
|
|
33
33
|
return response;
|
|
34
|
-
}, [
|
|
34
|
+
}, [referralCode]);
|
|
35
35
|
return {
|
|
36
36
|
authenticate,
|
|
37
37
|
};
|
|
@@ -9,6 +9,7 @@ interface OrderDetailsProps {
|
|
|
9
9
|
refundTxs: components["schemas"]["RefundTx"][] | null;
|
|
10
10
|
cryptoPaymentMethod?: CryptoPaymentMethodType;
|
|
11
11
|
onBack?: () => void;
|
|
12
|
+
disableUrlParamManagement?: boolean;
|
|
12
13
|
}
|
|
13
14
|
export declare const OrderDetails: import("react").NamedExoticComponent<OrderDetailsProps>;
|
|
14
15
|
export declare const OrderDetailsLoadingView: import("react/jsx-runtime").JSX.Element;
|
|
@@ -19,8 +19,9 @@ interface UseAnyspendFlowProps {
|
|
|
19
19
|
sourceTokenAddress?: string;
|
|
20
20
|
sourceTokenChainId?: number;
|
|
21
21
|
slippage?: number;
|
|
22
|
+
disableUrlParamManagement?: boolean;
|
|
22
23
|
}
|
|
23
|
-
export declare function useAnyspendFlow({ paymentType, recipientAddress, loadOrder, isDepositMode, onOrderSuccess, onTransactionSuccess, sourceTokenAddress, sourceTokenChainId, slippage, }: UseAnyspendFlowProps): {
|
|
24
|
+
export declare function useAnyspendFlow({ paymentType, recipientAddress, loadOrder, isDepositMode, onOrderSuccess, onTransactionSuccess, sourceTokenAddress, sourceTokenChainId, slippage, disableUrlParamManagement, }: UseAnyspendFlowProps): {
|
|
24
25
|
activePanel: PanelView;
|
|
25
26
|
setActivePanel: import("react").Dispatch<import("react").SetStateAction<PanelView>>;
|
|
26
27
|
orderId: string | undefined;
|
|
@@ -75,6 +76,8 @@ export declare function useAnyspendFlow({ paymentType, recipientAddress, loadOrd
|
|
|
75
76
|
setSelectedRecipientAddress: import("react").Dispatch<import("react").SetStateAction<string | undefined>>;
|
|
76
77
|
recipientName: string | null | undefined;
|
|
77
78
|
globalAddress: string | undefined;
|
|
79
|
+
hasEnoughBalance: boolean;
|
|
80
|
+
isBalanceLoading: boolean;
|
|
78
81
|
anyspendQuote: {
|
|
79
82
|
success: boolean;
|
|
80
83
|
message: string;
|
|
@@ -72,7 +72,7 @@ export declare const useSigMintCollection: ({ address, chainId }: FindByAddressP
|
|
|
72
72
|
description?: string | undefined;
|
|
73
73
|
createdAt?: string | undefined;
|
|
74
74
|
updatedAt?: string | undefined;
|
|
75
|
-
status?: "
|
|
75
|
+
status?: "ACTIVE" | "DRAFT" | "INACTIVE" | undefined;
|
|
76
76
|
metadata?: {} | undefined;
|
|
77
77
|
logoURI?: string | undefined;
|
|
78
78
|
creator?: string | undefined;
|
|
@@ -1,17 +1,16 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { User } from "@b3dotfun/sdk/global-account/types/b3-api.types";
|
|
3
|
-
import { Wallet } from "thirdweb/wallets";
|
|
1
|
+
import { Users } from "@b3dotfun/b3-api";
|
|
4
2
|
import { PermissionsConfig } from "@b3dotfun/sdk/global-account/types/permissions";
|
|
3
|
+
import { Account, Wallet } from "thirdweb/wallets";
|
|
5
4
|
/**
|
|
6
5
|
* Context type for B3Provider
|
|
7
6
|
*/
|
|
8
7
|
export interface B3ContextType {
|
|
9
8
|
account?: Account;
|
|
10
9
|
automaticallySetFirstEoa: boolean;
|
|
11
|
-
user?:
|
|
10
|
+
user?: Users;
|
|
12
11
|
setWallet: (wallet: Wallet) => void;
|
|
13
12
|
wallet?: Wallet;
|
|
14
|
-
setUser: (user?:
|
|
13
|
+
setUser: (user?: Users) => void;
|
|
15
14
|
initialized: boolean;
|
|
16
15
|
ready: boolean;
|
|
17
16
|
environment?: "development" | "production";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@b3dotfun/sdk",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.32-alpha.0",
|
|
4
4
|
"source": "src/index.ts",
|
|
5
5
|
"main": "./dist/cjs/index.js",
|
|
6
6
|
"react-native": "./dist/cjs/index.native.js",
|
|
@@ -237,7 +237,7 @@
|
|
|
237
237
|
"constants"
|
|
238
238
|
],
|
|
239
239
|
"dependencies": {
|
|
240
|
-
"@b3dotfun/b3-api": "0.0.
|
|
240
|
+
"@b3dotfun/b3-api": "0.0.45",
|
|
241
241
|
"@b3dotfun/basement-api": "0.0.11",
|
|
242
242
|
"@chakra-ui/react": "2.10.7",
|
|
243
243
|
"@feathersjs/authentication-client": "5.0.33",
|
|
@@ -115,6 +115,7 @@ function AnySpendDepositHypeInner({
|
|
|
115
115
|
sourceTokenAddress,
|
|
116
116
|
sourceTokenChainId,
|
|
117
117
|
slippage: SLIPPAGE_PERCENT,
|
|
118
|
+
disableUrlParamManagement: true,
|
|
118
119
|
});
|
|
119
120
|
|
|
120
121
|
// Button state logic
|
|
@@ -434,8 +435,8 @@ function AnySpendDepositHypeInner({
|
|
|
434
435
|
onBack={() => {
|
|
435
436
|
setOrderId(undefined);
|
|
436
437
|
setActivePanel(PanelView.MAIN);
|
|
437
|
-
onSuccess?.();
|
|
438
438
|
}}
|
|
439
|
+
disableUrlParamManagement
|
|
439
440
|
/>
|
|
440
441
|
</>
|
|
441
442
|
)}
|
|
@@ -63,6 +63,7 @@ interface OrderDetailsProps {
|
|
|
63
63
|
refundTxs: components["schemas"]["RefundTx"][] | null;
|
|
64
64
|
cryptoPaymentMethod?: CryptoPaymentMethodType; // Now optional since we read from URL
|
|
65
65
|
onBack?: () => void;
|
|
66
|
+
disableUrlParamManagement?: boolean; // When true, will not modify URL parameters
|
|
66
67
|
}
|
|
67
68
|
|
|
68
69
|
// Add this helper function near the top or just above the component
|
|
@@ -202,6 +203,7 @@ export const OrderDetails = memo(function OrderDetails({
|
|
|
202
203
|
refundTxs,
|
|
203
204
|
cryptoPaymentMethod,
|
|
204
205
|
onBack,
|
|
206
|
+
disableUrlParamManagement = false,
|
|
205
207
|
}: OrderDetailsProps) {
|
|
206
208
|
const router = useRouter();
|
|
207
209
|
const searchParams = useSearchParams();
|
|
@@ -284,13 +286,15 @@ export const OrderDetails = memo(function OrderDetails({
|
|
|
284
286
|
|
|
285
287
|
// When waitingForDeposit is true, we show a message to the user to wait for the deposit to be processed.
|
|
286
288
|
const setWaitingForDeposit = useCallback(() => {
|
|
289
|
+
if (disableUrlParamManagement) return;
|
|
287
290
|
const params = new URLSearchParams(searchParams.toString());
|
|
288
291
|
params.set("waitingForDeposit", "true");
|
|
289
292
|
router.push(`?${params}`);
|
|
290
|
-
}, [router, searchParams]);
|
|
293
|
+
}, [router, searchParams, disableUrlParamManagement]);
|
|
291
294
|
|
|
292
295
|
// Clean up URL parameters before closing modal or navigating back
|
|
293
296
|
const cleanupUrlParams = useCallback(() => {
|
|
297
|
+
if (disableUrlParamManagement) return;
|
|
294
298
|
const params = new URLSearchParams(searchParams.toString());
|
|
295
299
|
params.delete("waitingForDeposit");
|
|
296
300
|
params.delete("orderId");
|
|
@@ -300,7 +304,7 @@ export const OrderDetails = memo(function OrderDetails({
|
|
|
300
304
|
if (params.toString() !== searchParams.toString()) {
|
|
301
305
|
router.push(`?${params}`);
|
|
302
306
|
}
|
|
303
|
-
}, [router, searchParams]);
|
|
307
|
+
}, [router, searchParams, disableUrlParamManagement]);
|
|
304
308
|
|
|
305
309
|
// Helper functions that clean up URL params before executing actions
|
|
306
310
|
const handleCloseModal = useCallback(() => {
|
|
@@ -7,12 +7,19 @@ import {
|
|
|
7
7
|
useGeoOnrampOptions,
|
|
8
8
|
} from "@b3dotfun/sdk/anyspend/react";
|
|
9
9
|
import { anyspendService } from "@b3dotfun/sdk/anyspend/services/anyspend";
|
|
10
|
-
import {
|
|
10
|
+
import {
|
|
11
|
+
useAccountWallet,
|
|
12
|
+
useProfile,
|
|
13
|
+
useRouter,
|
|
14
|
+
useSearchParamsSSR,
|
|
15
|
+
useTokenBalance,
|
|
16
|
+
} from "@b3dotfun/sdk/global-account/react";
|
|
11
17
|
import { formatTokenAmount, formatUnits } from "@b3dotfun/sdk/shared/utils/number";
|
|
12
|
-
import { useEffect, useState } from "react";
|
|
18
|
+
import { useEffect, useMemo, useState } from "react";
|
|
13
19
|
import { toast } from "sonner";
|
|
14
20
|
import { parseUnits } from "viem";
|
|
15
21
|
import { base, mainnet } from "viem/chains";
|
|
22
|
+
import { useAccount } from "wagmi";
|
|
16
23
|
import { components } from "../../types/api";
|
|
17
24
|
import { CryptoPaymentMethodType } from "../components/common/CryptoPaymentMethod";
|
|
18
25
|
import { FiatPaymentMethod } from "../components/common/FiatPaymentMethod";
|
|
@@ -36,6 +43,7 @@ interface UseAnyspendFlowProps {
|
|
|
36
43
|
sourceTokenAddress?: string;
|
|
37
44
|
sourceTokenChainId?: number;
|
|
38
45
|
slippage?: number;
|
|
46
|
+
disableUrlParamManagement?: boolean;
|
|
39
47
|
}
|
|
40
48
|
|
|
41
49
|
export function useAnyspendFlow({
|
|
@@ -48,6 +56,7 @@ export function useAnyspendFlow({
|
|
|
48
56
|
sourceTokenAddress,
|
|
49
57
|
sourceTokenChainId,
|
|
50
58
|
slippage = 0,
|
|
59
|
+
disableUrlParamManagement = false,
|
|
51
60
|
}: UseAnyspendFlowProps) {
|
|
52
61
|
const searchParams = useSearchParamsSSR();
|
|
53
62
|
const router = useRouter();
|
|
@@ -76,6 +85,7 @@ export function useAnyspendFlow({
|
|
|
76
85
|
|
|
77
86
|
// Recipient state
|
|
78
87
|
const { address: globalAddress } = useAccountWallet();
|
|
88
|
+
const { address: wagmiAddress } = useAccount();
|
|
79
89
|
const [selectedRecipientAddress, setSelectedRecipientAddress] = useState<string | undefined>(recipientAddress);
|
|
80
90
|
const recipientProfile = useProfile({ address: selectedRecipientAddress, fresh: true });
|
|
81
91
|
const recipientName = recipientProfile.data?.name;
|
|
@@ -87,11 +97,33 @@ export function useAnyspendFlow({
|
|
|
87
97
|
}
|
|
88
98
|
}, [selectedRecipientAddress, globalAddress]);
|
|
89
99
|
|
|
100
|
+
// Check token balance for crypto payments
|
|
101
|
+
const { rawBalance, isLoading: isBalanceLoading } = useTokenBalance({
|
|
102
|
+
token: selectedSrcToken,
|
|
103
|
+
address: wagmiAddress,
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
// Check if user has enough balance
|
|
107
|
+
const hasEnoughBalance = useMemo(() => {
|
|
108
|
+
if (!rawBalance || isBalanceLoading || paymentType !== "crypto") return false;
|
|
109
|
+
try {
|
|
110
|
+
const requiredAmount = parseUnits(srcAmount.replace(/,/g, ""), selectedSrcToken.decimals);
|
|
111
|
+
return rawBalance >= requiredAmount;
|
|
112
|
+
} catch {
|
|
113
|
+
return false;
|
|
114
|
+
}
|
|
115
|
+
}, [rawBalance, srcAmount, selectedSrcToken.decimals, isBalanceLoading, paymentType]);
|
|
116
|
+
|
|
117
|
+
// Auto-set crypto payment method based on balance
|
|
90
118
|
useEffect(() => {
|
|
91
|
-
if (paymentType === "crypto") {
|
|
92
|
-
|
|
119
|
+
if (paymentType === "crypto" && !isBalanceLoading) {
|
|
120
|
+
if (hasEnoughBalance) {
|
|
121
|
+
setSelectedCryptoPaymentMethod(CryptoPaymentMethodType.CONNECT_WALLET);
|
|
122
|
+
} else {
|
|
123
|
+
setSelectedCryptoPaymentMethod(CryptoPaymentMethodType.TRANSFER_CRYPTO);
|
|
124
|
+
}
|
|
93
125
|
}
|
|
94
|
-
}, [paymentType]);
|
|
126
|
+
}, [paymentType, hasEnoughBalance, isBalanceLoading]);
|
|
95
127
|
|
|
96
128
|
// Fetch specific token when sourceTokenAddress and sourceTokenChainId are provided
|
|
97
129
|
useEffect(() => {
|
|
@@ -159,14 +191,14 @@ export function useAnyspendFlow({
|
|
|
159
191
|
|
|
160
192
|
// Update useEffect for URL parameter to not override loadOrder
|
|
161
193
|
useEffect(() => {
|
|
162
|
-
if (loadOrder) return; // Skip if we have a loadOrder
|
|
194
|
+
if (loadOrder || disableUrlParamManagement) return; // Skip if we have a loadOrder or URL param management is disabled
|
|
163
195
|
|
|
164
196
|
const orderIdParam = searchParams.get("orderId");
|
|
165
197
|
if (orderIdParam) {
|
|
166
198
|
setOrderId(orderIdParam);
|
|
167
199
|
setActivePanel(PanelView.ORDER_DETAILS);
|
|
168
200
|
}
|
|
169
|
-
}, [searchParams, loadOrder]);
|
|
201
|
+
}, [searchParams, loadOrder, disableUrlParamManagement]);
|
|
170
202
|
|
|
171
203
|
// Order creation hooks
|
|
172
204
|
const { createOrder, isCreatingOrder } = useAnyspendCreateOrder({
|
|
@@ -177,16 +209,18 @@ export function useAnyspendFlow({
|
|
|
177
209
|
onOrderSuccess?.(newOrderId);
|
|
178
210
|
|
|
179
211
|
// Add orderId and payment method to URL for persistence
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
212
|
+
if (!disableUrlParamManagement) {
|
|
213
|
+
const params = new URLSearchParams(searchParams.toString()); // Preserve existing params
|
|
214
|
+
params.set("orderId", newOrderId);
|
|
215
|
+
if (selectedCryptoPaymentMethod !== CryptoPaymentMethodType.NONE) {
|
|
216
|
+
console.log("Setting cryptoPaymentMethod in URL:", selectedCryptoPaymentMethod);
|
|
217
|
+
params.set("cryptoPaymentMethod", selectedCryptoPaymentMethod);
|
|
218
|
+
} else {
|
|
219
|
+
console.log("Payment method is NONE, not setting in URL");
|
|
220
|
+
}
|
|
221
|
+
console.log("Final URL params:", params.toString());
|
|
222
|
+
router.push(`${window.location.pathname}?${params.toString()}`);
|
|
187
223
|
}
|
|
188
|
-
console.log("Final URL params:", params.toString());
|
|
189
|
-
router.push(`${window.location.pathname}?${params.toString()}`);
|
|
190
224
|
},
|
|
191
225
|
onError: error => {
|
|
192
226
|
console.error(error);
|
|
@@ -245,6 +279,9 @@ export function useAnyspendFlow({
|
|
|
245
279
|
setSelectedRecipientAddress,
|
|
246
280
|
recipientName,
|
|
247
281
|
globalAddress,
|
|
282
|
+
// Balance check
|
|
283
|
+
hasEnoughBalance,
|
|
284
|
+
isBalanceLoading,
|
|
248
285
|
// Quote data
|
|
249
286
|
anyspendQuote,
|
|
250
287
|
isLoadingAnyspendQuote,
|
|
@@ -4,7 +4,7 @@ import { useState } from "react";
|
|
|
4
4
|
import { ThirdwebProvider, useActiveAccount } from "thirdweb/react";
|
|
5
5
|
import { Account } from "thirdweb/wallets";
|
|
6
6
|
|
|
7
|
-
import {
|
|
7
|
+
import { Users } from "@b3dotfun/b3-api";
|
|
8
8
|
import { B3Context, B3ContextType } from "./types";
|
|
9
9
|
|
|
10
10
|
/**
|
|
@@ -64,7 +64,7 @@ export function InnerProvider({
|
|
|
64
64
|
theme: "light" | "dark";
|
|
65
65
|
}) {
|
|
66
66
|
const activeAccount = useActiveAccount();
|
|
67
|
-
const [user, setUser] = useState<
|
|
67
|
+
const [user, setUser] = useState<Users | undefined>(undefined);
|
|
68
68
|
|
|
69
69
|
// Use given accountOverride or activeAccount from thirdweb
|
|
70
70
|
const effectiveAccount = accountOverride || activeAccount;
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { RelayKitProviderWrapper, TooltipProvider, useAuthStore } from "@b3dotfun/sdk/global-account/react";
|
|
2
|
-
import { User } from "@b3dotfun/sdk/global-account/types/b3-api.types";
|
|
3
2
|
import { PermissionsConfig } from "@b3dotfun/sdk/global-account/types/permissions";
|
|
4
3
|
import { loadGA4Script } from "@b3dotfun/sdk/global-account/utils/analytics";
|
|
5
4
|
import { supportedChains } from "@b3dotfun/sdk/shared/constants/chains/supported";
|
|
@@ -18,6 +17,7 @@ import { createConfig, http, WagmiProvider } from "wagmi";
|
|
|
18
17
|
import { StyleRoot } from "../StyleRoot";
|
|
19
18
|
import { B3Context, B3ContextType } from "./types";
|
|
20
19
|
|
|
20
|
+
import { Users } from "@b3dotfun/b3-api";
|
|
21
21
|
import "@reservoir0x/relay-kit-ui/styles.css";
|
|
22
22
|
|
|
23
23
|
/**
|
|
@@ -115,7 +115,7 @@ export function InnerProvider({
|
|
|
115
115
|
const setActiveWallet = useSetActiveWallet();
|
|
116
116
|
const isAuthenticated = useAuthStore(state => state.isAuthenticated);
|
|
117
117
|
|
|
118
|
-
const [user, setUser] = useState<
|
|
118
|
+
const [user, setUser] = useState<Users | undefined>(undefined);
|
|
119
119
|
|
|
120
120
|
// Use given accountOverride or activeAccount from thirdweb
|
|
121
121
|
const effectiveAccount = isAuthenticated ? accountOverride || activeAccount : undefined;
|
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { User } from "@b3dotfun/sdk/global-account/types/b3-api.types";
|
|
3
|
-
import { Wallet } from "thirdweb/wallets";
|
|
1
|
+
import { Users } from "@b3dotfun/b3-api";
|
|
4
2
|
import { PermissionsConfig } from "@b3dotfun/sdk/global-account/types/permissions";
|
|
5
3
|
import { createContext } from "react";
|
|
4
|
+
import { Account, Wallet } from "thirdweb/wallets";
|
|
6
5
|
|
|
7
6
|
/**
|
|
8
7
|
* Context type for B3Provider
|
|
@@ -10,10 +9,10 @@ import { createContext } from "react";
|
|
|
10
9
|
export interface B3ContextType {
|
|
11
10
|
account?: Account;
|
|
12
11
|
automaticallySetFirstEoa: boolean;
|
|
13
|
-
user?:
|
|
12
|
+
user?: Users;
|
|
14
13
|
setWallet: (wallet: Wallet) => void;
|
|
15
14
|
wallet?: Wallet;
|
|
16
|
-
setUser: (user?:
|
|
15
|
+
setUser: (user?: Users) => void;
|
|
17
16
|
initialized: boolean;
|
|
18
17
|
ready: boolean;
|
|
19
18
|
environment?: "development" | "production";
|