@b3dotfun/sdk 0.0.30-alpha.9 → 0.0.31
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.d.ts +4 -0
- package/dist/cjs/anyspend/react/components/AnyspendDepositHype.js +6 -1
- package/dist/cjs/anyspend/react/components/common/CryptoReceiveSection.d.ts +3 -1
- package/dist/cjs/anyspend/react/components/common/CryptoReceiveSection.js +2 -2
- package/dist/cjs/anyspend/react/components/common/PanelOnramp.d.ts +3 -1
- package/dist/cjs/anyspend/react/components/common/PanelOnramp.js +3 -3
- package/dist/cjs/global-account/react/components/ManageAccount/BalanceContent.d.ts +6 -0
- package/dist/cjs/global-account/react/components/ManageAccount/BalanceContent.js +94 -0
- package/dist/cjs/global-account/react/components/ManageAccount/ContentTokens.js +5 -0
- package/dist/cjs/global-account/react/components/ManageAccount/ManageAccount.js +3 -40
- package/dist/cjs/global-account/react/components/ManageAccount/TokenBalanceRow.d.ts +10 -0
- package/dist/cjs/global-account/react/components/ManageAccount/TokenBalanceRow.js +8 -0
- package/dist/cjs/global-account/react/components/TokenIcon.d.ts +11 -0
- package/dist/cjs/global-account/react/components/TokenIcon.js +43 -0
- package/dist/cjs/global-account/react/components/ui/accordion.d.ts +7 -0
- package/dist/cjs/global-account/react/components/ui/accordion.js +53 -0
- package/dist/cjs/global-account/react/components/ui/dialog.js +1 -1
- package/dist/cjs/global-account/react/hooks/useUnifiedChainSwitchAndExecute.js +2 -0
- package/dist/cjs/global-account/utils/analytics.d.ts +6 -0
- package/dist/cjs/global-account/utils/analytics.js +1 -0
- package/dist/esm/anyspend/react/components/AnyspendDepositHype.d.ts +4 -0
- package/dist/esm/anyspend/react/components/AnyspendDepositHype.js +5 -1
- package/dist/esm/anyspend/react/components/common/CryptoReceiveSection.d.ts +3 -1
- package/dist/esm/anyspend/react/components/common/CryptoReceiveSection.js +2 -2
- package/dist/esm/anyspend/react/components/common/PanelOnramp.d.ts +3 -1
- package/dist/esm/anyspend/react/components/common/PanelOnramp.js +4 -4
- package/dist/esm/global-account/react/components/ManageAccount/BalanceContent.d.ts +6 -0
- package/dist/esm/global-account/react/components/ManageAccount/BalanceContent.js +88 -0
- package/dist/esm/global-account/react/components/ManageAccount/ContentTokens.js +2 -0
- package/dist/esm/global-account/react/components/ManageAccount/ManageAccount.js +6 -40
- package/dist/esm/global-account/react/components/ManageAccount/TokenBalanceRow.d.ts +10 -0
- package/dist/esm/global-account/react/components/ManageAccount/TokenBalanceRow.js +5 -0
- package/dist/esm/global-account/react/components/TokenIcon.d.ts +11 -0
- package/dist/esm/global-account/react/components/TokenIcon.js +37 -0
- package/dist/esm/global-account/react/components/ui/accordion.d.ts +7 -0
- package/dist/esm/global-account/react/components/ui/accordion.js +14 -0
- package/dist/esm/global-account/react/components/ui/dialog.js +1 -1
- package/dist/esm/global-account/react/hooks/useUnifiedChainSwitchAndExecute.js +2 -0
- package/dist/esm/global-account/utils/analytics.d.ts +6 -0
- package/dist/esm/global-account/utils/analytics.js +1 -0
- package/dist/styles/index.css +1 -1
- package/dist/types/anyspend/react/components/AnyspendDepositHype.d.ts +4 -0
- package/dist/types/anyspend/react/components/common/CryptoReceiveSection.d.ts +3 -1
- package/dist/types/anyspend/react/components/common/PanelOnramp.d.ts +3 -1
- package/dist/types/global-account/react/components/ManageAccount/BalanceContent.d.ts +6 -0
- package/dist/types/global-account/react/components/ManageAccount/TokenBalanceRow.d.ts +10 -0
- package/dist/types/global-account/react/components/TokenIcon.d.ts +11 -0
- package/dist/types/global-account/react/components/ui/accordion.d.ts +7 -0
- package/dist/types/global-account/utils/analytics.d.ts +6 -0
- package/package.json +10 -18
- package/src/anyspend/react/components/AnySpendStakeB3.tsx +1 -1
- package/src/anyspend/react/components/AnyspendDepositHype.tsx +9 -0
- package/src/anyspend/react/components/AnyspendSignatureMint.tsx +4 -4
- package/src/anyspend/react/components/common/CryptoReceiveSection.tsx +12 -3
- package/src/anyspend/react/components/common/PanelOnramp.tsx +8 -4
- package/src/global-account/react/components/ManageAccount/BalanceContent.tsx +228 -0
- package/src/global-account/react/components/ManageAccount/ContentTokens.tsx +3 -0
- package/src/global-account/react/components/ManageAccount/ManageAccount.tsx +7 -285
- package/src/global-account/react/components/ManageAccount/TokenBalanceRow.tsx +46 -0
- package/src/global-account/react/components/TokenIcon.tsx +87 -0
- package/src/global-account/react/components/ui/accordion.tsx +53 -0
- package/src/global-account/react/components/ui/dialog.tsx +1 -1
- package/src/global-account/react/hooks/useB3BalanceFromAddresses.ts +1 -1
- package/src/global-account/react/hooks/useUnifiedChainSwitchAndExecute.ts +3 -0
- package/src/global-account/utils/analytics.ts +10 -0
- package/dist/cjs/index.d.ts +0 -0
- package/dist/cjs/index.js +0 -2
- package/dist/esm/index.d.ts +0 -0
- package/dist/esm/index.js +0 -2
- package/dist/types/index.d.ts +0 -0
- package/src/index.ts +0 -1
|
@@ -18,15 +18,15 @@ function generateEncodedDataForSignatureMint(signatureData: GenerateSigMintRespo
|
|
|
18
18
|
invariant(payload, "Payload is required");
|
|
19
19
|
|
|
20
20
|
const mintRequest = {
|
|
21
|
-
to: payload.to
|
|
22
|
-
royaltyRecipient: payload.royaltyRecipient
|
|
21
|
+
to: payload.to as `0x${string}`,
|
|
22
|
+
royaltyRecipient: payload.royaltyRecipient as `0x${string}`,
|
|
23
23
|
royaltyBps: BigInt(payload.royaltyBps || 0),
|
|
24
|
-
primarySaleRecipient: payload.primarySaleRecipient
|
|
24
|
+
primarySaleRecipient: payload.primarySaleRecipient as `0x${string}`,
|
|
25
25
|
tokenId: BigInt(payload.tokenId || 0),
|
|
26
26
|
uri: payload.uri,
|
|
27
27
|
quantity: BigInt(payload.quantity || 1),
|
|
28
28
|
pricePerToken: parseEther(payload.price?.toString() || "0"),
|
|
29
|
-
currency: payload.currencyAddress
|
|
29
|
+
currency: payload.currencyAddress as `0x${string}`,
|
|
30
30
|
validityStartTimestamp: BigInt(payload.mintStartTime || 0),
|
|
31
31
|
validityEndTimestamp: BigInt(payload.mintEndTime || 0),
|
|
32
32
|
uid: payload.uid as `0x${string}`,
|
|
@@ -24,6 +24,9 @@ interface CryptoReceiveSectionProps {
|
|
|
24
24
|
onChangeDstAmount?: (value: string) => void;
|
|
25
25
|
// Quote data
|
|
26
26
|
anyspendQuote?: any;
|
|
27
|
+
// custom dst token data
|
|
28
|
+
dstTokenSymbol?: string;
|
|
29
|
+
dstTokenLogoURI?: string;
|
|
27
30
|
}
|
|
28
31
|
|
|
29
32
|
export function CryptoReceiveSection({
|
|
@@ -39,6 +42,8 @@ export function CryptoReceiveSection({
|
|
|
39
42
|
setSelectedDstToken,
|
|
40
43
|
onChangeDstAmount,
|
|
41
44
|
anyspendQuote,
|
|
45
|
+
dstTokenSymbol,
|
|
46
|
+
dstTokenLogoURI,
|
|
42
47
|
}: CryptoReceiveSectionProps) {
|
|
43
48
|
return (
|
|
44
49
|
<motion.div
|
|
@@ -72,10 +77,14 @@ export function CryptoReceiveSection({
|
|
|
72
77
|
<div className="flex items-center justify-between">
|
|
73
78
|
<div className="text-as-primary text-2xl font-bold">{dstAmount || "0"}</div>
|
|
74
79
|
<div className="bg-as-brand/10 border-as-brand/30 flex items-center gap-3 rounded-xl border px-4 py-3">
|
|
75
|
-
{dstToken.metadata?.logoURI && (
|
|
76
|
-
<img
|
|
80
|
+
{(dstTokenLogoURI || dstToken.metadata?.logoURI) && (
|
|
81
|
+
<img
|
|
82
|
+
src={dstTokenLogoURI || dstToken.metadata?.logoURI}
|
|
83
|
+
alt={dstTokenSymbol || dstToken.symbol}
|
|
84
|
+
className="h-8 w-8 rounded-full"
|
|
85
|
+
/>
|
|
77
86
|
)}
|
|
78
|
-
<span className="text-as-brand text-lg font-bold">{dstToken.symbol}</span>
|
|
87
|
+
<span className="text-as-brand text-lg font-bold">{dstTokenSymbol || dstToken.symbol}</span>
|
|
79
88
|
</div>
|
|
80
89
|
</div>
|
|
81
90
|
) : (
|
|
@@ -2,7 +2,7 @@ import { useCoinbaseOnrampOptions, useGeoOnrampOptions } from "@b3dotfun/sdk/any
|
|
|
2
2
|
import { components } from "@b3dotfun/sdk/anyspend/types/api";
|
|
3
3
|
import { ALL_CHAINS } from "@b3dotfun/sdk/anyspend/utils/chain";
|
|
4
4
|
import { Input, useGetGeo, useProfile } from "@b3dotfun/sdk/global-account/react";
|
|
5
|
-
import { formatUsername } from "@b3dotfun/sdk/shared/utils";
|
|
5
|
+
import { cn, formatUsername } from "@b3dotfun/sdk/shared/utils";
|
|
6
6
|
import { formatAddress } from "@b3dotfun/sdk/shared/utils/formatAddress";
|
|
7
7
|
import { ChevronRight, Wallet } from "lucide-react";
|
|
8
8
|
import { useRef } from "react";
|
|
@@ -23,6 +23,8 @@ export function PanelOnramp({
|
|
|
23
23
|
onDestinationChainChange,
|
|
24
24
|
fiatPaymentMethodIndex,
|
|
25
25
|
recipientSelectionPanelIndex,
|
|
26
|
+
dstTokenSymbol,
|
|
27
|
+
hideDstToken = false,
|
|
26
28
|
}: {
|
|
27
29
|
srcAmountOnRamp: string;
|
|
28
30
|
setSrcAmountOnRamp: (amount: string) => void;
|
|
@@ -36,6 +38,8 @@ export function PanelOnramp({
|
|
|
36
38
|
onDestinationChainChange?: (chainId: number) => void;
|
|
37
39
|
fiatPaymentMethodIndex: number;
|
|
38
40
|
recipientSelectionPanelIndex: number;
|
|
41
|
+
dstTokenSymbol?: string;
|
|
42
|
+
hideDstToken?: boolean;
|
|
39
43
|
}) {
|
|
40
44
|
// Get geo-based onramp options to access fee information
|
|
41
45
|
const { stripeWeb2Support } = useGeoOnrampOptions(srcAmountOnRamp);
|
|
@@ -163,7 +167,7 @@ export function PanelOnramp({
|
|
|
163
167
|
</div>
|
|
164
168
|
|
|
165
169
|
{/* Quick Amount Buttons */}
|
|
166
|
-
<div className="mx-auto mb-6 inline-grid grid-cols-4 gap-2">
|
|
170
|
+
<div className={cn("mx-auto mb-6 inline-grid grid-cols-4 gap-2", hideDstToken && "mb-0")}>
|
|
167
171
|
{["5", "10", "20", "25"].map(value => (
|
|
168
172
|
<button
|
|
169
173
|
key={value}
|
|
@@ -180,7 +184,7 @@ export function PanelOnramp({
|
|
|
180
184
|
</div>
|
|
181
185
|
|
|
182
186
|
{/* Token Display */}
|
|
183
|
-
{destinationToken && destinationChainId && (
|
|
187
|
+
{destinationToken && destinationChainId && !hideDstToken && (
|
|
184
188
|
<OrderTokenAmountFiat
|
|
185
189
|
address={_recipientAddress}
|
|
186
190
|
context="to"
|
|
@@ -226,7 +230,7 @@ export function PanelOnramp({
|
|
|
226
230
|
<span className="text-as-tertiarry text-sm">Expected to receive</span>
|
|
227
231
|
<div className="flex items-center gap-2">
|
|
228
232
|
<span className="text-as-primary font-semibold">
|
|
229
|
-
{destinationAmount || "0"} {destinationToken?.symbol || ""}
|
|
233
|
+
{destinationAmount || "0"} {dstTokenSymbol || destinationToken?.symbol || ""}
|
|
230
234
|
</span>
|
|
231
235
|
<span className="text-as-tertiarry text-sm">
|
|
232
236
|
on {destinationChainId ? ALL_CHAINS[destinationChainId]?.name : ""}
|
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Button,
|
|
3
|
+
CopyToClipboard,
|
|
4
|
+
useAuthentication,
|
|
5
|
+
useB3BalanceFromAddresses,
|
|
6
|
+
useModalStore,
|
|
7
|
+
useNativeBalance,
|
|
8
|
+
useProfile,
|
|
9
|
+
} from "@b3dotfun/sdk/global-account/react";
|
|
10
|
+
import { BankIcon } from "@b3dotfun/sdk/global-account/react/components/icons/BankIcon";
|
|
11
|
+
import { SignOutIcon } from "@b3dotfun/sdk/global-account/react/components/icons/SignOutIcon";
|
|
12
|
+
import { SwapIcon } from "@b3dotfun/sdk/global-account/react/components/icons/SwapIcon";
|
|
13
|
+
import { formatUsername } from "@b3dotfun/sdk/shared/utils";
|
|
14
|
+
import { Loader2, Pencil } from "lucide-react";
|
|
15
|
+
import { useEffect, useRef, useState } from "react";
|
|
16
|
+
import { useActiveAccount } from "thirdweb/react";
|
|
17
|
+
import useFirstEOA from "../../hooks/useFirstEOA";
|
|
18
|
+
import { B3TokenIcon, EthereumTokenIcon } from "../TokenIcon";
|
|
19
|
+
import { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from "../ui/accordion";
|
|
20
|
+
import { TokenBalanceRow } from "./TokenBalanceRow";
|
|
21
|
+
|
|
22
|
+
interface BalanceContentProps {
|
|
23
|
+
onLogout?: () => void;
|
|
24
|
+
partnerId: string;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function centerTruncate(str: string, length = 4) {
|
|
28
|
+
if (str.length <= length * 2) return str;
|
|
29
|
+
return `${str.slice(0, length)}...${str.slice(-length)}`;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export function BalanceContent({ onLogout, partnerId }: BalanceContentProps) {
|
|
33
|
+
const account = useActiveAccount();
|
|
34
|
+
const { address: eoaAddress, info: eoaInfo } = useFirstEOA();
|
|
35
|
+
const { data: profile } = useProfile({
|
|
36
|
+
address: eoaAddress || account?.address,
|
|
37
|
+
fresh: true,
|
|
38
|
+
});
|
|
39
|
+
const { setB3ModalOpen, setB3ModalContentType } = useModalStore();
|
|
40
|
+
const { logout } = useAuthentication(partnerId);
|
|
41
|
+
const [logoutLoading, setLogoutLoading] = useState(false);
|
|
42
|
+
const [openAccordions, setOpenAccordions] = useState<string[]>([]);
|
|
43
|
+
const hasExpandedRef = useRef(false);
|
|
44
|
+
|
|
45
|
+
console.log("eoaAddress", eoaAddress);
|
|
46
|
+
console.log("account?.address", account?.address);
|
|
47
|
+
|
|
48
|
+
// Balance data fetching
|
|
49
|
+
const { data: eoaNativeBalance, isLoading: eoaNativeLoading } = useNativeBalance(eoaAddress);
|
|
50
|
+
const { data: eoaB3Balance, isLoading: eoaB3Loading } = useB3BalanceFromAddresses(eoaAddress);
|
|
51
|
+
const { data: b3Balance, isLoading: b3Loading } = useB3BalanceFromAddresses(account?.address);
|
|
52
|
+
const { data: nativeBalance, isLoading: nativeLoading } = useNativeBalance(account?.address);
|
|
53
|
+
|
|
54
|
+
// Calculate total USD values for comparison
|
|
55
|
+
const globalAccountTotalUsd = (b3Balance?.balanceUsd || 0) + (nativeBalance?.totalUsd || 0);
|
|
56
|
+
const eoaTotalUsd = (eoaB3Balance?.balanceUsd || 0) + (eoaNativeBalance?.totalUsd || 0);
|
|
57
|
+
|
|
58
|
+
// Check if both data sets are ready (not loading and have data)
|
|
59
|
+
const isGlobalDataReady = !b3Loading && !nativeLoading && b3Balance !== undefined && nativeBalance !== undefined;
|
|
60
|
+
const isEoaDataReady =
|
|
61
|
+
!eoaAddress || (!eoaB3Loading && !eoaNativeLoading && eoaB3Balance !== undefined && eoaNativeBalance !== undefined);
|
|
62
|
+
const isBothDataReady = isGlobalDataReady && isEoaDataReady;
|
|
63
|
+
|
|
64
|
+
// Reset expansion flag when component mounts
|
|
65
|
+
useEffect(() => {
|
|
66
|
+
hasExpandedRef.current = false;
|
|
67
|
+
setOpenAccordions([]);
|
|
68
|
+
}, []);
|
|
69
|
+
|
|
70
|
+
// Auto-expand the appropriate section when data becomes ready
|
|
71
|
+
useEffect(() => {
|
|
72
|
+
if (isBothDataReady && !hasExpandedRef.current && eoaAddress && account?.address) {
|
|
73
|
+
hasExpandedRef.current = true;
|
|
74
|
+
|
|
75
|
+
// Determine which section to expand based on higher balance
|
|
76
|
+
if (globalAccountTotalUsd === 0 && eoaTotalUsd === 0) {
|
|
77
|
+
// If both have 0 balance, expand global account by default
|
|
78
|
+
setOpenAccordions(["global-account"]);
|
|
79
|
+
} else if (globalAccountTotalUsd >= eoaTotalUsd) {
|
|
80
|
+
setOpenAccordions(["global-account"]);
|
|
81
|
+
} else {
|
|
82
|
+
setOpenAccordions(["eoa-account"]);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}, [isBothDataReady, globalAccountTotalUsd, eoaTotalUsd, eoaAddress, account?.address]);
|
|
86
|
+
|
|
87
|
+
const onLogoutEnhanced = async () => {
|
|
88
|
+
setLogoutLoading(true);
|
|
89
|
+
await logout();
|
|
90
|
+
onLogout?.();
|
|
91
|
+
setB3ModalOpen(false);
|
|
92
|
+
setLogoutLoading(false);
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
return (
|
|
96
|
+
<div className="flex flex-col gap-6">
|
|
97
|
+
{/* Profile Section */}
|
|
98
|
+
<div className="flex items-center justify-between">
|
|
99
|
+
<div className="flex items-center gap-4">
|
|
100
|
+
<div className="relative">
|
|
101
|
+
{profile?.avatar ? (
|
|
102
|
+
<img src={profile?.avatar} alt="Profile" className="size-24 rounded-full" />
|
|
103
|
+
) : (
|
|
104
|
+
<div className="bg-b3-primary-wash size-24 rounded-full" />
|
|
105
|
+
)}
|
|
106
|
+
<div className="bg-b3-grey border-b3-background absolute -bottom-1 -right-1 flex size-8 items-center justify-center rounded-full border-4">
|
|
107
|
+
<Pencil size={16} className="text-b3-background" />
|
|
108
|
+
</div>
|
|
109
|
+
</div>
|
|
110
|
+
<div>
|
|
111
|
+
<h2 className="text-b3-grey text-xl font-semibold">
|
|
112
|
+
{profile?.displayName || formatUsername(profile?.name || "")}
|
|
113
|
+
</h2>
|
|
114
|
+
<div className="border-b3-line bg-b3-line/20 hover:bg-b3-line/40 flex w-fit items-center gap-2 rounded-full border px-3 py-1 transition-colors">
|
|
115
|
+
<span className="text-b3-foreground-muted font-mono text-xs">
|
|
116
|
+
{centerTruncate(account?.address || "", 6)}
|
|
117
|
+
</span>
|
|
118
|
+
<CopyToClipboard text={account?.address || ""} />
|
|
119
|
+
</div>
|
|
120
|
+
</div>
|
|
121
|
+
</div>
|
|
122
|
+
</div>
|
|
123
|
+
|
|
124
|
+
{/* Quick Actions */}
|
|
125
|
+
<div className="grid grid-cols-2 gap-3">
|
|
126
|
+
<Button
|
|
127
|
+
className="manage-account-deposit bg-b3-primary-wash hover:bg-b3-primary-wash/70 h-[84px] w-full flex-col items-start gap-2 rounded-2xl"
|
|
128
|
+
onClick={() => {
|
|
129
|
+
setB3ModalOpen(true);
|
|
130
|
+
setB3ModalContentType({
|
|
131
|
+
type: "anySpend",
|
|
132
|
+
defaultActiveTab: "fiat",
|
|
133
|
+
showBackButton: true,
|
|
134
|
+
});
|
|
135
|
+
}}
|
|
136
|
+
>
|
|
137
|
+
<BankIcon size={24} className="text-b3-primary-blue shrink-0" />
|
|
138
|
+
<div className="text-b3-grey font-neue-montreal-semibold">Deposit</div>
|
|
139
|
+
</Button>
|
|
140
|
+
<Button
|
|
141
|
+
className="manage-account-swap bg-b3-primary-wash hover:bg-b3-primary-wash/70 flex h-[84px] w-full flex-col items-start gap-2 rounded-2xl"
|
|
142
|
+
onClick={() => {
|
|
143
|
+
setB3ModalOpen(true);
|
|
144
|
+
setB3ModalContentType({
|
|
145
|
+
type: "anySpend",
|
|
146
|
+
showBackButton: true,
|
|
147
|
+
});
|
|
148
|
+
}}
|
|
149
|
+
>
|
|
150
|
+
<SwapIcon size={24} className="text-b3-primary-blue" />
|
|
151
|
+
<div className="text-b3-grey font-neue-montreal-semibold">Swap</div>
|
|
152
|
+
</Button>
|
|
153
|
+
</div>
|
|
154
|
+
|
|
155
|
+
{/* Balance Sections with Accordions */}
|
|
156
|
+
<Accordion type="multiple" value={openAccordions} onValueChange={setOpenAccordions} className="space-y-2">
|
|
157
|
+
{/* Global Account Balance Section */}
|
|
158
|
+
<AccordionItem value="global-account" className="border-none">
|
|
159
|
+
<AccordionTrigger className="text-b3-grey font-neue-montreal-semibold py-2 hover:no-underline">
|
|
160
|
+
<span>Balance</span>
|
|
161
|
+
</AccordionTrigger>
|
|
162
|
+
<AccordionContent className="space-y-4">
|
|
163
|
+
<TokenBalanceRow
|
|
164
|
+
icon={<B3TokenIcon className="size-10" />}
|
|
165
|
+
name="B3"
|
|
166
|
+
balance={`${b3Balance?.formattedTotal || "0.00"} B3`}
|
|
167
|
+
usdValue={b3Balance?.balanceUsdFormatted || "0.00"}
|
|
168
|
+
priceChange={b3Balance?.priceChange24h}
|
|
169
|
+
/>
|
|
170
|
+
<TokenBalanceRow
|
|
171
|
+
icon={<EthereumTokenIcon className="size-10" />}
|
|
172
|
+
name="Ethereum"
|
|
173
|
+
balance={`${nativeBalance?.formattedTotal || "0.00"} ETH`}
|
|
174
|
+
usdValue={nativeBalance?.formattedTotalUsd || "0.00"}
|
|
175
|
+
priceChange={nativeBalance?.priceChange24h}
|
|
176
|
+
/>
|
|
177
|
+
</AccordionContent>
|
|
178
|
+
</AccordionItem>
|
|
179
|
+
|
|
180
|
+
{/* EOA Account Balance Section */}
|
|
181
|
+
{eoaAddress && (
|
|
182
|
+
<AccordionItem value="eoa-account" className="border-none">
|
|
183
|
+
<AccordionTrigger className="text-b3-grey font-neue-montreal-semibold py-2 hover:no-underline">
|
|
184
|
+
<div className="flex items-center gap-3">
|
|
185
|
+
<span>Connected {eoaInfo?.data?.name || "Wallet"}</span>
|
|
186
|
+
<div className="border-b3-line bg-b3-line/20 hover:bg-b3-line/40 flex w-fit items-center gap-2 rounded-full border px-3 py-1 transition-colors">
|
|
187
|
+
<span className="text-b3-foreground-muted font-mono text-xs">{centerTruncate(eoaAddress, 6)}</span>
|
|
188
|
+
<CopyToClipboard text={eoaAddress} />
|
|
189
|
+
</div>
|
|
190
|
+
</div>
|
|
191
|
+
</AccordionTrigger>
|
|
192
|
+
<AccordionContent className="space-y-4">
|
|
193
|
+
<TokenBalanceRow
|
|
194
|
+
icon={<B3TokenIcon className="size-10" />}
|
|
195
|
+
name="B3"
|
|
196
|
+
balance={`${eoaB3Balance?.formattedTotal || "0.00"} B3`}
|
|
197
|
+
usdValue={eoaB3Balance?.balanceUsdFormatted || "0.00"}
|
|
198
|
+
priceChange={eoaB3Balance?.priceChange24h}
|
|
199
|
+
/>
|
|
200
|
+
<TokenBalanceRow
|
|
201
|
+
icon={<EthereumTokenIcon className="size-10" />}
|
|
202
|
+
name="Ethereum"
|
|
203
|
+
balance={`${eoaNativeBalance?.formattedTotal || "0.00"} ETH`}
|
|
204
|
+
usdValue={eoaNativeBalance?.formattedTotalUsd || "0.00"}
|
|
205
|
+
priceChange={eoaNativeBalance?.priceChange24h}
|
|
206
|
+
/>
|
|
207
|
+
</AccordionContent>
|
|
208
|
+
</AccordionItem>
|
|
209
|
+
)}
|
|
210
|
+
</Accordion>
|
|
211
|
+
|
|
212
|
+
{/* Sign Out */}
|
|
213
|
+
<button
|
|
214
|
+
className="border-b3-line hover:bg-b3-line relative flex w-full items-center justify-center rounded-2xl border p-4 transition-colors"
|
|
215
|
+
onClick={onLogoutEnhanced}
|
|
216
|
+
>
|
|
217
|
+
<span className="font-neue-montreal-semibold text-b3-grey">Sign out</span>
|
|
218
|
+
<div className="absolute right-4">
|
|
219
|
+
{logoutLoading ? (
|
|
220
|
+
<Loader2 className="animate-spin" size={16} />
|
|
221
|
+
) : (
|
|
222
|
+
<SignOutIcon size={16} className="text-b3-grey" />
|
|
223
|
+
)}
|
|
224
|
+
</div>
|
|
225
|
+
</button>
|
|
226
|
+
</div>
|
|
227
|
+
);
|
|
228
|
+
}
|
|
@@ -15,6 +15,7 @@ import { toast } from "sonner";
|
|
|
15
15
|
import { useActiveAccount } from "thirdweb/react";
|
|
16
16
|
import { encodeFunctionData, erc20Abi, isAddress, parseUnits } from "viem";
|
|
17
17
|
import { SimBalanceItem } from "../../hooks/useSimBalance";
|
|
18
|
+
import invariant from "invariant";
|
|
18
19
|
|
|
19
20
|
// Panel view enum for managing navigation between token list and send form
|
|
20
21
|
enum TokenPanelView {
|
|
@@ -172,6 +173,8 @@ export function ContentTokens({ activeTab }: ContentTokensProps) {
|
|
|
172
173
|
};
|
|
173
174
|
|
|
174
175
|
try {
|
|
176
|
+
invariant(isAddress(recipientAddress), "Recipient address is not a valid address");
|
|
177
|
+
|
|
175
178
|
const sendTokenData = encodeFunctionData({
|
|
176
179
|
abi: erc20Abi,
|
|
177
180
|
functionName: "transfer",
|