@b3dotfun/sdk 0.0.62-alpha.2 → 0.0.62-alpha.3
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 +61 -23
- package/dist/cjs/anyspend/react/components/AnySpendCustom.js +3 -0
- package/dist/cjs/anyspend/react/components/AnyspendDepositHype.js +4 -4
- package/dist/cjs/anyspend/react/components/common/CryptoPaySection.js +4 -6
- package/dist/cjs/anyspend/react/components/common/CryptoPaymentMethod.js +9 -17
- package/dist/cjs/anyspend/react/components/common/CryptoReceiveSection.d.ts +6 -1
- package/dist/cjs/anyspend/react/components/common/CryptoReceiveSection.js +11 -1
- package/dist/cjs/anyspend/react/components/common/OrderDetails.js +56 -145
- package/dist/cjs/anyspend/react/components/common/OrderTokenAmount.d.ts +2 -1
- package/dist/cjs/anyspend/react/components/common/OrderTokenAmount.js +39 -15
- package/dist/cjs/anyspend/react/components/common/PaySection.js +1 -1
- package/dist/cjs/anyspend/react/components/common/TokenBalance.js +1 -1
- package/dist/cjs/anyspend/react/hooks/useAnyspendFlow.js +12 -11
- package/dist/cjs/anyspend/react/hooks/useAutoSelectCryptoPaymentMethod.d.ts +26 -0
- package/dist/cjs/anyspend/react/hooks/useAutoSelectCryptoPaymentMethod.js +56 -0
- package/dist/cjs/anyspend/react/hooks/useAutoSetActiveWalletFromWagmi.d.ts +10 -0
- package/dist/cjs/anyspend/react/hooks/useAutoSetActiveWalletFromWagmi.js +73 -0
- package/dist/cjs/anyspend/react/hooks/useConnectedWalletDisplay.d.ts +14 -0
- package/dist/cjs/anyspend/react/hooks/useConnectedWalletDisplay.js +57 -0
- package/dist/cjs/anyspend/react/hooks/usePhantomTransfer.d.ts +36 -0
- package/dist/cjs/anyspend/react/hooks/usePhantomTransfer.js +211 -0
- package/dist/cjs/global-account/react/hooks/index.d.ts +2 -1
- package/dist/cjs/global-account/react/hooks/index.js +5 -3
- package/dist/cjs/global-account/react/hooks/useTokenBalanceDirect.d.ts +12 -0
- package/dist/cjs/global-account/react/hooks/useTokenBalanceDirect.js +62 -0
- package/dist/cjs/global-account/react/hooks/useTokenFromUrl.js +4 -3
- package/dist/esm/anyspend/react/components/AnySpend.js +62 -24
- package/dist/esm/anyspend/react/components/AnySpendCustom.js +3 -0
- package/dist/esm/anyspend/react/components/AnyspendDepositHype.js +4 -4
- package/dist/esm/anyspend/react/components/common/CryptoPaySection.js +5 -7
- package/dist/esm/anyspend/react/components/common/CryptoPaymentMethod.js +9 -17
- package/dist/esm/anyspend/react/components/common/CryptoReceiveSection.d.ts +6 -1
- package/dist/esm/anyspend/react/components/common/CryptoReceiveSection.js +11 -1
- package/dist/esm/anyspend/react/components/common/OrderDetails.js +57 -146
- package/dist/esm/anyspend/react/components/common/OrderTokenAmount.d.ts +2 -1
- package/dist/esm/anyspend/react/components/common/OrderTokenAmount.js +40 -16
- package/dist/esm/anyspend/react/components/common/PaySection.js +1 -1
- package/dist/esm/anyspend/react/components/common/TokenBalance.js +2 -2
- package/dist/esm/anyspend/react/hooks/useAnyspendFlow.js +12 -11
- package/dist/esm/anyspend/react/hooks/useAutoSelectCryptoPaymentMethod.d.ts +26 -0
- package/dist/esm/anyspend/react/hooks/useAutoSelectCryptoPaymentMethod.js +53 -0
- package/dist/esm/anyspend/react/hooks/useAutoSetActiveWalletFromWagmi.d.ts +10 -0
- package/dist/esm/anyspend/react/hooks/useAutoSetActiveWalletFromWagmi.js +70 -0
- package/dist/esm/anyspend/react/hooks/useConnectedWalletDisplay.d.ts +14 -0
- package/dist/esm/anyspend/react/hooks/useConnectedWalletDisplay.js +54 -0
- package/dist/esm/anyspend/react/hooks/usePhantomTransfer.d.ts +36 -0
- package/dist/esm/anyspend/react/hooks/usePhantomTransfer.js +208 -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/useTokenBalanceDirect.d.ts +12 -0
- package/dist/esm/global-account/react/hooks/useTokenBalanceDirect.js +59 -0
- package/dist/esm/global-account/react/hooks/useTokenFromUrl.js +4 -3
- package/dist/types/anyspend/react/components/common/CryptoReceiveSection.d.ts +6 -1
- package/dist/types/anyspend/react/components/common/OrderTokenAmount.d.ts +2 -1
- package/dist/types/anyspend/react/hooks/useAutoSelectCryptoPaymentMethod.d.ts +26 -0
- package/dist/types/anyspend/react/hooks/useAutoSetActiveWalletFromWagmi.d.ts +10 -0
- package/dist/types/anyspend/react/hooks/useConnectedWalletDisplay.d.ts +14 -0
- package/dist/types/anyspend/react/hooks/usePhantomTransfer.d.ts +36 -0
- package/dist/types/global-account/react/hooks/index.d.ts +2 -1
- package/dist/types/global-account/react/hooks/useTokenBalanceDirect.d.ts +12 -0
- package/package.json +1 -1
- package/src/anyspend/react/components/AnySpend.tsx +73 -22
- package/src/anyspend/react/components/AnySpendCustom.tsx +4 -0
- package/src/anyspend/react/components/AnyspendDepositHype.tsx +7 -3
- package/src/anyspend/react/components/common/CryptoPaySection.tsx +5 -7
- package/src/anyspend/react/components/common/CryptoPaymentMethod.tsx +9 -18
- package/src/anyspend/react/components/common/CryptoReceiveSection.tsx +22 -0
- package/src/anyspend/react/components/common/OrderDetails.tsx +66 -188
- package/src/anyspend/react/components/common/OrderTokenAmount.tsx +48 -17
- package/src/anyspend/react/components/common/PaySection.tsx +1 -0
- package/src/anyspend/react/components/common/TokenBalance.tsx +2 -2
- package/src/anyspend/react/hooks/useAnyspendFlow.ts +13 -10
- package/src/anyspend/react/hooks/useAutoSelectCryptoPaymentMethod.ts +72 -0
- package/src/anyspend/react/hooks/useAutoSetActiveWalletFromWagmi.ts +80 -0
- package/src/anyspend/react/hooks/useConnectedWalletDisplay.ts +69 -0
- package/src/anyspend/react/hooks/usePhantomTransfer.ts +301 -0
- package/src/global-account/react/hooks/index.ts +2 -1
- package/src/global-account/react/hooks/useTokenBalanceDirect.tsx +84 -0
- package/src/global-account/react/hooks/useTokenFromUrl.tsx +6 -5
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.useConnectedWalletDisplay = useConnectedWalletDisplay;
|
|
4
|
+
const react_1 = require("../../../global-account/react");
|
|
5
|
+
const wagmi_1 = require("wagmi");
|
|
6
|
+
const CryptoPaymentMethod_1 = require("../components/common/CryptoPaymentMethod");
|
|
7
|
+
/**
|
|
8
|
+
* Custom hook to determine which wallet to display and its address
|
|
9
|
+
* Handles logic for showing EOA wallet, wagmi wallet, or global wallet based on payment method
|
|
10
|
+
*/
|
|
11
|
+
function useConnectedWalletDisplay(selectedCryptoPaymentMethod) {
|
|
12
|
+
const { connectedEOAWallet, connectedSmartWallet } = (0, react_1.useAccountWallet)();
|
|
13
|
+
const { address: wagmiAddress, isConnected: wagmiWalletIsConnected } = (0, wagmi_1.useAccount)();
|
|
14
|
+
// Helper function to check if two addresses are the same
|
|
15
|
+
const isSameAddress = (addr1, addr2) => {
|
|
16
|
+
if (!addr1 || !addr2)
|
|
17
|
+
return false;
|
|
18
|
+
return addr1.toLowerCase() === addr2.toLowerCase();
|
|
19
|
+
};
|
|
20
|
+
// Check if connectedEOAWallet and wagmi wallet represent the same wallet
|
|
21
|
+
const connectedEOAAddress = connectedEOAWallet?.getAccount()?.address;
|
|
22
|
+
const isWalletDuplicated = isSameAddress(connectedEOAAddress, wagmiAddress);
|
|
23
|
+
// Determine which wallet to show (prefer connectedEOAWallet if both exist and are the same)
|
|
24
|
+
const shouldShowConnectedEOA = !!connectedEOAWallet;
|
|
25
|
+
const shouldShowWagmiWallet = wagmiWalletIsConnected && (!isWalletDuplicated || !connectedEOAWallet);
|
|
26
|
+
// Determine which address to use based on payment method
|
|
27
|
+
let walletAddress;
|
|
28
|
+
if (selectedCryptoPaymentMethod === CryptoPaymentMethod_1.CryptoPaymentMethodType.GLOBAL_WALLET) {
|
|
29
|
+
walletAddress = connectedSmartWallet?.getAccount()?.address;
|
|
30
|
+
}
|
|
31
|
+
else if (selectedCryptoPaymentMethod === CryptoPaymentMethod_1.CryptoPaymentMethodType.CONNECT_WALLET) {
|
|
32
|
+
// Prefer connectedEOAWallet, fallback to wagmi wallet
|
|
33
|
+
walletAddress = connectedEOAAddress || wagmiAddress;
|
|
34
|
+
}
|
|
35
|
+
else {
|
|
36
|
+
// Default behavior: use connectedEOAWallet if available, otherwise wagmi
|
|
37
|
+
walletAddress = connectedEOAAddress || wagmiAddress;
|
|
38
|
+
}
|
|
39
|
+
// Suggest a payment method based on available wallets
|
|
40
|
+
// Priority: Connected EOA/Wagmi wallet > Global wallet > None
|
|
41
|
+
let suggestedPaymentMethod = CryptoPaymentMethod_1.CryptoPaymentMethodType.NONE;
|
|
42
|
+
if (connectedEOAAddress || wagmiAddress) {
|
|
43
|
+
// If there's a connected EOA or wagmi wallet, suggest CONNECT_WALLET
|
|
44
|
+
suggestedPaymentMethod = CryptoPaymentMethod_1.CryptoPaymentMethodType.CONNECT_WALLET;
|
|
45
|
+
}
|
|
46
|
+
else if (connectedSmartWallet?.getAccount()?.address) {
|
|
47
|
+
// If only global wallet is available, suggest that
|
|
48
|
+
suggestedPaymentMethod = CryptoPaymentMethod_1.CryptoPaymentMethodType.GLOBAL_WALLET;
|
|
49
|
+
}
|
|
50
|
+
return {
|
|
51
|
+
walletAddress,
|
|
52
|
+
shouldShowConnectedEOA,
|
|
53
|
+
shouldShowWagmiWallet,
|
|
54
|
+
isWalletDuplicated,
|
|
55
|
+
suggestedPaymentMethod,
|
|
56
|
+
};
|
|
57
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
interface UsePhantomTransferParams {
|
|
2
|
+
/** RPC endpoint URL for Solana network */
|
|
3
|
+
rpcEndpoint?: string;
|
|
4
|
+
}
|
|
5
|
+
interface PhantomTransferParams {
|
|
6
|
+
/** Amount in lamports (for SOL) or smallest token unit (for SPL tokens) */
|
|
7
|
+
amountLamports: string;
|
|
8
|
+
/** Token address (use "11111111111111111111111111111111" for native SOL) */
|
|
9
|
+
tokenAddress: string;
|
|
10
|
+
/** Recipient address */
|
|
11
|
+
recipientAddress: string;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Custom hook for handling Phantom wallet transfers on Solana.
|
|
15
|
+
* Supports both native SOL and SPL token transfers with automatic priority fee calculation.
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* ```tsx
|
|
19
|
+
* const { initiateTransfer, isPhantomAvailable } = usePhantomTransfer();
|
|
20
|
+
*
|
|
21
|
+
* await initiateTransfer({
|
|
22
|
+
* amountLamports: "1000000000", // 1 SOL
|
|
23
|
+
* tokenAddress: "11111111111111111111111111111111",
|
|
24
|
+
* recipientAddress: "..."
|
|
25
|
+
* });
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
28
|
+
export declare function usePhantomTransfer({ rpcEndpoint }?: UsePhantomTransferParams): {
|
|
29
|
+
/** Function to initiate a transfer */
|
|
30
|
+
initiateTransfer: ({ amountLamports, tokenAddress, recipientAddress }: PhantomTransferParams) => Promise<void>;
|
|
31
|
+
/** Whether Phantom wallet is available (installed) */
|
|
32
|
+
isPhantomAvailable: any;
|
|
33
|
+
/** Get the currently connected Phantom wallet address */
|
|
34
|
+
getConnectedAddress: () => any;
|
|
35
|
+
};
|
|
36
|
+
export {};
|
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.usePhantomTransfer = usePhantomTransfer;
|
|
4
|
+
const spl_token_1 = require("@solana/spl-token");
|
|
5
|
+
const web3_js_1 = require("@solana/web3.js");
|
|
6
|
+
const react_1 = require("react");
|
|
7
|
+
const sonner_1 = require("sonner");
|
|
8
|
+
/**
|
|
9
|
+
* Custom hook for handling Phantom wallet transfers on Solana.
|
|
10
|
+
* Supports both native SOL and SPL token transfers with automatic priority fee calculation.
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```tsx
|
|
14
|
+
* const { initiateTransfer, isPhantomAvailable } = usePhantomTransfer();
|
|
15
|
+
*
|
|
16
|
+
* await initiateTransfer({
|
|
17
|
+
* amountLamports: "1000000000", // 1 SOL
|
|
18
|
+
* tokenAddress: "11111111111111111111111111111111",
|
|
19
|
+
* recipientAddress: "..."
|
|
20
|
+
* });
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
23
|
+
function usePhantomTransfer({ rpcEndpoint } = {}) {
|
|
24
|
+
// Default RPC endpoint
|
|
25
|
+
const defaultRpcEndpoint = "https://mainnet.helius-rpc.com/?api-key=efafd9b3-1807-4cf8-8aa4-3d984f56d8fb";
|
|
26
|
+
const effectiveRpcEndpoint = rpcEndpoint || defaultRpcEndpoint;
|
|
27
|
+
// Check for Phantom wallet availability
|
|
28
|
+
const isPhantomMobile = (0, react_1.useMemo)(() => navigator.userAgent.includes("Phantom"), []);
|
|
29
|
+
const isPhantomBrowser = (0, react_1.useMemo)(() => window.phantom?.solana?.isPhantom, []);
|
|
30
|
+
const isPhantomAvailable = isPhantomMobile || isPhantomBrowser;
|
|
31
|
+
/**
|
|
32
|
+
* Get the connected Phantom wallet address if available
|
|
33
|
+
*/
|
|
34
|
+
const getConnectedAddress = (0, react_1.useCallback)(() => {
|
|
35
|
+
const phantom = window.phantom?.solana;
|
|
36
|
+
if (phantom?.isConnected && phantom?.publicKey) {
|
|
37
|
+
return phantom.publicKey.toString();
|
|
38
|
+
}
|
|
39
|
+
return null;
|
|
40
|
+
}, []);
|
|
41
|
+
/**
|
|
42
|
+
* Calculate optimal priority fee based on recent network activity
|
|
43
|
+
*/
|
|
44
|
+
const calculatePriorityFee = (0, react_1.useCallback)(async (connection, fromPubkey) => {
|
|
45
|
+
let priorityFee = 10000; // Default fallback (10,000 micro-lamports)
|
|
46
|
+
try {
|
|
47
|
+
const recentFees = await connection.getRecentPrioritizationFees({
|
|
48
|
+
lockedWritableAccounts: [fromPubkey],
|
|
49
|
+
});
|
|
50
|
+
if (recentFees && recentFees.length > 0) {
|
|
51
|
+
// Use 75th percentile of recent fees for good priority
|
|
52
|
+
const sortedFees = recentFees.map(fee => fee.prioritizationFee).sort((a, b) => a - b);
|
|
53
|
+
const percentile75Index = Math.floor(sortedFees.length * 0.75);
|
|
54
|
+
priorityFee = Math.max(sortedFees[percentile75Index] || 10000, 10000);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
catch (feeError) {
|
|
58
|
+
console.warn("Failed to fetch recent priority fees, using default:", feeError);
|
|
59
|
+
}
|
|
60
|
+
return priorityFee;
|
|
61
|
+
}, []);
|
|
62
|
+
/**
|
|
63
|
+
* Create a native SOL transfer transaction with priority fees
|
|
64
|
+
*/
|
|
65
|
+
const createNativeTransferTransaction = (0, react_1.useCallback)(async (_connection, fromPubkey, toPubkey, amount, priorityFee) => {
|
|
66
|
+
const computeUnitLimit = 1000; // SOL transfer + compute budget instructions need ~600-800 CU
|
|
67
|
+
const computeUnitPrice = Math.min(priorityFee, 100000); // Cap at 100k micro-lamports for safety
|
|
68
|
+
const transaction = new web3_js_1.Transaction()
|
|
69
|
+
.add(
|
|
70
|
+
// Set compute unit limit first (must come before other instructions)
|
|
71
|
+
web3_js_1.ComputeBudgetProgram.setComputeUnitLimit({
|
|
72
|
+
units: computeUnitLimit,
|
|
73
|
+
}))
|
|
74
|
+
.add(
|
|
75
|
+
// Set priority fee
|
|
76
|
+
web3_js_1.ComputeBudgetProgram.setComputeUnitPrice({
|
|
77
|
+
microLamports: computeUnitPrice,
|
|
78
|
+
}))
|
|
79
|
+
.add(
|
|
80
|
+
// Actual transfer instruction
|
|
81
|
+
web3_js_1.SystemProgram.transfer({
|
|
82
|
+
fromPubkey,
|
|
83
|
+
toPubkey,
|
|
84
|
+
lamports: Number(amount),
|
|
85
|
+
}));
|
|
86
|
+
console.log(`Using priority fee: ${computeUnitPrice} micro-lamports per CU, limit: ${computeUnitLimit} CU`);
|
|
87
|
+
return transaction;
|
|
88
|
+
}, []);
|
|
89
|
+
/**
|
|
90
|
+
* Create an SPL token transfer transaction with priority fees
|
|
91
|
+
*/
|
|
92
|
+
const createSPLTransferTransaction = (0, react_1.useCallback)(async (connection, fromPubkey, toPubkey, mintPubkey, amount, priorityFee) => {
|
|
93
|
+
// Get associated token accounts
|
|
94
|
+
const fromTokenAccount = (0, spl_token_1.getAssociatedTokenAddressSync)(mintPubkey, fromPubkey);
|
|
95
|
+
const toTokenAccount = (0, spl_token_1.getAssociatedTokenAddressSync)(mintPubkey, toPubkey);
|
|
96
|
+
// Check if destination token account exists
|
|
97
|
+
const toTokenAccountInfo = await connection.getAccountInfo(toTokenAccount);
|
|
98
|
+
const needsDestinationAccount = !toTokenAccountInfo;
|
|
99
|
+
// Get mint info to determine decimals
|
|
100
|
+
const mintInfo = await connection.getParsedAccountInfo(mintPubkey);
|
|
101
|
+
const decimals = mintInfo.value?.data?.parsed?.info?.decimals || 9;
|
|
102
|
+
// SPL transfers need more compute units than SOL transfers
|
|
103
|
+
// Add extra CU if we need to create destination account
|
|
104
|
+
const computeUnitLimit = needsDestinationAccount ? 40000 : 20000;
|
|
105
|
+
const computeUnitPrice = Math.min(priorityFee, 100000);
|
|
106
|
+
// Create transfer instruction
|
|
107
|
+
const transferInstruction = (0, spl_token_1.createTransferCheckedInstruction)(fromTokenAccount, mintPubkey, toTokenAccount, fromPubkey, Number(amount), decimals);
|
|
108
|
+
const transaction = new web3_js_1.Transaction()
|
|
109
|
+
.add(web3_js_1.ComputeBudgetProgram.setComputeUnitLimit({
|
|
110
|
+
units: computeUnitLimit,
|
|
111
|
+
}))
|
|
112
|
+
.add(web3_js_1.ComputeBudgetProgram.setComputeUnitPrice({
|
|
113
|
+
microLamports: computeUnitPrice,
|
|
114
|
+
}));
|
|
115
|
+
// Add create destination account instruction if needed
|
|
116
|
+
if (needsDestinationAccount) {
|
|
117
|
+
transaction.add((0, spl_token_1.createAssociatedTokenAccountInstruction)(fromPubkey, // payer
|
|
118
|
+
toTokenAccount, // ata
|
|
119
|
+
toPubkey, // owner
|
|
120
|
+
mintPubkey));
|
|
121
|
+
}
|
|
122
|
+
// Add the transfer instruction
|
|
123
|
+
transaction.add(transferInstruction);
|
|
124
|
+
console.log(`SPL Token transfer: ${computeUnitPrice} micro-lamports per CU, limit: ${computeUnitLimit} CU, creating destination: ${needsDestinationAccount}`);
|
|
125
|
+
return transaction;
|
|
126
|
+
}, []);
|
|
127
|
+
/**
|
|
128
|
+
* Initiate a Phantom wallet transfer for SOL or SPL tokens
|
|
129
|
+
*/
|
|
130
|
+
const initiateTransfer = (0, react_1.useCallback)(async ({ amountLamports, tokenAddress, recipientAddress }) => {
|
|
131
|
+
try {
|
|
132
|
+
// Step 1: Check if Phantom is installed
|
|
133
|
+
if (!isPhantomAvailable) {
|
|
134
|
+
sonner_1.toast.error("Phantom wallet not installed. Please install Phantom wallet to continue.");
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
// Step 2: Ensure Phantom is connected/unlocked
|
|
138
|
+
const phantom = window.phantom?.solana;
|
|
139
|
+
if (!phantom) {
|
|
140
|
+
sonner_1.toast.error("Phantom wallet not accessible");
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
// Connect and unlock wallet if needed
|
|
144
|
+
let publicKey;
|
|
145
|
+
try {
|
|
146
|
+
const connection = await phantom.connect();
|
|
147
|
+
publicKey = connection.publicKey;
|
|
148
|
+
}
|
|
149
|
+
catch (connectError) {
|
|
150
|
+
sonner_1.toast.error("Failed to connect to Phantom wallet");
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
// Step 3: Setup connection and public keys
|
|
154
|
+
const connection = new web3_js_1.Connection(effectiveRpcEndpoint);
|
|
155
|
+
const fromPubkey = new web3_js_1.PublicKey(publicKey.toString());
|
|
156
|
+
const toPubkey = new web3_js_1.PublicKey(recipientAddress);
|
|
157
|
+
const amount = BigInt(amountLamports);
|
|
158
|
+
// Step 4: Calculate optimal priority fee
|
|
159
|
+
const priorityFee = await calculatePriorityFee(connection, fromPubkey);
|
|
160
|
+
// Step 5: Create transaction based on token type
|
|
161
|
+
let transaction;
|
|
162
|
+
if (tokenAddress === "11111111111111111111111111111111") {
|
|
163
|
+
// Native SOL transfer
|
|
164
|
+
transaction = await createNativeTransferTransaction(connection, fromPubkey, toPubkey, amount, priorityFee);
|
|
165
|
+
}
|
|
166
|
+
else {
|
|
167
|
+
// SPL Token transfer
|
|
168
|
+
const mintPubkey = new web3_js_1.PublicKey(tokenAddress);
|
|
169
|
+
transaction = await createSPLTransferTransaction(connection, fromPubkey, toPubkey, mintPubkey, amount, priorityFee);
|
|
170
|
+
}
|
|
171
|
+
// Step 6: Get latest blockhash and set fee payer
|
|
172
|
+
const { blockhash } = await connection.getLatestBlockhash("confirmed");
|
|
173
|
+
transaction.recentBlockhash = blockhash;
|
|
174
|
+
transaction.feePayer = fromPubkey;
|
|
175
|
+
// Step 7: Sign and send transaction
|
|
176
|
+
const signedTransaction = await phantom.signAndSendTransaction(transaction);
|
|
177
|
+
sonner_1.toast.success(`Transaction successful! Signature: ${signedTransaction.signature}`);
|
|
178
|
+
console.log("Transaction sent with priority fees. Signature:", signedTransaction.signature);
|
|
179
|
+
}
|
|
180
|
+
catch (error) {
|
|
181
|
+
console.error("Transfer error:", error);
|
|
182
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
183
|
+
if (errorMessage.includes("User rejected")) {
|
|
184
|
+
sonner_1.toast.error("Transaction was cancelled by user");
|
|
185
|
+
}
|
|
186
|
+
else if (errorMessage.includes("insufficient")) {
|
|
187
|
+
sonner_1.toast.error("Insufficient balance for this transaction");
|
|
188
|
+
}
|
|
189
|
+
else if (errorMessage.includes("blockhash not found")) {
|
|
190
|
+
sonner_1.toast.error("Network congestion detected. Please try again in a moment.");
|
|
191
|
+
}
|
|
192
|
+
else {
|
|
193
|
+
sonner_1.toast.error(`Transfer failed: ${errorMessage}`);
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
}, [
|
|
197
|
+
isPhantomAvailable,
|
|
198
|
+
effectiveRpcEndpoint,
|
|
199
|
+
calculatePriorityFee,
|
|
200
|
+
createNativeTransferTransaction,
|
|
201
|
+
createSPLTransferTransaction,
|
|
202
|
+
]);
|
|
203
|
+
return {
|
|
204
|
+
/** Function to initiate a transfer */
|
|
205
|
+
initiateTransfer,
|
|
206
|
+
/** Whether Phantom wallet is available (installed) */
|
|
207
|
+
isPhantomAvailable,
|
|
208
|
+
/** Get the currently connected Phantom wallet address */
|
|
209
|
+
getConnectedAddress,
|
|
210
|
+
};
|
|
211
|
+
}
|
|
@@ -32,11 +32,12 @@ export { useSearchParamsSSR } from "./useSearchParamsSSR";
|
|
|
32
32
|
export { useSimBalance } from "./useSimBalance";
|
|
33
33
|
export { useSiwe } from "./useSiwe";
|
|
34
34
|
export { useTokenBalance } from "./useTokenBalance";
|
|
35
|
+
export { useTokenBalanceDirect } from "./useTokenBalanceDirect";
|
|
35
36
|
export { useTokenBalancesByChain } from "./useTokenBalancesByChain";
|
|
36
37
|
export { useTokenData } from "./useTokenData";
|
|
37
38
|
export { useTokenFromUrl } from "./useTokenFromUrl";
|
|
38
39
|
export { useTokenPrice } from "./useTokenPrice";
|
|
39
40
|
export { useTokenPriceWithFallback } from "./useTokenPriceWithFallback";
|
|
40
41
|
export { useTokensFromAddress } from "./useTokensFromAddress";
|
|
41
|
-
export { useUnifiedChainSwitchAndExecute } from "./useUnifiedChainSwitchAndExecute";
|
|
42
42
|
export { useURLParams } from "./useURLParams";
|
|
43
|
+
export { useUnifiedChainSwitchAndExecute } from "./useUnifiedChainSwitchAndExecute";
|
|
@@ -14,7 +14,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
14
14
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
15
|
};
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
-
exports.
|
|
17
|
+
exports.useUnifiedChainSwitchAndExecute = exports.useURLParams = exports.useTokensFromAddress = exports.useTokenPriceWithFallback = exports.useTokenPrice = exports.useTokenFromUrl = exports.useTokenData = exports.useTokenBalancesByChain = exports.useTokenBalanceDirect = exports.useTokenBalance = exports.useSiwe = exports.useSimBalance = exports.useSearchParamsSSR = exports.useRouter = exports.useRemoveSessionKey = exports.useQueryBSMNT = exports.useQueryB3 = exports.useProfilePreference = exports.useProfile = exports.useOneBalance = exports.useNativeBalanceFromRPC = exports.useNativeBalance = exports.useMediaQuery = exports.useIsomorphicLayoutEffect = exports.useIsMobile = exports.useHasMounted = exports.useHandleConnectWithPrivy = exports.useGlobalAccount = exports.useGetGeo = exports.useGetAllTWSigners = exports.useFirstEOA = exports.useExchangeRate = exports.useConnect = exports.useClient = exports.useChainSwitchWithAction = exports.useBestTransactionPath = exports.useB3EnsName = exports.useB3BalanceFromAddresses = exports.useAuthentication = exports.useAnalytics = exports.useAddTWSessionKey = exports.useAccountWallet = exports.useAccountAssets = exports.createWagmiConfig = void 0;
|
|
18
18
|
var createWagmiConfig_1 = require("../utils/createWagmiConfig");
|
|
19
19
|
Object.defineProperty(exports, "createWagmiConfig", { enumerable: true, get: function () { return createWagmiConfig_1.createWagmiConfig; } });
|
|
20
20
|
var useAccountAssets_1 = require("./useAccountAssets");
|
|
@@ -84,6 +84,8 @@ var useSiwe_1 = require("./useSiwe");
|
|
|
84
84
|
Object.defineProperty(exports, "useSiwe", { enumerable: true, get: function () { return useSiwe_1.useSiwe; } });
|
|
85
85
|
var useTokenBalance_1 = require("./useTokenBalance");
|
|
86
86
|
Object.defineProperty(exports, "useTokenBalance", { enumerable: true, get: function () { return useTokenBalance_1.useTokenBalance; } });
|
|
87
|
+
var useTokenBalanceDirect_1 = require("./useTokenBalanceDirect");
|
|
88
|
+
Object.defineProperty(exports, "useTokenBalanceDirect", { enumerable: true, get: function () { return useTokenBalanceDirect_1.useTokenBalanceDirect; } });
|
|
87
89
|
var useTokenBalancesByChain_1 = require("./useTokenBalancesByChain");
|
|
88
90
|
Object.defineProperty(exports, "useTokenBalancesByChain", { enumerable: true, get: function () { return useTokenBalancesByChain_1.useTokenBalancesByChain; } });
|
|
89
91
|
var useTokenData_1 = require("./useTokenData");
|
|
@@ -96,7 +98,7 @@ var useTokenPriceWithFallback_1 = require("./useTokenPriceWithFallback");
|
|
|
96
98
|
Object.defineProperty(exports, "useTokenPriceWithFallback", { enumerable: true, get: function () { return useTokenPriceWithFallback_1.useTokenPriceWithFallback; } });
|
|
97
99
|
var useTokensFromAddress_1 = require("./useTokensFromAddress");
|
|
98
100
|
Object.defineProperty(exports, "useTokensFromAddress", { enumerable: true, get: function () { return useTokensFromAddress_1.useTokensFromAddress; } });
|
|
99
|
-
var useUnifiedChainSwitchAndExecute_1 = require("./useUnifiedChainSwitchAndExecute");
|
|
100
|
-
Object.defineProperty(exports, "useUnifiedChainSwitchAndExecute", { enumerable: true, get: function () { return useUnifiedChainSwitchAndExecute_1.useUnifiedChainSwitchAndExecute; } });
|
|
101
101
|
var useURLParams_1 = require("./useURLParams");
|
|
102
102
|
Object.defineProperty(exports, "useURLParams", { enumerable: true, get: function () { return useURLParams_1.useURLParams; } });
|
|
103
|
+
var useUnifiedChainSwitchAndExecute_1 = require("./useUnifiedChainSwitchAndExecute");
|
|
104
|
+
Object.defineProperty(exports, "useUnifiedChainSwitchAndExecute", { enumerable: true, get: function () { return useUnifiedChainSwitchAndExecute_1.useUnifiedChainSwitchAndExecute; } });
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { components } from "../../../anyspend/types/api";
|
|
2
|
+
interface UseTokenBalanceProps {
|
|
3
|
+
token: components["schemas"]["Token"];
|
|
4
|
+
address?: string;
|
|
5
|
+
}
|
|
6
|
+
export interface TokenBalanceResult {
|
|
7
|
+
rawBalance: bigint | null;
|
|
8
|
+
formattedBalance: string;
|
|
9
|
+
isLoading: boolean;
|
|
10
|
+
}
|
|
11
|
+
export declare function useTokenBalanceDirect({ token, address }: UseTokenBalanceProps): TokenBalanceResult;
|
|
12
|
+
export {};
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
"use client";
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
exports.useTokenBalanceDirect = useTokenBalanceDirect;
|
|
5
|
+
const anyspend_1 = require("../../../anyspend");
|
|
6
|
+
const react_1 = require("../../../global-account/react");
|
|
7
|
+
const number_1 = require("../../../shared/utils/number");
|
|
8
|
+
const thirdweb_insights_1 = require("../../../shared/utils/thirdweb-insights");
|
|
9
|
+
const react_query_1 = require("@tanstack/react-query");
|
|
10
|
+
const react_2 = require("react");
|
|
11
|
+
function useTokenBalanceDirect({ token, address }) {
|
|
12
|
+
const account = (0, react_1.useAccountWallet)();
|
|
13
|
+
const effectiveAddress = address || account?.address;
|
|
14
|
+
const { data: tokenBalance, isLoading, isFetching, refetch, } = (0, react_query_1.useQuery)({
|
|
15
|
+
queryKey: ["tokenBalance", effectiveAddress, token.chainId, token.address],
|
|
16
|
+
queryFn: async () => {
|
|
17
|
+
if (!effectiveAddress)
|
|
18
|
+
return { formatted: "0", raw: null };
|
|
19
|
+
if ((0, anyspend_1.isNativeToken)(token.address)) {
|
|
20
|
+
const nativeToken = await (0, thirdweb_insights_1.getNativeTokenBalance)(effectiveAddress, token.chainId);
|
|
21
|
+
if (nativeToken && nativeToken.balance) {
|
|
22
|
+
const rawBalance = nativeToken.balance;
|
|
23
|
+
return {
|
|
24
|
+
formatted: (0, number_1.formatTokenAmount)(BigInt(rawBalance), Number(nativeToken.decimals || 18)),
|
|
25
|
+
raw: BigInt(rawBalance),
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
return { formatted: "0", raw: null };
|
|
29
|
+
}
|
|
30
|
+
const response = await (0, thirdweb_insights_1.getERC20Balances)(effectiveAddress, {
|
|
31
|
+
chainIds: [token.chainId],
|
|
32
|
+
includeSpam: false,
|
|
33
|
+
});
|
|
34
|
+
const tokenBalance = response.data?.find(t => t.token_address === token.address);
|
|
35
|
+
if (tokenBalance?.balance) {
|
|
36
|
+
return {
|
|
37
|
+
formatted: (0, number_1.formatTokenAmount)(BigInt(tokenBalance.balance), Number(tokenBalance.decimals || 18)),
|
|
38
|
+
raw: BigInt(tokenBalance.balance),
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
return { formatted: "0", raw: null };
|
|
42
|
+
},
|
|
43
|
+
enabled: !!effectiveAddress,
|
|
44
|
+
staleTime: 30000,
|
|
45
|
+
gcTime: 5 * 60 * 1000,
|
|
46
|
+
retry: 2,
|
|
47
|
+
structuralSharing: false,
|
|
48
|
+
});
|
|
49
|
+
// Force a refetch when the wallet or token changes
|
|
50
|
+
(0, react_2.useEffect)(() => {
|
|
51
|
+
if (effectiveAddress) {
|
|
52
|
+
refetch();
|
|
53
|
+
}
|
|
54
|
+
}, [effectiveAddress, token.address, token.chainId, token.symbol, refetch]);
|
|
55
|
+
// Determine if we're actually loading
|
|
56
|
+
const isActuallyLoading = !effectiveAddress || isLoading || (isFetching && !tokenBalance);
|
|
57
|
+
return {
|
|
58
|
+
rawBalance: tokenBalance?.raw || BigInt(0),
|
|
59
|
+
formattedBalance: tokenBalance?.formatted || "0",
|
|
60
|
+
isLoading: isActuallyLoading,
|
|
61
|
+
};
|
|
62
|
+
}
|
|
@@ -32,10 +32,11 @@ function useTokenFromUrl({ defaultToken, prefix }) {
|
|
|
32
32
|
// Get parameters from URL
|
|
33
33
|
const currencyParam = searchParams.get(`${prefix}Currency`);
|
|
34
34
|
const chainIdParam = searchParams.get(`${prefix}ChainId`);
|
|
35
|
-
// Determine if we should fetch token info
|
|
36
|
-
const shouldFetchToken = Boolean(currencyParam && chainIdParam && currencyParam.toLowerCase() !== defaultToken.address.toLowerCase());
|
|
37
35
|
// Determine network based on chainId
|
|
38
|
-
const
|
|
36
|
+
const chainInfo = chainIdParam ? (0, supported_1.getCoingeckoChainInfo)(Number(chainIdParam)) : null;
|
|
37
|
+
const network = chainInfo?.coingecko_id || "";
|
|
38
|
+
// Determine if we should fetch token info
|
|
39
|
+
const shouldFetchToken = Boolean(currencyParam && chainIdParam && chainInfo && currencyParam.toLowerCase() !== defaultToken.address.toLowerCase());
|
|
39
40
|
const { data: tokenInfo, isError } = (0, react_query_1.useQuery)({
|
|
40
41
|
queryKey: ["tokenInfo", network, currencyParam],
|
|
41
42
|
queryFn: () => fetchTokenInfo(network, currencyParam || ""),
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
3
|
import { getDefaultToken, USDC_BASE } from "../../../anyspend/index.js";
|
|
4
4
|
import { useAnyspendCreateOnrampOrder, useAnyspendCreateOrder, useAnyspendOrderAndTransactions, useAnyspendQuote, useGeoOnrampOptions, } from "../../../anyspend/react/index.js";
|
|
5
|
-
import { Button, ShinyButton, StyleRoot, TransitionPanel, useAccountWallet, useProfile, useRouter, useSearchParamsSSR, useTokenData, useTokenFromUrl, } from "../../../global-account/react/index.js";
|
|
5
|
+
import { Button, ShinyButton, StyleRoot, TransitionPanel, useAccountWallet, useProfile, useRouter, useSearchParamsSSR, useTokenBalanceDirect, useTokenData, useTokenFromUrl, } from "../../../global-account/react/index.js";
|
|
6
6
|
import { cn } from "../../../shared/utils/cn.js";
|
|
7
7
|
import { formatTokenAmount } from "../../../shared/utils/number.js";
|
|
8
8
|
import invariant from "invariant";
|
|
@@ -12,17 +12,19 @@ import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
|
12
12
|
import { toast } from "sonner";
|
|
13
13
|
import { parseUnits } from "viem";
|
|
14
14
|
import { base, mainnet } from "viem/chains";
|
|
15
|
+
import { useAutoSelectCryptoPaymentMethod } from "../hooks/useAutoSelectCryptoPaymentMethod.js";
|
|
16
|
+
import { useAutoSetActiveWalletFromWagmi } from "../hooks/useAutoSetActiveWalletFromWagmi.js";
|
|
15
17
|
import { AnySpendFingerprintWrapper, getFingerprintConfig } from "./AnySpendFingerprintWrapper.js";
|
|
16
18
|
import { CryptoPaymentMethod, CryptoPaymentMethodType } from "./common/CryptoPaymentMethod.js";
|
|
17
19
|
import { CryptoPaySection } from "./common/CryptoPaySection.js";
|
|
18
20
|
import { CryptoReceiveSection } from "./common/CryptoReceiveSection.js";
|
|
21
|
+
import { FeeDetailPanel } from "./common/FeeDetailPanel.js";
|
|
19
22
|
import { FiatPaymentMethod, FiatPaymentMethodComponent } from "./common/FiatPaymentMethod.js";
|
|
20
23
|
import { OrderDetails, OrderDetailsLoadingView } from "./common/OrderDetails.js";
|
|
21
24
|
import { OrderHistory } from "./common/OrderHistory.js";
|
|
22
25
|
import { PanelOnramp } from "./common/PanelOnramp.js";
|
|
23
26
|
import { PanelOnrampPayment } from "./common/PanelOnrampPayment.js";
|
|
24
27
|
import { PointsDetailPanel } from "./common/PointsDetailPanel.js";
|
|
25
|
-
import { FeeDetailPanel } from "./common/FeeDetailPanel.js";
|
|
26
28
|
import { RecipientSelection } from "./common/RecipientSelection.js";
|
|
27
29
|
import { TabSection } from "./common/TabSection.js";
|
|
28
30
|
export var PanelView;
|
|
@@ -304,13 +306,36 @@ function AnySpendInner({ destinationTokenAddress, destinationTokenChainId, mode
|
|
|
304
306
|
// );
|
|
305
307
|
// State for recipient selection
|
|
306
308
|
const [recipientAddress, setRecipientAddress] = useState();
|
|
307
|
-
const { address: globalAddress, wallet: globalWallet } = useAccountWallet();
|
|
309
|
+
const { address: globalAddress, wallet: globalWallet, connectedEOAWallet } = useAccountWallet();
|
|
308
310
|
const recipientProfile = useProfile({ address: recipientAddress, fresh: true });
|
|
309
311
|
const recipientName = recipientProfile.data?.name;
|
|
310
|
-
//
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
312
|
+
// Auto-set active wallet from wagmi
|
|
313
|
+
useAutoSetActiveWalletFromWagmi();
|
|
314
|
+
// Check token balance for crypto payments
|
|
315
|
+
const { rawBalance, isLoading: isBalanceLoading } = useTokenBalanceDirect({
|
|
316
|
+
token: selectedSrcToken,
|
|
317
|
+
address: connectedEOAWallet?.getAccount()?.address,
|
|
318
|
+
});
|
|
319
|
+
// Check if user has enough balanceuseAutoSetActiveWalletFromWagmi
|
|
320
|
+
const hasEnoughBalance = useMemo(() => {
|
|
321
|
+
if (!rawBalance || isBalanceLoading || activeTab !== "crypto")
|
|
322
|
+
return false;
|
|
323
|
+
try {
|
|
324
|
+
const requiredAmount = parseUnits(srcAmount.replace(/,/g, ""), selectedSrcToken.decimals);
|
|
325
|
+
return rawBalance >= requiredAmount;
|
|
326
|
+
}
|
|
327
|
+
catch {
|
|
328
|
+
return false;
|
|
329
|
+
}
|
|
330
|
+
}, [rawBalance, srcAmount, selectedSrcToken.decimals, isBalanceLoading, activeTab]);
|
|
331
|
+
// Auto-select crypto payment method based on available wallets and balance
|
|
332
|
+
useAutoSelectCryptoPaymentMethod({
|
|
333
|
+
paymentType: activeTab,
|
|
334
|
+
selectedCryptoPaymentMethod,
|
|
335
|
+
setSelectedCryptoPaymentMethod,
|
|
336
|
+
hasEnoughBalance,
|
|
337
|
+
isBalanceLoading,
|
|
338
|
+
});
|
|
314
339
|
// Get geo-based onramp options for fiat payments
|
|
315
340
|
const { geoData, coinbaseAvailablePaymentMethods, stripeWeb2Support } = useGeoOnrampOptions(srcAmountOnRamp);
|
|
316
341
|
// Helper function to map payment method to onramp vendor
|
|
@@ -474,17 +499,30 @@ function AnySpendInner({ destinationTokenAddress, destinationTokenChainId, mode
|
|
|
474
499
|
return { text: "Select a different token or chain", disable: true, error: false, loading: false };
|
|
475
500
|
if (isLoadingAnyspendQuote)
|
|
476
501
|
return { text: "Loading quote...", disable: true, error: false, loading: true };
|
|
477
|
-
if (!recipientAddress)
|
|
478
|
-
return { text: "Select recipient", disable: false, error: false, loading: false };
|
|
479
502
|
if (isCreatingOrder || isCreatingOnrampOrder)
|
|
480
503
|
return { text: "Creating order...", disable: true, error: false, loading: true };
|
|
481
504
|
if (!anyspendQuote || !anyspendQuote.success)
|
|
482
505
|
return { text: "No quote found", disable: true, error: false, loading: false };
|
|
506
|
+
if (activeTab === "fiat") {
|
|
507
|
+
// For fiat: check recipient first, then payment method
|
|
508
|
+
if (!recipientAddress)
|
|
509
|
+
return { text: "Select recipient", disable: false, error: false, loading: false };
|
|
510
|
+
// If no fiat payment method selected, show "Select payment method"
|
|
511
|
+
if (selectedFiatPaymentMethod === FiatPaymentMethod.NONE) {
|
|
512
|
+
return { text: "Select payment method", disable: false, error: false, loading: false };
|
|
513
|
+
}
|
|
514
|
+
// If payment method is selected, show "Buy"
|
|
515
|
+
return { text: "Buy", disable: false, error: false, loading: false };
|
|
516
|
+
}
|
|
483
517
|
if (activeTab === "crypto") {
|
|
518
|
+
// For crypto: check payment method first, then recipient
|
|
484
519
|
// If no payment method selected, show "Choose payment method"
|
|
485
520
|
if (selectedCryptoPaymentMethod === CryptoPaymentMethodType.NONE) {
|
|
486
521
|
return { text: "Choose payment method", disable: false, error: false, loading: false };
|
|
487
522
|
}
|
|
523
|
+
// Check recipient after payment method
|
|
524
|
+
if (!recipientAddress)
|
|
525
|
+
return { text: "Select recipient", disable: false, error: false, loading: false };
|
|
488
526
|
// If payment method selected, show appropriate action
|
|
489
527
|
if (selectedCryptoPaymentMethod === CryptoPaymentMethodType.CONNECT_WALLET ||
|
|
490
528
|
selectedCryptoPaymentMethod === CryptoPaymentMethodType.GLOBAL_WALLET) {
|
|
@@ -494,14 +532,6 @@ function AnySpendInner({ destinationTokenAddress, destinationTokenChainId, mode
|
|
|
494
532
|
return { text: "Continue to payment", disable: false, error: false, loading: false };
|
|
495
533
|
}
|
|
496
534
|
}
|
|
497
|
-
if (activeTab === "fiat") {
|
|
498
|
-
// If no fiat payment method selected, show "Select payment method"
|
|
499
|
-
if (selectedFiatPaymentMethod === FiatPaymentMethod.NONE) {
|
|
500
|
-
return { text: "Select payment method", disable: false, error: false, loading: false };
|
|
501
|
-
}
|
|
502
|
-
// If payment method is selected, show "Buy"
|
|
503
|
-
return { text: "Buy", disable: false, error: false, loading: false };
|
|
504
|
-
}
|
|
505
535
|
return { text: "Buy", disable: false, error: false, loading: false };
|
|
506
536
|
}, [
|
|
507
537
|
activeInputAmountInWei,
|
|
@@ -519,14 +549,15 @@ function AnySpendInner({ destinationTokenAddress, destinationTokenChainId, mode
|
|
|
519
549
|
const onMainButtonClick = async () => {
|
|
520
550
|
if (btnInfo.disable)
|
|
521
551
|
return;
|
|
522
|
-
if (!recipientAddress) {
|
|
523
|
-
navigateToPanel(PanelView.RECIPIENT_SELECTION, "forward");
|
|
524
|
-
return;
|
|
525
|
-
}
|
|
526
552
|
try {
|
|
527
553
|
invariant(anyspendQuote, "Relay price is not found");
|
|
528
|
-
invariant(recipientAddress, "Recipient address is not found");
|
|
529
554
|
if (activeTab === "fiat") {
|
|
555
|
+
// For fiat: check recipient first
|
|
556
|
+
if (!recipientAddress) {
|
|
557
|
+
navigateToPanel(PanelView.RECIPIENT_SELECTION, "forward");
|
|
558
|
+
return;
|
|
559
|
+
}
|
|
560
|
+
invariant(recipientAddress, "Recipient address is not found");
|
|
530
561
|
// If no fiat payment method selected, show payment method selection
|
|
531
562
|
if (selectedFiatPaymentMethod === FiatPaymentMethod.NONE) {
|
|
532
563
|
navigateToPanel(PanelView.FIAT_PAYMENT_METHOD, "forward");
|
|
@@ -537,12 +568,19 @@ function AnySpendInner({ destinationTokenAddress, destinationTokenChainId, mode
|
|
|
537
568
|
return;
|
|
538
569
|
}
|
|
539
570
|
if (activeTab === "crypto") {
|
|
571
|
+
// For crypto: check payment method first, then recipient
|
|
540
572
|
// If no payment method selected, show payment method selection
|
|
541
573
|
if (selectedCryptoPaymentMethod === CryptoPaymentMethodType.NONE) {
|
|
542
574
|
console.log("No payment method selected, showing selection panel");
|
|
543
575
|
navigateToPanel(PanelView.CRYPTO_PAYMENT_METHOD, "forward");
|
|
544
576
|
return;
|
|
545
577
|
}
|
|
578
|
+
// Check recipient after payment method
|
|
579
|
+
if (!recipientAddress) {
|
|
580
|
+
navigateToPanel(PanelView.RECIPIENT_SELECTION, "forward");
|
|
581
|
+
return;
|
|
582
|
+
}
|
|
583
|
+
invariant(recipientAddress, "Recipient address is not found");
|
|
546
584
|
// If payment method is selected, create order with payment method info
|
|
547
585
|
if (selectedCryptoPaymentMethod === CryptoPaymentMethodType.CONNECT_WALLET ||
|
|
548
586
|
selectedCryptoPaymentMethod === CryptoPaymentMethodType.GLOBAL_WALLET ||
|
|
@@ -755,10 +793,10 @@ function AnySpendInner({ destinationTokenAddress, destinationTokenChainId, mode
|
|
|
755
793
|
const tempDstAmount = dstAmount;
|
|
756
794
|
setSrcAmount(tempDstAmount);
|
|
757
795
|
setDstAmount(tempSrcAmount);
|
|
758
|
-
}, children: _jsx("div", { className: "relative flex items-center justify-center transition-opacity", children: _jsx(ArrowDown, { className: "text-as-primary/50 h-5 w-5" }) }) }), activeTab === "crypto" && (_jsx(CryptoReceiveSection, { isDepositMode: false, isBuyMode: isBuyMode, selectedRecipientAddress: recipientAddress, recipientName: recipientName || undefined, onSelectRecipient: () => navigateToPanel(PanelView.RECIPIENT_SELECTION, "forward"), dstAmount: dstAmount, dstToken: selectedDstToken, selectedDstChainId: selectedDstChainId, setSelectedDstChainId: setSelectedDstChainId, setSelectedDstToken: setSelectedDstToken, isSrcInputDirty: isSrcInputDirty, onChangeDstAmount: value => {
|
|
796
|
+
}, children: _jsx("div", { className: "relative flex items-center justify-center transition-opacity", children: _jsx(ArrowDown, { className: "text-as-primary/50 h-5 w-5" }) }) }), activeTab === "crypto" && (_jsx(CryptoReceiveSection, { isDepositMode: false, isBuyMode: isBuyMode, selectedRecipientAddress: recipientAddress, recipientName: recipientName || undefined, onSelectRecipient: () => navigateToPanel(PanelView.RECIPIENT_SELECTION, "forward"), setRecipientAddress: setRecipientAddress, recipientAddressFromProps: recipientAddressFromProps, globalAddress: globalAddress, dstAmount: dstAmount, dstToken: selectedDstToken, selectedDstChainId: selectedDstChainId, setSelectedDstChainId: setSelectedDstChainId, setSelectedDstToken: setSelectedDstToken, isSrcInputDirty: isSrcInputDirty, onChangeDstAmount: value => {
|
|
759
797
|
setIsSrcInputDirty(false);
|
|
760
798
|
setDstAmount(value);
|
|
761
|
-
}, anyspendQuote: anyspendQuote, onShowPointsDetail: () => navigateToPanel(PanelView.POINTS_DETAIL, "forward"), onShowFeeDetail: () => navigateToPanel(PanelView.FEE_DETAIL, "forward") }))] }), _jsxs(motion.div, { initial: { opacity: 0, y: 20, filter: "blur(10px)" }, animate: { opacity: 1, y: 0, filter: "blur(0px)" }, transition: { duration: 0.3, delay: 0.2, ease: "easeInOut" }, className: cn("mt-4 flex w-full max-w-[460px] flex-col gap-2"), children: [_jsx(ShinyButton, { accentColor: "hsl(var(--as-brand))", disabled: btnInfo.disable, onClick: onMainButtonClick, className: cn("as-main-button relative w-full", btnInfo.error ? "!bg-as-red" : btnInfo.disable ? "!bg-as-on-surface-2" : "!bg-as-brand"), textClassName: cn(btnInfo.error ? "text-white" : btnInfo.disable ? "text-as-secondary" : "text-white"), children: _jsxs("div", { className: "flex items-center justify-center gap-2", children: [btnInfo.loading && _jsx(Loader2, { className: "h-4 w-4 animate-spin" }), btnInfo.text] }) }), !hideTransactionHistoryButton && (globalAddress || recipientAddress) ? (_jsxs(Button, { variant: "link", onClick: onClickHistory, className: "text-as-primary/50 hover:text-as-primary flex items-center gap-1 transition-colors", children: [_jsx(HistoryIcon, { className: "h-4 w-4" }), " ", _jsx("span", { className: "pr-4", children: "Transaction History" })] })) : null] })] }));
|
|
799
|
+
}, anyspendQuote: anyspendQuote, onShowPointsDetail: () => navigateToPanel(PanelView.POINTS_DETAIL, "forward"), onShowFeeDetail: () => navigateToPanel(PanelView.FEE_DETAIL, "forward"), selectedCryptoPaymentMethod: selectedCryptoPaymentMethod }))] }), _jsxs(motion.div, { initial: { opacity: 0, y: 20, filter: "blur(10px)" }, animate: { opacity: 1, y: 0, filter: "blur(0px)" }, transition: { duration: 0.3, delay: 0.2, ease: "easeInOut" }, className: cn("mt-4 flex w-full max-w-[460px] flex-col gap-2"), children: [_jsx(ShinyButton, { accentColor: "hsl(var(--as-brand))", disabled: btnInfo.disable, onClick: onMainButtonClick, className: cn("as-main-button relative w-full", btnInfo.error ? "!bg-as-red" : btnInfo.disable ? "!bg-as-on-surface-2" : "!bg-as-brand"), textClassName: cn(btnInfo.error ? "text-white" : btnInfo.disable ? "text-as-secondary" : "text-white"), children: _jsxs("div", { className: "flex items-center justify-center gap-2", children: [btnInfo.loading && _jsx(Loader2, { className: "h-4 w-4 animate-spin" }), btnInfo.text] }) }), !hideTransactionHistoryButton && (globalAddress || recipientAddress) ? (_jsxs(Button, { variant: "link", onClick: onClickHistory, className: "text-as-primary/50 hover:text-as-primary flex items-center gap-1 transition-colors", children: [_jsx(HistoryIcon, { className: "h-4 w-4" }), " ", _jsx("span", { className: "pr-4", children: "Transaction History" })] })) : null] })] }));
|
|
762
800
|
const onrampPaymentView = (_jsx(PanelOnrampPayment, { srcAmountOnRamp: srcAmountOnRamp, recipientName: recipientName || undefined, recipientAddress: recipientAddress, isBuyMode: isBuyMode, destinationTokenChainId: destinationTokenChainId, destinationTokenAddress: destinationTokenAddress, selectedDstChainId: selectedDstChainId, selectedDstToken: selectedDstToken, orderType: "swap", anyspendQuote: anyspendQuote, globalAddress: globalAddress, onOrderCreated: orderId => {
|
|
763
801
|
setOrderId(orderId);
|
|
764
802
|
navigateToPanel(PanelView.ORDER_DETAILS, "forward");
|
|
@@ -14,6 +14,7 @@ import React, { useCallback, useEffect, useMemo, useState } from "react";
|
|
|
14
14
|
import { toast } from "sonner";
|
|
15
15
|
import { base } from "viem/chains";
|
|
16
16
|
import { useFeatureFlags } from "../contexts/FeatureFlagsContext.js";
|
|
17
|
+
import { useAutoSetActiveWalletFromWagmi } from "../hooks/useAutoSetActiveWalletFromWagmi.js";
|
|
17
18
|
import { AnySpendFingerprintWrapper, getFingerprintConfig } from "./AnySpendFingerprintWrapper.js";
|
|
18
19
|
import { CryptoPaymentMethod, CryptoPaymentMethodType } from "./common/CryptoPaymentMethod.js";
|
|
19
20
|
import { FeeBreakDown } from "./common/FeeBreakDown.js";
|
|
@@ -110,6 +111,8 @@ function AnySpendCustomInner({ loadOrder, mode = "modal", activeTab: activeTabPr
|
|
|
110
111
|
const featureFlags = useFeatureFlags();
|
|
111
112
|
const searchParams = useSearchParamsSSR();
|
|
112
113
|
const router = useRouter();
|
|
114
|
+
// Auto-set active wallet from wagmi
|
|
115
|
+
useAutoSetActiveWalletFromWagmi();
|
|
113
116
|
const [activePanel, setActivePanel] = useState(loadOrder ? PanelView.ORDER_DETAILS : PanelView.CONFIRM_ORDER);
|
|
114
117
|
const [activeTab, setActiveTab] = useState(activeTabProps);
|
|
115
118
|
// Add state for selected payment methods
|