@b3dotfun/sdk 0.0.29-alpha.2 → 0.0.29-alpha.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/anyspend/react/components/AnyspendDepositHype.js +3 -1
- package/dist/cjs/anyspend/react/components/common/ConnectWalletPayment.js +9 -1
- package/dist/cjs/anyspend/react/components/common/CryptoPaymentMethod.js +130 -41
- package/dist/cjs/anyspend/react/components/common/OrderDetails.js +3 -3
- package/dist/cjs/anyspend/react/components/common/PaySection.js +6 -4
- package/dist/cjs/anyspend/react/hooks/useAnyspendFlow.js +29 -0
- package/dist/cjs/anyspend/react/hooks/useSigMint.d.ts +1 -1
- package/dist/cjs/bondkit/abis/BondkitTokenABI.d.ts +60 -12
- package/dist/cjs/bondkit/abis/BondkitTokenABI.js +39 -6
- package/dist/cjs/bondkit/abis/BondkitTokenFactoryABI.d.ts +0 -25
- package/dist/cjs/bondkit/abis/BondkitTokenFactoryABI.js +0 -9
- package/dist/cjs/bondkit/constants.js +1 -1
- package/dist/cjs/global-account/react/hooks/useUnifiedChainSwitchAndExecute.d.ts +1 -0
- package/dist/cjs/global-account/react/hooks/useUnifiedChainSwitchAndExecute.js +1 -0
- package/dist/cjs/shared/constants/chains/b3Chain.d.ts +2 -2
- package/dist/cjs/shared/constants/chains/supported.d.ts +4 -4
- package/dist/esm/anyspend/react/components/AnyspendDepositHype.js +3 -1
- package/dist/esm/anyspend/react/components/common/ConnectWalletPayment.js +6 -1
- package/dist/esm/anyspend/react/components/common/CryptoPaymentMethod.js +133 -44
- package/dist/esm/anyspend/react/components/common/OrderDetails.js +3 -3
- package/dist/esm/anyspend/react/components/common/PaySection.js +7 -5
- package/dist/esm/anyspend/react/hooks/useAnyspendFlow.js +30 -1
- package/dist/esm/anyspend/react/hooks/useSigMint.d.ts +1 -1
- package/dist/esm/bondkit/abis/BondkitTokenABI.d.ts +60 -12
- package/dist/esm/bondkit/abis/BondkitTokenABI.js +39 -6
- package/dist/esm/bondkit/abis/BondkitTokenFactoryABI.d.ts +0 -25
- package/dist/esm/bondkit/abis/BondkitTokenFactoryABI.js +0 -9
- package/dist/esm/bondkit/constants.js +1 -1
- package/dist/esm/global-account/react/hooks/useUnifiedChainSwitchAndExecute.d.ts +1 -0
- package/dist/esm/global-account/react/hooks/useUnifiedChainSwitchAndExecute.js +1 -0
- package/dist/esm/shared/constants/chains/b3Chain.d.ts +2 -2
- package/dist/esm/shared/constants/chains/supported.d.ts +4 -4
- package/dist/styles/index.css +1 -1
- package/dist/types/anyspend/react/hooks/useSigMint.d.ts +1 -1
- package/dist/types/bondkit/abis/BondkitTokenABI.d.ts +60 -12
- package/dist/types/bondkit/abis/BondkitTokenFactoryABI.d.ts +0 -25
- package/dist/types/global-account/react/hooks/useUnifiedChainSwitchAndExecute.d.ts +1 -0
- package/dist/types/shared/constants/chains/b3Chain.d.ts +2 -2
- package/dist/types/shared/constants/chains/supported.d.ts +4 -4
- package/package.json +1 -1
- package/src/anyspend/react/components/AnyspendDepositHype.tsx +4 -0
- package/src/anyspend/react/components/common/ConnectWalletPayment.tsx +9 -0
- package/src/anyspend/react/components/common/CryptoPaymentMethod.tsx +289 -103
- package/src/anyspend/react/components/common/OrderDetails.tsx +3 -3
- package/src/anyspend/react/components/common/PaySection.tsx +9 -7
- package/src/anyspend/react/hooks/useAnyspendFlow.ts +33 -1
- package/src/bondkit/abis/BondkitTokenABI.ts +39 -6
- package/src/bondkit/abis/BondkitTokenFactoryABI.ts +0 -9
- package/src/bondkit/constants.ts +1 -1
- package/src/global-account/react/hooks/useUnifiedChainSwitchAndExecute.ts +1 -0
|
@@ -70,6 +70,7 @@ function AnySpendDepositHypeInner({
|
|
|
70
70
|
activePanel,
|
|
71
71
|
setActivePanel,
|
|
72
72
|
orderId,
|
|
73
|
+
setOrderId,
|
|
73
74
|
oat,
|
|
74
75
|
selectedSrcChainId,
|
|
75
76
|
setSelectedSrcChainId,
|
|
@@ -413,6 +414,7 @@ function AnySpendDepositHypeInner({
|
|
|
413
414
|
refundTxs={oat.data.refundTxs}
|
|
414
415
|
cryptoPaymentMethod={paymentType === "fiat" ? CryptoPaymentMethodType.NONE : selectedCryptoPaymentMethod}
|
|
415
416
|
onBack={() => {
|
|
417
|
+
setOrderId(undefined);
|
|
416
418
|
setActivePanel(PanelView.MAIN);
|
|
417
419
|
onSuccess?.();
|
|
418
420
|
}}
|
|
@@ -470,6 +472,8 @@ function AnySpendDepositHypeInner({
|
|
|
470
472
|
/>
|
|
471
473
|
);
|
|
472
474
|
|
|
475
|
+
console.log("activePanel", activePanel, orderId, oat);
|
|
476
|
+
|
|
473
477
|
// If showing token selection, render with panel transitions
|
|
474
478
|
return (
|
|
475
479
|
<StyleRoot>
|
|
@@ -3,9 +3,11 @@
|
|
|
3
3
|
import { RELAY_SOLANA_MAINNET_CHAIN_ID } from "@b3dotfun/sdk/anyspend";
|
|
4
4
|
import { components } from "@b3dotfun/sdk/anyspend/types/api";
|
|
5
5
|
import { ShinyButton, useProfile } from "@b3dotfun/sdk/global-account/react";
|
|
6
|
+
import centerTruncate from "@b3dotfun/sdk/shared/utils/centerTruncate";
|
|
6
7
|
import { formatTokenAmount } from "@b3dotfun/sdk/shared/utils/number";
|
|
7
8
|
import { motion } from "framer-motion";
|
|
8
9
|
import { ChevronRight, Loader2 } from "lucide-react";
|
|
10
|
+
import { useAccount } from "wagmi";
|
|
9
11
|
import { OrderDetailsCollapsible } from "./OrderDetailsCollapsible";
|
|
10
12
|
|
|
11
13
|
type Tournament = components["schemas"]["Tournament"];
|
|
@@ -33,6 +35,7 @@ export default function ConnectWalletPayment({
|
|
|
33
35
|
}: ConnectWalletPaymentProps) {
|
|
34
36
|
const profile = useProfile({ address: order.recipientAddress });
|
|
35
37
|
const recipientName = profile.data?.name?.replace(/\.b3\.fun/g, "");
|
|
38
|
+
const { address: connectedAddress } = useAccount();
|
|
36
39
|
|
|
37
40
|
const srcToken = order.metadata.srcToken;
|
|
38
41
|
const dstToken = order.metadata.dstToken;
|
|
@@ -82,6 +85,12 @@ export default function ConnectWalletPayment({
|
|
|
82
85
|
</>
|
|
83
86
|
)}
|
|
84
87
|
</ShinyButton>
|
|
88
|
+
<span className="label-style text-as-primary/50 text-xs">
|
|
89
|
+
Connected to:{" "}
|
|
90
|
+
{order.srcChain === RELAY_SOLANA_MAINNET_CHAIN_ID && phantomWalletAddress
|
|
91
|
+
? centerTruncate(phantomWalletAddress, 6)
|
|
92
|
+
: centerTruncate(connectedAddress || "")}
|
|
93
|
+
</span>
|
|
85
94
|
|
|
86
95
|
<div className="mt-4">
|
|
87
96
|
<OrderDetailsCollapsible
|
|
@@ -1,17 +1,13 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
3
|
import { useAccountWallet } from "@b3dotfun/sdk/global-account/react";
|
|
4
|
-
import { thirdwebB3Mainnet } from "@b3dotfun/sdk/shared/constants/chains/b3Chain";
|
|
5
4
|
import { cn } from "@b3dotfun/sdk/shared/utils/cn";
|
|
6
5
|
import { shortenAddress } from "@b3dotfun/sdk/shared/utils/formatAddress";
|
|
7
|
-
import {
|
|
8
|
-
import { ChevronLeft, ChevronRightCircle, Wallet, X } from "lucide-react";
|
|
6
|
+
import { ChevronLeft, ChevronRightCircle, Wallet, X, ZapIcon } from "lucide-react";
|
|
9
7
|
import { useState } from "react";
|
|
10
8
|
import { createPortal } from "react-dom";
|
|
11
9
|
import { toast } from "sonner";
|
|
12
|
-
import {
|
|
13
|
-
import { createWallet } from "thirdweb/wallets";
|
|
14
|
-
import { useDisconnect } from "wagmi";
|
|
10
|
+
import { useAccount, useConnect, useDisconnect, useWalletClient } from "wagmi";
|
|
15
11
|
|
|
16
12
|
export enum CryptoPaymentMethodType {
|
|
17
13
|
NONE = "none",
|
|
@@ -41,20 +37,107 @@ export function CryptoPaymentMethod({
|
|
|
41
37
|
onSelectPaymentMethod,
|
|
42
38
|
}: CryptoPaymentMethodProps) {
|
|
43
39
|
const { wallet: globalWallet } = useAccountWallet();
|
|
44
|
-
const
|
|
40
|
+
const { address, isConnected, connector } = useAccount();
|
|
41
|
+
const { connect, connectors, isPending } = useConnect();
|
|
45
42
|
const { disconnect } = useDisconnect();
|
|
46
|
-
const {
|
|
43
|
+
const { data: walletClient } = useWalletClient();
|
|
47
44
|
const [showWalletModal, setShowWalletModal] = useState(false);
|
|
45
|
+
const [selectedWalletConnector, setSelectedWalletConnector] = useState<any>(null);
|
|
46
|
+
const [modalStep, setModalStep] = useState<"wallet-selection" | "account-selection">("wallet-selection");
|
|
48
47
|
|
|
49
|
-
// Define available
|
|
50
|
-
const
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
48
|
+
// Define available wallet connectors
|
|
49
|
+
const availableConnectors = connectors.filter(connector =>
|
|
50
|
+
["MetaMask", "WalletConnect", "Coinbase Wallet", "Rainbow"].includes(connector.name),
|
|
51
|
+
);
|
|
52
|
+
|
|
53
|
+
// Define wallet options with icons and info
|
|
54
|
+
const walletOptions = [
|
|
55
|
+
{
|
|
56
|
+
id: "metamask",
|
|
57
|
+
name: "MetaMask",
|
|
58
|
+
icon: "🦊",
|
|
59
|
+
description: "Connect using MetaMask browser extension",
|
|
60
|
+
connector: availableConnectors.find(c => c.name === "MetaMask"),
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
id: "coinbase",
|
|
64
|
+
name: "Coinbase Wallet",
|
|
65
|
+
icon: "🔵",
|
|
66
|
+
description: "Connect using Coinbase Wallet",
|
|
67
|
+
connector: availableConnectors.find(c => c.name === "Coinbase Wallet"),
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
id: "rainbow",
|
|
71
|
+
name: "Rainbow",
|
|
72
|
+
icon: "🌈",
|
|
73
|
+
description: "Connect using Rainbow wallet",
|
|
74
|
+
connector: availableConnectors.find(c => c.name === "Rainbow"),
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
id: "walletconnect",
|
|
78
|
+
name: "WalletConnect",
|
|
79
|
+
icon: "🔗",
|
|
80
|
+
description: "Connect using WalletConnect protocol",
|
|
81
|
+
connector: availableConnectors.find(c => c.name === "WalletConnect"),
|
|
82
|
+
},
|
|
83
|
+
].filter(wallet => wallet.connector); // Only show wallets that have available connectors
|
|
84
|
+
|
|
85
|
+
// Reset modal state when closing
|
|
86
|
+
const handleCloseModal = () => {
|
|
87
|
+
setShowWalletModal(false);
|
|
88
|
+
setModalStep("wallet-selection");
|
|
89
|
+
setSelectedWalletConnector(null);
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
// Function to request wallet permissions for specific wallet
|
|
93
|
+
const requestWalletPermissions = async (walletConnector?: any) => {
|
|
94
|
+
try {
|
|
95
|
+
// If a specific wallet connector is provided and it's different from current
|
|
96
|
+
if (walletConnector && connector?.name !== walletConnector.name) {
|
|
97
|
+
// Disconnect current and connect to the selected wallet
|
|
98
|
+
// if (isConnected) {
|
|
99
|
+
// disconnect();
|
|
100
|
+
// // Small delay to ensure disconnection
|
|
101
|
+
// await new Promise(resolve => setTimeout(resolve, 100));
|
|
102
|
+
// }
|
|
103
|
+
await connect({ connector: walletConnector });
|
|
104
|
+
setSelectedPaymentMethod(CryptoPaymentMethodType.CONNECT_WALLET);
|
|
105
|
+
onSelectPaymentMethod(CryptoPaymentMethodType.CONNECT_WALLET);
|
|
106
|
+
toast.success(`Connected to ${walletConnector.name}`);
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// If same wallet or no specific wallet, request permissions for account switching
|
|
111
|
+
if (walletClient && "request" in walletClient) {
|
|
112
|
+
await walletClient.request({
|
|
113
|
+
method: "wallet_requestPermissions",
|
|
114
|
+
params: [{ eth_accounts: {} }],
|
|
115
|
+
});
|
|
116
|
+
toast.success("Account selection completed");
|
|
117
|
+
setSelectedPaymentMethod(CryptoPaymentMethodType.CONNECT_WALLET);
|
|
118
|
+
onSelectPaymentMethod(CryptoPaymentMethodType.CONNECT_WALLET);
|
|
119
|
+
} else {
|
|
120
|
+
// Fallback: show modal for manual wallet selection
|
|
121
|
+
setShowWalletModal(true);
|
|
122
|
+
}
|
|
123
|
+
} catch (error) {
|
|
124
|
+
console.error("Failed to request wallet permissions:", error);
|
|
125
|
+
if (error && typeof error === "object" && "message" in error) {
|
|
126
|
+
const errorMessage = (error as any).message.toLowerCase();
|
|
127
|
+
if (
|
|
128
|
+
errorMessage.includes("rejected") ||
|
|
129
|
+
errorMessage.includes("denied") ||
|
|
130
|
+
errorMessage.includes("cancelled")
|
|
131
|
+
) {
|
|
132
|
+
toast.error("Account selection cancelled");
|
|
133
|
+
} else {
|
|
134
|
+
toast.error("Failed to open account selection");
|
|
135
|
+
}
|
|
136
|
+
} else {
|
|
137
|
+
toast.error("Failed to open account selection");
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
};
|
|
58
141
|
|
|
59
142
|
return (
|
|
60
143
|
<div className="crypto-payment-method mx-auto h-fit w-[460px] max-w-full">
|
|
@@ -68,78 +151,32 @@ export function CryptoPaymentMethod({
|
|
|
68
151
|
</button>
|
|
69
152
|
<div className="flex items-center justify-around gap-4">
|
|
70
153
|
<div className="flex-1 text-center">
|
|
71
|
-
<h2 className="text-as-primary text-lg font-semibold">
|
|
154
|
+
<h2 className="text-as-primary text-lg font-semibold">Select a payment method</h2>
|
|
72
155
|
</div>
|
|
73
156
|
</div>
|
|
74
157
|
|
|
75
158
|
{/* Payment Methods */}
|
|
76
|
-
<div className="crypto-payment-methods flex flex-col gap-
|
|
77
|
-
{/* Connect Wallet
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
<div className="flex flex-col items-start text-left">
|
|
89
|
-
<h4 className="text-as-primary font-semibold">Connect wallet</h4>
|
|
90
|
-
<p className="text-as-primary/60 text-sm">Choose from multiple wallet options</p>
|
|
91
|
-
</div>
|
|
159
|
+
<div className="crypto-payment-methods flex flex-col gap-6">
|
|
160
|
+
{/* Connect Wallet Section */}
|
|
161
|
+
<button
|
|
162
|
+
onClick={() => {
|
|
163
|
+
// Always show wallet selection modal first
|
|
164
|
+
setShowWalletModal(true);
|
|
165
|
+
}}
|
|
166
|
+
className="crypto-payment-method-connect-wallet bg-as-surface-primary border-as-border-secondary hover:border-as-secondary/80 group flex w-full items-center justify-between gap-4 rounded-xl border px-4 py-3.5 transition-all duration-200 hover:shadow-md"
|
|
167
|
+
>
|
|
168
|
+
<div className="flex items-center gap-3">
|
|
169
|
+
<div className="wallet-icon flex h-8 w-8 items-center justify-center rounded-full bg-blue-100">
|
|
170
|
+
<Wallet className="h-4 w-4 text-blue-600" />
|
|
92
171
|
</div>
|
|
93
|
-
<
|
|
94
|
-
|
|
95
|
-
) : (
|
|
96
|
-
// Connected - show wallet info
|
|
97
|
-
<div className="crypto-payment-method-connect-wallet wallet-connected bg-as-surface-primary border-as-border-secondary rounded-xl border">
|
|
98
|
-
<div className="flex items-center justify-between p-4">
|
|
99
|
-
<div className="flex items-center gap-3">
|
|
100
|
-
{globalWallet?.meta?.icon ? (
|
|
101
|
-
<img src={globalWallet.meta.icon} alt="Connected Wallet" className="h-8 w-8 rounded-full" />
|
|
102
|
-
) : (
|
|
103
|
-
<div className="wallet-icon flex h-8 w-8 items-center justify-center rounded-full bg-green-100">
|
|
104
|
-
<Wallet className="h-4 w-4 text-green-600" />
|
|
105
|
-
</div>
|
|
106
|
-
)}
|
|
107
|
-
<div className="flex flex-col">
|
|
108
|
-
<span className="text-as-primary font-semibold">Connected Wallet</span>
|
|
109
|
-
<span className="text-as-primary/60 text-sm">
|
|
110
|
-
{shortenAddress(activeWallet.getAccount()?.address || "")}
|
|
111
|
-
</span>
|
|
112
|
-
</div>
|
|
113
|
-
</div>
|
|
114
|
-
<div className="flex items-center gap-2">
|
|
115
|
-
<button
|
|
116
|
-
onClick={() => {
|
|
117
|
-
setSelectedPaymentMethod(CryptoPaymentMethodType.CONNECT_WALLET);
|
|
118
|
-
onSelectPaymentMethod(CryptoPaymentMethodType.CONNECT_WALLET);
|
|
119
|
-
}}
|
|
120
|
-
className="bg-as-brand hover:bg-as-brand/90 rounded-lg px-3 py-1.5 text-sm font-medium text-white transition-colors"
|
|
121
|
-
>
|
|
122
|
-
Use Wallet
|
|
123
|
-
</button>
|
|
124
|
-
<button
|
|
125
|
-
onClick={async () => {
|
|
126
|
-
disconnect();
|
|
127
|
-
disconnectThirdweb(activeWallet);
|
|
128
|
-
toast.success("Wallet disconnected");
|
|
129
|
-
if (selectedPaymentMethod === CryptoPaymentMethodType.CONNECT_WALLET) {
|
|
130
|
-
setSelectedPaymentMethod(CryptoPaymentMethodType.NONE);
|
|
131
|
-
}
|
|
132
|
-
}}
|
|
133
|
-
className="text-as-primary/60 hover:text-as-primary/80 rounded-lg p-1.5 transition-colors"
|
|
134
|
-
>
|
|
135
|
-
<X className="h-4 w-4" />
|
|
136
|
-
</button>
|
|
137
|
-
</div>
|
|
172
|
+
<div className="flex flex-col items-start text-left">
|
|
173
|
+
<h4 className="text-as-primary font-semibold">Connect wallet</h4>
|
|
138
174
|
</div>
|
|
139
175
|
</div>
|
|
140
|
-
|
|
176
|
+
<ChevronRightCircle className="text-as-primary/40 group-hover:text-as-primary/60 h-5 w-5 transition-colors" />
|
|
177
|
+
</button>
|
|
141
178
|
|
|
142
|
-
{/* Transfer Crypto
|
|
179
|
+
{/* Transfer Crypto Section */}
|
|
143
180
|
<button
|
|
144
181
|
onClick={() => {
|
|
145
182
|
setSelectedPaymentMethod(CryptoPaymentMethodType.TRANSFER_CRYPTO);
|
|
@@ -148,11 +185,73 @@ export function CryptoPaymentMethod({
|
|
|
148
185
|
disabled={isCreatingOrder}
|
|
149
186
|
className="crypto-payment-method-transfer bg-as-surface-primary border-as-border-secondary hover:border-as-secondary/80 group flex w-full items-center justify-between gap-4 rounded-xl border px-4 py-3.5 transition-all duration-200 hover:shadow-md"
|
|
150
187
|
>
|
|
151
|
-
<div className="flex
|
|
152
|
-
<
|
|
188
|
+
<div className="flex items-center gap-3">
|
|
189
|
+
<div className="wallet-icon flex h-8 w-8 items-center justify-center rounded-full bg-orange-100">
|
|
190
|
+
<ZapIcon className="h-4 w-4" />
|
|
191
|
+
</div>
|
|
192
|
+
<div className="flex flex-col items-start text-left">
|
|
193
|
+
<h4 className="text-as-primary font-semibold">Transfer crypto</h4>
|
|
194
|
+
</div>
|
|
153
195
|
</div>
|
|
154
196
|
<ChevronRightCircle className="text-as-primary/40 group-hover:text-as-primary/60 h-5 w-5 transition-colors" />
|
|
155
197
|
</button>
|
|
198
|
+
|
|
199
|
+
{/* Installed Wallets Section */}
|
|
200
|
+
{isConnected && (
|
|
201
|
+
<div className="installed-wallets">
|
|
202
|
+
<h3 className="text-as-primary/80 mb-3 text-sm font-medium">Connected wallets</h3>
|
|
203
|
+
<div className="space-y-2">
|
|
204
|
+
{/* Current Connected Wallet */}
|
|
205
|
+
<button
|
|
206
|
+
onClick={() => {
|
|
207
|
+
setSelectedPaymentMethod(CryptoPaymentMethodType.CONNECT_WALLET);
|
|
208
|
+
onSelectPaymentMethod(CryptoPaymentMethodType.CONNECT_WALLET);
|
|
209
|
+
toast.success(`Selected ${connector?.name || "wallet"}`);
|
|
210
|
+
}}
|
|
211
|
+
className={cn(
|
|
212
|
+
"crypto-payment-method-connect-wallet w-full rounded-xl border p-4 text-left transition-all hover:shadow-md",
|
|
213
|
+
selectedPaymentMethod === CryptoPaymentMethodType.CONNECT_WALLET
|
|
214
|
+
? "connected-wallet border-as-brand bg-as-brand/5"
|
|
215
|
+
: "border-as-border-secondary bg-as-surface-primary hover:border-as-secondary/80",
|
|
216
|
+
)}
|
|
217
|
+
>
|
|
218
|
+
<div className="flex items-center justify-between">
|
|
219
|
+
<div className="flex items-center gap-3">
|
|
220
|
+
{globalWallet?.meta?.icon ? (
|
|
221
|
+
<img src={globalWallet.meta.icon} alt="Wallet" className="h-10 w-10 rounded-full" />
|
|
222
|
+
) : (
|
|
223
|
+
<div className="wallet-icon flex h-10 w-10 items-center justify-center rounded-full bg-blue-100">
|
|
224
|
+
<Wallet className="h-5 w-5 text-blue-600" />
|
|
225
|
+
</div>
|
|
226
|
+
)}
|
|
227
|
+
<div className="flex flex-col">
|
|
228
|
+
<span className="text-as-primary font-semibold">{connector?.name || "Connected Wallet"}</span>
|
|
229
|
+
<span className="text-as-primary/60 text-sm">{shortenAddress(address || "")}</span>
|
|
230
|
+
</div>
|
|
231
|
+
</div>
|
|
232
|
+
<div className="flex items-center gap-2">
|
|
233
|
+
{selectedPaymentMethod === CryptoPaymentMethodType.CONNECT_WALLET && (
|
|
234
|
+
<div className="h-2 w-2 rounded-full bg-green-500"></div>
|
|
235
|
+
)}
|
|
236
|
+
<button
|
|
237
|
+
onClick={e => {
|
|
238
|
+
e.stopPropagation();
|
|
239
|
+
disconnect();
|
|
240
|
+
toast.success("Wallet disconnected");
|
|
241
|
+
if (selectedPaymentMethod === CryptoPaymentMethodType.CONNECT_WALLET) {
|
|
242
|
+
setSelectedPaymentMethod(CryptoPaymentMethodType.NONE);
|
|
243
|
+
}
|
|
244
|
+
}}
|
|
245
|
+
className="text-as-primary/60 hover:text-as-primary/80 rounded-lg p-1.5 transition-colors"
|
|
246
|
+
>
|
|
247
|
+
<X className="h-4 w-4" />
|
|
248
|
+
</button>
|
|
249
|
+
</div>
|
|
250
|
+
</div>
|
|
251
|
+
</button>
|
|
252
|
+
</div>
|
|
253
|
+
</div>
|
|
254
|
+
)}
|
|
156
255
|
</div>
|
|
157
256
|
</div>
|
|
158
257
|
|
|
@@ -162,32 +261,119 @@ export function CryptoPaymentMethod({
|
|
|
162
261
|
<div className="pointer-events-auto fixed inset-0 z-[9999] flex items-center justify-center bg-black/50">
|
|
163
262
|
<div className="max-h-[80vh] w-[400px] max-w-[90vw] overflow-auto rounded-xl bg-white p-6 dark:bg-gray-900">
|
|
164
263
|
<div className="mb-4 flex items-center justify-between">
|
|
165
|
-
<
|
|
264
|
+
<div className="flex items-center gap-2">
|
|
265
|
+
{modalStep === "account-selection" && (
|
|
266
|
+
<button
|
|
267
|
+
onClick={() => setModalStep("wallet-selection")}
|
|
268
|
+
className="text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-200"
|
|
269
|
+
>
|
|
270
|
+
<ChevronLeft className="h-5 w-5" />
|
|
271
|
+
</button>
|
|
272
|
+
)}
|
|
273
|
+
<h3 className="text-lg font-semibold text-gray-900 dark:text-white">
|
|
274
|
+
{modalStep === "wallet-selection"
|
|
275
|
+
? "Select a payment method"
|
|
276
|
+
: `Connect ${selectedWalletConnector?.name}`}
|
|
277
|
+
</h3>
|
|
278
|
+
</div>
|
|
166
279
|
<button
|
|
167
|
-
onClick={
|
|
280
|
+
onClick={handleCloseModal}
|
|
168
281
|
className="text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-200"
|
|
169
282
|
>
|
|
170
283
|
<X className="h-5 w-5" />
|
|
171
284
|
</button>
|
|
172
285
|
</div>
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
286
|
+
|
|
287
|
+
<div className="space-y-4">
|
|
288
|
+
{modalStep === "wallet-selection" ? (
|
|
289
|
+
<>
|
|
290
|
+
{/* Custom wallet options */}
|
|
291
|
+
<div className="space-y-3">
|
|
292
|
+
<h4 className="text-sm font-medium text-gray-700 dark:text-gray-300">
|
|
293
|
+
{isConnected ? "Switch wallet or account" : "Choose wallet to connect"}
|
|
294
|
+
</h4>
|
|
295
|
+
{walletOptions.map(walletOption => {
|
|
296
|
+
const isCurrentWallet = isConnected && connector?.name === walletOption.connector?.name;
|
|
297
|
+
|
|
298
|
+
return (
|
|
299
|
+
<button
|
|
300
|
+
key={walletOption.id}
|
|
301
|
+
onClick={async () => {
|
|
302
|
+
setSelectedWalletConnector(walletOption.connector);
|
|
303
|
+
setModalStep("account-selection");
|
|
304
|
+
}}
|
|
305
|
+
disabled={isPending}
|
|
306
|
+
className={`w-full rounded-xl border p-4 text-left transition-all hover:shadow-md disabled:opacity-50 ${
|
|
307
|
+
isCurrentWallet
|
|
308
|
+
? "border-blue-500 bg-blue-50 dark:bg-blue-900/20"
|
|
309
|
+
: "border-gray-200 bg-white hover:border-gray-300 dark:border-gray-600 dark:bg-gray-800 dark:hover:border-gray-500"
|
|
310
|
+
}`}
|
|
311
|
+
>
|
|
312
|
+
<div className="flex items-center justify-between">
|
|
313
|
+
<div className="flex items-center gap-3">
|
|
314
|
+
<div
|
|
315
|
+
className={`flex h-12 w-12 items-center justify-center rounded-xl text-xl ${
|
|
316
|
+
isCurrentWallet ? "bg-blue-100 dark:bg-blue-800" : "bg-gray-100 dark:bg-gray-700"
|
|
317
|
+
}`}
|
|
318
|
+
>
|
|
319
|
+
{walletOption.icon}
|
|
320
|
+
</div>
|
|
321
|
+
<div>
|
|
322
|
+
<div className="flex items-center gap-2">
|
|
323
|
+
<div className="text-sm font-semibold text-gray-900 dark:text-white">
|
|
324
|
+
{walletOption.name}
|
|
325
|
+
</div>
|
|
326
|
+
{isCurrentWallet && (
|
|
327
|
+
<span className="rounded-full bg-blue-100 px-2 py-0.5 text-xs font-medium text-blue-700 dark:bg-blue-800 dark:text-blue-200">
|
|
328
|
+
Connected
|
|
329
|
+
</span>
|
|
330
|
+
)}
|
|
331
|
+
</div>
|
|
332
|
+
<div className="text-xs text-gray-500 dark:text-gray-400">
|
|
333
|
+
{isCurrentWallet ? "Switch account or reconnect" : walletOption.description}
|
|
334
|
+
</div>
|
|
335
|
+
</div>
|
|
336
|
+
</div>
|
|
337
|
+
<ChevronRightCircle className="h-5 w-5 text-gray-400" />
|
|
338
|
+
</div>
|
|
339
|
+
</button>
|
|
340
|
+
);
|
|
341
|
+
})}
|
|
342
|
+
</div>
|
|
343
|
+
</>
|
|
344
|
+
) : (
|
|
345
|
+
/* Account Selection Step */
|
|
346
|
+
<div className="space-y-4">
|
|
347
|
+
<p className="text-sm text-gray-600 dark:text-gray-400">
|
|
348
|
+
Connect to {selectedWalletConnector?.name} to view available accounts
|
|
349
|
+
</p>
|
|
350
|
+
<button
|
|
351
|
+
onClick={async () => {
|
|
352
|
+
handleCloseModal();
|
|
353
|
+
await requestWalletPermissions(selectedWalletConnector);
|
|
354
|
+
}}
|
|
355
|
+
disabled={isPending}
|
|
356
|
+
className="w-full rounded-lg border border-gray-200 bg-white p-4 text-center transition-all hover:border-gray-300 hover:shadow-md disabled:opacity-50 dark:border-gray-600 dark:bg-gray-800 dark:hover:border-gray-500"
|
|
357
|
+
>
|
|
358
|
+
<div className="flex items-center justify-center gap-3">
|
|
359
|
+
<div className="flex h-10 w-10 items-center justify-center rounded-lg bg-gray-100 dark:bg-gray-700">
|
|
360
|
+
<Wallet className="h-5 w-5 text-gray-600 dark:text-gray-400" />
|
|
361
|
+
</div>
|
|
362
|
+
<div>
|
|
363
|
+
<div className="text-sm font-medium text-gray-900 dark:text-white">
|
|
364
|
+
{isPending
|
|
365
|
+
? `Connecting to ${selectedWalletConnector?.name}...`
|
|
366
|
+
: `Connect ${selectedWalletConnector?.name}`}
|
|
367
|
+
</div>
|
|
368
|
+
<div className="text-xs text-gray-500 dark:text-gray-400">
|
|
369
|
+
{isPending ? "Please check your wallet" : "Click to connect and select account"}
|
|
370
|
+
</div>
|
|
371
|
+
</div>
|
|
372
|
+
</div>
|
|
373
|
+
</button>
|
|
374
|
+
</div>
|
|
375
|
+
)}
|
|
376
|
+
</div>
|
|
191
377
|
</div>
|
|
192
378
|
</div>,
|
|
193
379
|
typeof window !== "undefined" ? document.getElementById("b3-root") || document.body : document.body,
|
|
@@ -225,7 +225,7 @@ export const OrderDetails = memo(function OrderDetails({
|
|
|
225
225
|
const [showQRCode, setShowQRCode] = useState(false);
|
|
226
226
|
const { isLoading: txLoading, isSuccess: txSuccess } = useWaitForTransactionReceipt({ hash: txHash });
|
|
227
227
|
|
|
228
|
-
const {
|
|
228
|
+
const { switchChainAndExecuteWithEOA, isSwitchingOrExecuting } = useUnifiedChainSwitchAndExecute();
|
|
229
229
|
|
|
230
230
|
const { colorMode } = useColorMode();
|
|
231
231
|
|
|
@@ -260,12 +260,12 @@ export const OrderDetails = memo(function OrderDetails({
|
|
|
260
260
|
value = BigInt(0);
|
|
261
261
|
}
|
|
262
262
|
|
|
263
|
-
const txHash = await
|
|
263
|
+
const txHash = await switchChainAndExecuteWithEOA(order.srcChain, { to, data: txData, value });
|
|
264
264
|
|
|
265
265
|
if (txHash) {
|
|
266
266
|
setTxHash(txHash as `0x${string}`);
|
|
267
267
|
}
|
|
268
|
-
}, [order,
|
|
268
|
+
}, [order, switchChainAndExecuteWithEOA]);
|
|
269
269
|
|
|
270
270
|
// Main payment handler that triggers chain switch and payment
|
|
271
271
|
const handlePayment = async () => {
|
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import { Input,
|
|
1
|
+
import { Input, useProfile, useTokenData } from "@b3dotfun/sdk/global-account/react";
|
|
2
2
|
import { formatUsername } from "@b3dotfun/sdk/shared/utils";
|
|
3
3
|
import { shortenAddress } from "@b3dotfun/sdk/shared/utils/formatAddress";
|
|
4
4
|
import { formatDisplayNumber } from "@b3dotfun/sdk/shared/utils/number";
|
|
5
5
|
import { ChevronRight } from "lucide-react";
|
|
6
6
|
import { motion } from "motion/react";
|
|
7
7
|
import { useEffect, useRef } from "react";
|
|
8
|
+
import { useAccount } from "wagmi";
|
|
8
9
|
import { components } from "../../../types/api";
|
|
9
10
|
import { CryptoPaymentMethodType } from "./CryptoPaymentMethod";
|
|
10
11
|
import { FiatPaymentMethod } from "./FiatPaymentMethod";
|
|
@@ -45,8 +46,9 @@ export function PaySection({
|
|
|
45
46
|
onSelectFiatPaymentMethod,
|
|
46
47
|
anyspendQuote,
|
|
47
48
|
}: PaySectionProps) {
|
|
48
|
-
const { address:
|
|
49
|
-
const
|
|
49
|
+
const { address: connectedAddress, isConnected } = useAccount();
|
|
50
|
+
const { data: profileData } = useProfile({ address: connectedAddress });
|
|
51
|
+
const connectedName = profileData?.displayName;
|
|
50
52
|
const { data: srcTokenMetadata } = useTokenData(selectedSrcToken?.chainId, selectedSrcToken?.address);
|
|
51
53
|
|
|
52
54
|
// Add ref to track if we've applied metadata
|
|
@@ -88,12 +90,12 @@ export function PaySection({
|
|
|
88
90
|
<div className="text-as-primary/50 flex h-7 items-center text-sm">Pay</div>
|
|
89
91
|
{paymentType === "crypto" ? (
|
|
90
92
|
<button
|
|
91
|
-
className="text-as-tertiarry flex h-7 items-center gap-2 text-sm transition-colors"
|
|
93
|
+
className="text-as-tertiarry flex h-7 items-center gap-2 text-sm transition-colors focus:!outline-none"
|
|
92
94
|
onClick={onSelectCryptoPaymentMethod}
|
|
93
95
|
>
|
|
94
96
|
{selectedCryptoPaymentMethod === CryptoPaymentMethodType.CONNECT_WALLET ? (
|
|
95
97
|
<>
|
|
96
|
-
{
|
|
98
|
+
{isConnected ? (
|
|
97
99
|
<div className="flex items-center gap-1">
|
|
98
100
|
{connectedName ? formatUsername(connectedName) : shortenAddress(connectedAddress || "")}
|
|
99
101
|
</div>
|
|
@@ -151,7 +153,7 @@ export function PaySection({
|
|
|
151
153
|
{paymentType === "crypto" ? (
|
|
152
154
|
<>
|
|
153
155
|
<OrderTokenAmount
|
|
154
|
-
address={
|
|
156
|
+
address={connectedAddress}
|
|
155
157
|
context="from"
|
|
156
158
|
inputValue={srcAmount}
|
|
157
159
|
onChangeInput={value => {
|
|
@@ -172,7 +174,7 @@ export function PaySection({
|
|
|
172
174
|
</div>
|
|
173
175
|
<TokenBalance
|
|
174
176
|
token={selectedSrcToken}
|
|
175
|
-
walletAddress={
|
|
177
|
+
walletAddress={connectedAddress}
|
|
176
178
|
onChangeInput={value => {
|
|
177
179
|
setIsSrcInputDirty(true);
|
|
178
180
|
setSrcAmount(value);
|
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
useGeoOnrampOptions,
|
|
8
8
|
} from "@b3dotfun/sdk/anyspend/react";
|
|
9
9
|
import { anyspendService } from "@b3dotfun/sdk/anyspend/services/anyspend";
|
|
10
|
-
import { useAccountWallet, useProfile } from "@b3dotfun/sdk/global-account/react";
|
|
10
|
+
import { useAccountWallet, useProfile, useRouter, useSearchParamsSSR } from "@b3dotfun/sdk/global-account/react";
|
|
11
11
|
import { formatTokenAmount, formatUnits } from "@b3dotfun/sdk/shared/utils/number";
|
|
12
12
|
import { useEffect, useState } from "react";
|
|
13
13
|
import { toast } from "sonner";
|
|
@@ -47,6 +47,9 @@ export function useAnyspendFlow({
|
|
|
47
47
|
sourceTokenAddress,
|
|
48
48
|
sourceTokenChainId,
|
|
49
49
|
}: UseAnyspendFlowProps) {
|
|
50
|
+
const searchParams = useSearchParamsSSR();
|
|
51
|
+
const router = useRouter();
|
|
52
|
+
|
|
50
53
|
// Panel and order state
|
|
51
54
|
const [activePanel, setActivePanel] = useState<PanelView>(loadOrder ? PanelView.ORDER_DETAILS : PanelView.MAIN);
|
|
52
55
|
const [orderId, setOrderId] = useState<string | undefined>(loadOrder);
|
|
@@ -82,6 +85,12 @@ export function useAnyspendFlow({
|
|
|
82
85
|
}
|
|
83
86
|
}, [selectedRecipientAddress, globalAddress]);
|
|
84
87
|
|
|
88
|
+
useEffect(() => {
|
|
89
|
+
if (paymentType === "crypto") {
|
|
90
|
+
setSelectedCryptoPaymentMethod(CryptoPaymentMethodType.CONNECT_WALLET);
|
|
91
|
+
}
|
|
92
|
+
}, [paymentType]);
|
|
93
|
+
|
|
85
94
|
// Fetch specific token when sourceTokenAddress and sourceTokenChainId are provided
|
|
86
95
|
useEffect(() => {
|
|
87
96
|
const fetchSourceToken = async () => {
|
|
@@ -142,6 +151,17 @@ export function useAnyspendFlow({
|
|
|
142
151
|
}
|
|
143
152
|
}, [anyspendQuote]);
|
|
144
153
|
|
|
154
|
+
// Update useEffect for URL parameter to not override loadOrder
|
|
155
|
+
useEffect(() => {
|
|
156
|
+
if (loadOrder) return; // Skip if we have a loadOrder
|
|
157
|
+
|
|
158
|
+
const orderIdParam = searchParams.get("orderId");
|
|
159
|
+
if (orderIdParam) {
|
|
160
|
+
setOrderId(orderIdParam);
|
|
161
|
+
setActivePanel(PanelView.ORDER_DETAILS);
|
|
162
|
+
}
|
|
163
|
+
}, [searchParams, loadOrder]);
|
|
164
|
+
|
|
145
165
|
// Order creation hooks
|
|
146
166
|
const { createOrder, isCreatingOrder } = useAnyspendCreateOrder({
|
|
147
167
|
onSuccess: data => {
|
|
@@ -149,6 +169,18 @@ export function useAnyspendFlow({
|
|
|
149
169
|
setOrderId(newOrderId);
|
|
150
170
|
setActivePanel(PanelView.ORDER_DETAILS);
|
|
151
171
|
onOrderSuccess?.(newOrderId);
|
|
172
|
+
|
|
173
|
+
// Add orderId and payment method to URL for persistence
|
|
174
|
+
const params = new URLSearchParams(searchParams.toString()); // Preserve existing params
|
|
175
|
+
params.set("orderId", newOrderId);
|
|
176
|
+
if (selectedCryptoPaymentMethod !== CryptoPaymentMethodType.NONE) {
|
|
177
|
+
console.log("Setting cryptoPaymentMethod in URL:", selectedCryptoPaymentMethod);
|
|
178
|
+
params.set("cryptoPaymentMethod", selectedCryptoPaymentMethod);
|
|
179
|
+
} else {
|
|
180
|
+
console.log("Payment method is NONE, not setting in URL");
|
|
181
|
+
}
|
|
182
|
+
console.log("Final URL params:", params.toString());
|
|
183
|
+
router.push(`${window.location.pathname}?${params.toString()}`);
|
|
152
184
|
},
|
|
153
185
|
onError: error => {
|
|
154
186
|
console.error(error);
|