@b3dotfun/sdk 0.0.62-alpha.1 → 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.
Files changed (88) hide show
  1. package/dist/cjs/anyspend/react/components/AnySpend.js +61 -23
  2. package/dist/cjs/anyspend/react/components/AnySpendCustom.js +3 -0
  3. package/dist/cjs/anyspend/react/components/AnySpendStakeB3.js +5 -4
  4. package/dist/cjs/anyspend/react/components/AnyspendDepositHype.js +4 -4
  5. package/dist/cjs/anyspend/react/components/common/CryptoPaySection.js +4 -6
  6. package/dist/cjs/anyspend/react/components/common/CryptoPaymentMethod.js +9 -17
  7. package/dist/cjs/anyspend/react/components/common/CryptoReceiveSection.d.ts +6 -1
  8. package/dist/cjs/anyspend/react/components/common/CryptoReceiveSection.js +11 -1
  9. package/dist/cjs/anyspend/react/components/common/OrderDetails.js +56 -145
  10. package/dist/cjs/anyspend/react/components/common/OrderTokenAmount.d.ts +2 -1
  11. package/dist/cjs/anyspend/react/components/common/OrderTokenAmount.js +39 -15
  12. package/dist/cjs/anyspend/react/components/common/PaySection.js +1 -1
  13. package/dist/cjs/anyspend/react/components/common/TokenBalance.js +1 -1
  14. package/dist/cjs/anyspend/react/hooks/useAnyspendFlow.js +12 -11
  15. package/dist/cjs/anyspend/react/hooks/useAutoSelectCryptoPaymentMethod.d.ts +26 -0
  16. package/dist/cjs/anyspend/react/hooks/useAutoSelectCryptoPaymentMethod.js +56 -0
  17. package/dist/cjs/anyspend/react/hooks/useAutoSetActiveWalletFromWagmi.d.ts +10 -0
  18. package/dist/cjs/anyspend/react/hooks/useAutoSetActiveWalletFromWagmi.js +73 -0
  19. package/dist/cjs/anyspend/react/hooks/useConnectedWalletDisplay.d.ts +14 -0
  20. package/dist/cjs/anyspend/react/hooks/useConnectedWalletDisplay.js +57 -0
  21. package/dist/cjs/anyspend/react/hooks/usePhantomTransfer.d.ts +36 -0
  22. package/dist/cjs/anyspend/react/hooks/usePhantomTransfer.js +211 -0
  23. package/dist/cjs/global-account/react/hooks/index.d.ts +2 -1
  24. package/dist/cjs/global-account/react/hooks/index.js +5 -3
  25. package/dist/cjs/global-account/react/hooks/useSimBalance.d.ts +1 -1
  26. package/dist/cjs/global-account/react/hooks/useSimBalance.js +6 -5
  27. package/dist/cjs/global-account/react/hooks/useTokenBalanceDirect.d.ts +12 -0
  28. package/dist/cjs/global-account/react/hooks/useTokenBalanceDirect.js +62 -0
  29. package/dist/cjs/global-account/react/hooks/useTokenFromUrl.js +4 -3
  30. package/dist/esm/anyspend/react/components/AnySpend.js +62 -24
  31. package/dist/esm/anyspend/react/components/AnySpendCustom.js +3 -0
  32. package/dist/esm/anyspend/react/components/AnySpendStakeB3.js +7 -6
  33. package/dist/esm/anyspend/react/components/AnyspendDepositHype.js +4 -4
  34. package/dist/esm/anyspend/react/components/common/CryptoPaySection.js +5 -7
  35. package/dist/esm/anyspend/react/components/common/CryptoPaymentMethod.js +9 -17
  36. package/dist/esm/anyspend/react/components/common/CryptoReceiveSection.d.ts +6 -1
  37. package/dist/esm/anyspend/react/components/common/CryptoReceiveSection.js +11 -1
  38. package/dist/esm/anyspend/react/components/common/OrderDetails.js +57 -146
  39. package/dist/esm/anyspend/react/components/common/OrderTokenAmount.d.ts +2 -1
  40. package/dist/esm/anyspend/react/components/common/OrderTokenAmount.js +40 -16
  41. package/dist/esm/anyspend/react/components/common/PaySection.js +1 -1
  42. package/dist/esm/anyspend/react/components/common/TokenBalance.js +2 -2
  43. package/dist/esm/anyspend/react/hooks/useAnyspendFlow.js +12 -11
  44. package/dist/esm/anyspend/react/hooks/useAutoSelectCryptoPaymentMethod.d.ts +26 -0
  45. package/dist/esm/anyspend/react/hooks/useAutoSelectCryptoPaymentMethod.js +53 -0
  46. package/dist/esm/anyspend/react/hooks/useAutoSetActiveWalletFromWagmi.d.ts +10 -0
  47. package/dist/esm/anyspend/react/hooks/useAutoSetActiveWalletFromWagmi.js +70 -0
  48. package/dist/esm/anyspend/react/hooks/useConnectedWalletDisplay.d.ts +14 -0
  49. package/dist/esm/anyspend/react/hooks/useConnectedWalletDisplay.js +54 -0
  50. package/dist/esm/anyspend/react/hooks/usePhantomTransfer.d.ts +36 -0
  51. package/dist/esm/anyspend/react/hooks/usePhantomTransfer.js +208 -0
  52. package/dist/esm/global-account/react/hooks/index.d.ts +2 -1
  53. package/dist/esm/global-account/react/hooks/index.js +2 -1
  54. package/dist/esm/global-account/react/hooks/useSimBalance.d.ts +1 -1
  55. package/dist/esm/global-account/react/hooks/useSimBalance.js +6 -5
  56. package/dist/esm/global-account/react/hooks/useTokenBalanceDirect.d.ts +12 -0
  57. package/dist/esm/global-account/react/hooks/useTokenBalanceDirect.js +59 -0
  58. package/dist/esm/global-account/react/hooks/useTokenFromUrl.js +4 -3
  59. package/dist/types/anyspend/react/components/common/CryptoReceiveSection.d.ts +6 -1
  60. package/dist/types/anyspend/react/components/common/OrderTokenAmount.d.ts +2 -1
  61. package/dist/types/anyspend/react/hooks/useAutoSelectCryptoPaymentMethod.d.ts +26 -0
  62. package/dist/types/anyspend/react/hooks/useAutoSetActiveWalletFromWagmi.d.ts +10 -0
  63. package/dist/types/anyspend/react/hooks/useConnectedWalletDisplay.d.ts +14 -0
  64. package/dist/types/anyspend/react/hooks/usePhantomTransfer.d.ts +36 -0
  65. package/dist/types/global-account/react/hooks/index.d.ts +2 -1
  66. package/dist/types/global-account/react/hooks/useSimBalance.d.ts +1 -1
  67. package/dist/types/global-account/react/hooks/useTokenBalanceDirect.d.ts +12 -0
  68. package/package.json +1 -1
  69. package/src/anyspend/react/components/AnySpend.tsx +73 -22
  70. package/src/anyspend/react/components/AnySpendCustom.tsx +4 -0
  71. package/src/anyspend/react/components/AnySpendStakeB3.tsx +8 -11
  72. package/src/anyspend/react/components/AnyspendDepositHype.tsx +7 -3
  73. package/src/anyspend/react/components/common/CryptoPaySection.tsx +5 -7
  74. package/src/anyspend/react/components/common/CryptoPaymentMethod.tsx +9 -18
  75. package/src/anyspend/react/components/common/CryptoReceiveSection.tsx +22 -0
  76. package/src/anyspend/react/components/common/OrderDetails.tsx +66 -188
  77. package/src/anyspend/react/components/common/OrderTokenAmount.tsx +48 -17
  78. package/src/anyspend/react/components/common/PaySection.tsx +1 -0
  79. package/src/anyspend/react/components/common/TokenBalance.tsx +2 -2
  80. package/src/anyspend/react/hooks/useAnyspendFlow.ts +13 -10
  81. package/src/anyspend/react/hooks/useAutoSelectCryptoPaymentMethod.ts +72 -0
  82. package/src/anyspend/react/hooks/useAutoSetActiveWalletFromWagmi.ts +80 -0
  83. package/src/anyspend/react/hooks/useConnectedWalletDisplay.ts +69 -0
  84. package/src/anyspend/react/hooks/usePhantomTransfer.ts +301 -0
  85. package/src/global-account/react/hooks/index.ts +2 -1
  86. package/src/global-account/react/hooks/useSimBalance.ts +6 -5
  87. package/src/global-account/react/hooks/useTokenBalanceDirect.tsx +84 -0
  88. package/src/global-account/react/hooks/useTokenFromUrl.tsx +6 -5
@@ -0,0 +1,54 @@
1
+ import { useAccountWallet } from "../../../global-account/react/index.js";
2
+ import { useAccount } from "wagmi";
3
+ import { CryptoPaymentMethodType } from "../components/common/CryptoPaymentMethod.js";
4
+ /**
5
+ * Custom hook to determine which wallet to display and its address
6
+ * Handles logic for showing EOA wallet, wagmi wallet, or global wallet based on payment method
7
+ */
8
+ export function useConnectedWalletDisplay(selectedCryptoPaymentMethod) {
9
+ const { connectedEOAWallet, connectedSmartWallet } = useAccountWallet();
10
+ const { address: wagmiAddress, isConnected: wagmiWalletIsConnected } = useAccount();
11
+ // Helper function to check if two addresses are the same
12
+ const isSameAddress = (addr1, addr2) => {
13
+ if (!addr1 || !addr2)
14
+ return false;
15
+ return addr1.toLowerCase() === addr2.toLowerCase();
16
+ };
17
+ // Check if connectedEOAWallet and wagmi wallet represent the same wallet
18
+ const connectedEOAAddress = connectedEOAWallet?.getAccount()?.address;
19
+ const isWalletDuplicated = isSameAddress(connectedEOAAddress, wagmiAddress);
20
+ // Determine which wallet to show (prefer connectedEOAWallet if both exist and are the same)
21
+ const shouldShowConnectedEOA = !!connectedEOAWallet;
22
+ const shouldShowWagmiWallet = wagmiWalletIsConnected && (!isWalletDuplicated || !connectedEOAWallet);
23
+ // Determine which address to use based on payment method
24
+ let walletAddress;
25
+ if (selectedCryptoPaymentMethod === CryptoPaymentMethodType.GLOBAL_WALLET) {
26
+ walletAddress = connectedSmartWallet?.getAccount()?.address;
27
+ }
28
+ else if (selectedCryptoPaymentMethod === CryptoPaymentMethodType.CONNECT_WALLET) {
29
+ // Prefer connectedEOAWallet, fallback to wagmi wallet
30
+ walletAddress = connectedEOAAddress || wagmiAddress;
31
+ }
32
+ else {
33
+ // Default behavior: use connectedEOAWallet if available, otherwise wagmi
34
+ walletAddress = connectedEOAAddress || wagmiAddress;
35
+ }
36
+ // Suggest a payment method based on available wallets
37
+ // Priority: Connected EOA/Wagmi wallet > Global wallet > None
38
+ let suggestedPaymentMethod = CryptoPaymentMethodType.NONE;
39
+ if (connectedEOAAddress || wagmiAddress) {
40
+ // If there's a connected EOA or wagmi wallet, suggest CONNECT_WALLET
41
+ suggestedPaymentMethod = CryptoPaymentMethodType.CONNECT_WALLET;
42
+ }
43
+ else if (connectedSmartWallet?.getAccount()?.address) {
44
+ // If only global wallet is available, suggest that
45
+ suggestedPaymentMethod = CryptoPaymentMethodType.GLOBAL_WALLET;
46
+ }
47
+ return {
48
+ walletAddress,
49
+ shouldShowConnectedEOA,
50
+ shouldShowWagmiWallet,
51
+ isWalletDuplicated,
52
+ suggestedPaymentMethod,
53
+ };
54
+ }
@@ -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,208 @@
1
+ import { createAssociatedTokenAccountInstruction, createTransferCheckedInstruction, getAssociatedTokenAddressSync, } from "@solana/spl-token";
2
+ import { ComputeBudgetProgram, Connection, PublicKey, SystemProgram, Transaction } from "@solana/web3.js";
3
+ import { useCallback, useMemo } from "react";
4
+ import { toast } from "sonner";
5
+ /**
6
+ * Custom hook for handling Phantom wallet transfers on Solana.
7
+ * Supports both native SOL and SPL token transfers with automatic priority fee calculation.
8
+ *
9
+ * @example
10
+ * ```tsx
11
+ * const { initiateTransfer, isPhantomAvailable } = usePhantomTransfer();
12
+ *
13
+ * await initiateTransfer({
14
+ * amountLamports: "1000000000", // 1 SOL
15
+ * tokenAddress: "11111111111111111111111111111111",
16
+ * recipientAddress: "..."
17
+ * });
18
+ * ```
19
+ */
20
+ export function usePhantomTransfer({ rpcEndpoint } = {}) {
21
+ // Default RPC endpoint
22
+ const defaultRpcEndpoint = "https://mainnet.helius-rpc.com/?api-key=efafd9b3-1807-4cf8-8aa4-3d984f56d8fb";
23
+ const effectiveRpcEndpoint = rpcEndpoint || defaultRpcEndpoint;
24
+ // Check for Phantom wallet availability
25
+ const isPhantomMobile = useMemo(() => navigator.userAgent.includes("Phantom"), []);
26
+ const isPhantomBrowser = useMemo(() => window.phantom?.solana?.isPhantom, []);
27
+ const isPhantomAvailable = isPhantomMobile || isPhantomBrowser;
28
+ /**
29
+ * Get the connected Phantom wallet address if available
30
+ */
31
+ const getConnectedAddress = useCallback(() => {
32
+ const phantom = window.phantom?.solana;
33
+ if (phantom?.isConnected && phantom?.publicKey) {
34
+ return phantom.publicKey.toString();
35
+ }
36
+ return null;
37
+ }, []);
38
+ /**
39
+ * Calculate optimal priority fee based on recent network activity
40
+ */
41
+ const calculatePriorityFee = useCallback(async (connection, fromPubkey) => {
42
+ let priorityFee = 10000; // Default fallback (10,000 micro-lamports)
43
+ try {
44
+ const recentFees = await connection.getRecentPrioritizationFees({
45
+ lockedWritableAccounts: [fromPubkey],
46
+ });
47
+ if (recentFees && recentFees.length > 0) {
48
+ // Use 75th percentile of recent fees for good priority
49
+ const sortedFees = recentFees.map(fee => fee.prioritizationFee).sort((a, b) => a - b);
50
+ const percentile75Index = Math.floor(sortedFees.length * 0.75);
51
+ priorityFee = Math.max(sortedFees[percentile75Index] || 10000, 10000);
52
+ }
53
+ }
54
+ catch (feeError) {
55
+ console.warn("Failed to fetch recent priority fees, using default:", feeError);
56
+ }
57
+ return priorityFee;
58
+ }, []);
59
+ /**
60
+ * Create a native SOL transfer transaction with priority fees
61
+ */
62
+ const createNativeTransferTransaction = useCallback(async (_connection, fromPubkey, toPubkey, amount, priorityFee) => {
63
+ const computeUnitLimit = 1000; // SOL transfer + compute budget instructions need ~600-800 CU
64
+ const computeUnitPrice = Math.min(priorityFee, 100000); // Cap at 100k micro-lamports for safety
65
+ const transaction = new Transaction()
66
+ .add(
67
+ // Set compute unit limit first (must come before other instructions)
68
+ ComputeBudgetProgram.setComputeUnitLimit({
69
+ units: computeUnitLimit,
70
+ }))
71
+ .add(
72
+ // Set priority fee
73
+ ComputeBudgetProgram.setComputeUnitPrice({
74
+ microLamports: computeUnitPrice,
75
+ }))
76
+ .add(
77
+ // Actual transfer instruction
78
+ SystemProgram.transfer({
79
+ fromPubkey,
80
+ toPubkey,
81
+ lamports: Number(amount),
82
+ }));
83
+ console.log(`Using priority fee: ${computeUnitPrice} micro-lamports per CU, limit: ${computeUnitLimit} CU`);
84
+ return transaction;
85
+ }, []);
86
+ /**
87
+ * Create an SPL token transfer transaction with priority fees
88
+ */
89
+ const createSPLTransferTransaction = useCallback(async (connection, fromPubkey, toPubkey, mintPubkey, amount, priorityFee) => {
90
+ // Get associated token accounts
91
+ const fromTokenAccount = getAssociatedTokenAddressSync(mintPubkey, fromPubkey);
92
+ const toTokenAccount = getAssociatedTokenAddressSync(mintPubkey, toPubkey);
93
+ // Check if destination token account exists
94
+ const toTokenAccountInfo = await connection.getAccountInfo(toTokenAccount);
95
+ const needsDestinationAccount = !toTokenAccountInfo;
96
+ // Get mint info to determine decimals
97
+ const mintInfo = await connection.getParsedAccountInfo(mintPubkey);
98
+ const decimals = mintInfo.value?.data?.parsed?.info?.decimals || 9;
99
+ // SPL transfers need more compute units than SOL transfers
100
+ // Add extra CU if we need to create destination account
101
+ const computeUnitLimit = needsDestinationAccount ? 40000 : 20000;
102
+ const computeUnitPrice = Math.min(priorityFee, 100000);
103
+ // Create transfer instruction
104
+ const transferInstruction = createTransferCheckedInstruction(fromTokenAccount, mintPubkey, toTokenAccount, fromPubkey, Number(amount), decimals);
105
+ const transaction = new Transaction()
106
+ .add(ComputeBudgetProgram.setComputeUnitLimit({
107
+ units: computeUnitLimit,
108
+ }))
109
+ .add(ComputeBudgetProgram.setComputeUnitPrice({
110
+ microLamports: computeUnitPrice,
111
+ }));
112
+ // Add create destination account instruction if needed
113
+ if (needsDestinationAccount) {
114
+ transaction.add(createAssociatedTokenAccountInstruction(fromPubkey, // payer
115
+ toTokenAccount, // ata
116
+ toPubkey, // owner
117
+ mintPubkey));
118
+ }
119
+ // Add the transfer instruction
120
+ transaction.add(transferInstruction);
121
+ console.log(`SPL Token transfer: ${computeUnitPrice} micro-lamports per CU, limit: ${computeUnitLimit} CU, creating destination: ${needsDestinationAccount}`);
122
+ return transaction;
123
+ }, []);
124
+ /**
125
+ * Initiate a Phantom wallet transfer for SOL or SPL tokens
126
+ */
127
+ const initiateTransfer = useCallback(async ({ amountLamports, tokenAddress, recipientAddress }) => {
128
+ try {
129
+ // Step 1: Check if Phantom is installed
130
+ if (!isPhantomAvailable) {
131
+ toast.error("Phantom wallet not installed. Please install Phantom wallet to continue.");
132
+ return;
133
+ }
134
+ // Step 2: Ensure Phantom is connected/unlocked
135
+ const phantom = window.phantom?.solana;
136
+ if (!phantom) {
137
+ toast.error("Phantom wallet not accessible");
138
+ return;
139
+ }
140
+ // Connect and unlock wallet if needed
141
+ let publicKey;
142
+ try {
143
+ const connection = await phantom.connect();
144
+ publicKey = connection.publicKey;
145
+ }
146
+ catch (connectError) {
147
+ toast.error("Failed to connect to Phantom wallet");
148
+ return;
149
+ }
150
+ // Step 3: Setup connection and public keys
151
+ const connection = new Connection(effectiveRpcEndpoint);
152
+ const fromPubkey = new PublicKey(publicKey.toString());
153
+ const toPubkey = new PublicKey(recipientAddress);
154
+ const amount = BigInt(amountLamports);
155
+ // Step 4: Calculate optimal priority fee
156
+ const priorityFee = await calculatePriorityFee(connection, fromPubkey);
157
+ // Step 5: Create transaction based on token type
158
+ let transaction;
159
+ if (tokenAddress === "11111111111111111111111111111111") {
160
+ // Native SOL transfer
161
+ transaction = await createNativeTransferTransaction(connection, fromPubkey, toPubkey, amount, priorityFee);
162
+ }
163
+ else {
164
+ // SPL Token transfer
165
+ const mintPubkey = new PublicKey(tokenAddress);
166
+ transaction = await createSPLTransferTransaction(connection, fromPubkey, toPubkey, mintPubkey, amount, priorityFee);
167
+ }
168
+ // Step 6: Get latest blockhash and set fee payer
169
+ const { blockhash } = await connection.getLatestBlockhash("confirmed");
170
+ transaction.recentBlockhash = blockhash;
171
+ transaction.feePayer = fromPubkey;
172
+ // Step 7: Sign and send transaction
173
+ const signedTransaction = await phantom.signAndSendTransaction(transaction);
174
+ toast.success(`Transaction successful! Signature: ${signedTransaction.signature}`);
175
+ console.log("Transaction sent with priority fees. Signature:", signedTransaction.signature);
176
+ }
177
+ catch (error) {
178
+ console.error("Transfer error:", error);
179
+ const errorMessage = error instanceof Error ? error.message : String(error);
180
+ if (errorMessage.includes("User rejected")) {
181
+ toast.error("Transaction was cancelled by user");
182
+ }
183
+ else if (errorMessage.includes("insufficient")) {
184
+ toast.error("Insufficient balance for this transaction");
185
+ }
186
+ else if (errorMessage.includes("blockhash not found")) {
187
+ toast.error("Network congestion detected. Please try again in a moment.");
188
+ }
189
+ else {
190
+ toast.error(`Transfer failed: ${errorMessage}`);
191
+ }
192
+ }
193
+ }, [
194
+ isPhantomAvailable,
195
+ effectiveRpcEndpoint,
196
+ calculatePriorityFee,
197
+ createNativeTransferTransaction,
198
+ createSPLTransferTransaction,
199
+ ]);
200
+ return {
201
+ /** Function to initiate a transfer */
202
+ initiateTransfer,
203
+ /** Whether Phantom wallet is available (installed) */
204
+ isPhantomAvailable,
205
+ /** Get the currently connected Phantom wallet address */
206
+ getConnectedAddress,
207
+ };
208
+ }
@@ -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";
@@ -32,11 +32,12 @@ export { useSearchParamsSSR } from "./useSearchParamsSSR.js";
32
32
  export { useSimBalance } from "./useSimBalance.js";
33
33
  export { useSiwe } from "./useSiwe.js";
34
34
  export { useTokenBalance } from "./useTokenBalance.js";
35
+ export { useTokenBalanceDirect } from "./useTokenBalanceDirect.js";
35
36
  export { useTokenBalancesByChain } from "./useTokenBalancesByChain.js";
36
37
  export { useTokenData } from "./useTokenData.js";
37
38
  export { useTokenFromUrl } from "./useTokenFromUrl.js";
38
39
  export { useTokenPrice } from "./useTokenPrice.js";
39
40
  export { useTokenPriceWithFallback } from "./useTokenPriceWithFallback.js";
40
41
  export { useTokensFromAddress } from "./useTokensFromAddress.js";
41
- export { useUnifiedChainSwitchAndExecute } from "./useUnifiedChainSwitchAndExecute.js";
42
42
  export { useURLParams } from "./useURLParams.js";
43
+ export { useUnifiedChainSwitchAndExecute } from "./useUnifiedChainSwitchAndExecute.js";
@@ -21,4 +21,4 @@ export interface SimBalanceResponse {
21
21
  wallet_address: string;
22
22
  balances: SimBalanceItem[];
23
23
  }
24
- export declare function useSimBalance(address?: string): import("@tanstack/react-query").UseQueryResult<SimBalanceResponse, Error>;
24
+ export declare function useSimBalance(address?: string, chainIdsParam?: number[]): import("@tanstack/react-query").UseQueryResult<SimBalanceResponse, Error>;
@@ -1,8 +1,9 @@
1
1
  import { useQuery } from "@tanstack/react-query";
2
- async function fetchSimBalance(address) {
2
+ async function fetchSimBalance(address, chainIdsParam) {
3
3
  if (!address)
4
4
  throw new Error("Address is required");
5
- let url = `https://simdune-api.sean-430.workers.dev/?url=https://api.sim.dune.com/v1/evm/balances/${address}?metadata=logo&chain_ids=mainnet`;
5
+ const chainIds = chainIdsParam.length === 0 ? "mainnet" : chainIdsParam.join(",");
6
+ let url = `https://simdune-api.sean-430.workers.dev/?url=https://api.sim.dune.com/v1/evm/balances/${address}?metadata=logo&chain_ids=${chainIds}`;
6
7
  if (process.env.NEXT_PUBLIC_LOCAL_KEY) {
7
8
  url += `&localkey=${process.env.NEXT_PUBLIC_LOCAL_KEY}`;
8
9
  }
@@ -13,13 +14,13 @@ async function fetchSimBalance(address) {
13
14
  const balanceData = await response.json();
14
15
  return balanceData;
15
16
  }
16
- export function useSimBalance(address) {
17
+ export function useSimBalance(address, chainIdsParam) {
17
18
  return useQuery({
18
- queryKey: ["simBalance", address],
19
+ queryKey: ["simBalance", address, chainIdsParam],
19
20
  queryFn: () => {
20
21
  if (!address)
21
22
  throw new Error("Address is required");
22
- return fetchSimBalance(address);
23
+ return fetchSimBalance(address, chainIdsParam || []);
23
24
  },
24
25
  enabled: Boolean(address),
25
26
  });
@@ -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,59 @@
1
+ "use client";
2
+ import { isNativeToken } from "../../../anyspend/index.js";
3
+ import { useAccountWallet } from "../../../global-account/react/index.js";
4
+ import { formatTokenAmount } from "../../../shared/utils/number.js";
5
+ import { getERC20Balances, getNativeTokenBalance } from "../../../shared/utils/thirdweb-insights.js";
6
+ import { useQuery } from "@tanstack/react-query";
7
+ import { useEffect } from "react";
8
+ export function useTokenBalanceDirect({ token, address }) {
9
+ const account = useAccountWallet();
10
+ const effectiveAddress = address || account?.address;
11
+ const { data: tokenBalance, isLoading, isFetching, refetch, } = useQuery({
12
+ queryKey: ["tokenBalance", effectiveAddress, token.chainId, token.address],
13
+ queryFn: async () => {
14
+ if (!effectiveAddress)
15
+ return { formatted: "0", raw: null };
16
+ if (isNativeToken(token.address)) {
17
+ const nativeToken = await getNativeTokenBalance(effectiveAddress, token.chainId);
18
+ if (nativeToken && nativeToken.balance) {
19
+ const rawBalance = nativeToken.balance;
20
+ return {
21
+ formatted: formatTokenAmount(BigInt(rawBalance), Number(nativeToken.decimals || 18)),
22
+ raw: BigInt(rawBalance),
23
+ };
24
+ }
25
+ return { formatted: "0", raw: null };
26
+ }
27
+ const response = await getERC20Balances(effectiveAddress, {
28
+ chainIds: [token.chainId],
29
+ includeSpam: false,
30
+ });
31
+ const tokenBalance = response.data?.find(t => t.token_address === token.address);
32
+ if (tokenBalance?.balance) {
33
+ return {
34
+ formatted: formatTokenAmount(BigInt(tokenBalance.balance), Number(tokenBalance.decimals || 18)),
35
+ raw: BigInt(tokenBalance.balance),
36
+ };
37
+ }
38
+ return { formatted: "0", raw: null };
39
+ },
40
+ enabled: !!effectiveAddress,
41
+ staleTime: 30000,
42
+ gcTime: 5 * 60 * 1000,
43
+ retry: 2,
44
+ structuralSharing: false,
45
+ });
46
+ // Force a refetch when the wallet or token changes
47
+ useEffect(() => {
48
+ if (effectiveAddress) {
49
+ refetch();
50
+ }
51
+ }, [effectiveAddress, token.address, token.chainId, token.symbol, refetch]);
52
+ // Determine if we're actually loading
53
+ const isActuallyLoading = !effectiveAddress || isLoading || (isFetching && !tokenBalance);
54
+ return {
55
+ rawBalance: tokenBalance?.raw || BigInt(0),
56
+ formattedBalance: tokenBalance?.formatted || "0",
57
+ isLoading: isActuallyLoading,
58
+ };
59
+ }
@@ -28,10 +28,11 @@ export function useTokenFromUrl({ defaultToken, prefix }) {
28
28
  // Get parameters from URL
29
29
  const currencyParam = searchParams.get(`${prefix}Currency`);
30
30
  const chainIdParam = searchParams.get(`${prefix}ChainId`);
31
- // Determine if we should fetch token info
32
- const shouldFetchToken = Boolean(currencyParam && chainIdParam && currencyParam.toLowerCase() !== defaultToken.address.toLowerCase());
33
31
  // Determine network based on chainId
34
- const network = chainIdParam ? getCoingeckoChainInfo(Number(chainIdParam)).coingecko_id : "";
32
+ const chainInfo = chainIdParam ? getCoingeckoChainInfo(Number(chainIdParam)) : null;
33
+ const network = chainInfo?.coingecko_id || "";
34
+ // Determine if we should fetch token info
35
+ const shouldFetchToken = Boolean(currencyParam && chainIdParam && chainInfo && currencyParam.toLowerCase() !== defaultToken.address.toLowerCase());
35
36
  const { data: tokenInfo, isError } = useQuery({
36
37
  queryKey: ["tokenInfo", network, currencyParam],
37
38
  queryFn: () => fetchTokenInfo(network, currencyParam || ""),
@@ -1,10 +1,14 @@
1
1
  import { components } from "../../../types/api";
2
+ import { CryptoPaymentMethodType } from "./CryptoPaymentMethod";
2
3
  interface CryptoReceiveSectionProps {
3
4
  isDepositMode?: boolean;
4
5
  isBuyMode?: boolean;
5
6
  selectedRecipientAddress?: string;
6
7
  recipientName?: string;
7
8
  onSelectRecipient: () => void;
9
+ setRecipientAddress?: (address: string | undefined) => void;
10
+ recipientAddressFromProps?: string;
11
+ globalAddress?: string;
8
12
  dstAmount: string;
9
13
  dstToken: components["schemas"]["Token"];
10
14
  selectedDstChainId?: number;
@@ -17,6 +21,7 @@ interface CryptoReceiveSectionProps {
17
21
  dstTokenLogoURI?: string;
18
22
  onShowPointsDetail?: () => void;
19
23
  onShowFeeDetail?: () => void;
24
+ selectedCryptoPaymentMethod?: CryptoPaymentMethodType;
20
25
  }
21
- export declare function CryptoReceiveSection({ isDepositMode, isBuyMode, selectedRecipientAddress, recipientName, onSelectRecipient, dstAmount, dstToken, selectedDstChainId, setSelectedDstChainId, setSelectedDstToken, isSrcInputDirty, onChangeDstAmount, anyspendQuote, dstTokenSymbol, dstTokenLogoURI, onShowPointsDetail, onShowFeeDetail, }: CryptoReceiveSectionProps): import("react/jsx-runtime").JSX.Element;
26
+ export declare function CryptoReceiveSection({ isDepositMode, isBuyMode, selectedRecipientAddress, recipientName, onSelectRecipient, setRecipientAddress, recipientAddressFromProps, globalAddress, dstAmount, dstToken, selectedDstChainId, setSelectedDstChainId, setSelectedDstToken, isSrcInputDirty, onChangeDstAmount, anyspendQuote, dstTokenSymbol, dstTokenLogoURI, onShowPointsDetail, onShowFeeDetail, selectedCryptoPaymentMethod, }: CryptoReceiveSectionProps): import("react/jsx-runtime").JSX.Element;
22
27
  export {};
@@ -1,5 +1,5 @@
1
1
  import { components } from "@b3dotfun/sdk/anyspend/types/api";
2
- export declare function OrderTokenAmount({ disabled, inputValue, onChangeInput, context, address, chainId, setChainId, token, setToken, hideTokenSelect, canEditAmount, className, innerClassName, amountClassName, tokenSelectClassName, onTokenSelect, }: {
2
+ export declare function OrderTokenAmount({ disabled, inputValue, onChangeInput, context, address, chainId, setChainId, token, setToken, hideTokenSelect, canEditAmount, className, innerClassName, amountClassName, tokenSelectClassName, onTokenSelect, walletAddress, }: {
3
3
  disabled?: boolean;
4
4
  inputValue: string;
5
5
  onChangeInput: (value: string) => void;
@@ -18,4 +18,5 @@ export declare function OrderTokenAmount({ disabled, inputValue, onChangeInput,
18
18
  onTokenSelect?: (token: components["schemas"]["Token"], event: {
19
19
  preventDefault: () => void;
20
20
  }) => void;
21
+ walletAddress?: string | undefined;
21
22
  }): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,26 @@
1
+ import { CryptoPaymentMethodType } from "../components/common/CryptoPaymentMethod";
2
+ interface UseAutoSelectCryptoPaymentMethodParams {
3
+ /** Current payment type (crypto or fiat) */
4
+ paymentType?: "crypto" | "fiat";
5
+ /** Currently selected payment method */
6
+ selectedCryptoPaymentMethod: CryptoPaymentMethodType;
7
+ /** Function to update the selected payment method */
8
+ setSelectedCryptoPaymentMethod: (method: CryptoPaymentMethodType) => void;
9
+ /** Whether user has enough balance to pay */
10
+ hasEnoughBalance: boolean;
11
+ /** Whether balance is still loading */
12
+ isBalanceLoading: boolean;
13
+ }
14
+ /**
15
+ * Custom hook to automatically select appropriate crypto payment method
16
+ * based on available wallets and balance.
17
+ *
18
+ * Auto-selection logic:
19
+ * - Only auto-selects when payment method is NONE (doesn't override user choices)
20
+ * - If EOA/Wagmi wallet connected + has balance → CONNECT_WALLET
21
+ * - If EOA/Wagmi wallet connected + insufficient balance → TRANSFER_CRYPTO
22
+ * - If only Global wallet available → GLOBAL_WALLET
23
+ * - If no wallets → remains NONE
24
+ */
25
+ export declare function useAutoSelectCryptoPaymentMethod({ paymentType, selectedCryptoPaymentMethod, setSelectedCryptoPaymentMethod, hasEnoughBalance, isBalanceLoading, }: UseAutoSelectCryptoPaymentMethodParams): void;
26
+ export {};
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Hook that automatically sets the active thirdweb wallet when a wagmi wallet connects.
3
+ *
4
+ * This is useful for syncing wagmi wallet connections with thirdweb's wallet system,
5
+ * ensuring that when users connect via wagmi, the active wallet is properly set.
6
+ *
7
+ * Place this hook in components that stay mounted throughout the user flow
8
+ * (not in components that unmount during navigation).
9
+ */
10
+ export declare function useAutoSetActiveWalletFromWagmi(): void;
@@ -0,0 +1,14 @@
1
+ import { CryptoPaymentMethodType } from "../components/common/CryptoPaymentMethod";
2
+ interface UseConnectedWalletDisplayResult {
3
+ walletAddress: string | undefined;
4
+ shouldShowConnectedEOA: boolean;
5
+ shouldShowWagmiWallet: boolean;
6
+ isWalletDuplicated: boolean;
7
+ suggestedPaymentMethod: CryptoPaymentMethodType;
8
+ }
9
+ /**
10
+ * Custom hook to determine which wallet to display and its address
11
+ * Handles logic for showing EOA wallet, wagmi wallet, or global wallet based on payment method
12
+ */
13
+ export declare function useConnectedWalletDisplay(selectedCryptoPaymentMethod?: CryptoPaymentMethodType): UseConnectedWalletDisplayResult;
14
+ export {};
@@ -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 {};
@@ -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";
@@ -21,4 +21,4 @@ export interface SimBalanceResponse {
21
21
  wallet_address: string;
22
22
  balances: SimBalanceItem[];
23
23
  }
24
- export declare function useSimBalance(address?: string): import("@tanstack/react-query").UseQueryResult<SimBalanceResponse, Error>;
24
+ export declare function useSimBalance(address?: string, chainIdsParam?: number[]): import("@tanstack/react-query").UseQueryResult<SimBalanceResponse, Error>;
@@ -0,0 +1,12 @@
1
+ import { components } from "@b3dotfun/sdk/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 {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@b3dotfun/sdk",
3
- "version": "0.0.62-alpha.1",
3
+ "version": "0.0.62-alpha.3",
4
4
  "source": "src/index.ts",
5
5
  "main": "./dist/cjs/index.js",
6
6
  "react-native": "./dist/cjs/index.native.js",