@b3dotfun/sdk 0.0.30-alpha.9 → 0.0.31-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.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
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import {
|
|
2
2
|
Button,
|
|
3
|
-
CopyToClipboard,
|
|
4
3
|
ManageAccountModalProps,
|
|
5
4
|
TabsContentPrimitive,
|
|
6
5
|
TabsListPrimitive,
|
|
@@ -9,30 +8,26 @@ import {
|
|
|
9
8
|
TWSignerWithMetadata,
|
|
10
9
|
useAccountAssets,
|
|
11
10
|
useAuthentication,
|
|
12
|
-
useB3BalanceFromAddresses,
|
|
13
11
|
useGetAllTWSigners,
|
|
14
12
|
useModalStore,
|
|
15
|
-
useNativeBalance,
|
|
16
|
-
useProfile,
|
|
17
13
|
useRemoveSessionKey,
|
|
18
14
|
} from "@b3dotfun/sdk/global-account/react";
|
|
19
|
-
import { BankIcon } from "@b3dotfun/sdk/global-account/react/components/icons/BankIcon";
|
|
20
15
|
import { SignOutIcon } from "@b3dotfun/sdk/global-account/react/components/icons/SignOutIcon";
|
|
21
|
-
import { SwapIcon } from "@b3dotfun/sdk/global-account/react/components/icons/SwapIcon";
|
|
22
|
-
import { formatUsername } from "@b3dotfun/sdk/shared/utils";
|
|
23
16
|
import { formatNumber } from "@b3dotfun/sdk/shared/utils/formatNumber";
|
|
24
17
|
|
|
25
18
|
import { client } from "@b3dotfun/sdk/shared/utils/thirdweb";
|
|
26
|
-
import { BarChart3, Coins, Image, LinkIcon, Loader2,
|
|
19
|
+
import { BarChart3, Coins, Image, LinkIcon, Loader2, Settings, UnlinkIcon } from "lucide-react";
|
|
27
20
|
import { useState } from "react";
|
|
28
21
|
import { Chain } from "thirdweb";
|
|
29
22
|
import { useActiveAccount, useProfiles, useUnlinkProfile } from "thirdweb/react";
|
|
30
23
|
import { formatUnits } from "viem";
|
|
31
|
-
|
|
24
|
+
|
|
32
25
|
import { getProfileDisplayInfo } from "../../utils/profileDisplay";
|
|
33
26
|
import { AccountAssets } from "../AccountAssets/AccountAssets";
|
|
34
27
|
import { ContentTokens } from "./ContentTokens";
|
|
35
28
|
|
|
29
|
+
import { BalanceContent } from "./BalanceContent";
|
|
30
|
+
|
|
36
31
|
type TabValue = "overview" | "tokens" | "nfts" | "apps" | "settings";
|
|
37
32
|
|
|
38
33
|
interface ManageAccountProps {
|
|
@@ -45,11 +40,6 @@ interface ManageAccountProps {
|
|
|
45
40
|
containerClassName?: string;
|
|
46
41
|
}
|
|
47
42
|
|
|
48
|
-
function centerTruncate(str: string, length = 4) {
|
|
49
|
-
if (str.length <= length * 2) return str;
|
|
50
|
-
return `${str.slice(0, length)}...${str.slice(-length)}`;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
43
|
export function ManageAccount({
|
|
54
44
|
onLogout,
|
|
55
45
|
onSwap: _onSwap,
|
|
@@ -60,20 +50,12 @@ export function ManageAccount({
|
|
|
60
50
|
const [revokingSignerId, setRevokingSignerId] = useState<string | null>(null);
|
|
61
51
|
const account = useActiveAccount();
|
|
62
52
|
const { data: nfts, isLoading } = useAccountAssets(account?.address);
|
|
63
|
-
|
|
64
|
-
const { data: nativeBalance } = useNativeBalance(account?.address);
|
|
65
|
-
const { address: eoaAddress } = useFirstEOA();
|
|
66
|
-
const { data: profile } = useProfile({
|
|
67
|
-
address: eoaAddress || account?.address,
|
|
68
|
-
fresh: true,
|
|
69
|
-
});
|
|
70
|
-
const { data: eoaNativeBalance } = useNativeBalance(eoaAddress);
|
|
71
|
-
const { data: eoaB3Balance } = useB3BalanceFromAddresses(eoaAddress);
|
|
53
|
+
|
|
72
54
|
const { data: signers, refetch: refetchSigners } = useGetAllTWSigners({
|
|
73
55
|
chain,
|
|
74
56
|
accountAddress: account?.address,
|
|
75
57
|
});
|
|
76
|
-
const { setB3ModalOpen,
|
|
58
|
+
const { setB3ModalOpen, contentType } = useModalStore();
|
|
77
59
|
const { activeTab = "overview", setActiveTab } = contentType as ManageAccountModalProps;
|
|
78
60
|
const { logout } = useAuthentication(partnerId);
|
|
79
61
|
const [logoutLoading, setLogoutLoading] = useState(false);
|
|
@@ -104,266 +86,6 @@ export function ManageAccount({
|
|
|
104
86
|
setLogoutLoading(false);
|
|
105
87
|
};
|
|
106
88
|
|
|
107
|
-
const BalanceContent = () => {
|
|
108
|
-
const { info: eoaInfo } = useFirstEOA();
|
|
109
|
-
|
|
110
|
-
return (
|
|
111
|
-
<div className="flex flex-col gap-6">
|
|
112
|
-
{/* Profile Section */}
|
|
113
|
-
<div className="flex items-center justify-between">
|
|
114
|
-
<div className="flex items-center gap-4">
|
|
115
|
-
<div className="relative">
|
|
116
|
-
{profile?.avatar ? (
|
|
117
|
-
<img src={profile?.avatar} alt="Profile" className="size-24 rounded-full" />
|
|
118
|
-
) : (
|
|
119
|
-
<div className="bg-b3-primary-wash size-24 rounded-full" />
|
|
120
|
-
)}
|
|
121
|
-
<div className="bg-b3-grey border-b3-background absolute -bottom-1 -right-1 flex size-8 items-center justify-center rounded-full border-4">
|
|
122
|
-
<Pencil size={16} className="text-b3-background" />
|
|
123
|
-
</div>
|
|
124
|
-
</div>
|
|
125
|
-
<div>
|
|
126
|
-
<h2 className="text-b3-grey text-xl font-semibold">
|
|
127
|
-
{profile?.displayName || formatUsername(profile?.name || "")}
|
|
128
|
-
</h2>
|
|
129
|
-
<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">
|
|
130
|
-
<span className="text-b3-foreground-muted font-mono text-xs">
|
|
131
|
-
{centerTruncate(account?.address || "", 6)}
|
|
132
|
-
</span>
|
|
133
|
-
<CopyToClipboard text={account?.address || ""} />
|
|
134
|
-
</div>
|
|
135
|
-
</div>
|
|
136
|
-
</div>
|
|
137
|
-
</div>
|
|
138
|
-
|
|
139
|
-
{/* Quick Actions */}
|
|
140
|
-
<div className="grid grid-cols-2 gap-3">
|
|
141
|
-
<Button
|
|
142
|
-
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"
|
|
143
|
-
onClick={() => {
|
|
144
|
-
setB3ModalOpen(true);
|
|
145
|
-
setB3ModalContentType({
|
|
146
|
-
type: "anySpend",
|
|
147
|
-
defaultActiveTab: "fiat",
|
|
148
|
-
showBackButton: true,
|
|
149
|
-
});
|
|
150
|
-
}}
|
|
151
|
-
>
|
|
152
|
-
<BankIcon size={24} className="text-b3-primary-blue shrink-0" />
|
|
153
|
-
<div className="text-b3-grey font-neue-montreal-semibold">Deposit</div>
|
|
154
|
-
</Button>
|
|
155
|
-
<Button
|
|
156
|
-
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"
|
|
157
|
-
onClick={() => {
|
|
158
|
-
setB3ModalOpen(true);
|
|
159
|
-
setB3ModalContentType({
|
|
160
|
-
type: "anySpend",
|
|
161
|
-
showBackButton: true,
|
|
162
|
-
});
|
|
163
|
-
}}
|
|
164
|
-
>
|
|
165
|
-
<SwapIcon size={24} className="text-b3-primary-blue" />
|
|
166
|
-
<div className="text-b3-grey font-neue-montreal-semibold">Swap</div>
|
|
167
|
-
</Button>
|
|
168
|
-
</div>
|
|
169
|
-
|
|
170
|
-
{/* Balance Section */}
|
|
171
|
-
<div className="space-y-4">
|
|
172
|
-
<h3 className="text-b3-grey font-neue-montreal-semibold">Balance</h3>
|
|
173
|
-
|
|
174
|
-
{/* B3 Balance */}
|
|
175
|
-
<div className="flex items-center justify-between">
|
|
176
|
-
<div className="flex items-center gap-3">
|
|
177
|
-
<div className="flex h-10 w-10 items-center justify-center rounded-full">
|
|
178
|
-
<img src="https://cdn.b3.fun/b3-coin-3d.png" alt="B3" className="size-10" />
|
|
179
|
-
</div>
|
|
180
|
-
<div>
|
|
181
|
-
<div className="flex items-center gap-2">
|
|
182
|
-
<span className="text-b3-grey font-neue-montreal-semibold">B3</span>
|
|
183
|
-
</div>
|
|
184
|
-
<div className="text-b3-foreground-muted font-neue-montreal-medium text-sm">
|
|
185
|
-
{b3Balance?.formattedTotal || "0.00"} B3
|
|
186
|
-
</div>
|
|
187
|
-
</div>
|
|
188
|
-
</div>
|
|
189
|
-
<div className="text-right">
|
|
190
|
-
<div className="text-b3-grey font-neue-montreal-semibold">
|
|
191
|
-
${b3Balance?.balanceUsdFormatted || "0.00"}
|
|
192
|
-
</div>
|
|
193
|
-
<div className="flex items-center gap-1">
|
|
194
|
-
{b3Balance?.priceChange24h !== null && b3Balance?.priceChange24h !== undefined ? (
|
|
195
|
-
<>
|
|
196
|
-
<Triangle
|
|
197
|
-
className={`size-3 ${b3Balance.priceChange24h >= 0 ? "text-b3-positive fill-b3-positive" : "text-b3-negative fill-b3-negative rotate-180"}`}
|
|
198
|
-
/>
|
|
199
|
-
<span
|
|
200
|
-
className={`font-neue-montreal-medium text-sm ${b3Balance.priceChange24h >= 0 ? "text-b3-positive" : "text-b3-negative"}`}
|
|
201
|
-
>
|
|
202
|
-
{b3Balance.priceChange24h >= 0 ? "+" : ""}
|
|
203
|
-
{b3Balance.priceChange24h.toFixed(2)}%
|
|
204
|
-
</span>
|
|
205
|
-
</>
|
|
206
|
-
) : (
|
|
207
|
-
<span className="text-b3-foreground-muted font-neue-montreal-medium text-sm">--</span>
|
|
208
|
-
)}
|
|
209
|
-
</div>
|
|
210
|
-
</div>
|
|
211
|
-
</div>
|
|
212
|
-
|
|
213
|
-
{/* ETH Balance */}
|
|
214
|
-
<div className="flex items-center justify-between">
|
|
215
|
-
<div className="flex items-center gap-3">
|
|
216
|
-
<div className="flex h-10 w-10 items-center justify-center rounded-full">
|
|
217
|
-
<img src="https://cdn.b3.fun/ethereum.svg" alt="ETH" className="size-10" />
|
|
218
|
-
</div>
|
|
219
|
-
<div>
|
|
220
|
-
<div className="flex items-center gap-2">
|
|
221
|
-
<span className="text-b3-grey font-neue-montreal-semibold">Ethereum</span>
|
|
222
|
-
</div>
|
|
223
|
-
<div className="text-b3-foreground-muted font-neue-montreal-medium text-sm">
|
|
224
|
-
{nativeBalance?.formattedTotal || "0.00"} ETH
|
|
225
|
-
</div>
|
|
226
|
-
</div>
|
|
227
|
-
</div>
|
|
228
|
-
<div className="text-right">
|
|
229
|
-
<div className="text-b3-grey font-neue-montreal-semibold">
|
|
230
|
-
${nativeBalance?.formattedTotalUsd || "0.00"}
|
|
231
|
-
</div>
|
|
232
|
-
<div className="flex items-center gap-2">
|
|
233
|
-
{nativeBalance?.priceChange24h !== null && nativeBalance?.priceChange24h !== undefined ? (
|
|
234
|
-
<>
|
|
235
|
-
<Triangle
|
|
236
|
-
className={`size-3 ${nativeBalance.priceChange24h >= 0 ? "text-b3-positive fill-b3-positive" : "text-b3-negative fill-b3-negative rotate-180"}`}
|
|
237
|
-
/>
|
|
238
|
-
<span
|
|
239
|
-
className={`font-neue-montreal-medium text-sm ${nativeBalance.priceChange24h >= 0 ? "text-b3-positive" : "text-b3-negative"}`}
|
|
240
|
-
>
|
|
241
|
-
{nativeBalance.priceChange24h >= 0 ? "+" : ""}
|
|
242
|
-
{nativeBalance.priceChange24h.toFixed(2)}%
|
|
243
|
-
</span>
|
|
244
|
-
</>
|
|
245
|
-
) : (
|
|
246
|
-
<span className="text-b3-foreground-muted font-neue-montreal-medium text-sm">--</span>
|
|
247
|
-
)}
|
|
248
|
-
</div>
|
|
249
|
-
</div>
|
|
250
|
-
</div>
|
|
251
|
-
</div>
|
|
252
|
-
|
|
253
|
-
{/* EOA Account Balance Section - matching global overview styling */}
|
|
254
|
-
{eoaAddress && (
|
|
255
|
-
<div className="space-y-4">
|
|
256
|
-
<div className="flex items-center gap-3">
|
|
257
|
-
<h3 className="text-b3-grey font-neue-montreal-semibold">Connected {eoaInfo?.data?.name || "Wallet"}</h3>
|
|
258
|
-
<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">
|
|
259
|
-
<span className="text-b3-foreground-muted font-mono text-xs">{centerTruncate(eoaAddress, 6)}</span>
|
|
260
|
-
<CopyToClipboard text={eoaAddress} />
|
|
261
|
-
</div>
|
|
262
|
-
</div>
|
|
263
|
-
|
|
264
|
-
{/* EOA B3 Balance */}
|
|
265
|
-
<div className="flex items-center justify-between">
|
|
266
|
-
<div className="flex items-center gap-3">
|
|
267
|
-
<div className="flex h-10 w-10 items-center justify-center rounded-full">
|
|
268
|
-
<img src="https://cdn.b3.fun/b3-coin-3d.png" alt="B3" className="size-10" />
|
|
269
|
-
</div>
|
|
270
|
-
<div>
|
|
271
|
-
<div className="flex items-center gap-2">
|
|
272
|
-
<span className="text-b3-grey font-neue-montreal-semibold">B3</span>
|
|
273
|
-
</div>
|
|
274
|
-
<div className="text-b3-foreground-muted font-neue-montreal-medium text-sm">
|
|
275
|
-
{eoaB3Balance?.formattedTotal || "0.00"} B3
|
|
276
|
-
</div>
|
|
277
|
-
</div>
|
|
278
|
-
</div>
|
|
279
|
-
<div className="text-right">
|
|
280
|
-
<div className="text-b3-grey font-neue-montreal-semibold">
|
|
281
|
-
${eoaB3Balance?.balanceUsdFormatted || "0.00"}
|
|
282
|
-
</div>
|
|
283
|
-
<div className="flex items-center gap-1">
|
|
284
|
-
{eoaB3Balance?.priceChange24h !== null && eoaB3Balance?.priceChange24h !== undefined ? (
|
|
285
|
-
<>
|
|
286
|
-
<Triangle
|
|
287
|
-
className={`size-3 ${eoaB3Balance.priceChange24h >= 0 ? "text-b3-positive fill-b3-positive" : "text-b3-negative fill-b3-negative rotate-180"}`}
|
|
288
|
-
/>
|
|
289
|
-
<span
|
|
290
|
-
className={`font-neue-montreal-medium text-sm ${eoaB3Balance.priceChange24h >= 0 ? "text-b3-positive" : "text-b3-negative"}`}
|
|
291
|
-
>
|
|
292
|
-
{eoaB3Balance.priceChange24h >= 0 ? "+" : ""}
|
|
293
|
-
{eoaB3Balance.priceChange24h.toFixed(2)}%
|
|
294
|
-
</span>
|
|
295
|
-
</>
|
|
296
|
-
) : (
|
|
297
|
-
<span className="text-b3-foreground-muted font-neue-montreal-medium text-sm">--</span>
|
|
298
|
-
)}
|
|
299
|
-
</div>
|
|
300
|
-
</div>
|
|
301
|
-
</div>
|
|
302
|
-
|
|
303
|
-
{/* EOA ETH Balance */}
|
|
304
|
-
<div className="flex items-center justify-between">
|
|
305
|
-
<div className="flex items-center gap-3">
|
|
306
|
-
<div className="flex h-10 w-10 items-center justify-center rounded-full">
|
|
307
|
-
<img src="https://cdn.b3.fun/ethereum.svg" alt="ETH" className="size-10" />
|
|
308
|
-
</div>
|
|
309
|
-
<div>
|
|
310
|
-
<div className="flex items-center gap-2">
|
|
311
|
-
<span className="text-b3-grey font-neue-montreal-semibold">Ethereum</span>
|
|
312
|
-
</div>
|
|
313
|
-
<div className="text-b3-foreground-muted font-neue-montreal-medium text-sm">
|
|
314
|
-
{eoaNativeBalance?.formattedTotal || "0.00"} ETH
|
|
315
|
-
</div>
|
|
316
|
-
</div>
|
|
317
|
-
</div>
|
|
318
|
-
<div className="text-right">
|
|
319
|
-
<div className="text-b3-grey font-neue-montreal-semibold">
|
|
320
|
-
${eoaNativeBalance?.formattedTotalUsd || "0.00"}
|
|
321
|
-
</div>
|
|
322
|
-
<div className="flex items-center gap-2">
|
|
323
|
-
{eoaNativeBalance?.priceChange24h !== null && eoaNativeBalance?.priceChange24h !== undefined ? (
|
|
324
|
-
<>
|
|
325
|
-
<Triangle
|
|
326
|
-
className={`size-3 ${eoaNativeBalance.priceChange24h >= 0 ? "text-b3-positive fill-b3-positive" : "text-b3-negative fill-b3-negative rotate-180"}`}
|
|
327
|
-
/>
|
|
328
|
-
<span
|
|
329
|
-
className={`font-neue-montreal-medium text-sm ${eoaNativeBalance.priceChange24h >= 0 ? "text-b3-positive" : "text-b3-negative"}`}
|
|
330
|
-
>
|
|
331
|
-
{eoaNativeBalance.priceChange24h >= 0 ? "+" : ""}
|
|
332
|
-
{eoaNativeBalance.priceChange24h.toFixed(2)}%
|
|
333
|
-
</span>
|
|
334
|
-
</>
|
|
335
|
-
) : (
|
|
336
|
-
<span className="text-b3-foreground-muted font-neue-montreal-medium text-sm">--</span>
|
|
337
|
-
)}
|
|
338
|
-
</div>
|
|
339
|
-
</div>
|
|
340
|
-
</div>
|
|
341
|
-
</div>
|
|
342
|
-
)}
|
|
343
|
-
|
|
344
|
-
{/* Global Account Info */}
|
|
345
|
-
<div className="border-b3-line flex items-center justify-between rounded-2xl border p-4">
|
|
346
|
-
<div className="">
|
|
347
|
-
<div className="flex items-center gap-2">
|
|
348
|
-
<img src="https://cdn.b3.fun/b3_logo.svg" alt="B3" className="h-4" />
|
|
349
|
-
<h3 className="font-neue-montreal-semibold text-b3-grey">Global Account</h3>
|
|
350
|
-
</div>
|
|
351
|
-
|
|
352
|
-
<p className="text-b3-foreground-muted font-neue-montreal-medium mt-2 text-sm">
|
|
353
|
-
Your universal account for all B3 apps
|
|
354
|
-
</p>
|
|
355
|
-
</div>
|
|
356
|
-
<button
|
|
357
|
-
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"
|
|
358
|
-
onClick={onLogoutEnhanced}
|
|
359
|
-
>
|
|
360
|
-
{logoutLoading ? <Loader2 className="animate-spin" /> : <SignOutIcon size={16} className="text-b3-grey" />}
|
|
361
|
-
</button>
|
|
362
|
-
</div>
|
|
363
|
-
</div>
|
|
364
|
-
);
|
|
365
|
-
};
|
|
366
|
-
|
|
367
89
|
const AppsContent = () => (
|
|
368
90
|
<div className="space-y-4">
|
|
369
91
|
{signers?.map((signer: TWSignerWithMetadata) => (
|
|
@@ -629,7 +351,7 @@ export function ManageAccount({
|
|
|
629
351
|
</div>
|
|
630
352
|
|
|
631
353
|
<TabsContentPrimitive value="overview" className="px-4 pb-4 pt-2">
|
|
632
|
-
<BalanceContent />
|
|
354
|
+
<BalanceContent onLogout={onLogout} partnerId={partnerId} />
|
|
633
355
|
</TabsContentPrimitive>
|
|
634
356
|
|
|
635
357
|
<TabsContentPrimitive value="tokens" className="px-4 pb-4 pt-2">
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { Triangle } from "lucide-react";
|
|
2
|
+
import { ReactNode } from "react";
|
|
3
|
+
|
|
4
|
+
interface TokenBalanceRowProps {
|
|
5
|
+
icon: ReactNode;
|
|
6
|
+
name: string;
|
|
7
|
+
balance: string;
|
|
8
|
+
usdValue: string;
|
|
9
|
+
priceChange?: number | null;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export function TokenBalanceRow({ icon, name, balance, usdValue, priceChange }: TokenBalanceRowProps) {
|
|
13
|
+
return (
|
|
14
|
+
<div className="flex items-center justify-between">
|
|
15
|
+
<div className="flex items-center gap-3">
|
|
16
|
+
<div className="flex h-10 w-10 items-center justify-center rounded-full">{icon}</div>
|
|
17
|
+
<div>
|
|
18
|
+
<div className="flex items-center gap-2">
|
|
19
|
+
<span className="text-b3-grey font-neue-montreal-semibold">{name}</span>
|
|
20
|
+
</div>
|
|
21
|
+
<div className="text-b3-foreground-muted font-neue-montreal-medium text-sm">{balance}</div>
|
|
22
|
+
</div>
|
|
23
|
+
</div>
|
|
24
|
+
<div className="text-right">
|
|
25
|
+
<div className="text-b3-grey font-neue-montreal-semibold">${usdValue}</div>
|
|
26
|
+
<div className="flex items-center gap-1">
|
|
27
|
+
{priceChange !== null && priceChange !== undefined ? (
|
|
28
|
+
<>
|
|
29
|
+
<Triangle
|
|
30
|
+
className={`size-3 ${priceChange >= 0 ? "text-b3-positive fill-b3-positive" : "text-b3-negative fill-b3-negative rotate-180"}`}
|
|
31
|
+
/>
|
|
32
|
+
<span
|
|
33
|
+
className={`font-neue-montreal-medium text-sm ${priceChange >= 0 ? "text-b3-positive" : "text-b3-negative"}`}
|
|
34
|
+
>
|
|
35
|
+
{priceChange >= 0 ? "+" : ""}
|
|
36
|
+
{priceChange.toFixed(2)}%
|
|
37
|
+
</span>
|
|
38
|
+
</>
|
|
39
|
+
) : (
|
|
40
|
+
<span className="text-b3-foreground-muted font-neue-montreal-medium text-sm">--</span>
|
|
41
|
+
)}
|
|
42
|
+
</div>
|
|
43
|
+
</div>
|
|
44
|
+
</div>
|
|
45
|
+
);
|
|
46
|
+
}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { cn } from "@b3dotfun/sdk/shared/utils";
|
|
2
|
+
import React, { useCallback, useMemo, useState } from "react";
|
|
3
|
+
|
|
4
|
+
interface TokenIconProps {
|
|
5
|
+
src: string;
|
|
6
|
+
alt: string;
|
|
7
|
+
className?: string;
|
|
8
|
+
size?: number;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
// Create a global image cache to prevent re-loading
|
|
12
|
+
const imageCache = new Map<string, boolean>();
|
|
13
|
+
|
|
14
|
+
export const TokenIcon: React.FC<TokenIconProps> = ({ src, alt, className, size = 40 }) => {
|
|
15
|
+
const [isLoaded, setIsLoaded] = useState(() => imageCache.get(src) || false);
|
|
16
|
+
const [hasError, setHasError] = useState(false);
|
|
17
|
+
|
|
18
|
+
const handleLoad = useCallback(() => {
|
|
19
|
+
imageCache.set(src, true);
|
|
20
|
+
setIsLoaded(true);
|
|
21
|
+
}, [src]);
|
|
22
|
+
|
|
23
|
+
const handleError = useCallback(() => {
|
|
24
|
+
setHasError(true);
|
|
25
|
+
}, []);
|
|
26
|
+
|
|
27
|
+
// Memoize the image element to prevent unnecessary re-renders
|
|
28
|
+
const imageElement = useMemo(
|
|
29
|
+
() => (
|
|
30
|
+
<img
|
|
31
|
+
src={src}
|
|
32
|
+
alt={alt}
|
|
33
|
+
className={cn("transition-opacity duration-200", className, {
|
|
34
|
+
"opacity-100": isLoaded && !hasError,
|
|
35
|
+
"opacity-0": !isLoaded || hasError,
|
|
36
|
+
})}
|
|
37
|
+
onLoad={handleLoad}
|
|
38
|
+
onError={handleError}
|
|
39
|
+
loading="eager" // Load immediately since these are critical UI elements
|
|
40
|
+
decoding="async"
|
|
41
|
+
style={{
|
|
42
|
+
width: size,
|
|
43
|
+
height: size,
|
|
44
|
+
}}
|
|
45
|
+
/>
|
|
46
|
+
),
|
|
47
|
+
[src, alt, className, isLoaded, hasError, handleLoad, handleError, size],
|
|
48
|
+
);
|
|
49
|
+
|
|
50
|
+
// Show a placeholder while loading or if there's an error
|
|
51
|
+
const placeholder = useMemo(
|
|
52
|
+
() => (
|
|
53
|
+
<div
|
|
54
|
+
className={cn(
|
|
55
|
+
"bg-b3-primary-wash flex items-center justify-center rounded-full transition-opacity duration-200",
|
|
56
|
+
{
|
|
57
|
+
"opacity-0": isLoaded && !hasError,
|
|
58
|
+
"opacity-100": !isLoaded || hasError,
|
|
59
|
+
},
|
|
60
|
+
)}
|
|
61
|
+
style={{
|
|
62
|
+
width: size,
|
|
63
|
+
height: size,
|
|
64
|
+
}}
|
|
65
|
+
>
|
|
66
|
+
<span className="text-b3-grey font-neue-montreal-semibold text-xs">{alt.charAt(0).toUpperCase()}</span>
|
|
67
|
+
</div>
|
|
68
|
+
),
|
|
69
|
+
[alt, isLoaded, hasError, size],
|
|
70
|
+
);
|
|
71
|
+
|
|
72
|
+
return (
|
|
73
|
+
<div className="relative inline-block" style={{ width: size, height: size }}>
|
|
74
|
+
{placeholder}
|
|
75
|
+
<div className="absolute inset-0">{imageElement}</div>
|
|
76
|
+
</div>
|
|
77
|
+
);
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
// Pre-defined token icons for common tokens
|
|
81
|
+
export const B3TokenIcon: React.FC<Omit<TokenIconProps, "src" | "alt">> = props => (
|
|
82
|
+
<TokenIcon src="https://cdn.b3.fun/b3-coin-3d.png" alt="B3" {...props} />
|
|
83
|
+
);
|
|
84
|
+
|
|
85
|
+
export const EthereumTokenIcon: React.FC<Omit<TokenIconProps, "src" | "alt">> = props => (
|
|
86
|
+
<TokenIcon src="https://cdn.b3.fun/ethereum.svg" alt="ETH" {...props} />
|
|
87
|
+
);
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import * as AccordionPrimitive from "@radix-ui/react-accordion";
|
|
4
|
+
import { ChevronDown } from "lucide-react";
|
|
5
|
+
import * as React from "react";
|
|
6
|
+
|
|
7
|
+
import { cn } from "@b3dotfun/sdk/shared/utils";
|
|
8
|
+
|
|
9
|
+
const Accordion = AccordionPrimitive.Root;
|
|
10
|
+
|
|
11
|
+
const AccordionItem = React.forwardRef<
|
|
12
|
+
React.ElementRef<typeof AccordionPrimitive.Item>,
|
|
13
|
+
React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Item>
|
|
14
|
+
>(({ className, ...props }, ref) => (
|
|
15
|
+
<AccordionPrimitive.Item ref={ref} className={cn("border-b3-line border-b", className)} {...props} />
|
|
16
|
+
));
|
|
17
|
+
AccordionItem.displayName = "AccordionItem";
|
|
18
|
+
|
|
19
|
+
const AccordionTrigger = React.forwardRef<
|
|
20
|
+
React.ElementRef<typeof AccordionPrimitive.Trigger>,
|
|
21
|
+
React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Trigger>
|
|
22
|
+
>(({ className, children, ...props }, ref) => (
|
|
23
|
+
<AccordionPrimitive.Header className="flex">
|
|
24
|
+
<AccordionPrimitive.Trigger
|
|
25
|
+
ref={ref}
|
|
26
|
+
className={cn(
|
|
27
|
+
"flex flex-1 items-center justify-between py-4 font-medium transition-all hover:underline [&[data-state=open]>svg]:rotate-180",
|
|
28
|
+
className,
|
|
29
|
+
)}
|
|
30
|
+
{...props}
|
|
31
|
+
>
|
|
32
|
+
{children}
|
|
33
|
+
<ChevronDown className="h-4 w-4 shrink-0 transition-transform duration-200" />
|
|
34
|
+
</AccordionPrimitive.Trigger>
|
|
35
|
+
</AccordionPrimitive.Header>
|
|
36
|
+
));
|
|
37
|
+
AccordionTrigger.displayName = AccordionPrimitive.Trigger.displayName;
|
|
38
|
+
|
|
39
|
+
const AccordionContent = React.forwardRef<
|
|
40
|
+
React.ElementRef<typeof AccordionPrimitive.Content>,
|
|
41
|
+
React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Content>
|
|
42
|
+
>(({ className, children, ...props }, ref) => (
|
|
43
|
+
<AccordionPrimitive.Content
|
|
44
|
+
ref={ref}
|
|
45
|
+
className="data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down overflow-hidden text-sm transition-all"
|
|
46
|
+
{...props}
|
|
47
|
+
>
|
|
48
|
+
<div className={cn("pb-4 pt-0", className)}>{children}</div>
|
|
49
|
+
</AccordionPrimitive.Content>
|
|
50
|
+
));
|
|
51
|
+
AccordionContent.displayName = AccordionPrimitive.Content.displayName;
|
|
52
|
+
|
|
53
|
+
export { Accordion, AccordionContent, AccordionItem, AccordionTrigger };
|
|
@@ -64,7 +64,7 @@ const DialogContent: React.ForwardRefExoticComponent<DialogContentProps & React.
|
|
|
64
64
|
{!hideCloseButton && (
|
|
65
65
|
<DialogPrimitive.Close
|
|
66
66
|
className={cn(
|
|
67
|
-
"data-[state=open]:bg-b3-react-background data-[state=open]:text-b3-react-muted-foreground absolute right-2 top-2 rounded-sm opacity-70 transition-opacity hover:opacity-100 focus:outline-none disabled:pointer-events-none dark:data-[state=open]:bg-gray-800 dark:data-[state=open]:text-gray-400",
|
|
67
|
+
"modal-close-button data-[state=open]:bg-b3-react-background data-[state=open]:text-b3-react-muted-foreground absolute right-2 top-2 rounded-sm opacity-70 transition-opacity hover:opacity-100 focus:outline-none disabled:pointer-events-none dark:data-[state=open]:bg-gray-800 dark:data-[state=open]:text-gray-400",
|
|
68
68
|
closeBtnClassName,
|
|
69
69
|
)}
|
|
70
70
|
>
|
|
@@ -46,7 +46,7 @@ async function fetchB3Balances(addresses: string[]): Promise<{
|
|
|
46
46
|
const balances = await Promise.all(
|
|
47
47
|
addresses.map(async address => {
|
|
48
48
|
const balance = await client.readContract({
|
|
49
|
-
address: B3_TOKEN.address
|
|
49
|
+
address: B3_TOKEN.address as `0x${string}`,
|
|
50
50
|
abi,
|
|
51
51
|
functionName: "balanceOf",
|
|
52
52
|
args: [address as `0x${string}`],
|
|
@@ -9,6 +9,7 @@ import { prepareTransaction, sendTransaction as twSendTransaction } from "thirdw
|
|
|
9
9
|
import { useSwitchChain, useWalletClient } from "wagmi";
|
|
10
10
|
import { useB3 } from "../components";
|
|
11
11
|
import { useAccountWallet } from "./useAccountWallet";
|
|
12
|
+
import { isAddress } from "viem";
|
|
12
13
|
|
|
13
14
|
export interface UnifiedTransactionParams {
|
|
14
15
|
to: string;
|
|
@@ -56,6 +57,8 @@ export function useUnifiedChainSwitchAndExecute() {
|
|
|
56
57
|
throw new Error(`Chain ${targetChainId} is not supported`);
|
|
57
58
|
}
|
|
58
59
|
|
|
60
|
+
invariant(isAddress(params.to), "params.to is not a valid address");
|
|
61
|
+
|
|
59
62
|
const hash = await walletClient.sendTransaction({
|
|
60
63
|
account: signer,
|
|
61
64
|
chain: targetChain,
|
package/dist/cjs/index.d.ts
DELETED
|
File without changes
|
package/dist/cjs/index.js
DELETED
package/dist/esm/index.d.ts
DELETED
|
File without changes
|
package/dist/esm/index.js
DELETED
package/dist/types/index.d.ts
DELETED
|
File without changes
|
package/src/index.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
//
|