@b3dotfun/sdk 0.0.83 → 0.0.84-alpha.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/anyspend/constants/index.d.ts +1 -1
- package/dist/cjs/anyspend/constants/index.js +2 -2
- package/dist/cjs/anyspend/react/components/AnySpend.js +21 -9
- package/dist/cjs/anyspend/react/components/AnySpendCustom.js +4 -3
- package/dist/cjs/anyspend/react/components/common/CryptoPaySection.js +2 -4
- package/dist/cjs/anyspend/react/components/common/CryptoPaymentMethodDisplay.d.ts +15 -0
- package/dist/cjs/anyspend/react/components/common/CryptoPaymentMethodDisplay.js +28 -0
- package/dist/cjs/anyspend/react/components/common/InsufficientDepositPayment.js +1 -1
- package/dist/cjs/anyspend/react/components/common/OrderDetails.js +5 -4
- package/dist/cjs/anyspend/react/components/common/OrderToken.js +2 -2
- package/dist/cjs/anyspend/react/components/common/OrderTokenAmount.js +1 -1
- package/dist/cjs/anyspend/react/components/common/OrderTokenAmountFiat.js +1 -1
- package/dist/cjs/anyspend/react/components/common/OrderTokenAmountNew.js +2 -2
- package/dist/cjs/anyspend/react/components/common/PaymentStripeWeb2.js +4 -6
- package/dist/cjs/anyspend/react/components/common/PaymentVendorUI.js +41 -2
- package/dist/cjs/anyspend/react/components/common/TransferCryptoDetails.js +1 -1
- package/dist/cjs/anyspend/react/components/webview/WebviewOnrampPayment.js +2 -3
- package/dist/cjs/anyspend/react/hooks/index.d.ts +1 -0
- package/dist/cjs/anyspend/react/hooks/index.js +1 -0
- package/dist/cjs/anyspend/react/hooks/useConnectedUserProfile.d.ts +2 -1
- package/dist/cjs/anyspend/react/hooks/useConnectedUserProfile.js +5 -8
- package/dist/cjs/anyspend/react/hooks/useConnectedWalletDisplay.d.ts +0 -2
- package/dist/cjs/anyspend/react/hooks/useConnectedWalletDisplay.js +2 -12
- package/dist/cjs/anyspend/react/hooks/useHyperliquidTransfer.d.ts +37 -0
- package/dist/cjs/anyspend/react/hooks/useHyperliquidTransfer.js +133 -0
- package/dist/cjs/anyspend/react/providers/AnyspendProvider.js +1 -13
- package/dist/cjs/anyspend/types/chain.d.ts +10 -2
- package/dist/cjs/anyspend/types/chain.js +1 -0
- package/dist/cjs/anyspend/utils/address.d.ts +11 -0
- package/dist/cjs/anyspend/utils/address.js +15 -0
- package/dist/cjs/anyspend/utils/chain.d.ts +20 -1
- package/dist/cjs/anyspend/utils/chain.js +73 -4
- package/dist/cjs/anyspend/utils/token.d.ts +1 -0
- package/dist/cjs/anyspend/utils/token.js +19 -6
- package/dist/cjs/global-account/react/components/B3Provider/B3Provider.js +1 -1
- package/dist/cjs/global-account/react/components/SignInWithB3/SignIn.js +3 -4
- package/dist/cjs/global-account/react/components/SignInWithB3/steps/LoginStep.js +1 -1
- package/dist/cjs/global-account/react/hooks/index.d.ts +0 -1
- package/dist/cjs/global-account/react/hooks/index.js +1 -3
- package/dist/cjs/global-account/react/hooks/useAccountWallet.js +11 -10
- package/dist/cjs/shared/utils/payment.utils.d.ts +1 -0
- package/dist/cjs/shared/utils/payment.utils.js +9 -0
- package/dist/esm/anyspend/constants/index.d.ts +1 -1
- package/dist/esm/anyspend/constants/index.js +1 -1
- package/dist/esm/anyspend/react/components/AnySpend.js +22 -10
- package/dist/esm/anyspend/react/components/AnySpendCustom.js +5 -4
- package/dist/esm/anyspend/react/components/common/CryptoPaySection.js +4 -6
- package/dist/esm/anyspend/react/components/common/CryptoPaymentMethodDisplay.d.ts +15 -0
- package/dist/esm/anyspend/react/components/common/CryptoPaymentMethodDisplay.js +25 -0
- package/dist/esm/anyspend/react/components/common/InsufficientDepositPayment.js +2 -2
- package/dist/esm/anyspend/react/components/common/OrderDetails.js +6 -5
- package/dist/esm/anyspend/react/components/common/OrderToken.js +3 -3
- package/dist/esm/anyspend/react/components/common/OrderTokenAmount.js +2 -2
- package/dist/esm/anyspend/react/components/common/OrderTokenAmountFiat.js +2 -2
- package/dist/esm/anyspend/react/components/common/OrderTokenAmountNew.js +3 -3
- package/dist/esm/anyspend/react/components/common/PaymentStripeWeb2.js +2 -4
- package/dist/esm/anyspend/react/components/common/PaymentVendorUI.js +9 -3
- package/dist/esm/anyspend/react/components/common/TransferCryptoDetails.js +2 -2
- package/dist/esm/anyspend/react/components/webview/WebviewOnrampPayment.js +3 -4
- package/dist/esm/anyspend/react/hooks/index.d.ts +1 -0
- package/dist/esm/anyspend/react/hooks/index.js +1 -0
- package/dist/esm/anyspend/react/hooks/useConnectedUserProfile.d.ts +2 -1
- package/dist/esm/anyspend/react/hooks/useConnectedUserProfile.js +6 -9
- package/dist/esm/anyspend/react/hooks/useConnectedWalletDisplay.d.ts +0 -2
- package/dist/esm/anyspend/react/hooks/useConnectedWalletDisplay.js +2 -12
- package/dist/esm/anyspend/react/hooks/useHyperliquidTransfer.d.ts +37 -0
- package/dist/esm/anyspend/react/hooks/useHyperliquidTransfer.js +127 -0
- package/dist/esm/anyspend/react/providers/AnyspendProvider.js +1 -13
- package/dist/esm/anyspend/types/chain.d.ts +10 -2
- package/dist/esm/anyspend/types/chain.js +1 -0
- package/dist/esm/anyspend/utils/address.d.ts +11 -0
- package/dist/esm/anyspend/utils/address.js +14 -0
- package/dist/esm/anyspend/utils/chain.d.ts +20 -1
- package/dist/esm/anyspend/utils/chain.js +70 -4
- package/dist/esm/anyspend/utils/token.d.ts +1 -0
- package/dist/esm/anyspend/utils/token.js +19 -7
- package/dist/esm/global-account/react/components/B3Provider/B3Provider.js +2 -2
- package/dist/esm/global-account/react/components/SignInWithB3/SignIn.js +4 -5
- package/dist/esm/global-account/react/components/SignInWithB3/steps/LoginStep.js +1 -1
- package/dist/esm/global-account/react/hooks/index.d.ts +0 -1
- package/dist/esm/global-account/react/hooks/index.js +0 -1
- package/dist/esm/global-account/react/hooks/useAccountWallet.js +11 -10
- package/dist/esm/shared/utils/payment.utils.d.ts +1 -0
- package/dist/esm/shared/utils/payment.utils.js +9 -1
- package/dist/types/anyspend/constants/index.d.ts +1 -1
- package/dist/types/anyspend/react/components/common/CryptoPaymentMethodDisplay.d.ts +15 -0
- package/dist/types/anyspend/react/hooks/index.d.ts +1 -0
- package/dist/types/anyspend/react/hooks/useConnectedUserProfile.d.ts +2 -1
- package/dist/types/anyspend/react/hooks/useConnectedWalletDisplay.d.ts +0 -2
- package/dist/types/anyspend/react/hooks/useHyperliquidTransfer.d.ts +37 -0
- package/dist/types/anyspend/types/chain.d.ts +10 -2
- package/dist/types/anyspend/utils/address.d.ts +11 -0
- package/dist/types/anyspend/utils/chain.d.ts +20 -1
- package/dist/types/anyspend/utils/token.d.ts +1 -0
- package/dist/types/global-account/react/hooks/index.d.ts +0 -1
- package/dist/types/shared/utils/payment.utils.d.ts +1 -0
- package/package.json +1 -1
- package/src/anyspend/constants/index.ts +1 -1
- package/src/anyspend/react/components/AnySpend.tsx +31 -9
- package/src/anyspend/react/components/AnySpendCustom.tsx +9 -25
- package/src/anyspend/react/components/common/CryptoPaySection.tsx +7 -30
- package/src/anyspend/react/components/common/CryptoPaymentMethodDisplay.tsx +64 -0
- package/src/anyspend/react/components/common/InsufficientDepositPayment.tsx +2 -2
- package/src/anyspend/react/components/common/OrderDetails.tsx +6 -5
- package/src/anyspend/react/components/common/OrderToken.tsx +5 -5
- package/src/anyspend/react/components/common/OrderTokenAmount.tsx +3 -3
- package/src/anyspend/react/components/common/OrderTokenAmountFiat.tsx +3 -3
- package/src/anyspend/react/components/common/OrderTokenAmountNew.tsx +6 -6
- package/src/anyspend/react/components/common/PaymentStripeWeb2.tsx +3 -5
- package/src/anyspend/react/components/common/PaymentVendorUI.tsx +26 -2
- package/src/anyspend/react/components/common/TransferCryptoDetails.tsx +2 -2
- package/src/anyspend/react/components/webview/WebviewOnrampPayment.tsx +3 -5
- package/src/anyspend/react/hooks/index.ts +1 -0
- package/src/anyspend/react/hooks/useConnectedUserProfile.ts +7 -10
- package/src/anyspend/react/hooks/useConnectedWalletDisplay.ts +2 -15
- package/src/anyspend/react/hooks/useHyperliquidTransfer.ts +152 -0
- package/src/anyspend/react/providers/AnyspendProvider.tsx +7 -22
- package/src/anyspend/types/chain.ts +10 -1
- package/src/anyspend/utils/address.ts +15 -0
- package/src/anyspend/utils/chain.ts +84 -4
- package/src/anyspend/utils/token.ts +20 -7
- package/src/global-account/react/components/B3Provider/B3Provider.tsx +6 -2
- package/src/global-account/react/components/SignInWithB3/SignIn.tsx +4 -6
- package/src/global-account/react/components/SignInWithB3/steps/LoginStep.tsx +1 -1
- package/src/global-account/react/hooks/index.ts +0 -1
- package/src/global-account/react/hooks/useAccountWallet.tsx +12 -11
- package/src/shared/utils/payment.utils.ts +10 -1
- package/dist/cjs/global-account/react/hooks/useBestTransactionPath.d.ts +0 -41
- package/dist/cjs/global-account/react/hooks/useBestTransactionPath.js +0 -148
- package/dist/esm/global-account/react/hooks/useBestTransactionPath.d.ts +0 -41
- package/dist/esm/global-account/react/hooks/useBestTransactionPath.js +0 -145
- package/dist/types/global-account/react/hooks/useBestTransactionPath.d.ts +0 -41
- package/src/global-account/react/hooks/useBestTransactionPath.tsx +0 -201
|
@@ -5,8 +5,6 @@ import { CryptoPaymentMethodType } from "../components/common/CryptoPaymentMetho
|
|
|
5
5
|
interface UseConnectedWalletDisplayResult {
|
|
6
6
|
walletAddress: string | undefined;
|
|
7
7
|
shouldShowConnectedEOA: boolean;
|
|
8
|
-
shouldShowWagmiWallet: boolean;
|
|
9
|
-
isWalletDuplicated: boolean;
|
|
10
8
|
suggestedPaymentMethod: CryptoPaymentMethodType;
|
|
11
9
|
}
|
|
12
10
|
|
|
@@ -22,27 +20,18 @@ export function useConnectedWalletDisplay(
|
|
|
22
20
|
|
|
23
21
|
const globalWalletAddress = connectedSmartWallet?.getAccount()?.address;
|
|
24
22
|
|
|
25
|
-
// Helper function to check if two addresses are the same
|
|
26
|
-
const isSameAddress = (addr1?: string, addr2?: string): boolean => {
|
|
27
|
-
if (!addr1 || !addr2) return false;
|
|
28
|
-
return addr1.toLowerCase() === addr2.toLowerCase();
|
|
29
|
-
};
|
|
30
|
-
|
|
31
23
|
// Check if connectedEOAWallet and wagmi wallet represent the same wallet
|
|
32
24
|
const connectedEOAAddress = connectedEOAWallet?.getAccount()?.address;
|
|
33
|
-
const isWalletDuplicated =
|
|
34
|
-
isSameAddress(connectedEOAAddress, wagmiAddress) || isSameAddress(globalWalletAddress, wagmiAddress);
|
|
35
25
|
|
|
36
26
|
// Determine which wallet to show (prefer connectedEOAWallet if both exist and are the same)
|
|
37
27
|
const shouldShowConnectedEOA = !!connectedEOAWallet;
|
|
38
28
|
// this is disabled because we don't want to display In-App Wallet as a payment method
|
|
39
|
-
const shouldShowWagmiWallet = false; // wagmiWalletIsConnected && (!isWalletDuplicated || !connectedEOAWallet);
|
|
40
29
|
|
|
41
30
|
// Determine which address to use based on payment method
|
|
42
31
|
let walletAddress: string | undefined;
|
|
43
32
|
|
|
44
33
|
if (selectedCryptoPaymentMethod === CryptoPaymentMethodType.GLOBAL_WALLET) {
|
|
45
|
-
walletAddress =
|
|
34
|
+
walletAddress = globalWalletAddress;
|
|
46
35
|
} else if (selectedCryptoPaymentMethod === CryptoPaymentMethodType.CONNECT_WALLET) {
|
|
47
36
|
// Prefer connectedEOAWallet, fallback to wagmi wallet
|
|
48
37
|
walletAddress = connectedEOAAddress || wagmiAddress;
|
|
@@ -58,7 +47,7 @@ export function useConnectedWalletDisplay(
|
|
|
58
47
|
if (connectedEOAAddress || wagmiAddress) {
|
|
59
48
|
// If there's a connected EOA or wagmi wallet, suggest CONNECT_WALLET
|
|
60
49
|
suggestedPaymentMethod = CryptoPaymentMethodType.CONNECT_WALLET;
|
|
61
|
-
} else if (
|
|
50
|
+
} else if (globalWalletAddress) {
|
|
62
51
|
// If only global wallet is available, suggest that
|
|
63
52
|
suggestedPaymentMethod = CryptoPaymentMethodType.GLOBAL_WALLET;
|
|
64
53
|
}
|
|
@@ -66,8 +55,6 @@ export function useConnectedWalletDisplay(
|
|
|
66
55
|
return {
|
|
67
56
|
walletAddress,
|
|
68
57
|
shouldShowConnectedEOA,
|
|
69
|
-
shouldShowWagmiWallet,
|
|
70
|
-
isWalletDuplicated,
|
|
71
58
|
suggestedPaymentMethod,
|
|
72
59
|
};
|
|
73
60
|
}
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import { HYPERLIQUID_CHAIN_ID, HYPERLIQUID_MAINNET } from "@b3dotfun/sdk/anyspend";
|
|
2
|
+
import { toast } from "@b3dotfun/sdk/global-account/react";
|
|
3
|
+
import { formatUnits } from "@b3dotfun/sdk/shared/utils/number";
|
|
4
|
+
import axios from "axios";
|
|
5
|
+
import { useCallback } from "react";
|
|
6
|
+
import { parseSignature } from "viem";
|
|
7
|
+
import { useWalletClient } from "wagmi";
|
|
8
|
+
|
|
9
|
+
interface HyperliquidTransferParams {
|
|
10
|
+
/** Amount in smallest unit (USDC has 6 decimals) */
|
|
11
|
+
amount: string;
|
|
12
|
+
/** Recipient address */
|
|
13
|
+
destination: string;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* @deprecated This hook is NOT USED in production.
|
|
18
|
+
*
|
|
19
|
+
* Hyperliquid is only supported as DESTINATION CHAIN (not source chain).
|
|
20
|
+
* Users cannot send FROM Hyperliquid in our flow, so EIP-712 signing is not needed.
|
|
21
|
+
*
|
|
22
|
+
* This hook was created during initial planning but is kept for:
|
|
23
|
+
* - Reference if we need to support source chain in the future
|
|
24
|
+
* - Understanding how Hyperliquid EIP-712 transfers work
|
|
25
|
+
*
|
|
26
|
+
* DO NOT USE THIS HOOK IN PRODUCTION CODE.
|
|
27
|
+
*
|
|
28
|
+
* Custom hook for handling Hyperliquid transfers via EIP-712 signature.
|
|
29
|
+
* Based on Relay SDK's Hyperliquid implementation.
|
|
30
|
+
*
|
|
31
|
+
* @example
|
|
32
|
+
* ```tsx
|
|
33
|
+
* const { initiateTransfer } = useHyperliquidTransfer();
|
|
34
|
+
*
|
|
35
|
+
* await initiateTransfer({
|
|
36
|
+
* amount: "1000000", // 1 USDC
|
|
37
|
+
* destination: "0x..."
|
|
38
|
+
* });
|
|
39
|
+
* ```
|
|
40
|
+
*/
|
|
41
|
+
export function useHyperliquidTransfer() {
|
|
42
|
+
const { data: walletClient } = useWalletClient();
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Get the connected wallet address if available.
|
|
46
|
+
*/
|
|
47
|
+
const getConnectedAddress = useCallback(() => {
|
|
48
|
+
return walletClient?.account?.address || null;
|
|
49
|
+
}, [walletClient]);
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Initiate Hyperliquid transfer by signing EIP-712 message and sending to Hyperliquid API.
|
|
53
|
+
*/
|
|
54
|
+
const initiateTransfer = useCallback(
|
|
55
|
+
async ({ amount, destination }: HyperliquidTransferParams): Promise<void> => {
|
|
56
|
+
if (!walletClient?.account) {
|
|
57
|
+
toast.error("Please connect your wallet");
|
|
58
|
+
throw new Error("Wallet not connected");
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
try {
|
|
62
|
+
const currentTime = new Date().getTime();
|
|
63
|
+
|
|
64
|
+
// Convert amount from smallest unit (6 decimals) to display format.
|
|
65
|
+
// e.g., "11151533" -> "11.151533"
|
|
66
|
+
const displayAmount = formatUnits(amount, 6);
|
|
67
|
+
|
|
68
|
+
// Prepare EIP-712 typed data for Hyperliquid USD send.
|
|
69
|
+
const typedData = {
|
|
70
|
+
domain: {
|
|
71
|
+
name: "HyperliquidSignTransaction",
|
|
72
|
+
version: "1",
|
|
73
|
+
chainId: HYPERLIQUID_CHAIN_ID,
|
|
74
|
+
verifyingContract: "0x0000000000000000000000000000000000000000" as `0x${string}`,
|
|
75
|
+
},
|
|
76
|
+
types: {
|
|
77
|
+
"HyperliquidTransaction:UsdSend": [
|
|
78
|
+
{ name: "hyperliquidChain", type: "string" },
|
|
79
|
+
{ name: "destination", type: "string" },
|
|
80
|
+
{ name: "amount", type: "string" },
|
|
81
|
+
{ name: "time", type: "uint64" },
|
|
82
|
+
],
|
|
83
|
+
},
|
|
84
|
+
primaryType: "HyperliquidTransaction:UsdSend" as const,
|
|
85
|
+
message: {
|
|
86
|
+
hyperliquidChain: "Mainnet",
|
|
87
|
+
destination: destination.toLowerCase(),
|
|
88
|
+
amount: displayAmount,
|
|
89
|
+
time: BigInt(currentTime),
|
|
90
|
+
},
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
toast.info("Please sign the message in your wallet");
|
|
94
|
+
|
|
95
|
+
// Sign EIP-712 message.
|
|
96
|
+
const signature = await walletClient.signTypedData(typedData);
|
|
97
|
+
|
|
98
|
+
// Parse signature to get r, s, v components.
|
|
99
|
+
const { r, s, v } = parseSignature(signature);
|
|
100
|
+
|
|
101
|
+
toast.info("Sending transaction to Hyperliquid...");
|
|
102
|
+
|
|
103
|
+
// Send signature to Hyperliquid API.
|
|
104
|
+
const response = await axios.post(HYPERLIQUID_MAINNET.apiUrl + "/exchange", {
|
|
105
|
+
signature: {
|
|
106
|
+
r,
|
|
107
|
+
s,
|
|
108
|
+
v: Number(v ?? BigInt(0)),
|
|
109
|
+
},
|
|
110
|
+
nonce: currentTime,
|
|
111
|
+
action: {
|
|
112
|
+
type: "usdSend",
|
|
113
|
+
signatureChainId: `0x${HYPERLIQUID_CHAIN_ID.toString(16)}`,
|
|
114
|
+
hyperliquidChain: "Mainnet",
|
|
115
|
+
destination: destination.toLowerCase(),
|
|
116
|
+
amount: displayAmount,
|
|
117
|
+
time: currentTime,
|
|
118
|
+
},
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
// Check response status.
|
|
122
|
+
if (!response || response.status !== 200 || response.data?.status !== "ok") {
|
|
123
|
+
const errorMsg = response?.data?.error || "Failed to send transaction to Hyperliquid";
|
|
124
|
+
toast.error(errorMsg);
|
|
125
|
+
throw new Error(errorMsg);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
toast.success("Transaction sent to Hyperliquid successfully!");
|
|
129
|
+
} catch (error: any) {
|
|
130
|
+
console.error("Hyperliquid transfer error:", error);
|
|
131
|
+
|
|
132
|
+
// Handle user rejection.
|
|
133
|
+
if (error?.message?.includes("User rejected") || error?.code === 4001) {
|
|
134
|
+
toast.error("Transaction signature rejected");
|
|
135
|
+
throw new Error("User rejected signature");
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// Handle other errors.
|
|
139
|
+
const errorMsg = error?.message || "Failed to complete Hyperliquid transfer";
|
|
140
|
+
toast.error(errorMsg);
|
|
141
|
+
throw error;
|
|
142
|
+
}
|
|
143
|
+
},
|
|
144
|
+
[walletClient],
|
|
145
|
+
);
|
|
146
|
+
|
|
147
|
+
return {
|
|
148
|
+
initiateTransfer,
|
|
149
|
+
getConnectedAddress,
|
|
150
|
+
isWalletConnected: !!walletClient?.account,
|
|
151
|
+
};
|
|
152
|
+
}
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
3
|
import { TooltipProvider } from "@b3dotfun/sdk/global-account/react";
|
|
4
|
-
import {
|
|
5
|
-
import { ReactNode, useState } from "react";
|
|
4
|
+
import { ReactNode } from "react";
|
|
6
5
|
import { FeatureFlags, FeatureFlagsProvider } from "../contexts/FeatureFlagsContext";
|
|
7
6
|
import { StripeRedirectHandler } from "./StripeRedirectHandler";
|
|
8
7
|
|
|
@@ -11,16 +10,6 @@ interface AnyspendProviderProps {
|
|
|
11
10
|
featureFlags?: FeatureFlags;
|
|
12
11
|
}
|
|
13
12
|
|
|
14
|
-
const defaultQueryClientConfig = {
|
|
15
|
-
defaultOptions: {
|
|
16
|
-
queries: {
|
|
17
|
-
refetchOnWindowFocus: false,
|
|
18
|
-
retry: false,
|
|
19
|
-
staleTime: 30000,
|
|
20
|
-
},
|
|
21
|
-
},
|
|
22
|
-
} as const;
|
|
23
|
-
|
|
24
13
|
/**
|
|
25
14
|
* AnyspendProvider is a top-level provider that wraps your application to provide
|
|
26
15
|
* query caching and state management for all Anyspend hooks.
|
|
@@ -45,16 +34,12 @@ const defaultQueryClientConfig = {
|
|
|
45
34
|
* ```
|
|
46
35
|
*/
|
|
47
36
|
export const AnyspendProvider = function AnyspendProvider({ children, featureFlags }: AnyspendProviderProps) {
|
|
48
|
-
const [queryClient] = useState(() => new QueryClient(defaultQueryClientConfig));
|
|
49
|
-
|
|
50
37
|
return (
|
|
51
|
-
<
|
|
52
|
-
<
|
|
53
|
-
<
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
</FeatureFlagsProvider>
|
|
58
|
-
</QueryClientProvider>
|
|
38
|
+
<FeatureFlagsProvider featureFlags={featureFlags}>
|
|
39
|
+
<TooltipProvider>
|
|
40
|
+
<StripeRedirectHandler />
|
|
41
|
+
{children}
|
|
42
|
+
</TooltipProvider>
|
|
43
|
+
</FeatureFlagsProvider>
|
|
59
44
|
);
|
|
60
45
|
};
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import { Chain } from "viem";
|
|
2
1
|
import { components } from "@b3dotfun/sdk/anyspend/types/api";
|
|
2
|
+
import { Chain } from "viem";
|
|
3
3
|
|
|
4
4
|
export enum ChainType {
|
|
5
5
|
EVM = "evm",
|
|
6
6
|
SOLANA = "solana",
|
|
7
|
+
HYPERLIQUID = "hyperliquid",
|
|
7
8
|
}
|
|
8
9
|
|
|
9
10
|
export interface IBaseChain {
|
|
@@ -29,3 +30,11 @@ export interface IEVMChain extends IBaseChain {
|
|
|
29
30
|
export interface ISolanaChain extends IBaseChain {
|
|
30
31
|
type: ChainType.SOLANA;
|
|
31
32
|
}
|
|
33
|
+
|
|
34
|
+
export interface IHyperliquidChain extends IBaseChain {
|
|
35
|
+
type: ChainType.HYPERLIQUID;
|
|
36
|
+
apiUrl: string;
|
|
37
|
+
blockExplorer: {
|
|
38
|
+
url: string;
|
|
39
|
+
};
|
|
40
|
+
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { isAddress } from "viem";
|
|
2
|
+
import { HYPERLIQUID_CHAIN_ID } from "./token";
|
|
2
3
|
|
|
3
4
|
export function isSolanaAddress(address: string): boolean {
|
|
4
5
|
// Solana addresses are 32-byte base58 strings (usually 32-44 characters)
|
|
@@ -10,6 +11,20 @@ export function isEvmOrSolanaAddress(address: string): boolean {
|
|
|
10
11
|
return isAddress(address) || isSolanaAddress(address);
|
|
11
12
|
}
|
|
12
13
|
|
|
14
|
+
/**
|
|
15
|
+
* Check if an address is Hyperliquid's special USDC address.
|
|
16
|
+
* Hyperliquid USDC uses a special 34-character format (0x + 32 hex digits)
|
|
17
|
+
* instead of the standard 42-character Ethereum address format.
|
|
18
|
+
* This is required by Relay SDK for Hyperliquid integration.
|
|
19
|
+
*
|
|
20
|
+
* @param chainId - The chain ID to check
|
|
21
|
+
* @param address - The token address to validate
|
|
22
|
+
* @returns true if the address is Hyperliquid USDC's special format
|
|
23
|
+
*/
|
|
24
|
+
export function isHyperliquidUSDC(chainId: number, address: string): boolean {
|
|
25
|
+
return chainId === HYPERLIQUID_CHAIN_ID && address.toLowerCase() === "0x00000000000000000000000000000000";
|
|
26
|
+
}
|
|
27
|
+
|
|
13
28
|
export function normalizeAddress(address: string): string {
|
|
14
29
|
if (isSolanaAddress(address)) {
|
|
15
30
|
return address;
|
|
@@ -14,15 +14,17 @@ import {
|
|
|
14
14
|
WalletClient,
|
|
15
15
|
} from "viem";
|
|
16
16
|
import { abstract, arbitrum, avalanche, b3, base, bsc, mainnet, optimism, polygon } from "viem/chains";
|
|
17
|
-
import { ChainType, IBaseChain, IEVMChain, ISolanaChain } from "../types/chain";
|
|
17
|
+
import { ChainType, IBaseChain, IEVMChain, IHyperliquidChain, ISolanaChain } from "../types/chain";
|
|
18
18
|
import {
|
|
19
19
|
getAvaxToken,
|
|
20
20
|
getBnbToken,
|
|
21
21
|
getEthToken,
|
|
22
22
|
getHyperEVMNativeToken,
|
|
23
|
+
getHyperliquidUSDCToken,
|
|
23
24
|
getPolToken,
|
|
24
25
|
getSolanaToken,
|
|
25
26
|
HYPEREVM_CHAIN_ID,
|
|
27
|
+
HYPERLIQUID_CHAIN_ID,
|
|
26
28
|
} from "./token";
|
|
27
29
|
|
|
28
30
|
function getCustomEvmChain(chain: Chain, rpcUrl: string): Chain {
|
|
@@ -283,11 +285,31 @@ export const SOLANA_MAINNET: ISolanaChain = {
|
|
|
283
285
|
coingeckoName: "solana",
|
|
284
286
|
};
|
|
285
287
|
|
|
288
|
+
export const HYPERLIQUID_MAINNET: IHyperliquidChain = {
|
|
289
|
+
id: HYPERLIQUID_CHAIN_ID,
|
|
290
|
+
name: "Hyperliquid",
|
|
291
|
+
type: ChainType.HYPERLIQUID,
|
|
292
|
+
logoUrl: "https://s2.coinmarketcap.com/static/img/coins/64x64/32196.png",
|
|
293
|
+
nativeRequired: BigInt(0), // No native transfer needed - using Relay's useDepositAddress flow (USDC is native)
|
|
294
|
+
canDepositNative: true, // Can deposit USDC (native token)
|
|
295
|
+
defaultToken: getHyperliquidUSDCToken(),
|
|
296
|
+
nativeToken: getHyperliquidUSDCToken(),
|
|
297
|
+
coingeckoName: null,
|
|
298
|
+
apiUrl: "https://api.hyperliquid.xyz",
|
|
299
|
+
blockExplorer: {
|
|
300
|
+
url: "https://app.hyperliquid.xyz/explorer",
|
|
301
|
+
},
|
|
302
|
+
};
|
|
303
|
+
|
|
286
304
|
export const EVM_CHAINS: Record<number, IEVMChain> = { ...EVM_MAINNET, ...EVM_TESTNET };
|
|
287
305
|
|
|
288
306
|
export const SOLANA_CHAINS: Record<number, ISolanaChain> = { [RELAY_SOLANA_MAINNET_CHAIN_ID]: SOLANA_MAINNET };
|
|
289
307
|
|
|
290
|
-
export const
|
|
308
|
+
export const HYPERLIQUID_CHAINS: Record<number, IHyperliquidChain> = {
|
|
309
|
+
[HYPERLIQUID_CHAIN_ID]: HYPERLIQUID_MAINNET,
|
|
310
|
+
};
|
|
311
|
+
|
|
312
|
+
export const ALL_CHAINS: Record<number, IBaseChain> = { ...EVM_CHAINS, ...SOLANA_CHAINS, ...HYPERLIQUID_CHAINS };
|
|
291
313
|
|
|
292
314
|
export function getSolanaChains(network: "mainnet" | "testnet"): ISolanaChain {
|
|
293
315
|
invariant(network === "mainnet", "Solana chain is only supported on mainnet");
|
|
@@ -335,7 +357,9 @@ export function canDepositNative(chainId: number): boolean {
|
|
|
335
357
|
}
|
|
336
358
|
|
|
337
359
|
export function isMainnet(chainId: number): boolean {
|
|
338
|
-
return
|
|
360
|
+
return (
|
|
361
|
+
EVM_MAINNET[chainId] !== undefined || RELAY_SOLANA_MAINNET_CHAIN_ID === chainId || HYPERLIQUID_CHAIN_ID === chainId
|
|
362
|
+
);
|
|
339
363
|
}
|
|
340
364
|
|
|
341
365
|
export function isTestnet(chainId: number): boolean {
|
|
@@ -349,7 +373,13 @@ export function getDefaultToken(chainId: number): components["schemas"]["Token"]
|
|
|
349
373
|
|
|
350
374
|
export function getChainName(chainId: number): string {
|
|
351
375
|
invariant(ALL_CHAINS[chainId], `Chain ${chainId} is not supported`);
|
|
352
|
-
|
|
376
|
+
const chain = ALL_CHAINS[chainId];
|
|
377
|
+
|
|
378
|
+
if (isEvmChain(chainId)) {
|
|
379
|
+
return (chain as IEVMChain).viem.name;
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
return chain.name;
|
|
353
383
|
}
|
|
354
384
|
|
|
355
385
|
export function getCoingeckoName(chainId: number): string | null {
|
|
@@ -511,6 +541,13 @@ export function getPaymentUrl(address: string, amount: bigint, currency: string,
|
|
|
511
541
|
return url;
|
|
512
542
|
}
|
|
513
543
|
|
|
544
|
+
case ChainType.HYPERLIQUID: {
|
|
545
|
+
// NOTE: Hyperliquid is only supported as destination chain (not source chain).
|
|
546
|
+
// Payment URLs are not needed since users cannot send FROM Hyperliquid in our flow.
|
|
547
|
+
// Return address as placeholder (this code path should not be reached).
|
|
548
|
+
return address;
|
|
549
|
+
}
|
|
550
|
+
|
|
514
551
|
default:
|
|
515
552
|
// Fallback to just the address if chain type is unknown
|
|
516
553
|
return address;
|
|
@@ -524,6 +561,10 @@ export function getExplorerTxUrl(chainId: number, txHash: string) {
|
|
|
524
561
|
if (EVM_CHAINS[chainId]) {
|
|
525
562
|
return EVM_CHAINS[chainId].viem.blockExplorers?.default.url + "/tx/" + txHash;
|
|
526
563
|
}
|
|
564
|
+
if (HYPERLIQUID_CHAINS[chainId]) {
|
|
565
|
+
return HYPERLIQUID_CHAINS[chainId].blockExplorer.url + "/tx/" + txHash;
|
|
566
|
+
}
|
|
567
|
+
// Default to Solscan for Solana transactions
|
|
527
568
|
return "https://solscan.io/tx/" + txHash;
|
|
528
569
|
}
|
|
529
570
|
|
|
@@ -531,6 +572,10 @@ export function getExplorerAddressUrl(chainId: number, address: string) {
|
|
|
531
572
|
if (EVM_CHAINS[chainId]) {
|
|
532
573
|
return EVM_CHAINS[chainId].viem.blockExplorers?.default.url + "/address/" + address;
|
|
533
574
|
}
|
|
575
|
+
if (HYPERLIQUID_CHAINS[chainId]) {
|
|
576
|
+
return HYPERLIQUID_CHAINS[chainId].blockExplorer.url + "/address/" + address;
|
|
577
|
+
}
|
|
578
|
+
// Default to Solscan for Solana addresses
|
|
534
579
|
return "https://solscan.io/account/" + address;
|
|
535
580
|
}
|
|
536
581
|
|
|
@@ -550,3 +595,38 @@ export function getNativeToken(chainId: number): components["schemas"]["Token"]
|
|
|
550
595
|
export function isEvmChain(chainId: number): boolean {
|
|
551
596
|
return Boolean(EVM_CHAINS[chainId]);
|
|
552
597
|
}
|
|
598
|
+
|
|
599
|
+
export function isHyperliquidChain(chainId: number): boolean {
|
|
600
|
+
return HYPERLIQUID_CHAINS[chainId] !== undefined;
|
|
601
|
+
}
|
|
602
|
+
|
|
603
|
+
export function getHyperliquidChain(chainId: number): IHyperliquidChain {
|
|
604
|
+
invariant(HYPERLIQUID_CHAINS[chainId], `Chain ${chainId} is not a Hyperliquid chain`);
|
|
605
|
+
return HYPERLIQUID_CHAINS[chainId];
|
|
606
|
+
}
|
|
607
|
+
|
|
608
|
+
/**
|
|
609
|
+
* Get available chain IDs for AnySpend based on context (source or destination).
|
|
610
|
+
* Filters out chains that shouldn't be available for the given context.
|
|
611
|
+
*
|
|
612
|
+
* @param context - "from" for source chains, "to" for destination chains
|
|
613
|
+
* @returns Array of available chain IDs
|
|
614
|
+
*
|
|
615
|
+
* @example
|
|
616
|
+
* // Get source chains (excludes Hyperliquid)
|
|
617
|
+
* const sourceChains = getAvailableChainIds("from") // [1, 8453, 137, ...]
|
|
618
|
+
*
|
|
619
|
+
* // Get destination chains (includes Hyperliquid)
|
|
620
|
+
* const destChains = getAvailableChainIds("to") // [1, 8453, 137, ..., 1337]
|
|
621
|
+
*/
|
|
622
|
+
export function getAvailableChainIds(context: "from" | "to"): number[] {
|
|
623
|
+
const allChainIds = Object.values(ALL_CHAINS).map(chain => chain.id);
|
|
624
|
+
|
|
625
|
+
if (context === "from") {
|
|
626
|
+
// Hyperliquid is only supported as destination chain, not source chain
|
|
627
|
+
return allChainIds.filter(chainId => chainId !== HYPERLIQUID_CHAIN_ID);
|
|
628
|
+
}
|
|
629
|
+
|
|
630
|
+
// For destination ("to"), all chains are available including Hyperliquid
|
|
631
|
+
return allChainIds;
|
|
632
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { RELAY_SOL_ADDRESS, RELAY_SOLANA_MAINNET_CHAIN_ID, ZERO_ADDRESS } from "@b3dotfun/sdk/anyspend/constants";
|
|
2
2
|
import { components } from "@b3dotfun/sdk/anyspend/types/api";
|
|
3
3
|
import { avalanche, bsc, polygon } from "viem/chains";
|
|
4
4
|
|
|
@@ -6,7 +6,7 @@ export const HYPERLIQUID_CHAIN_ID = 1337;
|
|
|
6
6
|
export const HYPEREVM_CHAIN_ID = 999;
|
|
7
7
|
|
|
8
8
|
export function isNativeToken(address: string): boolean {
|
|
9
|
-
return address.toLowerCase() ===
|
|
9
|
+
return address.toLowerCase() === ZERO_ADDRESS || address.toLowerCase() === RELAY_SOL_ADDRESS;
|
|
10
10
|
}
|
|
11
11
|
|
|
12
12
|
export function getSolanaToken(): components["schemas"]["Token"] {
|
|
@@ -25,7 +25,7 @@ export function getSolanaToken(): components["schemas"]["Token"] {
|
|
|
25
25
|
export function getEthToken(chainId: number): components["schemas"]["Token"] {
|
|
26
26
|
return {
|
|
27
27
|
chainId: chainId,
|
|
28
|
-
address:
|
|
28
|
+
address: ZERO_ADDRESS,
|
|
29
29
|
symbol: "ETH",
|
|
30
30
|
name: "Ethereum",
|
|
31
31
|
decimals: 18,
|
|
@@ -38,7 +38,7 @@ export function getEthToken(chainId: number): components["schemas"]["Token"] {
|
|
|
38
38
|
export function getPolToken(): components["schemas"]["Token"] {
|
|
39
39
|
return {
|
|
40
40
|
chainId: polygon.id,
|
|
41
|
-
address:
|
|
41
|
+
address: ZERO_ADDRESS,
|
|
42
42
|
symbol: "POL",
|
|
43
43
|
name: "Polygon",
|
|
44
44
|
decimals: 18,
|
|
@@ -51,7 +51,7 @@ export function getPolToken(): components["schemas"]["Token"] {
|
|
|
51
51
|
export function getBnbToken(): components["schemas"]["Token"] {
|
|
52
52
|
return {
|
|
53
53
|
chainId: bsc.id,
|
|
54
|
-
address:
|
|
54
|
+
address: ZERO_ADDRESS,
|
|
55
55
|
symbol: "BNB",
|
|
56
56
|
name: "BNB",
|
|
57
57
|
decimals: 18,
|
|
@@ -64,7 +64,7 @@ export function getBnbToken(): components["schemas"]["Token"] {
|
|
|
64
64
|
export function getAvaxToken(): components["schemas"]["Token"] {
|
|
65
65
|
return {
|
|
66
66
|
chainId: avalanche.id,
|
|
67
|
-
address:
|
|
67
|
+
address: ZERO_ADDRESS,
|
|
68
68
|
symbol: "AVAX",
|
|
69
69
|
name: "AVAX",
|
|
70
70
|
decimals: 18,
|
|
@@ -77,7 +77,7 @@ export function getAvaxToken(): components["schemas"]["Token"] {
|
|
|
77
77
|
export function getHyperEVMNativeToken(): components["schemas"]["Token"] {
|
|
78
78
|
return {
|
|
79
79
|
chainId: HYPEREVM_CHAIN_ID,
|
|
80
|
-
address:
|
|
80
|
+
address: ZERO_ADDRESS,
|
|
81
81
|
symbol: "HYPE",
|
|
82
82
|
name: "HYPE",
|
|
83
83
|
decimals: 18,
|
|
@@ -86,3 +86,16 @@ export function getHyperEVMNativeToken(): components["schemas"]["Token"] {
|
|
|
86
86
|
},
|
|
87
87
|
};
|
|
88
88
|
}
|
|
89
|
+
|
|
90
|
+
export function getHyperliquidUSDCToken(): components["schemas"]["Token"] {
|
|
91
|
+
return {
|
|
92
|
+
chainId: HYPERLIQUID_CHAIN_ID,
|
|
93
|
+
address: ZERO_ADDRESS,
|
|
94
|
+
symbol: "USDC",
|
|
95
|
+
name: "USD Coin",
|
|
96
|
+
decimals: 6,
|
|
97
|
+
metadata: {
|
|
98
|
+
logoURI: "https://ethereum-optimism.github.io/data/USDC/logo.png",
|
|
99
|
+
},
|
|
100
|
+
};
|
|
101
|
+
}
|
|
@@ -12,7 +12,7 @@ import { loadGA4Script } from "@b3dotfun/sdk/global-account/utils/analytics";
|
|
|
12
12
|
import { debugB3React } from "@b3dotfun/sdk/shared/utils/debug";
|
|
13
13
|
import "@relayprotocol/relay-kit-ui/styles.css";
|
|
14
14
|
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
|
|
15
|
-
import { useCallback, useEffect, useState } from "react";
|
|
15
|
+
import { useCallback, useEffect, useMemo, useState } from "react";
|
|
16
16
|
import {
|
|
17
17
|
getLastAuthProvider,
|
|
18
18
|
ThirdwebProvider,
|
|
@@ -92,7 +92,11 @@ export function B3Provider({
|
|
|
92
92
|
useEffect(() => {
|
|
93
93
|
setClientType(clientType);
|
|
94
94
|
}, [clientType]);
|
|
95
|
-
|
|
95
|
+
|
|
96
|
+
const wagmiConfig = useMemo(
|
|
97
|
+
() => createWagmiConfig({ partnerId, rpcUrls, connectors, overrideDefaultConnectors }),
|
|
98
|
+
[partnerId, rpcUrls, connectors, overrideDefaultConnectors],
|
|
99
|
+
);
|
|
96
100
|
|
|
97
101
|
return (
|
|
98
102
|
<ThirdwebProvider>
|
|
@@ -13,8 +13,7 @@ import { ecosystemWalletId } from "@b3dotfun/sdk/shared/constants";
|
|
|
13
13
|
import { cn, truncateAddress } from "@b3dotfun/sdk/shared/utils";
|
|
14
14
|
import { Menu, MenuButton, MenuItems, Transition } from "@headlessui/react";
|
|
15
15
|
import { ReactNode, useEffect } from "react";
|
|
16
|
-
import { useConnectedWallets, useSetActiveWallet } from "thirdweb/react";
|
|
17
|
-
import { useAccountWalletImage } from "../../hooks/useAccountWallet";
|
|
16
|
+
import { useConnectedWallets, useSetActiveWallet, useWalletImage } from "thirdweb/react";
|
|
18
17
|
import { ManageAccountButton } from "../custom/ManageAccountButton";
|
|
19
18
|
|
|
20
19
|
type SignInProps = {
|
|
@@ -40,9 +39,10 @@ export function SignIn(props: SignInWithB3Props) {
|
|
|
40
39
|
isActiveSmartWallet,
|
|
41
40
|
isActiveEOAWallet,
|
|
42
41
|
smartWalletIcon,
|
|
43
|
-
eoaWalletIcon,
|
|
44
42
|
} = useAccountWallet();
|
|
45
43
|
|
|
44
|
+
const { data: walletImage } = useWalletImage(connectedEOAWallet?.id);
|
|
45
|
+
|
|
46
46
|
const isMobile = useIsMobile();
|
|
47
47
|
const { logout } = useAuthentication(partnerId);
|
|
48
48
|
const onDisconnect = async (): Promise<void> => {
|
|
@@ -72,8 +72,6 @@ export function SignIn(props: SignInWithB3Props) {
|
|
|
72
72
|
}
|
|
73
73
|
}, [connectedEOAWallet, isActiveEOAWallet, setActiveWallet, automaticallySetFirstEoa]);
|
|
74
74
|
|
|
75
|
-
const walletImage = useAccountWalletImage();
|
|
76
|
-
|
|
77
75
|
// Desktop version - original dropdown menu
|
|
78
76
|
return (
|
|
79
77
|
<StyleRoot>
|
|
@@ -115,7 +113,7 @@ export function SignIn(props: SignInWithB3Props) {
|
|
|
115
113
|
<div className="flex items-center">
|
|
116
114
|
<img
|
|
117
115
|
className="bg-b3-react-primary h-16 w-16 rounded-full opacity-100"
|
|
118
|
-
src={
|
|
116
|
+
src={walletImage}
|
|
119
117
|
alt={connectedEOAWallet?.id}
|
|
120
118
|
/>
|
|
121
119
|
<div className="ml-4 grow">
|
|
@@ -40,7 +40,7 @@ export function LoginStepContainer({ children, partnerId }: LoginStepContainerPr
|
|
|
40
40
|
const partnerLogo = partner?.data?.[0]?.loginCustomization?.logoUrl;
|
|
41
41
|
|
|
42
42
|
return (
|
|
43
|
-
<div className="flex flex-col items-center justify-center pt-6">
|
|
43
|
+
<div className="bg-b3-react-background flex flex-col items-center justify-center pt-6">
|
|
44
44
|
{partnerLogo && (
|
|
45
45
|
<img src={partnerLogo} alt="Partner Logo" className="partner-logo mb-6 h-12 w-auto object-contain" />
|
|
46
46
|
)}
|
|
@@ -6,7 +6,6 @@ export { useAnalytics } from "./useAnalytics";
|
|
|
6
6
|
export { useAuthentication } from "./useAuthentication";
|
|
7
7
|
export { useB3BalanceFromAddresses } from "./useB3BalanceFromAddresses";
|
|
8
8
|
export { useB3EnsName } from "./useB3EnsName";
|
|
9
|
-
export { useBestTransactionPath } from "./useBestTransactionPath";
|
|
10
9
|
export { useChainSwitchWithAction } from "./useChainSwitchWithAction";
|
|
11
10
|
export * from "./useClaim";
|
|
12
11
|
export { useClient } from "./useClient";
|