@b3dotfun/sdk 0.1.0 → 0.1.1-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/AnySpend.js +1 -1
- package/dist/cjs/anyspend/react/components/AnySpendDeposit.d.ts +15 -10
- package/dist/cjs/anyspend/react/components/AnySpendDeposit.js +22 -14
- package/dist/cjs/anyspend/react/components/QRDeposit.js +31 -5
- package/dist/cjs/anyspend/react/components/common/CryptoPaymentMethod.js +9 -2
- package/dist/cjs/anyspend/react/components/common/GasIndicator.d.ts +1 -1
- package/dist/cjs/anyspend/react/components/common/GasIndicator.js +6 -16
- package/dist/cjs/anyspend/react/components/common/TokenBalance.js +15 -4
- package/dist/cjs/anyspend/react/components/common/TransferResultScreen.d.ts +22 -0
- package/dist/cjs/anyspend/react/components/common/TransferResultScreen.js +25 -0
- package/dist/cjs/anyspend/react/hooks/index.d.ts +1 -0
- package/dist/cjs/anyspend/react/hooks/index.js +1 -0
- package/dist/cjs/anyspend/react/hooks/useWatchTransfer.d.ts +41 -0
- package/dist/cjs/anyspend/react/hooks/useWatchTransfer.js +75 -0
- package/dist/cjs/anyspend/react/providers/AnyspendProvider.js +1 -2
- package/dist/cjs/anyspend/utils/address.d.ts +5 -0
- package/dist/cjs/anyspend/utils/address.js +8 -0
- package/dist/cjs/global-account/react/components/AccountAssets/AccountAssets.js +7 -3
- package/dist/cjs/global-account/react/components/B3DynamicModal.js +4 -14
- package/dist/cjs/global-account/react/components/B3Provider/B3ConfigProvider.d.ts +31 -0
- package/dist/cjs/global-account/react/components/B3Provider/B3ConfigProvider.js +37 -0
- package/dist/cjs/global-account/react/components/B3Provider/B3Provider.d.ts +2 -1
- package/dist/cjs/global-account/react/components/B3Provider/B3Provider.js +3 -31
- package/dist/cjs/global-account/react/components/B3Provider/B3Provider.native.js +4 -31
- package/dist/cjs/global-account/react/components/B3Provider/LocalSDKProvider.d.ts +3 -1
- package/dist/cjs/global-account/react/components/B3Provider/LocalSDKProvider.js +3 -1
- package/dist/cjs/global-account/react/components/B3Provider/useB3.d.ts +1 -12
- package/dist/cjs/global-account/react/components/B3Provider/useB3Config.d.ts +1 -17
- package/dist/cjs/global-account/react/components/B3Provider/useB3Config.js +2 -21
- package/dist/cjs/global-account/react/components/ManageAccount/NFTContent.js +2 -2
- package/dist/cjs/global-account/react/components/SignInWithB3/SignInWithB3Flow.js +12 -1
- package/dist/cjs/global-account/react/components/SingleUserSearchSelector/SingleUserSearchSelector.d.ts +64 -0
- package/dist/cjs/global-account/react/components/SingleUserSearchSelector/SingleUserSearchSelector.js +163 -0
- package/dist/cjs/global-account/react/components/SingleUserSearchSelector/index.d.ts +2 -0
- package/dist/cjs/global-account/react/components/SingleUserSearchSelector/index.js +5 -0
- package/dist/cjs/global-account/react/components/WalletImage/WalletImage.d.ts +1 -1
- package/dist/cjs/global-account/react/components/index.d.ts +2 -0
- package/dist/cjs/global-account/react/components/index.js +6 -3
- package/dist/cjs/global-account/react/hooks/index.d.ts +2 -1
- package/dist/cjs/global-account/react/hooks/index.js +5 -1
- package/dist/cjs/global-account/react/hooks/useAuthentication.js +5 -2
- package/dist/cjs/global-account/react/hooks/useProfile.js +4 -23
- package/dist/cjs/global-account/react/hooks/useSimBalance.d.ts +7 -0
- package/dist/cjs/global-account/react/hooks/useSimBalance.js +43 -11
- package/dist/cjs/global-account/react/hooks/useSimCollectibles.d.ts +45 -0
- package/dist/cjs/global-account/react/hooks/useSimCollectibles.js +190 -0
- package/dist/cjs/global-account/react/stores/index.d.ts +0 -1
- package/dist/cjs/global-account/react/stores/index.js +1 -3
- package/dist/cjs/global-account/react/stores/useModalStore.d.ts +63 -1
- package/dist/cjs/global-account/react/stores/useModalStore.js +3 -0
- package/dist/cjs/global-account/react/utils/profileApi.d.ts +13 -0
- package/dist/cjs/global-account/react/utils/profileApi.js +29 -0
- package/dist/cjs/global-account/react/utils/simdune.d.ts +7 -0
- package/dist/cjs/global-account/react/utils/simdune.js +21 -0
- package/dist/esm/anyspend/react/components/AnySpend.js +1 -1
- package/dist/esm/anyspend/react/components/AnySpendDeposit.d.ts +15 -10
- package/dist/esm/anyspend/react/components/AnySpendDeposit.js +23 -15
- package/dist/esm/anyspend/react/components/QRDeposit.js +32 -6
- package/dist/esm/anyspend/react/components/common/CryptoPaymentMethod.js +10 -3
- package/dist/esm/anyspend/react/components/common/GasIndicator.d.ts +1 -1
- package/dist/esm/anyspend/react/components/common/GasIndicator.js +7 -17
- package/dist/esm/anyspend/react/components/common/TokenBalance.js +16 -5
- package/dist/esm/anyspend/react/components/common/TransferResultScreen.d.ts +22 -0
- package/dist/esm/anyspend/react/components/common/TransferResultScreen.js +22 -0
- package/dist/esm/anyspend/react/hooks/index.d.ts +1 -0
- package/dist/esm/anyspend/react/hooks/index.js +1 -0
- package/dist/esm/anyspend/react/hooks/useWatchTransfer.d.ts +41 -0
- package/dist/esm/anyspend/react/hooks/useWatchTransfer.js +72 -0
- package/dist/esm/anyspend/react/providers/AnyspendProvider.js +1 -2
- package/dist/esm/anyspend/utils/address.d.ts +5 -0
- package/dist/esm/anyspend/utils/address.js +7 -0
- package/dist/esm/global-account/react/components/AccountAssets/AccountAssets.js +7 -3
- package/dist/esm/global-account/react/components/B3DynamicModal.js +5 -15
- package/dist/esm/global-account/react/components/B3Provider/B3ConfigProvider.d.ts +31 -0
- package/dist/esm/global-account/react/components/B3Provider/B3ConfigProvider.js +33 -0
- package/dist/esm/global-account/react/components/B3Provider/B3Provider.d.ts +2 -1
- package/dist/esm/global-account/react/components/B3Provider/B3Provider.js +3 -31
- package/dist/esm/global-account/react/components/B3Provider/B3Provider.native.js +3 -30
- package/dist/esm/global-account/react/components/B3Provider/LocalSDKProvider.d.ts +3 -1
- package/dist/esm/global-account/react/components/B3Provider/LocalSDKProvider.js +3 -1
- package/dist/esm/global-account/react/components/B3Provider/useB3.d.ts +1 -12
- package/dist/esm/global-account/react/components/B3Provider/useB3Config.d.ts +1 -17
- package/dist/esm/global-account/react/components/B3Provider/useB3Config.js +1 -20
- package/dist/esm/global-account/react/components/ManageAccount/NFTContent.js +3 -3
- package/dist/esm/global-account/react/components/SignInWithB3/SignInWithB3Flow.js +13 -2
- package/dist/esm/global-account/react/components/SingleUserSearchSelector/SingleUserSearchSelector.d.ts +64 -0
- package/dist/esm/global-account/react/components/SingleUserSearchSelector/SingleUserSearchSelector.js +160 -0
- package/dist/esm/global-account/react/components/SingleUserSearchSelector/index.d.ts +2 -0
- package/dist/esm/global-account/react/components/SingleUserSearchSelector/index.js +1 -0
- package/dist/esm/global-account/react/components/WalletImage/WalletImage.d.ts +1 -1
- package/dist/esm/global-account/react/components/index.d.ts +2 -0
- package/dist/esm/global-account/react/components/index.js +2 -0
- package/dist/esm/global-account/react/hooks/index.d.ts +2 -1
- package/dist/esm/global-account/react/hooks/index.js +2 -1
- package/dist/esm/global-account/react/hooks/useAuthentication.js +5 -2
- package/dist/esm/global-account/react/hooks/useProfile.js +1 -20
- package/dist/esm/global-account/react/hooks/useSimBalance.d.ts +7 -0
- package/dist/esm/global-account/react/hooks/useSimBalance.js +42 -11
- package/dist/esm/global-account/react/hooks/useSimCollectibles.d.ts +45 -0
- package/dist/esm/global-account/react/hooks/useSimCollectibles.js +187 -0
- package/dist/esm/global-account/react/stores/index.d.ts +0 -1
- package/dist/esm/global-account/react/stores/index.js +0 -1
- package/dist/esm/global-account/react/stores/useModalStore.d.ts +63 -1
- package/dist/esm/global-account/react/stores/useModalStore.js +3 -0
- package/dist/esm/global-account/react/utils/profileApi.d.ts +13 -0
- package/dist/esm/global-account/react/utils/profileApi.js +25 -0
- package/dist/esm/global-account/react/utils/simdune.d.ts +7 -0
- package/dist/esm/global-account/react/utils/simdune.js +17 -0
- package/dist/styles/index.css +1 -1
- package/dist/types/anyspend/react/components/AnySpendDeposit.d.ts +15 -10
- package/dist/types/anyspend/react/components/common/GasIndicator.d.ts +1 -1
- package/dist/types/anyspend/react/components/common/TransferResultScreen.d.ts +22 -0
- package/dist/types/anyspend/react/hooks/index.d.ts +1 -0
- package/dist/types/anyspend/react/hooks/useWatchTransfer.d.ts +41 -0
- package/dist/types/anyspend/utils/address.d.ts +5 -0
- package/dist/types/global-account/react/components/B3Provider/B3ConfigProvider.d.ts +31 -0
- package/dist/types/global-account/react/components/B3Provider/B3Provider.d.ts +2 -1
- package/dist/types/global-account/react/components/B3Provider/LocalSDKProvider.d.ts +3 -1
- package/dist/types/global-account/react/components/B3Provider/useB3.d.ts +1 -12
- package/dist/types/global-account/react/components/B3Provider/useB3Config.d.ts +1 -17
- package/dist/types/global-account/react/components/SingleUserSearchSelector/SingleUserSearchSelector.d.ts +64 -0
- package/dist/types/global-account/react/components/SingleUserSearchSelector/index.d.ts +2 -0
- package/dist/types/global-account/react/components/WalletImage/WalletImage.d.ts +1 -1
- package/dist/types/global-account/react/components/index.d.ts +2 -0
- package/dist/types/global-account/react/hooks/index.d.ts +2 -1
- package/dist/types/global-account/react/hooks/useSimBalance.d.ts +7 -0
- package/dist/types/global-account/react/hooks/useSimCollectibles.d.ts +45 -0
- package/dist/types/global-account/react/stores/index.d.ts +0 -1
- package/dist/types/global-account/react/stores/useModalStore.d.ts +63 -1
- package/dist/types/global-account/react/utils/profileApi.d.ts +13 -0
- package/dist/types/global-account/react/utils/simdune.d.ts +7 -0
- package/package.json +6 -1
- package/src/anyspend/react/components/AnySpend.tsx +1 -0
- package/src/anyspend/react/components/AnySpendDeposit.tsx +60 -42
- package/src/anyspend/react/components/QRDeposit.tsx +57 -5
- package/src/anyspend/react/components/common/CryptoPaymentMethod.tsx +13 -3
- package/src/anyspend/react/components/common/GasIndicator.tsx +11 -30
- package/src/anyspend/react/components/common/TokenBalance.tsx +17 -5
- package/src/anyspend/react/components/common/TransferResultScreen.tsx +107 -0
- package/src/anyspend/react/hooks/index.ts +1 -0
- package/src/anyspend/react/hooks/useWatchTransfer.ts +114 -0
- package/src/anyspend/react/providers/AnyspendProvider.tsx +2 -5
- package/src/anyspend/utils/address.ts +13 -0
- package/src/global-account/react/components/AccountAssets/AccountAssets.tsx +25 -13
- package/src/global-account/react/components/B3DynamicModal.tsx +5 -17
- package/src/global-account/react/components/B3Provider/B3ConfigProvider.tsx +84 -0
- package/src/global-account/react/components/B3Provider/B3Provider.native.tsx +28 -36
- package/src/global-account/react/components/B3Provider/B3Provider.tsx +24 -39
- package/src/global-account/react/components/B3Provider/LocalSDKProvider.tsx +5 -0
- package/src/global-account/react/components/B3Provider/useB3Config.ts +1 -21
- package/src/global-account/react/components/ManageAccount/NFTContent.tsx +4 -4
- package/src/global-account/react/components/SignInWithB3/SignInWithB3Flow.tsx +13 -2
- package/src/global-account/react/components/SingleUserSearchSelector/README.md +266 -0
- package/src/global-account/react/components/SingleUserSearchSelector/SingleUserSearchSelector.tsx +330 -0
- package/src/global-account/react/components/SingleUserSearchSelector/index.ts +2 -0
- package/src/global-account/react/components/index.ts +7 -0
- package/src/global-account/react/hooks/index.ts +2 -1
- package/src/global-account/react/hooks/useAuthentication.ts +6 -2
- package/src/global-account/react/hooks/useProfile.ts +1 -32
- package/src/global-account/react/hooks/useSimBalance.ts +49 -12
- package/src/global-account/react/hooks/useSimCollectibles.ts +238 -0
- package/src/global-account/react/stores/index.ts +0 -1
- package/src/global-account/react/stores/useModalStore.ts +67 -1
- package/src/global-account/react/utils/profileApi.ts +38 -0
- package/src/global-account/react/utils/simdune.ts +20 -0
- package/dist/cjs/global-account/react/stores/configStore.d.ts +0 -24
- package/dist/cjs/global-account/react/stores/configStore.js +0 -30
- package/dist/esm/global-account/react/stores/configStore.d.ts +0 -24
- package/dist/esm/global-account/react/stores/configStore.js +0 -27
- package/dist/types/global-account/react/stores/configStore.d.ts +0 -24
- package/src/global-account/react/stores/configStore.ts +0 -51
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { ALL_CHAINS, getAvailableChainIds } from "../../../anyspend/index.js";
|
|
2
|
+
import { ALL_CHAINS, getAvailableChainIds, isSameChainAndToken } from "../../../anyspend/index.js";
|
|
3
3
|
import { Button, toast } from "../../../global-account/react/index.js";
|
|
4
4
|
import { cn } from "../../../shared/utils/cn.js";
|
|
5
5
|
import { TokenSelector } from "@relayprotocol/relay-kit-ui";
|
|
@@ -8,8 +8,10 @@ import { QRCodeSVG } from "qrcode.react";
|
|
|
8
8
|
import { useEffect, useRef, useState } from "react";
|
|
9
9
|
import { useAnyspendOrderAndTransactions } from "../hooks/useAnyspendOrderAndTransactions.js";
|
|
10
10
|
import { useCreateDepositFirstOrder } from "../hooks/useCreateDepositFirstOrder.js";
|
|
11
|
+
import { useWatchTransfer } from "../hooks/useWatchTransfer.js";
|
|
11
12
|
import { ChainTokenIcon } from "./common/ChainTokenIcon.js";
|
|
12
13
|
import { OrderDetails } from "./common/OrderDetails.js";
|
|
14
|
+
import { TransferResultScreen } from "./common/TransferResultScreen.js";
|
|
13
15
|
import { ChainWarningText, WarningText } from "./common/WarningText.js";
|
|
14
16
|
// Default source token: ETH on Base
|
|
15
17
|
const DEFAULT_ETH_ON_BASE = {
|
|
@@ -42,9 +44,24 @@ export function QRDeposit({ mode = "modal", recipientAddress, sourceToken: sourc
|
|
|
42
44
|
const [globalAddress, setGlobalAddress] = useState();
|
|
43
45
|
const orderCreatedRef = useRef(false);
|
|
44
46
|
const onSuccessCalled = useRef(false);
|
|
47
|
+
const [transferResult, setTransferResult] = useState(null);
|
|
45
48
|
// Source token/chain as state (can be changed by user)
|
|
46
49
|
const [sourceChainId, setSourceChainId] = useState(sourceChainIdProp ?? 8453);
|
|
47
50
|
const [sourceToken, setSourceToken] = useState(sourceTokenProp ?? DEFAULT_ETH_ON_BASE);
|
|
51
|
+
// Check if this is a pure transfer (same chain and token)
|
|
52
|
+
const isPureTransfer = isSameChainAndToken(sourceChainId, sourceToken.address, destinationChainId, destinationToken.address);
|
|
53
|
+
// Watch for pure transfers (same chain and token)
|
|
54
|
+
const { isWatching: isWatchingTransfer } = useWatchTransfer({
|
|
55
|
+
address: recipientAddress,
|
|
56
|
+
chainId: sourceChainId,
|
|
57
|
+
tokenAddress: sourceToken.address,
|
|
58
|
+
tokenDecimals: sourceToken.decimals,
|
|
59
|
+
enabled: isPureTransfer && !transferResult,
|
|
60
|
+
onTransferDetected: result => {
|
|
61
|
+
setTransferResult(result);
|
|
62
|
+
onSuccess?.();
|
|
63
|
+
},
|
|
64
|
+
});
|
|
48
65
|
// Handle token selection from TokenSelector
|
|
49
66
|
const handleTokenSelect = (newToken) => {
|
|
50
67
|
const token = {
|
|
@@ -59,6 +76,7 @@ export function QRDeposit({ mode = "modal", recipientAddress, sourceToken: sourc
|
|
|
59
76
|
setOrderId(undefined);
|
|
60
77
|
setGlobalAddress(undefined);
|
|
61
78
|
orderCreatedRef.current = false;
|
|
79
|
+
setTransferResult(null);
|
|
62
80
|
// Update token and chain
|
|
63
81
|
setSourceChainId(newToken.chainId);
|
|
64
82
|
setSourceToken(token);
|
|
@@ -79,10 +97,12 @@ export function QRDeposit({ mode = "modal", recipientAddress, sourceToken: sourc
|
|
|
79
97
|
});
|
|
80
98
|
// Fetch order status
|
|
81
99
|
const { orderAndTransactions: oat } = useAnyspendOrderAndTransactions(orderId);
|
|
82
|
-
// Create order on mount
|
|
100
|
+
// Create order on mount (skip for pure transfers)
|
|
83
101
|
useEffect(() => {
|
|
84
102
|
if (orderCreatedRef.current)
|
|
85
103
|
return;
|
|
104
|
+
if (isPureTransfer)
|
|
105
|
+
return; // Skip order creation for pure transfers
|
|
86
106
|
orderCreatedRef.current = true;
|
|
87
107
|
createOrder({
|
|
88
108
|
recipientAddress,
|
|
@@ -102,6 +122,7 @@ export function QRDeposit({ mode = "modal", recipientAddress, sourceToken: sourc
|
|
|
102
122
|
creatorAddress,
|
|
103
123
|
depositContractConfig,
|
|
104
124
|
createOrder,
|
|
125
|
+
isPureTransfer,
|
|
105
126
|
]);
|
|
106
127
|
// Call onSuccess when order is executed
|
|
107
128
|
useEffect(() => {
|
|
@@ -115,7 +136,8 @@ export function QRDeposit({ mode = "modal", recipientAddress, sourceToken: sourc
|
|
|
115
136
|
useEffect(() => {
|
|
116
137
|
onSuccessCalled.current = false;
|
|
117
138
|
}, [orderId]);
|
|
118
|
-
|
|
139
|
+
// For pure transfers, always use recipient address; for orders, use global address
|
|
140
|
+
const displayAddress = isPureTransfer ? recipientAddress : globalAddress || recipientAddress;
|
|
119
141
|
const handleCopyAddress = async () => {
|
|
120
142
|
if (displayAddress) {
|
|
121
143
|
await navigator.clipboard.writeText(displayAddress);
|
|
@@ -131,13 +153,17 @@ export function QRDeposit({ mode = "modal", recipientAddress, sourceToken: sourc
|
|
|
131
153
|
setCopied(false);
|
|
132
154
|
onClose?.();
|
|
133
155
|
};
|
|
156
|
+
// Show transfer result screen for completed pure transfers
|
|
157
|
+
if (isPureTransfer && transferResult) {
|
|
158
|
+
return (_jsx(TransferResultScreen, { mode: mode, transferResult: transferResult, token: sourceToken, chainId: sourceChainId, recipientAddress: recipientAddress, onBack: onBack, onClose: onClose }));
|
|
159
|
+
}
|
|
134
160
|
// Show order details if order has deposits or is being processed
|
|
135
161
|
if (oat?.data && oat.data.depositTxs && oat.data.depositTxs.length > 0) {
|
|
136
162
|
return (_jsx("div", { className: cn("anyspend-container anyspend-qr-order-details font-inter bg-as-surface-primary mx-auto w-full max-w-[460px] p-6", mode === "page" && "border-as-border-secondary overflow-hidden rounded-2xl border shadow-xl"), children: _jsx("div", { className: "anyspend-qr-order-details-content relative flex flex-col gap-4", children: _jsx(OrderDetails, { mode: mode, order: oat.data.order, depositTxs: oat.data.depositTxs, relayTxs: oat.data.relayTxs, executeTx: oat.data.executeTx, refundTxs: oat.data.refundTxs, onBack: handleBack }) }) }));
|
|
137
163
|
}
|
|
138
|
-
// Show loading state while creating order (but not if we already have an orderId)
|
|
139
|
-
if (isCreatingOrder && !orderId) {
|
|
164
|
+
// Show loading state while creating order (but not if we already have an orderId or for pure transfers)
|
|
165
|
+
if (isCreatingOrder && !orderId && !isPureTransfer) {
|
|
140
166
|
return (_jsx("div", { className: cn("anyspend-container anyspend-qr-loading font-inter bg-as-surface-primary mx-auto w-full max-w-[460px] p-6", mode === "page" && "border-as-border-secondary overflow-hidden rounded-2xl border shadow-xl"), children: _jsxs("div", { className: "anyspend-qr-loading-content flex flex-col items-center justify-center gap-4 py-12", children: [_jsx(Loader2, { className: "anyspend-qr-loading-spinner text-as-brand h-8 w-8 animate-spin" }), _jsx("p", { className: "anyspend-qr-loading-text text-as-secondary text-sm", children: "Creating deposit order..." })] }) }));
|
|
141
167
|
}
|
|
142
|
-
return (_jsx("div", { className: cn("anyspend-container anyspend-qr-deposit font-inter bg-as-surface-primary mx-auto w-full max-w-[460px] p-6", mode === "page" && "border-as-border-secondary overflow-hidden rounded-2xl border shadow-xl"), children: _jsxs("div", { className: "anyspend-qr-deposit-content flex flex-col gap-4", children: [_jsxs("div", { className: "anyspend-qr-header flex items-center justify-between", children: [_jsx("button", { onClick: handleBack, className: "anyspend-qr-back-button text-as-secondary hover:text-as-primary", children: _jsx("svg", { className: "h-5 w-5", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M15 19l-7-7 7-7" }) }) }), _jsx("h2", { className: "anyspend-qr-title text-as-primary text-base font-semibold", children: "Deposit" }), onClose ? (_jsx("button", { onClick: handleClose, className: "anyspend-qr-close-button text-as-secondary hover:text-as-primary", children: _jsx("svg", { className: "h-5 w-5", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M6 18L18 6M6 6l12 12" }) }) })) : (_jsx("div", { className: "w-5" }))] }), _jsxs("div", { className: "anyspend-qr-token-selector flex flex-col gap-1.5", children: [_jsx("label", { className: "anyspend-qr-token-label text-as-secondary text-sm", children: "Send" }), _jsx(TokenSelector, { chainIdsFilter: getAvailableChainIds("from"), context: "from", fromChainWalletVMSupported: true, isValidAddress: true, lockedChainIds: getAvailableChainIds("from"), multiWalletSupportEnabled: true, onAnalyticEvent: undefined, setToken: handleTokenSelect, supportedWalletVMs: ["evm"], token: undefined, trigger: _jsxs(Button, { variant: "outline", role: "combobox", className: "anyspend-qr-token-trigger border-as-stroke bg-as-surface-secondary flex h-auto w-full items-center justify-between gap-2 rounded-xl border px-3 py-2.5", children: [_jsxs("div", { className: "flex items-center gap-2", children: [sourceToken.metadata?.logoURI ? (_jsx(ChainTokenIcon, { chainUrl: ALL_CHAINS[sourceChainId]?.logoUrl, tokenUrl: sourceToken.metadata.logoURI, className: "h-8 min-h-8 w-8 min-w-8" })) : (_jsx("div", { className: "h-8 w-8 rounded-full bg-gray-700" })), _jsxs("div", { className: "flex flex-col items-start gap-0", children: [_jsx("div", { className: "text-as-primary font-semibold", children: sourceToken.symbol }), _jsx("div", { className: "text-as-primary/70 text-xs", children: ALL_CHAINS[sourceChainId]?.name ?? "Unknown" })] })] }), _jsx(ChevronsUpDown, { className: "h-4 w-4 shrink-0 opacity-70" })] }) })] }), _jsxs("div", { className: "anyspend-qr-content border-as-stroke flex items-start gap-4 rounded-xl border p-4", children: [_jsxs("div", { className: "anyspend-qr-code-container flex flex-col items-center gap-2", children: [_jsx("div", { className: "anyspend-qr-code rounded-lg bg-white p-2", children: _jsx(QRCodeSVG, { value: displayAddress, size: 120, level: "M", marginSize: 0 }) }), _jsxs("span", { className: "anyspend-qr-scan-hint text-as-secondary text-xs", children: ["SCAN WITH ", _jsx("span", { className: "inline-block", children: "\uD83E\uDD8A" })] })] }), _jsxs("div", { className: "anyspend-qr-address-container flex flex-1 flex-col gap-1", children: [_jsx("span", { className: "anyspend-qr-address-label text-as-secondary text-sm", children: "Deposit address:" }), _jsxs("div", { className: "anyspend-qr-address-row flex items-start gap-1", children: [_jsx("span", { className: "anyspend-qr-address text-as-primary break-all font-mono text-sm leading-relaxed", children: displayAddress }), _jsx("button", { onClick: handleCopyAddress, className: "anyspend-qr-copy-icon text-as-secondary hover:text-as-primary mt-0.5 shrink-0", children: copied ? _jsx(Check, { className: "h-4 w-4" }) : _jsx(Copy, { className: "h-4 w-4" }) })] })] })] }), _jsx(ChainWarningText, { chainId: destinationChainId }), _jsxs(WarningText, { children: ["Only send ", sourceToken.symbol, " on ", ALL_CHAINS[sourceChainId]?.name ?? "the specified chain", ". Other tokens will not be converted."] }), _jsx("button", { onClick: handleCopyAddress, className: "anyspend-qr-copy-button flex w-full items-center justify-center gap-2 rounded-xl bg-blue-500 py-3.5 font-medium text-white transition-all hover:bg-blue-600", children: "Copy deposit address" })] }) }));
|
|
168
|
+
return (_jsx("div", { className: cn("anyspend-container anyspend-qr-deposit font-inter bg-as-surface-primary mx-auto w-full max-w-[460px] p-6", mode === "page" && "border-as-border-secondary overflow-hidden rounded-2xl border shadow-xl"), children: _jsxs("div", { className: "anyspend-qr-deposit-content flex flex-col gap-4", children: [_jsxs("div", { className: "anyspend-qr-header flex items-center justify-between", children: [_jsx("button", { onClick: handleBack, className: "anyspend-qr-back-button text-as-secondary hover:text-as-primary", children: _jsx("svg", { className: "h-5 w-5", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M15 19l-7-7 7-7" }) }) }), _jsx("h2", { className: "anyspend-qr-title text-as-primary text-base font-semibold", children: "Deposit" }), onClose ? (_jsx("button", { onClick: handleClose, className: "anyspend-qr-close-button text-as-secondary hover:text-as-primary", children: _jsx("svg", { className: "h-5 w-5", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M6 18L18 6M6 6l12 12" }) }) })) : (_jsx("div", { className: "w-5" }))] }), _jsxs("div", { className: "anyspend-qr-token-selector flex flex-col gap-1.5", children: [_jsx("label", { className: "anyspend-qr-token-label text-as-secondary text-sm", children: "Send" }), _jsx(TokenSelector, { chainIdsFilter: getAvailableChainIds("from"), context: "from", fromChainWalletVMSupported: true, isValidAddress: true, lockedChainIds: getAvailableChainIds("from"), multiWalletSupportEnabled: true, onAnalyticEvent: undefined, setToken: handleTokenSelect, supportedWalletVMs: ["evm"], token: undefined, trigger: _jsxs(Button, { variant: "outline", role: "combobox", className: "anyspend-qr-token-trigger border-as-stroke bg-as-surface-secondary flex h-auto w-full items-center justify-between gap-2 rounded-xl border px-3 py-2.5", children: [_jsxs("div", { className: "flex items-center gap-2", children: [sourceToken.metadata?.logoURI ? (_jsx(ChainTokenIcon, { chainUrl: ALL_CHAINS[sourceChainId]?.logoUrl, tokenUrl: sourceToken.metadata.logoURI, className: "h-8 min-h-8 w-8 min-w-8" })) : (_jsx("div", { className: "h-8 w-8 rounded-full bg-gray-700" })), _jsxs("div", { className: "flex flex-col items-start gap-0", children: [_jsx("div", { className: "text-as-primary font-semibold", children: sourceToken.symbol }), _jsx("div", { className: "text-as-primary/70 text-xs", children: ALL_CHAINS[sourceChainId]?.name ?? "Unknown" })] })] }), _jsx(ChevronsUpDown, { className: "h-4 w-4 shrink-0 opacity-70" })] }) })] }), _jsxs("div", { className: "anyspend-qr-content border-as-stroke flex items-start gap-4 rounded-xl border p-4", children: [_jsxs("div", { className: "anyspend-qr-code-container flex flex-col items-center gap-2", children: [_jsx("div", { className: "anyspend-qr-code rounded-lg bg-white p-2", children: _jsx(QRCodeSVG, { value: displayAddress, size: 120, level: "M", marginSize: 0 }) }), _jsxs("span", { className: "anyspend-qr-scan-hint text-as-secondary text-xs", children: ["SCAN WITH ", _jsx("span", { className: "inline-block", children: "\uD83E\uDD8A" })] })] }), _jsxs("div", { className: "anyspend-qr-address-container flex flex-1 flex-col gap-1", children: [_jsx("span", { className: "anyspend-qr-address-label text-as-secondary text-sm", children: "Deposit address:" }), _jsxs("div", { className: "anyspend-qr-address-row flex items-start gap-1", children: [_jsx("span", { className: "anyspend-qr-address text-as-primary break-all font-mono text-sm leading-relaxed", children: displayAddress }), _jsx("button", { onClick: handleCopyAddress, className: "anyspend-qr-copy-icon text-as-secondary hover:text-as-primary mt-0.5 shrink-0", children: copied ? _jsx(Check, { className: "h-4 w-4" }) : _jsx(Copy, { className: "h-4 w-4" }) })] })] })] }), _jsx(ChainWarningText, { chainId: destinationChainId }), _jsxs(WarningText, { children: ["Only send ", sourceToken.symbol, " on ", ALL_CHAINS[sourceChainId]?.name ?? "the specified chain", ". Other tokens will not be converted."] }), isPureTransfer && isWatchingTransfer && (_jsxs("div", { className: "anyspend-qr-watching flex items-center justify-center gap-2 rounded-lg bg-blue-500/10 p-3", children: [_jsx(Loader2, { className: "h-4 w-4 animate-spin text-blue-500" }), _jsx("span", { className: "text-sm text-blue-500", children: "Watching for incoming transfer..." })] })), _jsx("button", { onClick: handleCopyAddress, className: "anyspend-qr-copy-button flex w-full items-center justify-center gap-2 rounded-xl bg-blue-500 py-3.5 font-medium text-white transition-all hover:bg-blue-600", children: "Copy deposit address" })] }) }));
|
|
143
169
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
-
import { toast, useAccountWallet, WalletImage } from "../../../../global-account/react/index.js";
|
|
3
|
+
import { toast, useAccountWallet, useModalStore, WalletImage } from "../../../../global-account/react/index.js";
|
|
4
4
|
import { cn } from "../../../../shared/utils/cn.js";
|
|
5
5
|
import { shortenAddress } from "../../../../shared/utils/formatAddress.js";
|
|
6
6
|
import { client } from "../../../../shared/utils/thirdweb.js";
|
|
@@ -29,12 +29,16 @@ export function CryptoPaymentMethod({ selectedPaymentMethod, setSelectedPaymentM
|
|
|
29
29
|
const globalAddress = connectedSmartWallet?.getAccount()?.address;
|
|
30
30
|
// Use custom hook to determine wallet display logic
|
|
31
31
|
const { shouldShowConnectedEOA } = useConnectedWalletDisplay(selectedPaymentMethod);
|
|
32
|
+
// Get modal store to block parent modal closing while connect modal is open
|
|
33
|
+
const setClosable = useModalStore(state => state.setClosable);
|
|
32
34
|
// Handle wallet connection using thirdweb modal
|
|
33
35
|
const handleConnectWallet = async () => {
|
|
36
|
+
// Block parent B3 modal from closing while thirdweb connect modal is open
|
|
37
|
+
setClosable(false);
|
|
34
38
|
try {
|
|
35
39
|
// Disconnect current wallet before connecting a new one
|
|
36
40
|
if (connectedEOAWallet) {
|
|
37
|
-
|
|
41
|
+
disconnect(connectedEOAWallet);
|
|
38
42
|
}
|
|
39
43
|
const wallet = await openConnectModal({
|
|
40
44
|
client,
|
|
@@ -44,7 +48,6 @@ export function CryptoPaymentMethod({ selectedPaymentMethod, setSelectedPaymentM
|
|
|
44
48
|
wallets: recommendWallets,
|
|
45
49
|
});
|
|
46
50
|
if (wallet) {
|
|
47
|
-
// setActiveWallet(wallet);
|
|
48
51
|
setSelectedPaymentMethod(CryptoPaymentMethodType.CONNECT_WALLET);
|
|
49
52
|
onSelectPaymentMethod(CryptoPaymentMethodType.CONNECT_WALLET);
|
|
50
53
|
toast.success("Wallet connected");
|
|
@@ -64,6 +67,10 @@ export function CryptoPaymentMethod({ selectedPaymentMethod, setSelectedPaymentM
|
|
|
64
67
|
}
|
|
65
68
|
}
|
|
66
69
|
}
|
|
70
|
+
finally {
|
|
71
|
+
// Always re-enable parent modal closing when connect modal closes
|
|
72
|
+
setClosable(true);
|
|
73
|
+
}
|
|
67
74
|
};
|
|
68
75
|
return (_jsx("div", { className: "crypto-payment-method mx-auto h-fit w-[460px] max-w-full px-5 pb-5 pt-5 sm:px-0 sm:pt-5", children: _jsxs("div", { className: cn("relative flex flex-col gap-10"), children: [_jsx("button", { onClick: onBack, className: "text-as-quaternary hover:text-as-primary absolute flex h-8 w-8 items-center justify-center rounded-lg transition-colors", children: _jsx(ChevronLeft, { className: "h-6 w-6" }) }), _jsx("div", { className: "flex items-center justify-around gap-4", children: _jsx("div", { className: "flex-1 text-center", children: _jsx("h2", { className: "text-as-primary text-lg font-semibold", children: "Select a payment method" }) }) }), process.env.NODE_ENV === "development" && (_jsxs("div", { className: "rounded-lg border border-yellow-500/50 bg-yellow-50 p-3 dark:bg-yellow-950/20", children: [_jsx("p", { className: "mb-2 text-xs font-semibold text-yellow-800 dark:text-yellow-300", children: "\uD83E\uDDEA Toast Test (Dev Only)" }), _jsxs("div", { className: "flex flex-wrap gap-2", children: [_jsx("button", { onClick: () => toast.success("Success! Transaction completed"), className: "rounded bg-green-600 px-2 py-1 text-xs font-medium text-white hover:bg-green-700", children: "Success" }), _jsx("button", { onClick: () => toast.error("Error! Transaction failed"), className: "rounded bg-red-600 px-2 py-1 text-xs font-medium text-white hover:bg-red-700", children: "Error" }), _jsx("button", { onClick: () => toast.info("Info: Processing your request..."), className: "rounded bg-blue-600 px-2 py-1 text-xs font-medium text-white hover:bg-blue-700", children: "Info" }), _jsx("button", { onClick: () => toast.warning("Warning: Low balance detected"), className: "rounded bg-yellow-600 px-2 py-1 text-xs font-medium text-white hover:bg-yellow-700", children: "Warning" }), _jsx("button", { onClick: () => {
|
|
69
76
|
toast.success("Multiple test 1");
|
|
@@ -3,4 +3,4 @@ export interface GasIndicatorProps {
|
|
|
3
3
|
gasPrice: GasPriceData;
|
|
4
4
|
className?: string;
|
|
5
5
|
}
|
|
6
|
-
export declare function GasIndicator({ gasPrice, className }: GasIndicatorProps): import("react/jsx-runtime").JSX.Element;
|
|
6
|
+
export declare function GasIndicator({ gasPrice, className }: GasIndicatorProps): import("react/jsx-runtime").JSX.Element | null;
|
|
@@ -1,22 +1,8 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import {
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
3
|
import { cn } from "../../../../shared/utils/cn.js";
|
|
4
4
|
import { motion } from "motion/react";
|
|
5
|
-
|
|
6
|
-
low: "Low",
|
|
7
|
-
normal: "Normal",
|
|
8
|
-
elevated: "Elevated",
|
|
9
|
-
high: "High",
|
|
10
|
-
spike: "Spike",
|
|
11
|
-
};
|
|
12
|
-
const LEVEL_STYLES = {
|
|
13
|
-
low: "bg-green-500/20 text-green-500",
|
|
14
|
-
normal: "bg-as-surface-tertiary text-as-secondary",
|
|
15
|
-
elevated: "bg-yellow-500/20 text-yellow-600",
|
|
16
|
-
high: "bg-orange-500/20 text-orange-500",
|
|
17
|
-
spike: "bg-red-500/20 text-red-500",
|
|
18
|
-
};
|
|
19
|
-
function formatGasPrice(gweiString) {
|
|
5
|
+
function formatGwei(gweiString) {
|
|
20
6
|
const gwei = parseFloat(gweiString);
|
|
21
7
|
if (gwei < 0.001)
|
|
22
8
|
return "<0.001";
|
|
@@ -27,5 +13,9 @@ function formatGasPrice(gweiString) {
|
|
|
27
13
|
return gwei.toFixed(1);
|
|
28
14
|
}
|
|
29
15
|
export function GasIndicator({ gasPrice, className }) {
|
|
30
|
-
|
|
16
|
+
// Only show when gas is high or spike
|
|
17
|
+
if (!["high", "spike"].includes(gasPrice.level)) {
|
|
18
|
+
return null;
|
|
19
|
+
}
|
|
20
|
+
return (_jsxs(motion.div, { initial: { opacity: 0, y: 10 }, animate: { opacity: 1, y: 0 }, transition: { duration: 0.2 }, className: cn("flex flex-col gap-1 rounded-lg bg-orange-500/10 px-3 py-2", className), children: [_jsxs("div", { className: "flex items-center justify-between", children: [_jsx("span", { className: "text-xs font-medium text-orange-500", children: "Gas is high - transaction may fail or cost more" }), _jsxs("span", { className: "text-xs font-medium text-orange-500", children: [formatGwei(gasPrice.gasPriceGwei), " Gwei"] })] }), _jsx("span", { className: "text-as-secondary text-xs", children: "Consider swapping later for better rates" })] }));
|
|
31
21
|
}
|
|
@@ -1,13 +1,24 @@
|
|
|
1
1
|
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { getNativeRequired } from "../../../../anyspend/utils/chain.js";
|
|
3
3
|
import { isNativeToken } from "../../../../anyspend/utils/token.js";
|
|
4
|
-
import {
|
|
4
|
+
import { useSimTokenBalance } from "../../../../global-account/react/index.js";
|
|
5
|
+
import { formatTokenAmount } from "../../../../shared/utils/number.js";
|
|
6
|
+
import { useMemo } from "react";
|
|
5
7
|
import { formatUnits } from "viem";
|
|
6
8
|
export function TokenBalance({ token, walletAddress, onChangeInput, }) {
|
|
7
|
-
const
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
9
|
+
const tokenAddress = isNativeToken(token.address) ? "native" : token.address;
|
|
10
|
+
const { data, isLoading } = useSimTokenBalance(walletAddress, tokenAddress, token.chainId);
|
|
11
|
+
const { rawBalance, formattedBalance } = useMemo(() => {
|
|
12
|
+
const balance = data?.balances?.[0];
|
|
13
|
+
if (!balance?.amount) {
|
|
14
|
+
return { rawBalance: null, formattedBalance: "0" };
|
|
15
|
+
}
|
|
16
|
+
const raw = BigInt(balance.amount);
|
|
17
|
+
return {
|
|
18
|
+
rawBalance: raw,
|
|
19
|
+
formattedBalance: formatTokenAmount(raw, balance.decimals),
|
|
20
|
+
};
|
|
21
|
+
}, [data]);
|
|
11
22
|
const handlePercentageClick = (percentage) => {
|
|
12
23
|
if (!rawBalance)
|
|
13
24
|
return;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { components } from "../../../../anyspend/types/api";
|
|
2
|
+
import { TransferResult } from "../../hooks/useWatchTransfer";
|
|
3
|
+
export interface TransferResultScreenProps {
|
|
4
|
+
mode?: "modal" | "page";
|
|
5
|
+
/** The transfer result containing amount info */
|
|
6
|
+
transferResult: TransferResult;
|
|
7
|
+
/** The token that was transferred */
|
|
8
|
+
token: components["schemas"]["Token"];
|
|
9
|
+
/** The chain ID where the transfer happened */
|
|
10
|
+
chainId: number;
|
|
11
|
+
/** The recipient address */
|
|
12
|
+
recipientAddress: string;
|
|
13
|
+
/** Callback when back/close button is clicked */
|
|
14
|
+
onBack?: () => void;
|
|
15
|
+
/** Callback when close button is clicked */
|
|
16
|
+
onClose?: () => void;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* A component for displaying the result of a pure transfer (same chain, same token).
|
|
20
|
+
* Shows the transferred amount with success styling.
|
|
21
|
+
*/
|
|
22
|
+
export declare function TransferResultScreen({ mode, transferResult, token, chainId, recipientAddress, onBack, onClose, }: TransferResultScreenProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
|
+
import { ALL_CHAINS } from "../../../../anyspend/index.js";
|
|
4
|
+
import { cn } from "../../../../shared/utils/cn.js";
|
|
5
|
+
import { CheckCircle2, Home } from "lucide-react";
|
|
6
|
+
import { ChainTokenIcon } from "./ChainTokenIcon.js";
|
|
7
|
+
/**
|
|
8
|
+
* A component for displaying the result of a pure transfer (same chain, same token).
|
|
9
|
+
* Shows the transferred amount with success styling.
|
|
10
|
+
*/
|
|
11
|
+
export function TransferResultScreen({ mode = "modal", transferResult, token, chainId, recipientAddress, onBack, onClose, }) {
|
|
12
|
+
const chain = ALL_CHAINS[chainId];
|
|
13
|
+
const handleClose = () => {
|
|
14
|
+
if (onClose) {
|
|
15
|
+
onClose();
|
|
16
|
+
}
|
|
17
|
+
else if (onBack) {
|
|
18
|
+
onBack();
|
|
19
|
+
}
|
|
20
|
+
};
|
|
21
|
+
return (_jsx("div", { className: cn("anyspend-container anyspend-transfer-result font-inter bg-as-surface-primary mx-auto w-full max-w-[460px] p-6", mode === "page" && "border-as-border-secondary overflow-hidden rounded-2xl border shadow-xl"), children: _jsxs("div", { className: "anyspend-transfer-result-content flex flex-col items-center gap-6", children: [_jsx("div", { className: "anyspend-transfer-success-icon bg-as-success-secondary flex h-16 w-16 items-center justify-center rounded-full", children: _jsx(CheckCircle2, { className: "text-as-content-icon-success h-10 w-10" }) }), _jsxs("div", { className: "anyspend-transfer-success-message flex flex-col items-center gap-2", children: [_jsx("h2", { className: "text-as-primary text-xl font-semibold", children: "Transfer Received!" }), _jsx("p", { className: "text-as-secondary text-center text-sm", children: "Your transfer has been successfully received." })] }), _jsx("div", { className: "anyspend-transfer-amount border-as-border-secondary bg-as-surface-secondary flex w-full flex-col items-center gap-3 rounded-xl border p-4", children: _jsxs("div", { className: "flex items-center gap-3", children: [_jsx(ChainTokenIcon, { chainUrl: chain?.logoUrl, tokenUrl: token.metadata?.logoURI, className: "h-10 min-h-10 w-10 min-w-10" }), _jsxs("div", { className: "flex flex-col", children: [_jsxs("span", { className: "text-as-primary text-2xl font-bold", children: [transferResult.formattedAmount, " ", token.symbol] }), _jsxs("span", { className: "text-as-secondary text-sm", children: ["on ", chain?.name ?? "Unknown Chain"] })] })] }) }), _jsxs("div", { className: "anyspend-transfer-recipient flex w-full flex-col gap-1", children: [_jsx("span", { className: "text-as-secondary text-xs", children: "Received at" }), _jsx("span", { className: "text-as-primary break-all font-mono text-sm", children: recipientAddress })] }), _jsx("button", { onClick: handleClose, className: "anyspend-transfer-close-button bg-as-brand flex w-full items-center justify-center gap-2 rounded-xl py-3.5 font-medium text-white transition-all hover:opacity-90", children: mode === "page" ? (_jsxs(_Fragment, { children: ["Return to Home ", _jsx(Home, { className: "ml-2 h-4 w-4" })] })) : ("Close") })] }) }));
|
|
22
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
export interface TransferResult {
|
|
2
|
+
amount: string;
|
|
3
|
+
formattedAmount: string;
|
|
4
|
+
txHash?: string;
|
|
5
|
+
timestamp: number;
|
|
6
|
+
}
|
|
7
|
+
export interface UseWatchTransferProps {
|
|
8
|
+
/** Address to watch for incoming transfers */
|
|
9
|
+
address: string;
|
|
10
|
+
/** Chain ID to watch on */
|
|
11
|
+
chainId: number;
|
|
12
|
+
/** Token address (use zero address for native token) */
|
|
13
|
+
tokenAddress: string;
|
|
14
|
+
/** Token decimals */
|
|
15
|
+
tokenDecimals: number;
|
|
16
|
+
/** Whether watching is enabled */
|
|
17
|
+
enabled?: boolean;
|
|
18
|
+
/** Callback when a transfer is detected */
|
|
19
|
+
onTransferDetected?: (result: TransferResult) => void;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Hook to watch for incoming transfers to an address by monitoring balance changes.
|
|
23
|
+
* When a transfer is detected (balance increases), it captures the amount and notifies.
|
|
24
|
+
*/
|
|
25
|
+
export declare function useWatchTransfer({ address, chainId, tokenAddress, tokenDecimals, enabled, onTransferDetected, }: UseWatchTransferProps): {
|
|
26
|
+
/** Whether currently watching for transfers */
|
|
27
|
+
isWatching: boolean;
|
|
28
|
+
/** The detected transfer result, if any */
|
|
29
|
+
transferResult: TransferResult | null;
|
|
30
|
+
/** Whether a transfer has been detected */
|
|
31
|
+
hasTransfer: boolean;
|
|
32
|
+
/** Reset and start watching again */
|
|
33
|
+
reset: () => void;
|
|
34
|
+
/** Manually refetch balance */
|
|
35
|
+
refetchBalance: (options?: import("@tanstack/query-core").RefetchOptions) => Promise<import("@tanstack/query-core").QueryObserverResult<{
|
|
36
|
+
decimals: number;
|
|
37
|
+
formatted: string;
|
|
38
|
+
symbol: string;
|
|
39
|
+
value: bigint;
|
|
40
|
+
}, import("viem").GetBalanceErrorType>>;
|
|
41
|
+
};
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
2
|
+
import { formatUnits } from "viem";
|
|
3
|
+
import { useBalance } from "wagmi";
|
|
4
|
+
import { isNativeToken } from "../../utils/index.js";
|
|
5
|
+
/**
|
|
6
|
+
* Hook to watch for incoming transfers to an address by monitoring balance changes.
|
|
7
|
+
* When a transfer is detected (balance increases), it captures the amount and notifies.
|
|
8
|
+
*/
|
|
9
|
+
export function useWatchTransfer({ address, chainId, tokenAddress, tokenDecimals, enabled = true, onTransferDetected, }) {
|
|
10
|
+
const [transferResult, setTransferResult] = useState(null);
|
|
11
|
+
const [isWatching, setIsWatching] = useState(false);
|
|
12
|
+
const initialBalanceRef = useRef(null);
|
|
13
|
+
const transferDetectedRef = useRef(false);
|
|
14
|
+
const isNative = isNativeToken(tokenAddress);
|
|
15
|
+
// Get current balance
|
|
16
|
+
const { data: balanceData, refetch: refetchBalance } = useBalance({
|
|
17
|
+
address: address,
|
|
18
|
+
chainId,
|
|
19
|
+
token: isNative ? undefined : tokenAddress,
|
|
20
|
+
query: {
|
|
21
|
+
enabled: enabled && !!address,
|
|
22
|
+
refetchInterval: 3000,
|
|
23
|
+
},
|
|
24
|
+
});
|
|
25
|
+
// Initialize or update the initial balance
|
|
26
|
+
useEffect(() => {
|
|
27
|
+
if (balanceData && initialBalanceRef.current === null && enabled) {
|
|
28
|
+
initialBalanceRef.current = balanceData.value;
|
|
29
|
+
setIsWatching(true);
|
|
30
|
+
}
|
|
31
|
+
}, [balanceData, enabled]);
|
|
32
|
+
// Check for balance increase (transfer detected)
|
|
33
|
+
useEffect(() => {
|
|
34
|
+
if (!enabled || transferDetectedRef.current || initialBalanceRef.current === null || !balanceData) {
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
const currentBalance = balanceData.value;
|
|
38
|
+
const initialBalance = initialBalanceRef.current;
|
|
39
|
+
if (currentBalance > initialBalance) {
|
|
40
|
+
const transferAmount = currentBalance - initialBalance;
|
|
41
|
+
const formattedAmount = formatUnits(transferAmount, tokenDecimals);
|
|
42
|
+
const result = {
|
|
43
|
+
amount: transferAmount.toString(),
|
|
44
|
+
formattedAmount,
|
|
45
|
+
timestamp: Date.now(),
|
|
46
|
+
};
|
|
47
|
+
transferDetectedRef.current = true;
|
|
48
|
+
setTransferResult(result);
|
|
49
|
+
setIsWatching(false);
|
|
50
|
+
onTransferDetected?.(result);
|
|
51
|
+
}
|
|
52
|
+
}, [balanceData, enabled, tokenDecimals, onTransferDetected]);
|
|
53
|
+
// Reset function to start watching again
|
|
54
|
+
const reset = useCallback(() => {
|
|
55
|
+
transferDetectedRef.current = false;
|
|
56
|
+
initialBalanceRef.current = null;
|
|
57
|
+
setTransferResult(null);
|
|
58
|
+
setIsWatching(false);
|
|
59
|
+
}, []);
|
|
60
|
+
return useMemo(() => ({
|
|
61
|
+
/** Whether currently watching for transfers */
|
|
62
|
+
isWatching,
|
|
63
|
+
/** The detected transfer result, if any */
|
|
64
|
+
transferResult,
|
|
65
|
+
/** Whether a transfer has been detected */
|
|
66
|
+
hasTransfer: transferResult !== null,
|
|
67
|
+
/** Reset and start watching again */
|
|
68
|
+
reset,
|
|
69
|
+
/** Manually refetch balance */
|
|
70
|
+
refetchBalance,
|
|
71
|
+
}), [isWatching, transferResult, reset, refetchBalance]);
|
|
72
|
+
}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
-
import { TooltipProvider } from "../../../global-account/react/index.js";
|
|
4
3
|
import { FeatureFlagsProvider } from "../contexts/FeatureFlagsContext.js";
|
|
5
4
|
import { StripeRedirectHandler } from "./StripeRedirectHandler.js";
|
|
6
5
|
/**
|
|
@@ -27,5 +26,5 @@ import { StripeRedirectHandler } from "./StripeRedirectHandler.js";
|
|
|
27
26
|
* ```
|
|
28
27
|
*/
|
|
29
28
|
export const AnyspendProvider = function AnyspendProvider({ children, featureFlags }) {
|
|
30
|
-
return (
|
|
29
|
+
return (_jsxs(FeatureFlagsProvider, { featureFlags: featureFlags, children: [_jsx(StripeRedirectHandler, {}), children] }));
|
|
31
30
|
};
|
|
@@ -13,3 +13,8 @@ export declare function isEvmOrSolanaAddress(address: string): boolean;
|
|
|
13
13
|
export declare function isHyperliquidUSDC(chainId: number, address: string): boolean;
|
|
14
14
|
export declare function normalizeAddress(address: string): string;
|
|
15
15
|
export declare function eqci(a: string | null | undefined, b: string | null | undefined): boolean;
|
|
16
|
+
/**
|
|
17
|
+
* Check if source and destination represent the same token on the same chain.
|
|
18
|
+
* When true, this is a pure transfer (no swap/bridge needed).
|
|
19
|
+
*/
|
|
20
|
+
export declare function isSameChainAndToken(sourceChainId: number, sourceTokenAddress: string, destinationChainId: number, destinationTokenAddress: string): boolean;
|
|
@@ -35,3 +35,10 @@ export function eqci(a, b) {
|
|
|
35
35
|
return false;
|
|
36
36
|
return a.toLowerCase() === b.toLowerCase();
|
|
37
37
|
}
|
|
38
|
+
/**
|
|
39
|
+
* Check if source and destination represent the same token on the same chain.
|
|
40
|
+
* When true, this is a pure transfer (no swap/bridge needed).
|
|
41
|
+
*/
|
|
42
|
+
export function isSameChainAndToken(sourceChainId, sourceTokenAddress, destinationChainId, destinationTokenAddress) {
|
|
43
|
+
return sourceChainId === destinationChainId && eqci(sourceTokenAddress, destinationTokenAddress);
|
|
44
|
+
}
|
|
@@ -18,6 +18,10 @@ export function AccountAssets({ nfts, isLoading }) {
|
|
|
18
18
|
}, {});
|
|
19
19
|
const collections = Object.values(groupedNFTs || {});
|
|
20
20
|
const [expandedCollections, setExpandedCollections] = useState(() => new Set(collections.map(c => c.collection_id)));
|
|
21
|
+
const [failedImages, setFailedImages] = useState(() => new Set());
|
|
22
|
+
const handleImageError = (imageId) => {
|
|
23
|
+
setFailedImages(prev => new Set(prev).add(imageId));
|
|
24
|
+
};
|
|
21
25
|
if (isLoading) {
|
|
22
26
|
return (_jsx("div", { className: "flex flex-col gap-3", children: [...Array(2)].map((_, i) => (_jsxs("div", { className: "animate-pulse", children: [_jsx("div", { className: "bg-b3-react-muted mb-3 h-6 w-48 rounded" }), _jsxs("div", { className: "flex gap-3", children: [_jsx("div", { className: "bg-b3-react-muted h-[98px] w-[98px] shrink-0 rounded-lg" }), _jsx("div", { className: "bg-b3-react-muted h-[98px] w-[98px] shrink-0 rounded-lg" })] })] }, i))) }));
|
|
23
27
|
}
|
|
@@ -36,11 +40,11 @@ export function AccountAssets({ nfts, isLoading }) {
|
|
|
36
40
|
return next;
|
|
37
41
|
});
|
|
38
42
|
};
|
|
39
|
-
return (_jsx("div", { className: "flex flex-col gap-3
|
|
43
|
+
return (_jsx("div", { className: "flex flex-col gap-3", children: collections.map(collection => {
|
|
40
44
|
const isExpanded = expandedCollections.has(collection.collection_id);
|
|
41
|
-
return (_jsxs("div", { className: "flex flex-col gap-3", children: [_jsxs("button", { onClick: () => toggleCollection(collection.collection_id), className: "flex w-full items-center justify-between", children: [_jsxs("div", { className: "flex items-center gap-1", children: [collection.collection_image && (_jsx("img", { src: collection.collection_image, alt: collection.collection_name, className: "h-5 w-5 shrink-0 rounded object-cover" })), _jsxs("p", { className: "font-neue-montreal-medium text-[14px] text-[#3f3f46]", children: [collection.collection_name, " (", collection.nfts.length, ")"] })] }), _jsx("svg", { className: `h-[18px] w-[18px] shrink-0 transition-transform ${isExpanded ? "rotate-180" : ""}`, viewBox: "0 0 18 18", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: _jsx("path", { d: "M4.5 6.75L9 11.25L13.5 6.75", stroke: "#51525C", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }) })] }), isExpanded && (_jsx("div", { className: "flex gap-3 overflow-x-auto", children: collection.nfts.map(nft => (_jsx("div", { className: "relative h-[98px] w-[98px] shrink-0 overflow-hidden rounded-lg", children: _jsx("img", { src: nft.previews?.image_medium_url ||
|
|
45
|
+
return (_jsxs("div", { className: "flex flex-col gap-3", children: [_jsxs("button", { onClick: () => toggleCollection(collection.collection_id), className: "flex w-full items-center justify-between", children: [_jsxs("div", { className: "flex items-center gap-1", children: [collection.collection_image && !failedImages.has(`collection-${collection.collection_id}`) && (_jsx("img", { src: collection.collection_image, alt: collection.collection_name, className: "h-5 w-5 shrink-0 rounded object-cover", onError: () => handleImageError(`collection-${collection.collection_id}`) })), _jsxs("p", { className: "font-neue-montreal-medium text-[14px] text-[#3f3f46]", children: [collection.collection_name, " (", collection.nfts.length, ")"] })] }), _jsx("svg", { className: `h-[18px] w-[18px] shrink-0 transition-transform ${isExpanded ? "rotate-180" : ""}`, viewBox: "0 0 18 18", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: _jsx("path", { d: "M4.5 6.75L9 11.25L13.5 6.75", stroke: "#51525C", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }) })] }), isExpanded && (_jsx("div", { className: "flex gap-3 overflow-x-auto", children: collection.nfts.map(nft => (_jsx("div", { className: "bg-b3-react-muted relative h-[98px] w-[98px] shrink-0 overflow-hidden rounded-lg", children: !failedImages.has(nft.nft_id) && (_jsx("img", { src: nft.previews?.image_medium_url ||
|
|
42
46
|
nft.extra_metadata?.image_original_url ||
|
|
43
47
|
nft.collection?.image_url ||
|
|
44
|
-
"", alt: nft.name || "NFT", className: "h-full w-full object-cover" }) }, nft.nft_id))) }))] }, collection.collection_id));
|
|
48
|
+
"", alt: nft.name || "NFT", className: "h-full w-full object-cover", onError: () => handleImageError(nft.nft_id) })) }, nft.nft_id))) }))] }, collection.collection_id));
|
|
45
49
|
}) }));
|
|
46
50
|
}
|
|
@@ -1,15 +1,14 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { AnySpend, AnySpendBondKit, AnySpendBuySpin, AnySpendCollectorClubPurchase, AnySpendNFT, AnyspendSignatureMint, AnySpendStakeB3, AnySpendStakeB3ExactIn, AnySpendTournament, OrderHistory, } from "../../../anyspend/react/index.js";
|
|
3
|
+
import { AnySpendDeposit } from "../../../anyspend/react/components/AnySpendDeposit.js";
|
|
3
4
|
import { AnySpendDepositHype } from "../../../anyspend/react/components/AnyspendDepositHype.js";
|
|
4
5
|
import { AnySpendDepositUpside } from "../../../anyspend/react/components/AnySpendDepositUpside.js";
|
|
5
6
|
import { AnySpendStakeUpside } from "../../../anyspend/react/components/AnySpendStakeUpside.js";
|
|
6
7
|
import { AnySpendStakeUpsideExactIn } from "../../../anyspend/react/components/AnySpendStakeUpsideExactIn.js";
|
|
7
|
-
import { useB3Config,
|
|
8
|
+
import { useB3Config, useIsMobile, useModalStore } from "../../../global-account/react/index.js";
|
|
8
9
|
import { cn } from "../../../shared/utils/cn.js";
|
|
9
10
|
import { debugB3React } from "../../../shared/utils/debug.js";
|
|
10
11
|
import { AnimatePresence, motion } from "framer-motion";
|
|
11
|
-
import { useEffect, useRef } from "react";
|
|
12
|
-
import { useSetActiveWallet } from "thirdweb/react";
|
|
13
12
|
import { AvatarEditor } from "./AvatarEditor/AvatarEditor.js";
|
|
14
13
|
import { Deposit } from "./Deposit/Deposit.js";
|
|
15
14
|
import { LinkAccount } from "./LinkAccount/LinkAccount.js";
|
|
@@ -31,19 +30,7 @@ export function B3DynamicModal() {
|
|
|
31
30
|
const navigateBack = useModalStore(state => state.navigateBack);
|
|
32
31
|
const { theme } = useB3Config();
|
|
33
32
|
const isMobile = useIsMobile();
|
|
34
|
-
const prevIsOpenRef = useRef(isOpen);
|
|
35
|
-
const { wallet } = useGlobalAccount();
|
|
36
|
-
const setActiveWallet = useSetActiveWallet();
|
|
37
33
|
const { toasts, removeToast } = useToastContext();
|
|
38
|
-
// anyspend cleanup global account chnages by setting account back
|
|
39
|
-
useEffect(() => {
|
|
40
|
-
if (prevIsOpenRef.current && !isOpen) {
|
|
41
|
-
if (wallet) {
|
|
42
|
-
setActiveWallet(wallet);
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
prevIsOpenRef.current = isOpen;
|
|
46
|
-
}, [isOpen, wallet, setActiveWallet]);
|
|
47
34
|
// Define arrays for different modal type groups
|
|
48
35
|
const fullWidthTypes = [
|
|
49
36
|
"anySpend",
|
|
@@ -66,6 +53,7 @@ export function B3DynamicModal() {
|
|
|
66
53
|
"deposit",
|
|
67
54
|
"send",
|
|
68
55
|
"notifications",
|
|
56
|
+
"anySpendDeposit",
|
|
69
57
|
];
|
|
70
58
|
const freestyleTypes = [
|
|
71
59
|
"anySpendNft",
|
|
@@ -136,6 +124,8 @@ export function B3DynamicModal() {
|
|
|
136
124
|
return _jsx(AnySpendDepositHype, { ...contentType, mode: "modal" });
|
|
137
125
|
case "anySpendCollectorClubPurchase":
|
|
138
126
|
return _jsx(AnySpendCollectorClubPurchase, { ...contentType, mode: "modal" });
|
|
127
|
+
case "anySpendDeposit":
|
|
128
|
+
return _jsx(AnySpendDeposit, { ...contentType, mode: "modal" });
|
|
139
129
|
case "avatarEditor":
|
|
140
130
|
return _jsx(AvatarEditor, { onSetAvatar: contentType.onSuccess });
|
|
141
131
|
case "deposit":
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { CreateOnrampOrderParams } from "../../../../anyspend/react/hooks/useAnyspendCreateOnrampOrder";
|
|
2
|
+
import { CreateOrderParams } from "../../../../anyspend/react/hooks/useAnyspendCreateOrder";
|
|
3
|
+
import { PermissionsConfig } from "../../../../global-account/types/permissions";
|
|
4
|
+
import { Account } from "thirdweb/wallets";
|
|
5
|
+
import { ClientType } from "../../../client-manager";
|
|
6
|
+
export interface B3ConfigContextType {
|
|
7
|
+
accountOverride?: Account;
|
|
8
|
+
automaticallySetFirstEoa: boolean;
|
|
9
|
+
environment: "development" | "production";
|
|
10
|
+
defaultPermissions: PermissionsConfig;
|
|
11
|
+
theme: "light" | "dark";
|
|
12
|
+
clientType: ClientType;
|
|
13
|
+
partnerId: string;
|
|
14
|
+
stripePublishableKey?: string;
|
|
15
|
+
createClientReferenceId?: (params: CreateOrderParams | CreateOnrampOrderParams) => Promise<string>;
|
|
16
|
+
enableTurnkey: boolean;
|
|
17
|
+
}
|
|
18
|
+
export declare function B3ConfigProvider({ children, accountOverride, environment, defaultPermissions, automaticallySetFirstEoa, theme, clientType, partnerId, stripePublishableKey, createClientReferenceId, enableTurnkey, }: {
|
|
19
|
+
children: React.ReactNode;
|
|
20
|
+
accountOverride?: Account;
|
|
21
|
+
environment?: "development" | "production";
|
|
22
|
+
defaultPermissions?: PermissionsConfig;
|
|
23
|
+
automaticallySetFirstEoa?: boolean;
|
|
24
|
+
theme?: "light" | "dark";
|
|
25
|
+
clientType?: ClientType;
|
|
26
|
+
partnerId: string;
|
|
27
|
+
stripePublishableKey?: string;
|
|
28
|
+
createClientReferenceId?: (params: CreateOrderParams | CreateOnrampOrderParams) => Promise<string>;
|
|
29
|
+
enableTurnkey?: boolean;
|
|
30
|
+
}): import("react/jsx-runtime").JSX.Element;
|
|
31
|
+
export declare function useB3Config(): B3ConfigContextType;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { createContext, useContext } from "react";
|
|
3
|
+
/**
|
|
4
|
+
* Default permissions configuration for B3 provider
|
|
5
|
+
*/
|
|
6
|
+
const DEFAULT_PERMISSIONS = {
|
|
7
|
+
approvedTargets: ["0xa8e42121e318e3D3BeD7f5969AF6D360045317DD"],
|
|
8
|
+
nativeTokenLimitPerTransaction: 0.1,
|
|
9
|
+
startDate: new Date(),
|
|
10
|
+
endDate: new Date(Date.now() + 1000 * 60 * 60 * 24 * 365), // 1 year from now
|
|
11
|
+
};
|
|
12
|
+
const B3ConfigContext = createContext(null);
|
|
13
|
+
export function B3ConfigProvider({ children, accountOverride, environment = "development", defaultPermissions = DEFAULT_PERMISSIONS, automaticallySetFirstEoa = false, theme = "light", clientType = "rest", partnerId, stripePublishableKey, createClientReferenceId, enableTurnkey = false, }) {
|
|
14
|
+
return (_jsx(B3ConfigContext.Provider, { value: {
|
|
15
|
+
accountOverride,
|
|
16
|
+
environment,
|
|
17
|
+
defaultPermissions,
|
|
18
|
+
automaticallySetFirstEoa,
|
|
19
|
+
theme,
|
|
20
|
+
clientType,
|
|
21
|
+
partnerId,
|
|
22
|
+
stripePublishableKey,
|
|
23
|
+
createClientReferenceId,
|
|
24
|
+
enableTurnkey,
|
|
25
|
+
}, children: children }));
|
|
26
|
+
}
|
|
27
|
+
export function useB3Config() {
|
|
28
|
+
const context = useContext(B3ConfigContext);
|
|
29
|
+
if (!context) {
|
|
30
|
+
throw new Error("useB3Config must be used within a B3ConfigProvider");
|
|
31
|
+
}
|
|
32
|
+
return context;
|
|
33
|
+
}
|