@b3dotfun/sdk 0.0.83-alpha.1 → 0.0.83-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 (70) hide show
  1. package/dist/cjs/anyspend/constants/index.d.ts +1 -1
  2. package/dist/cjs/anyspend/constants/index.js +2 -2
  3. package/dist/cjs/anyspend/react/components/AnySpend.js +5 -1
  4. package/dist/cjs/anyspend/react/components/AnySpendCustom.js +1 -1
  5. package/dist/cjs/anyspend/react/components/common/InsufficientDepositPayment.js +1 -1
  6. package/dist/cjs/anyspend/react/components/common/OrderDetails.js +5 -4
  7. package/dist/cjs/anyspend/react/components/common/OrderToken.js +2 -2
  8. package/dist/cjs/anyspend/react/components/common/OrderTokenAmount.js +1 -1
  9. package/dist/cjs/anyspend/react/components/common/OrderTokenAmountFiat.js +1 -1
  10. package/dist/cjs/anyspend/react/components/common/OrderTokenAmountNew.js +2 -2
  11. package/dist/cjs/anyspend/react/components/common/TransferCryptoDetails.js +1 -1
  12. package/dist/cjs/anyspend/react/hooks/index.d.ts +1 -0
  13. package/dist/cjs/anyspend/react/hooks/index.js +1 -0
  14. package/dist/cjs/anyspend/react/hooks/useHyperliquidTransfer.d.ts +37 -0
  15. package/dist/cjs/anyspend/react/hooks/useHyperliquidTransfer.js +133 -0
  16. package/dist/cjs/anyspend/types/chain.d.ts +10 -2
  17. package/dist/cjs/anyspend/types/chain.js +1 -0
  18. package/dist/cjs/anyspend/utils/address.d.ts +11 -0
  19. package/dist/cjs/anyspend/utils/address.js +15 -0
  20. package/dist/cjs/anyspend/utils/chain.d.ts +20 -1
  21. package/dist/cjs/anyspend/utils/chain.js +73 -4
  22. package/dist/cjs/anyspend/utils/token.d.ts +1 -0
  23. package/dist/cjs/anyspend/utils/token.js +19 -6
  24. package/dist/esm/anyspend/constants/index.d.ts +1 -1
  25. package/dist/esm/anyspend/constants/index.js +1 -1
  26. package/dist/esm/anyspend/react/components/AnySpend.js +6 -2
  27. package/dist/esm/anyspend/react/components/AnySpendCustom.js +2 -2
  28. package/dist/esm/anyspend/react/components/common/InsufficientDepositPayment.js +2 -2
  29. package/dist/esm/anyspend/react/components/common/OrderDetails.js +6 -5
  30. package/dist/esm/anyspend/react/components/common/OrderToken.js +3 -3
  31. package/dist/esm/anyspend/react/components/common/OrderTokenAmount.js +2 -2
  32. package/dist/esm/anyspend/react/components/common/OrderTokenAmountFiat.js +2 -2
  33. package/dist/esm/anyspend/react/components/common/OrderTokenAmountNew.js +3 -3
  34. package/dist/esm/anyspend/react/components/common/TransferCryptoDetails.js +2 -2
  35. package/dist/esm/anyspend/react/hooks/index.d.ts +1 -0
  36. package/dist/esm/anyspend/react/hooks/index.js +1 -0
  37. package/dist/esm/anyspend/react/hooks/useHyperliquidTransfer.d.ts +37 -0
  38. package/dist/esm/anyspend/react/hooks/useHyperliquidTransfer.js +127 -0
  39. package/dist/esm/anyspend/types/chain.d.ts +10 -2
  40. package/dist/esm/anyspend/types/chain.js +1 -0
  41. package/dist/esm/anyspend/utils/address.d.ts +11 -0
  42. package/dist/esm/anyspend/utils/address.js +14 -0
  43. package/dist/esm/anyspend/utils/chain.d.ts +20 -1
  44. package/dist/esm/anyspend/utils/chain.js +70 -4
  45. package/dist/esm/anyspend/utils/token.d.ts +1 -0
  46. package/dist/esm/anyspend/utils/token.js +19 -7
  47. package/dist/types/anyspend/constants/index.d.ts +1 -1
  48. package/dist/types/anyspend/react/hooks/index.d.ts +1 -0
  49. package/dist/types/anyspend/react/hooks/useHyperliquidTransfer.d.ts +37 -0
  50. package/dist/types/anyspend/types/chain.d.ts +10 -2
  51. package/dist/types/anyspend/utils/address.d.ts +11 -0
  52. package/dist/types/anyspend/utils/chain.d.ts +20 -1
  53. package/dist/types/anyspend/utils/token.d.ts +1 -0
  54. package/package.json +1 -1
  55. package/src/anyspend/constants/index.ts +1 -1
  56. package/src/anyspend/react/components/AnySpend.tsx +7 -1
  57. package/src/anyspend/react/components/AnySpendCustom.tsx +2 -2
  58. package/src/anyspend/react/components/common/InsufficientDepositPayment.tsx +2 -2
  59. package/src/anyspend/react/components/common/OrderDetails.tsx +6 -5
  60. package/src/anyspend/react/components/common/OrderToken.tsx +5 -5
  61. package/src/anyspend/react/components/common/OrderTokenAmount.tsx +3 -3
  62. package/src/anyspend/react/components/common/OrderTokenAmountFiat.tsx +3 -3
  63. package/src/anyspend/react/components/common/OrderTokenAmountNew.tsx +6 -6
  64. package/src/anyspend/react/components/common/TransferCryptoDetails.tsx +2 -2
  65. package/src/anyspend/react/hooks/index.ts +1 -0
  66. package/src/anyspend/react/hooks/useHyperliquidTransfer.ts +152 -0
  67. package/src/anyspend/types/chain.ts +10 -1
  68. package/src/anyspend/utils/address.ts +15 -0
  69. package/src/anyspend/utils/chain.ts +84 -4
  70. package/src/anyspend/utils/token.ts +20 -7
@@ -0,0 +1,127 @@
1
+ import { HYPERLIQUID_CHAIN_ID, HYPERLIQUID_MAINNET } from "../../../anyspend/index.js";
2
+ import { toast } from "../../../global-account/react/index.js";
3
+ import { formatUnits } from "../../../shared/utils/number.js";
4
+ import axios from "axios";
5
+ import { useCallback } from "react";
6
+ import { parseSignature } from "viem";
7
+ import { useWalletClient } from "wagmi";
8
+ /**
9
+ * @deprecated This hook is NOT USED in production.
10
+ *
11
+ * Hyperliquid is only supported as DESTINATION CHAIN (not source chain).
12
+ * Users cannot send FROM Hyperliquid in our flow, so EIP-712 signing is not needed.
13
+ *
14
+ * This hook was created during initial planning but is kept for:
15
+ * - Reference if we need to support source chain in the future
16
+ * - Understanding how Hyperliquid EIP-712 transfers work
17
+ *
18
+ * DO NOT USE THIS HOOK IN PRODUCTION CODE.
19
+ *
20
+ * Custom hook for handling Hyperliquid transfers via EIP-712 signature.
21
+ * Based on Relay SDK's Hyperliquid implementation.
22
+ *
23
+ * @example
24
+ * ```tsx
25
+ * const { initiateTransfer } = useHyperliquidTransfer();
26
+ *
27
+ * await initiateTransfer({
28
+ * amount: "1000000", // 1 USDC
29
+ * destination: "0x..."
30
+ * });
31
+ * ```
32
+ */
33
+ export function useHyperliquidTransfer() {
34
+ const { data: walletClient } = useWalletClient();
35
+ /**
36
+ * Get the connected wallet address if available.
37
+ */
38
+ const getConnectedAddress = useCallback(() => {
39
+ return walletClient?.account?.address || null;
40
+ }, [walletClient]);
41
+ /**
42
+ * Initiate Hyperliquid transfer by signing EIP-712 message and sending to Hyperliquid API.
43
+ */
44
+ const initiateTransfer = useCallback(async ({ amount, destination }) => {
45
+ if (!walletClient?.account) {
46
+ toast.error("Please connect your wallet");
47
+ throw new Error("Wallet not connected");
48
+ }
49
+ try {
50
+ const currentTime = new Date().getTime();
51
+ // Convert amount from smallest unit (6 decimals) to display format.
52
+ // e.g., "11151533" -> "11.151533"
53
+ const displayAmount = formatUnits(amount, 6);
54
+ // Prepare EIP-712 typed data for Hyperliquid USD send.
55
+ const typedData = {
56
+ domain: {
57
+ name: "HyperliquidSignTransaction",
58
+ version: "1",
59
+ chainId: HYPERLIQUID_CHAIN_ID,
60
+ verifyingContract: "0x0000000000000000000000000000000000000000",
61
+ },
62
+ types: {
63
+ "HyperliquidTransaction:UsdSend": [
64
+ { name: "hyperliquidChain", type: "string" },
65
+ { name: "destination", type: "string" },
66
+ { name: "amount", type: "string" },
67
+ { name: "time", type: "uint64" },
68
+ ],
69
+ },
70
+ primaryType: "HyperliquidTransaction:UsdSend",
71
+ message: {
72
+ hyperliquidChain: "Mainnet",
73
+ destination: destination.toLowerCase(),
74
+ amount: displayAmount,
75
+ time: BigInt(currentTime),
76
+ },
77
+ };
78
+ toast.info("Please sign the message in your wallet");
79
+ // Sign EIP-712 message.
80
+ const signature = await walletClient.signTypedData(typedData);
81
+ // Parse signature to get r, s, v components.
82
+ const { r, s, v } = parseSignature(signature);
83
+ toast.info("Sending transaction to Hyperliquid...");
84
+ // Send signature to Hyperliquid API.
85
+ const response = await axios.post(HYPERLIQUID_MAINNET.apiUrl + "/exchange", {
86
+ signature: {
87
+ r,
88
+ s,
89
+ v: Number(v ?? BigInt(0)),
90
+ },
91
+ nonce: currentTime,
92
+ action: {
93
+ type: "usdSend",
94
+ signatureChainId: `0x${HYPERLIQUID_CHAIN_ID.toString(16)}`,
95
+ hyperliquidChain: "Mainnet",
96
+ destination: destination.toLowerCase(),
97
+ amount: displayAmount,
98
+ time: currentTime,
99
+ },
100
+ });
101
+ // Check response status.
102
+ if (!response || response.status !== 200 || response.data?.status !== "ok") {
103
+ const errorMsg = response?.data?.error || "Failed to send transaction to Hyperliquid";
104
+ toast.error(errorMsg);
105
+ throw new Error(errorMsg);
106
+ }
107
+ toast.success("Transaction sent to Hyperliquid successfully!");
108
+ }
109
+ catch (error) {
110
+ console.error("Hyperliquid transfer error:", error);
111
+ // Handle user rejection.
112
+ if (error?.message?.includes("User rejected") || error?.code === 4001) {
113
+ toast.error("Transaction signature rejected");
114
+ throw new Error("User rejected signature");
115
+ }
116
+ // Handle other errors.
117
+ const errorMsg = error?.message || "Failed to complete Hyperliquid transfer";
118
+ toast.error(errorMsg);
119
+ throw error;
120
+ }
121
+ }, [walletClient]);
122
+ return {
123
+ initiateTransfer,
124
+ getConnectedAddress,
125
+ isWalletConnected: !!walletClient?.account,
126
+ };
127
+ }
@@ -1,8 +1,9 @@
1
- import { Chain } from "viem";
2
1
  import { components } from "../../anyspend/types/api";
2
+ import { Chain } from "viem";
3
3
  export declare enum ChainType {
4
4
  EVM = "evm",
5
- SOLANA = "solana"
5
+ SOLANA = "solana",
6
+ HYPERLIQUID = "hyperliquid"
6
7
  }
7
8
  export interface IBaseChain {
8
9
  id: number;
@@ -25,3 +26,10 @@ export interface IEVMChain extends IBaseChain {
25
26
  export interface ISolanaChain extends IBaseChain {
26
27
  type: ChainType.SOLANA;
27
28
  }
29
+ export interface IHyperliquidChain extends IBaseChain {
30
+ type: ChainType.HYPERLIQUID;
31
+ apiUrl: string;
32
+ blockExplorer: {
33
+ url: string;
34
+ };
35
+ }
@@ -2,4 +2,5 @@ export var ChainType;
2
2
  (function (ChainType) {
3
3
  ChainType["EVM"] = "evm";
4
4
  ChainType["SOLANA"] = "solana";
5
+ ChainType["HYPERLIQUID"] = "hyperliquid";
5
6
  })(ChainType || (ChainType = {}));
@@ -1,4 +1,15 @@
1
1
  export declare function isSolanaAddress(address: string): boolean;
2
2
  export declare function isEvmOrSolanaAddress(address: string): boolean;
3
+ /**
4
+ * Check if an address is Hyperliquid's special USDC address.
5
+ * Hyperliquid USDC uses a special 34-character format (0x + 32 hex digits)
6
+ * instead of the standard 42-character Ethereum address format.
7
+ * This is required by Relay SDK for Hyperliquid integration.
8
+ *
9
+ * @param chainId - The chain ID to check
10
+ * @param address - The token address to validate
11
+ * @returns true if the address is Hyperliquid USDC's special format
12
+ */
13
+ export declare function isHyperliquidUSDC(chainId: number, address: string): boolean;
3
14
  export declare function normalizeAddress(address: string): string;
4
15
  export declare function eqci(a: string | null | undefined, b: string | null | undefined): boolean;
@@ -1,4 +1,5 @@
1
1
  import { isAddress } from "viem";
2
+ import { HYPERLIQUID_CHAIN_ID } from "./token.js";
2
3
  export function isSolanaAddress(address) {
3
4
  // Solana addresses are 32-byte base58 strings (usually 32-44 characters)
4
5
  const solanaAddressRegex = /^[1-9A-HJ-NP-Za-km-z]{32,44}$/;
@@ -7,6 +8,19 @@ export function isSolanaAddress(address) {
7
8
  export function isEvmOrSolanaAddress(address) {
8
9
  return isAddress(address) || isSolanaAddress(address);
9
10
  }
11
+ /**
12
+ * Check if an address is Hyperliquid's special USDC address.
13
+ * Hyperliquid USDC uses a special 34-character format (0x + 32 hex digits)
14
+ * instead of the standard 42-character Ethereum address format.
15
+ * This is required by Relay SDK for Hyperliquid integration.
16
+ *
17
+ * @param chainId - The chain ID to check
18
+ * @param address - The token address to validate
19
+ * @returns true if the address is Hyperliquid USDC's special format
20
+ */
21
+ export function isHyperliquidUSDC(chainId, address) {
22
+ return chainId === HYPERLIQUID_CHAIN_ID && address.toLowerCase() === "0x00000000000000000000000000000000";
23
+ }
10
24
  export function normalizeAddress(address) {
11
25
  if (isSolanaAddress(address)) {
12
26
  return address;
@@ -1,6 +1,6 @@
1
1
  import { components } from "../../anyspend/types/api";
2
2
  import { Account, Chain, PublicClient, Transport, WalletClient } from "viem";
3
- import { ChainType, IBaseChain, IEVMChain, ISolanaChain } from "../types/chain";
3
+ import { ChainType, IBaseChain, IEVMChain, IHyperliquidChain, ISolanaChain } from "../types/chain";
4
4
  export declare const hyperEVM: {
5
5
  blockExplorers: {
6
6
  readonly default: {
@@ -42,8 +42,10 @@ export declare const hyperEVM: {
42
42
  export declare const EVM_MAINNET: Record<number, IEVMChain>;
43
43
  export declare const EVM_TESTNET: Record<number, IEVMChain>;
44
44
  export declare const SOLANA_MAINNET: ISolanaChain;
45
+ export declare const HYPERLIQUID_MAINNET: IHyperliquidChain;
45
46
  export declare const EVM_CHAINS: Record<number, IEVMChain>;
46
47
  export declare const SOLANA_CHAINS: Record<number, ISolanaChain>;
48
+ export declare const HYPERLIQUID_CHAINS: Record<number, IHyperliquidChain>;
47
49
  export declare const ALL_CHAINS: Record<number, IBaseChain>;
48
50
  export declare function getSolanaChains(network: "mainnet" | "testnet"): ISolanaChain;
49
51
  export declare function getAllEvmChains(network: "mainnet" | "testnet"): Record<number, IEVMChain>;
@@ -63,3 +65,20 @@ export declare function getExplorerAddressUrl(chainId: number, address: string):
63
65
  export declare function getMulticall3Address(chainId: number): string;
64
66
  export declare function getNativeToken(chainId: number): components["schemas"]["Token"];
65
67
  export declare function isEvmChain(chainId: number): boolean;
68
+ export declare function isHyperliquidChain(chainId: number): boolean;
69
+ export declare function getHyperliquidChain(chainId: number): IHyperliquidChain;
70
+ /**
71
+ * Get available chain IDs for AnySpend based on context (source or destination).
72
+ * Filters out chains that shouldn't be available for the given context.
73
+ *
74
+ * @param context - "from" for source chains, "to" for destination chains
75
+ * @returns Array of available chain IDs
76
+ *
77
+ * @example
78
+ * // Get source chains (excludes Hyperliquid)
79
+ * const sourceChains = getAvailableChainIds("from") // [1, 8453, 137, ...]
80
+ *
81
+ * // Get destination chains (includes Hyperliquid)
82
+ * const destChains = getAvailableChainIds("to") // [1, 8453, 137, ..., 1337]
83
+ */
84
+ export declare function getAvailableChainIds(context: "from" | "to"): number[];
@@ -3,7 +3,7 @@ import invariant from "invariant";
3
3
  import { createPublicClient, createWalletClient, defineChain, http, parseEther, } from "viem";
4
4
  import { abstract, arbitrum, avalanche, b3, base, bsc, mainnet, optimism, polygon } from "viem/chains";
5
5
  import { ChainType } from "../types/chain.js";
6
- import { getAvaxToken, getBnbToken, getEthToken, getHyperEVMNativeToken, getPolToken, getSolanaToken, HYPEREVM_CHAIN_ID, } from "./token.js";
6
+ import { getAvaxToken, getBnbToken, getEthToken, getHyperEVMNativeToken, getHyperliquidUSDCToken, getPolToken, getSolanaToken, HYPEREVM_CHAIN_ID, HYPERLIQUID_CHAIN_ID, } from "./token.js";
7
7
  function getCustomEvmChain(chain, rpcUrl) {
8
8
  return defineChain({ ...chain, rpcUrls: { default: { http: [rpcUrl] } } });
9
9
  }
@@ -232,9 +232,27 @@ export const SOLANA_MAINNET = {
232
232
  nativeToken: getSolanaToken(),
233
233
  coingeckoName: "solana",
234
234
  };
235
+ export const HYPERLIQUID_MAINNET = {
236
+ id: HYPERLIQUID_CHAIN_ID,
237
+ name: "Hyperliquid",
238
+ type: ChainType.HYPERLIQUID,
239
+ logoUrl: "https://s2.coinmarketcap.com/static/img/coins/64x64/32196.png",
240
+ nativeRequired: BigInt(0), // No native transfer needed - using Relay's useDepositAddress flow (USDC is native)
241
+ canDepositNative: true, // Can deposit USDC (native token)
242
+ defaultToken: getHyperliquidUSDCToken(),
243
+ nativeToken: getHyperliquidUSDCToken(),
244
+ coingeckoName: null,
245
+ apiUrl: "https://api.hyperliquid.xyz",
246
+ blockExplorer: {
247
+ url: "https://app.hyperliquid.xyz/explorer",
248
+ },
249
+ };
235
250
  export const EVM_CHAINS = { ...EVM_MAINNET, ...EVM_TESTNET };
236
251
  export const SOLANA_CHAINS = { [RELAY_SOLANA_MAINNET_CHAIN_ID]: SOLANA_MAINNET };
237
- export const ALL_CHAINS = { ...EVM_CHAINS, ...SOLANA_CHAINS };
252
+ export const HYPERLIQUID_CHAINS = {
253
+ [HYPERLIQUID_CHAIN_ID]: HYPERLIQUID_MAINNET,
254
+ };
255
+ export const ALL_CHAINS = { ...EVM_CHAINS, ...SOLANA_CHAINS, ...HYPERLIQUID_CHAINS };
238
256
  export function getSolanaChains(network) {
239
257
  invariant(network === "mainnet", "Solana chain is only supported on mainnet");
240
258
  return SOLANA_MAINNET;
@@ -272,7 +290,7 @@ export function canDepositNative(chainId) {
272
290
  return ALL_CHAINS[chainId].canDepositNative;
273
291
  }
274
292
  export function isMainnet(chainId) {
275
- return EVM_MAINNET[chainId] !== undefined || RELAY_SOLANA_MAINNET_CHAIN_ID === chainId;
293
+ return (EVM_MAINNET[chainId] !== undefined || RELAY_SOLANA_MAINNET_CHAIN_ID === chainId || HYPERLIQUID_CHAIN_ID === chainId);
276
294
  }
277
295
  export function isTestnet(chainId) {
278
296
  return EVM_TESTNET[chainId] !== undefined;
@@ -283,7 +301,11 @@ export function getDefaultToken(chainId) {
283
301
  }
284
302
  export function getChainName(chainId) {
285
303
  invariant(ALL_CHAINS[chainId], `Chain ${chainId} is not supported`);
286
- return EVM_CHAINS[chainId] ? EVM_CHAINS[chainId].viem.name : "Solana";
304
+ const chain = ALL_CHAINS[chainId];
305
+ if (isEvmChain(chainId)) {
306
+ return chain.viem.name;
307
+ }
308
+ return chain.name;
287
309
  }
288
310
  export function getCoingeckoName(chainId) {
289
311
  invariant(ALL_CHAINS[chainId], `Chain ${chainId} is not supported`);
@@ -432,6 +454,12 @@ export function getPaymentUrl(address, amount, currency, chainId, decimals) {
432
454
  console.log("Solana URL (isNativeSOL:", isNativeSOL, "):", url);
433
455
  return url;
434
456
  }
457
+ case ChainType.HYPERLIQUID: {
458
+ // NOTE: Hyperliquid is only supported as destination chain (not source chain).
459
+ // Payment URLs are not needed since users cannot send FROM Hyperliquid in our flow.
460
+ // Return address as placeholder (this code path should not be reached).
461
+ return address;
462
+ }
435
463
  default:
436
464
  // Fallback to just the address if chain type is unknown
437
465
  return address;
@@ -444,12 +472,20 @@ export function getExplorerTxUrl(chainId, txHash) {
444
472
  if (EVM_CHAINS[chainId]) {
445
473
  return EVM_CHAINS[chainId].viem.blockExplorers?.default.url + "/tx/" + txHash;
446
474
  }
475
+ if (HYPERLIQUID_CHAINS[chainId]) {
476
+ return HYPERLIQUID_CHAINS[chainId].blockExplorer.url + "/tx/" + txHash;
477
+ }
478
+ // Default to Solscan for Solana transactions
447
479
  return "https://solscan.io/tx/" + txHash;
448
480
  }
449
481
  export function getExplorerAddressUrl(chainId, address) {
450
482
  if (EVM_CHAINS[chainId]) {
451
483
  return EVM_CHAINS[chainId].viem.blockExplorers?.default.url + "/address/" + address;
452
484
  }
485
+ if (HYPERLIQUID_CHAINS[chainId]) {
486
+ return HYPERLIQUID_CHAINS[chainId].blockExplorer.url + "/address/" + address;
487
+ }
488
+ // Default to Solscan for Solana addresses
453
489
  return "https://solscan.io/account/" + address;
454
490
  }
455
491
  export function getMulticall3Address(chainId) {
@@ -466,3 +502,33 @@ export function getNativeToken(chainId) {
466
502
  export function isEvmChain(chainId) {
467
503
  return Boolean(EVM_CHAINS[chainId]);
468
504
  }
505
+ export function isHyperliquidChain(chainId) {
506
+ return HYPERLIQUID_CHAINS[chainId] !== undefined;
507
+ }
508
+ export function getHyperliquidChain(chainId) {
509
+ invariant(HYPERLIQUID_CHAINS[chainId], `Chain ${chainId} is not a Hyperliquid chain`);
510
+ return HYPERLIQUID_CHAINS[chainId];
511
+ }
512
+ /**
513
+ * Get available chain IDs for AnySpend based on context (source or destination).
514
+ * Filters out chains that shouldn't be available for the given context.
515
+ *
516
+ * @param context - "from" for source chains, "to" for destination chains
517
+ * @returns Array of available chain IDs
518
+ *
519
+ * @example
520
+ * // Get source chains (excludes Hyperliquid)
521
+ * const sourceChains = getAvailableChainIds("from") // [1, 8453, 137, ...]
522
+ *
523
+ * // Get destination chains (includes Hyperliquid)
524
+ * const destChains = getAvailableChainIds("to") // [1, 8453, 137, ..., 1337]
525
+ */
526
+ export function getAvailableChainIds(context) {
527
+ const allChainIds = Object.values(ALL_CHAINS).map(chain => chain.id);
528
+ if (context === "from") {
529
+ // Hyperliquid is only supported as destination chain, not source chain
530
+ return allChainIds.filter(chainId => chainId !== HYPERLIQUID_CHAIN_ID);
531
+ }
532
+ // For destination ("to"), all chains are available including Hyperliquid
533
+ return allChainIds;
534
+ }
@@ -8,3 +8,4 @@ export declare function getPolToken(): components["schemas"]["Token"];
8
8
  export declare function getBnbToken(): components["schemas"]["Token"];
9
9
  export declare function getAvaxToken(): components["schemas"]["Token"];
10
10
  export declare function getHyperEVMNativeToken(): components["schemas"]["Token"];
11
+ export declare function getHyperliquidUSDCToken(): components["schemas"]["Token"];
@@ -1,9 +1,9 @@
1
- import { RELAY_ETH_ADDRESS, RELAY_SOL_ADDRESS, RELAY_SOLANA_MAINNET_CHAIN_ID } from "../../anyspend/constants/index.js";
1
+ import { RELAY_SOL_ADDRESS, RELAY_SOLANA_MAINNET_CHAIN_ID, ZERO_ADDRESS } from "../../anyspend/constants/index.js";
2
2
  import { avalanche, bsc, polygon } from "viem/chains";
3
3
  export const HYPERLIQUID_CHAIN_ID = 1337;
4
4
  export const HYPEREVM_CHAIN_ID = 999;
5
5
  export function isNativeToken(address) {
6
- return address.toLowerCase() === RELAY_ETH_ADDRESS || address.toLowerCase() === RELAY_SOL_ADDRESS;
6
+ return address.toLowerCase() === ZERO_ADDRESS || address.toLowerCase() === RELAY_SOL_ADDRESS;
7
7
  }
8
8
  export function getSolanaToken() {
9
9
  return {
@@ -20,7 +20,7 @@ export function getSolanaToken() {
20
20
  export function getEthToken(chainId) {
21
21
  return {
22
22
  chainId: chainId,
23
- address: RELAY_ETH_ADDRESS,
23
+ address: ZERO_ADDRESS,
24
24
  symbol: "ETH",
25
25
  name: "Ethereum",
26
26
  decimals: 18,
@@ -32,7 +32,7 @@ export function getEthToken(chainId) {
32
32
  export function getPolToken() {
33
33
  return {
34
34
  chainId: polygon.id,
35
- address: RELAY_ETH_ADDRESS,
35
+ address: ZERO_ADDRESS,
36
36
  symbol: "POL",
37
37
  name: "Polygon",
38
38
  decimals: 18,
@@ -44,7 +44,7 @@ export function getPolToken() {
44
44
  export function getBnbToken() {
45
45
  return {
46
46
  chainId: bsc.id,
47
- address: RELAY_ETH_ADDRESS,
47
+ address: ZERO_ADDRESS,
48
48
  symbol: "BNB",
49
49
  name: "BNB",
50
50
  decimals: 18,
@@ -56,7 +56,7 @@ export function getBnbToken() {
56
56
  export function getAvaxToken() {
57
57
  return {
58
58
  chainId: avalanche.id,
59
- address: RELAY_ETH_ADDRESS,
59
+ address: ZERO_ADDRESS,
60
60
  symbol: "AVAX",
61
61
  name: "AVAX",
62
62
  decimals: 18,
@@ -68,7 +68,7 @@ export function getAvaxToken() {
68
68
  export function getHyperEVMNativeToken() {
69
69
  return {
70
70
  chainId: HYPEREVM_CHAIN_ID,
71
- address: RELAY_ETH_ADDRESS,
71
+ address: ZERO_ADDRESS,
72
72
  symbol: "HYPE",
73
73
  name: "HYPE",
74
74
  decimals: 18,
@@ -77,3 +77,15 @@ export function getHyperEVMNativeToken() {
77
77
  },
78
78
  };
79
79
  }
80
+ export function getHyperliquidUSDCToken() {
81
+ return {
82
+ chainId: HYPERLIQUID_CHAIN_ID,
83
+ address: ZERO_ADDRESS,
84
+ symbol: "USDC",
85
+ name: "USD Coin",
86
+ decimals: 6,
87
+ metadata: {
88
+ logoURI: "https://ethereum-optimism.github.io/data/USDC/logo.png",
89
+ },
90
+ };
91
+ }
@@ -1,6 +1,6 @@
1
1
  import { components } from "../types/api";
2
2
  export declare const ANYSPEND_MAINNET_BASE_URL: string;
3
- export declare const RELAY_ETH_ADDRESS = "0x0000000000000000000000000000000000000000";
3
+ export declare const ZERO_ADDRESS = "0x0000000000000000000000000000000000000000";
4
4
  export declare const RELAY_SOL_ADDRESS = "11111111111111111111111111111111";
5
5
  export declare const RELAY_SOLANA_MAINNET_CHAIN_ID = 792703809;
6
6
  export declare const SOLANA_ASSOCIATED_TOKEN_ACCOUNT_PROGRAM_ID = "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL";
@@ -8,6 +8,7 @@ export * from "./useCoinbaseOnrampOptions";
8
8
  export * from "./useConnectedUserProfile";
9
9
  export * from "./useGeoOnrampOptions";
10
10
  export * from "./useGetGeo";
11
+ export * from "./useHyperliquidTransfer";
11
12
  export * from "./useRecipientAddressState";
12
13
  export * from "./useSigMint";
13
14
  export * from "./useStripeClientSecret";
@@ -0,0 +1,37 @@
1
+ interface HyperliquidTransferParams {
2
+ /** Amount in smallest unit (USDC has 6 decimals) */
3
+ amount: string;
4
+ /** Recipient address */
5
+ destination: string;
6
+ }
7
+ /**
8
+ * @deprecated This hook is NOT USED in production.
9
+ *
10
+ * Hyperliquid is only supported as DESTINATION CHAIN (not source chain).
11
+ * Users cannot send FROM Hyperliquid in our flow, so EIP-712 signing is not needed.
12
+ *
13
+ * This hook was created during initial planning but is kept for:
14
+ * - Reference if we need to support source chain in the future
15
+ * - Understanding how Hyperliquid EIP-712 transfers work
16
+ *
17
+ * DO NOT USE THIS HOOK IN PRODUCTION CODE.
18
+ *
19
+ * Custom hook for handling Hyperliquid transfers via EIP-712 signature.
20
+ * Based on Relay SDK's Hyperliquid implementation.
21
+ *
22
+ * @example
23
+ * ```tsx
24
+ * const { initiateTransfer } = useHyperliquidTransfer();
25
+ *
26
+ * await initiateTransfer({
27
+ * amount: "1000000", // 1 USDC
28
+ * destination: "0x..."
29
+ * });
30
+ * ```
31
+ */
32
+ export declare function useHyperliquidTransfer(): {
33
+ initiateTransfer: ({ amount, destination }: HyperliquidTransferParams) => Promise<void>;
34
+ getConnectedAddress: () => `0x${string}` | null;
35
+ isWalletConnected: boolean;
36
+ };
37
+ export {};
@@ -1,8 +1,9 @@
1
- import { Chain } from "viem";
2
1
  import { components } from "@b3dotfun/sdk/anyspend/types/api";
2
+ import { Chain } from "viem";
3
3
  export declare enum ChainType {
4
4
  EVM = "evm",
5
- SOLANA = "solana"
5
+ SOLANA = "solana",
6
+ HYPERLIQUID = "hyperliquid"
6
7
  }
7
8
  export interface IBaseChain {
8
9
  id: number;
@@ -25,3 +26,10 @@ export interface IEVMChain extends IBaseChain {
25
26
  export interface ISolanaChain extends IBaseChain {
26
27
  type: ChainType.SOLANA;
27
28
  }
29
+ export interface IHyperliquidChain extends IBaseChain {
30
+ type: ChainType.HYPERLIQUID;
31
+ apiUrl: string;
32
+ blockExplorer: {
33
+ url: string;
34
+ };
35
+ }
@@ -1,4 +1,15 @@
1
1
  export declare function isSolanaAddress(address: string): boolean;
2
2
  export declare function isEvmOrSolanaAddress(address: string): boolean;
3
+ /**
4
+ * Check if an address is Hyperliquid's special USDC address.
5
+ * Hyperliquid USDC uses a special 34-character format (0x + 32 hex digits)
6
+ * instead of the standard 42-character Ethereum address format.
7
+ * This is required by Relay SDK for Hyperliquid integration.
8
+ *
9
+ * @param chainId - The chain ID to check
10
+ * @param address - The token address to validate
11
+ * @returns true if the address is Hyperliquid USDC's special format
12
+ */
13
+ export declare function isHyperliquidUSDC(chainId: number, address: string): boolean;
3
14
  export declare function normalizeAddress(address: string): string;
4
15
  export declare function eqci(a: string | null | undefined, b: string | null | undefined): boolean;
@@ -1,6 +1,6 @@
1
1
  import { components } from "@b3dotfun/sdk/anyspend/types/api";
2
2
  import { Account, Chain, PublicClient, Transport, WalletClient } from "viem";
3
- import { ChainType, IBaseChain, IEVMChain, ISolanaChain } from "../types/chain";
3
+ import { ChainType, IBaseChain, IEVMChain, IHyperliquidChain, ISolanaChain } from "../types/chain";
4
4
  export declare const hyperEVM: {
5
5
  blockExplorers: {
6
6
  readonly default: {
@@ -42,8 +42,10 @@ export declare const hyperEVM: {
42
42
  export declare const EVM_MAINNET: Record<number, IEVMChain>;
43
43
  export declare const EVM_TESTNET: Record<number, IEVMChain>;
44
44
  export declare const SOLANA_MAINNET: ISolanaChain;
45
+ export declare const HYPERLIQUID_MAINNET: IHyperliquidChain;
45
46
  export declare const EVM_CHAINS: Record<number, IEVMChain>;
46
47
  export declare const SOLANA_CHAINS: Record<number, ISolanaChain>;
48
+ export declare const HYPERLIQUID_CHAINS: Record<number, IHyperliquidChain>;
47
49
  export declare const ALL_CHAINS: Record<number, IBaseChain>;
48
50
  export declare function getSolanaChains(network: "mainnet" | "testnet"): ISolanaChain;
49
51
  export declare function getAllEvmChains(network: "mainnet" | "testnet"): Record<number, IEVMChain>;
@@ -63,3 +65,20 @@ export declare function getExplorerAddressUrl(chainId: number, address: string):
63
65
  export declare function getMulticall3Address(chainId: number): string;
64
66
  export declare function getNativeToken(chainId: number): components["schemas"]["Token"];
65
67
  export declare function isEvmChain(chainId: number): boolean;
68
+ export declare function isHyperliquidChain(chainId: number): boolean;
69
+ export declare function getHyperliquidChain(chainId: number): IHyperliquidChain;
70
+ /**
71
+ * Get available chain IDs for AnySpend based on context (source or destination).
72
+ * Filters out chains that shouldn't be available for the given context.
73
+ *
74
+ * @param context - "from" for source chains, "to" for destination chains
75
+ * @returns Array of available chain IDs
76
+ *
77
+ * @example
78
+ * // Get source chains (excludes Hyperliquid)
79
+ * const sourceChains = getAvailableChainIds("from") // [1, 8453, 137, ...]
80
+ *
81
+ * // Get destination chains (includes Hyperliquid)
82
+ * const destChains = getAvailableChainIds("to") // [1, 8453, 137, ..., 1337]
83
+ */
84
+ export declare function getAvailableChainIds(context: "from" | "to"): number[];
@@ -8,3 +8,4 @@ export declare function getPolToken(): components["schemas"]["Token"];
8
8
  export declare function getBnbToken(): components["schemas"]["Token"];
9
9
  export declare function getAvaxToken(): components["schemas"]["Token"];
10
10
  export declare function getHyperEVMNativeToken(): components["schemas"]["Token"];
11
+ export declare function getHyperliquidUSDCToken(): components["schemas"]["Token"];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@b3dotfun/sdk",
3
- "version": "0.0.83-alpha.1",
3
+ "version": "0.0.83-alpha.3",
4
4
  "source": "src/index.ts",
5
5
  "main": "./dist/cjs/index.js",
6
6
  "react-native": "./dist/cjs/index.native.js",
@@ -3,7 +3,7 @@ import { components } from "../types/api";
3
3
 
4
4
  export const ANYSPEND_MAINNET_BASE_URL = process.env.NEXT_PUBLIC_ANYSPEND_BASE_URL || "https://mainnet.anyspend.com";
5
5
 
6
- export const RELAY_ETH_ADDRESS = "0x0000000000000000000000000000000000000000";
6
+ export const ZERO_ADDRESS = "0x0000000000000000000000000000000000000000";
7
7
  export const RELAY_SOL_ADDRESS = "11111111111111111111111111111111";
8
8
 
9
9
  export const RELAY_SOLANA_MAINNET_CHAIN_ID = 792703809;
@@ -1,6 +1,6 @@
1
1
  "use client";
2
2
 
3
- import { getDefaultToken, USDC_BASE } from "@b3dotfun/sdk/anyspend";
3
+ import { getDefaultToken, HYPERLIQUID_CHAIN_ID, USDC_BASE } from "@b3dotfun/sdk/anyspend";
4
4
  import {
5
5
  useAnyspendCreateOnrampOrder,
6
6
  useAnyspendCreateOrder,
@@ -1126,12 +1126,18 @@ function AnySpendInner({
1126
1126
  "border-as-stroke bg-as-surface-primary absolute left-1/2 top-1/2 z-10 h-10 w-10 -translate-x-1/2 -translate-y-1/2 rounded-xl border-2 sm:h-8 sm:w-8 sm:rounded-xl",
1127
1127
  isBuyMode && "top-[calc(50%+56px)] cursor-default",
1128
1128
  activeTab === "fiat" && "hidden",
1129
+ selectedDstChainId === HYPERLIQUID_CHAIN_ID && "cursor-not-allowed opacity-50",
1129
1130
  )}
1130
1131
  onClick={() => {
1131
1132
  if (activeTab === "fiat" || isBuyMode) {
1132
1133
  return;
1133
1134
  }
1134
1135
 
1136
+ // Prevent swapping if destination is Hyperliquid (only supported as destination, not source)
1137
+ if (selectedDstChainId === HYPERLIQUID_CHAIN_ID) {
1138
+ return;
1139
+ }
1140
+
1135
1141
  // Swap chain selections
1136
1142
  const tempSrcChainId = selectedSrcChainId;
1137
1143
  const tempDstChainId = selectedDstChainId;
@@ -1,5 +1,5 @@
1
1
  import { eqci, getDefaultToken, roundUpUSDCBaseAmountToNearest } from "@b3dotfun/sdk/anyspend";
2
- import { RELAY_ETH_ADDRESS, USDC_BASE } from "@b3dotfun/sdk/anyspend/constants";
2
+ import { USDC_BASE, ZERO_ADDRESS } from "@b3dotfun/sdk/anyspend/constants";
3
3
  import {
4
4
  CreateOrderParams,
5
5
  useAnyspendCreateOnrampOrder,
@@ -295,7 +295,7 @@ function AnySpendCustomInner({
295
295
  // First check native tokens (ETH, etc.)
296
296
  const nativeToken = nativeTokens?.find(t => t.chainId === srcChainId && Number(t.displayValue) > 0);
297
297
  if (nativeToken) {
298
- const matchingToken = tokenList.find(t => t.address === RELAY_ETH_ADDRESS);
298
+ const matchingToken = tokenList.find(t => t.address === ZERO_ADDRESS);
299
299
  if (matchingToken) return matchingToken;
300
300
  }
301
301