opentool 0.7.13 → 0.8.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/index.js CHANGED
@@ -6,11 +6,14 @@ import * as path5 from 'path';
6
6
  import { fileURLToPath, pathToFileURL } from 'url';
7
7
  import { zodToJsonSchema } from '@alcyone-labs/zod-to-json-schema';
8
8
  import { z } from 'zod';
9
- import { zeroAddress, createWalletClient, http, createPublicClient } from 'viem';
9
+ import { zeroAddress, createWalletClient, http, createPublicClient, parseUnits, encodeFunctionData, erc20Abi } from 'viem';
10
10
  import { privateKeyToAccount } from 'viem/accounts';
11
11
  import { arbitrumSepolia, arbitrum, baseSepolia, mainnet, base } from 'viem/chains';
12
12
  import { Turnkey } from '@turnkey/sdk-server';
13
13
  import { createAccount } from '@turnkey/viem';
14
+ import { encode } from '@msgpack/msgpack';
15
+ import { keccak_256 } from '@noble/hashes/sha3';
16
+ import { hexToBytes, concatBytes, bytesToHex } from '@noble/hashes/utils';
14
17
  import { tmpdir } from 'os';
15
18
  import { build } from 'esbuild';
16
19
  import { createRequire } from 'module';
@@ -1343,6 +1346,18 @@ function normalizePrivateKey(raw) {
1343
1346
  }
1344
1347
  return withPrefix;
1345
1348
  }
1349
+ function createNonceSource(start = Date.now()) {
1350
+ let last = start;
1351
+ return () => {
1352
+ const now = Date.now();
1353
+ if (now > last) {
1354
+ last = now;
1355
+ } else {
1356
+ last += 1;
1357
+ }
1358
+ return last;
1359
+ };
1360
+ }
1346
1361
  function createPrivateKeyProvider(config) {
1347
1362
  const privateKey = normalizePrivateKey(config.privateKey);
1348
1363
  const account = privateKeyToAccount(privateKey);
@@ -1388,7 +1403,20 @@ function createPrivateKeyProvider(config) {
1388
1403
  publicClient,
1389
1404
  sendTransaction,
1390
1405
  getNativeBalance,
1391
- transfer
1406
+ transfer,
1407
+ nonceSource: createNonceSource()
1408
+ };
1409
+ }
1410
+ function createNonceSource2(start = Date.now()) {
1411
+ let last = start;
1412
+ return () => {
1413
+ const now = Date.now();
1414
+ if (now > last) {
1415
+ last = now;
1416
+ } else {
1417
+ last += 1;
1418
+ }
1419
+ return last;
1392
1420
  };
1393
1421
  }
1394
1422
  async function createTurnkeyProvider(config) {
@@ -1446,11 +1474,12 @@ async function createTurnkeyProvider(config) {
1446
1474
  publicClient,
1447
1475
  sendTransaction,
1448
1476
  getNativeBalance,
1449
- transfer
1477
+ transfer,
1478
+ nonceSource: createNonceSource2()
1450
1479
  };
1451
1480
  }
1452
1481
 
1453
- // src/wallets/index.ts
1482
+ // src/wallet/index.ts
1454
1483
  function resolveChainSlug(reference) {
1455
1484
  if (reference === void 0) {
1456
1485
  return Object.entries(chains).find(([, meta]) => meta.id === DEFAULT_CHAIN.id)?.[0] || DEFAULT_CHAIN.slug;
@@ -1492,40 +1521,59 @@ function getRpcUrl(chain, options) {
1492
1521
  return entry.rpcUrl(options);
1493
1522
  }
1494
1523
  async function wallet(options = {}) {
1495
- if (options.privateKey && options.turnkey) {
1524
+ const envPrivateKey = process.env.PRIVATE_KEY?.trim();
1525
+ const envTurnkey = {
1526
+ organizationId: process.env.TURNKEY_SUBORG_ID?.trim(),
1527
+ apiPublicKey: process.env.TURNKEY_API_PUBLIC_KEY?.trim(),
1528
+ apiPrivateKey: process.env.TURNKEY_API_PRIVATE_KEY?.trim(),
1529
+ signWith: process.env.TURNKEY_WALLET_ADDRESS?.trim(),
1530
+ apiBaseUrl: process.env.TURNKEY_API_BASE_URL?.trim()
1531
+ };
1532
+ const effectivePrivateKey = options.privateKey ?? envPrivateKey;
1533
+ const hasTurnkeyEnv = envTurnkey.organizationId && envTurnkey.apiPublicKey && envTurnkey.apiPrivateKey && envTurnkey.signWith;
1534
+ const effectiveTurnkey = options.turnkey ?? (hasTurnkeyEnv ? {
1535
+ organizationId: envTurnkey.organizationId,
1536
+ apiPublicKey: envTurnkey.apiPublicKey,
1537
+ apiPrivateKey: envTurnkey.apiPrivateKey,
1538
+ signWith: envTurnkey.signWith,
1539
+ ...envTurnkey.apiBaseUrl ? { apiBaseUrl: envTurnkey.apiBaseUrl } : {}
1540
+ } : void 0);
1541
+ if (effectivePrivateKey && effectiveTurnkey) {
1496
1542
  throw new Error("wallet() cannot be initialized with both privateKey and turnkey credentials");
1497
1543
  }
1498
1544
  const slug = resolveChainSlug(options.chain);
1499
1545
  const chain = chains[slug];
1500
1546
  const tokens2 = tokens[slug] ?? {};
1501
1547
  const overrides = {};
1502
- if (options.rpcUrl) {
1503
- overrides.url = options.rpcUrl;
1548
+ const envRpcUrl = process.env.RPC_URL?.trim();
1549
+ const envApiKey = process.env.ALCHEMY_API_KEY?.trim();
1550
+ if (options.rpcUrl ?? envRpcUrl) {
1551
+ overrides.url = options.rpcUrl ?? envRpcUrl;
1504
1552
  }
1505
- if (options.apiKey) {
1506
- overrides.apiKey = options.apiKey;
1553
+ if (options.apiKey ?? envApiKey) {
1554
+ overrides.apiKey = options.apiKey ?? envApiKey;
1507
1555
  }
1508
1556
  const rpcUrl = getRpcUrl(slug, overrides);
1509
1557
  let providerType = "readonly";
1510
1558
  let signerProvider;
1511
- if (options.privateKey) {
1559
+ if (effectivePrivateKey) {
1512
1560
  signerProvider = createPrivateKeyProvider({
1513
1561
  chain,
1514
1562
  rpcUrl,
1515
- privateKey: options.privateKey
1563
+ privateKey: effectivePrivateKey
1516
1564
  });
1517
1565
  providerType = "privateKey";
1518
- } else if (options.turnkey) {
1566
+ } else if (effectiveTurnkey) {
1519
1567
  const turnkeyConfig = {
1520
1568
  chain,
1521
1569
  rpcUrl,
1522
- organizationId: options.turnkey.organizationId,
1523
- apiPublicKey: options.turnkey.apiPublicKey,
1524
- apiPrivateKey: options.turnkey.apiPrivateKey,
1525
- signWith: options.turnkey.signWith
1570
+ organizationId: effectiveTurnkey.organizationId,
1571
+ apiPublicKey: effectiveTurnkey.apiPublicKey,
1572
+ apiPrivateKey: effectiveTurnkey.apiPrivateKey,
1573
+ signWith: effectiveTurnkey.signWith
1526
1574
  };
1527
- if (options.turnkey.apiBaseUrl) {
1528
- turnkeyConfig.apiBaseUrl = options.turnkey.apiBaseUrl;
1575
+ if (effectiveTurnkey.apiBaseUrl) {
1576
+ turnkeyConfig.apiBaseUrl = effectiveTurnkey.apiBaseUrl;
1529
1577
  }
1530
1578
  signerProvider = await createTurnkeyProvider(turnkeyConfig);
1531
1579
  providerType = "turnkey";
@@ -1540,7 +1588,8 @@ async function wallet(options = {}) {
1540
1588
  rpcUrl,
1541
1589
  providerType,
1542
1590
  publicClient,
1543
- getRpcUrl: (override) => getRpcUrl(slug, override)
1591
+ getRpcUrl: (override) => getRpcUrl(slug, override),
1592
+ ...signerProvider ? { address: signerProvider.address } : {}
1544
1593
  };
1545
1594
  if (signerProvider) {
1546
1595
  const { publicClient: _ignored, ...rest } = signerProvider;
@@ -1563,6 +1612,1450 @@ var walletToolkit = {
1563
1612
  wallet
1564
1613
  };
1565
1614
 
1615
+ // src/store/index.ts
1616
+ var StoreError = class extends Error {
1617
+ constructor(message, status, causeData) {
1618
+ super(message);
1619
+ this.status = status;
1620
+ this.causeData = causeData;
1621
+ this.name = "StoreError";
1622
+ }
1623
+ };
1624
+ function resolveConfig(options) {
1625
+ const baseUrl = options?.baseUrl ?? process.env.BASE_URL ?? "https://api.openpond.ai";
1626
+ const apiKey = options?.apiKey ?? process.env.OPENPOND_API_KEY;
1627
+ if (!baseUrl) {
1628
+ throw new StoreError("BASE_URL is required to store activity events");
1629
+ }
1630
+ if (!apiKey) {
1631
+ throw new StoreError(
1632
+ "OPENPOND_API_KEY is required to store activity events"
1633
+ );
1634
+ }
1635
+ const normalizedBaseUrl = baseUrl.replace(/\/$/, "");
1636
+ const fetchFn = options?.fetchFn ?? globalThis.fetch;
1637
+ if (!fetchFn) {
1638
+ throw new StoreError("Fetch is not available in this environment");
1639
+ }
1640
+ return { baseUrl: normalizedBaseUrl, apiKey, fetchFn };
1641
+ }
1642
+ async function store(input, options) {
1643
+ const { baseUrl, apiKey, fetchFn } = resolveConfig(options);
1644
+ const url = `${baseUrl}/apps/positions/tx`;
1645
+ let response;
1646
+ try {
1647
+ response = await fetchFn(url, {
1648
+ method: "POST",
1649
+ headers: {
1650
+ "content-type": "application/json",
1651
+ "openpond-api-key": apiKey
1652
+ },
1653
+ body: JSON.stringify(input)
1654
+ });
1655
+ } catch (error) {
1656
+ throw new StoreError("Failed to reach store endpoint", void 0, error);
1657
+ }
1658
+ if (!response.ok) {
1659
+ let body;
1660
+ try {
1661
+ body = await response.json();
1662
+ } catch {
1663
+ body = await response.text().catch(() => void 0);
1664
+ }
1665
+ throw new StoreError(
1666
+ `Store request failed with status ${response.status}`,
1667
+ response.status,
1668
+ body
1669
+ );
1670
+ }
1671
+ try {
1672
+ const data = await response.json();
1673
+ return {
1674
+ id: data.id ?? "",
1675
+ status: data.status ?? null
1676
+ };
1677
+ } catch {
1678
+ return { id: "", status: null };
1679
+ }
1680
+ }
1681
+ async function retrieve(params, options) {
1682
+ const { baseUrl, apiKey, fetchFn } = resolveConfig(options);
1683
+ const url = new URL(`${baseUrl}/apps/positions/tx`);
1684
+ if (params?.source) url.searchParams.set("source", params.source);
1685
+ if (params?.walletAddress) url.searchParams.set("walletAddress", params.walletAddress);
1686
+ if (params?.symbol) url.searchParams.set("symbol", params.symbol);
1687
+ if (params?.status?.length) url.searchParams.set("status", params.status.join(","));
1688
+ if (typeof params?.since === "number") url.searchParams.set("since", params.since.toString());
1689
+ if (typeof params?.until === "number") url.searchParams.set("until", params.until.toString());
1690
+ if (typeof params?.limit === "number") url.searchParams.set("limit", params.limit.toString());
1691
+ if (params?.cursor) url.searchParams.set("cursor", params.cursor);
1692
+ if (params?.history) url.searchParams.set("history", "true");
1693
+ let response;
1694
+ try {
1695
+ response = await fetchFn(url.toString(), {
1696
+ method: "GET",
1697
+ headers: {
1698
+ "content-type": "application/json",
1699
+ "openpond-api-key": apiKey
1700
+ }
1701
+ });
1702
+ } catch (error) {
1703
+ throw new StoreError("Failed to reach store endpoint", void 0, error);
1704
+ }
1705
+ if (!response.ok) {
1706
+ let body;
1707
+ try {
1708
+ body = await response.json();
1709
+ } catch {
1710
+ body = await response.text().catch(() => void 0);
1711
+ }
1712
+ throw new StoreError(
1713
+ `Store retrieve failed with status ${response.status}`,
1714
+ response.status,
1715
+ body
1716
+ );
1717
+ }
1718
+ const data = await response.json().catch(() => null);
1719
+ if (!data) {
1720
+ return { items: [], cursor: null };
1721
+ }
1722
+ return data;
1723
+ }
1724
+ var CACHE_TTL_MS = 5 * 60 * 1e3;
1725
+ var API_BASES = {
1726
+ mainnet: "https://api.hyperliquid.xyz",
1727
+ testnet: "https://api.hyperliquid-testnet.xyz"
1728
+ };
1729
+ var HL_ENDPOINT = {
1730
+ mainnet: "https://api.hyperliquid.xyz",
1731
+ testnet: "https://api.hyperliquid-testnet.xyz"
1732
+ };
1733
+ var HL_CHAIN_LABEL = {
1734
+ mainnet: "Mainnet",
1735
+ testnet: "Testnet"
1736
+ };
1737
+ var HL_BRIDGE_ADDRESSES = {
1738
+ mainnet: "0x2df1c51e09aecf9cacb7bc98cb1742757f163df7",
1739
+ testnet: "0x08cfc1b6b2dcf36a1480b99353a354aa8ac56f89"
1740
+ };
1741
+ var HL_USDC_ADDRESSES = {
1742
+ mainnet: "0xaf88d065e77c8cc2239327c5edb3a432268e5831",
1743
+ testnet: "0x1baAbB04529D43a73232B713C0FE471f7c7334d5"
1744
+ };
1745
+ var HL_SIGNATURE_CHAIN_ID = {
1746
+ mainnet: "0xa4b1",
1747
+ testnet: "0x66eee"
1748
+ };
1749
+ var EXCHANGE_TYPED_DATA_DOMAIN = {
1750
+ name: "Exchange",
1751
+ version: "1",
1752
+ chainId: 1337,
1753
+ verifyingContract: "0x0000000000000000000000000000000000000000"
1754
+ };
1755
+ var ZERO_ADDRESS = "0x0000000000000000000000000000000000000000";
1756
+ var MIN_DEPOSIT_USDC = 5;
1757
+ var BUILDER_CODE = {
1758
+ address: "0x4b2aec4F91612849d6e20C9c1881FabB1A48cd12",
1759
+ fee: 100
1760
+ };
1761
+ var metaCache = /* @__PURE__ */ new Map();
1762
+ var HyperliquidApiError = class extends Error {
1763
+ constructor(message, response) {
1764
+ super(message);
1765
+ this.response = response;
1766
+ this.name = "HyperliquidApiError";
1767
+ }
1768
+ };
1769
+ var HyperliquidGuardError = class extends Error {
1770
+ constructor(message) {
1771
+ super(message);
1772
+ this.name = "HyperliquidGuardError";
1773
+ }
1774
+ };
1775
+ var HyperliquidTermsError = class extends HyperliquidGuardError {
1776
+ constructor(message = "Hyperliquid terms must be accepted before proceeding.") {
1777
+ super(message);
1778
+ this.name = "HyperliquidTermsError";
1779
+ }
1780
+ };
1781
+ var HyperliquidBuilderApprovalError = class extends HyperliquidGuardError {
1782
+ constructor(message = "Hyperliquid builder approval is required before using builder codes.") {
1783
+ super(message);
1784
+ this.name = "HyperliquidBuilderApprovalError";
1785
+ }
1786
+ };
1787
+ function createMonotonicNonceFactory(start = Date.now()) {
1788
+ let last = start;
1789
+ return () => {
1790
+ const now = Date.now();
1791
+ if (now > last) {
1792
+ last = now;
1793
+ } else {
1794
+ last += 1;
1795
+ }
1796
+ return last;
1797
+ };
1798
+ }
1799
+ async function getUniverse(args) {
1800
+ const cacheKey = `${args.environment}:${args.baseUrl}`;
1801
+ const cached = metaCache.get(cacheKey);
1802
+ if (cached && Date.now() - cached.fetchedAt < CACHE_TTL_MS) {
1803
+ return cached.universe;
1804
+ }
1805
+ const response = await args.fetcher(`${args.baseUrl}/info`, {
1806
+ method: "POST",
1807
+ headers: { "content-type": "application/json" },
1808
+ body: JSON.stringify({ type: "meta" })
1809
+ });
1810
+ const json = await response.json().catch(() => null);
1811
+ if (!response.ok || !json?.universe) {
1812
+ throw new HyperliquidApiError(
1813
+ "Unable to load Hyperliquid metadata.",
1814
+ json ?? { status: response.status }
1815
+ );
1816
+ }
1817
+ metaCache.set(cacheKey, { fetchedAt: Date.now(), universe: json.universe });
1818
+ return json.universe;
1819
+ }
1820
+ function resolveAssetIndex(symbol, universe) {
1821
+ const [raw] = symbol.split("-");
1822
+ const target = raw.trim();
1823
+ const index = universe.findIndex(
1824
+ (entry) => entry.name.toUpperCase() === target.toUpperCase()
1825
+ );
1826
+ if (index === -1) {
1827
+ throw new Error(`Unknown Hyperliquid asset symbol: ${symbol}`);
1828
+ }
1829
+ return index;
1830
+ }
1831
+ function toApiDecimal(value) {
1832
+ if (typeof value === "string") {
1833
+ return value;
1834
+ }
1835
+ if (typeof value === "bigint") {
1836
+ return value.toString();
1837
+ }
1838
+ if (!Number.isFinite(value)) {
1839
+ throw new Error("Numeric values must be finite.");
1840
+ }
1841
+ const asString = value.toString();
1842
+ if (/e/i.test(asString)) {
1843
+ const [mantissa, exponentPart] = asString.split(/e/i);
1844
+ const exponent = Number(exponentPart);
1845
+ const [integerPart, fractionalPart = ""] = mantissa.split(".");
1846
+ if (exponent >= 0) {
1847
+ return integerPart + fractionalPart.padEnd(exponent + fractionalPart.length, "0");
1848
+ }
1849
+ const zeros = "0".repeat(Math.abs(exponent) - 1);
1850
+ return `0.${zeros}${integerPart}${fractionalPart}`.replace(/\.0+$/, "");
1851
+ }
1852
+ return asString;
1853
+ }
1854
+ function normalizeHex(value) {
1855
+ const lower = value.toLowerCase();
1856
+ return lower.replace(/^0x0+/, "0x") || "0x0";
1857
+ }
1858
+ function normalizeAddress(value) {
1859
+ return normalizeHex(value);
1860
+ }
1861
+ async function signL1Action(args) {
1862
+ const { wallet: wallet2, action, nonce, vaultAddress, expiresAfter, isTestnet } = args;
1863
+ const actionHash = createL1ActionHash({
1864
+ action,
1865
+ nonce,
1866
+ vaultAddress,
1867
+ expiresAfter
1868
+ });
1869
+ const message = {
1870
+ source: isTestnet ? "b" : "a",
1871
+ connectionId: actionHash
1872
+ };
1873
+ const signatureHex = await wallet2.walletClient.signTypedData({
1874
+ account: wallet2.account,
1875
+ domain: EXCHANGE_TYPED_DATA_DOMAIN,
1876
+ types: {
1877
+ Agent: [
1878
+ { name: "source", type: "string" },
1879
+ { name: "connectionId", type: "bytes32" }
1880
+ ]
1881
+ },
1882
+ primaryType: "Agent",
1883
+ message
1884
+ });
1885
+ return splitSignature(signatureHex);
1886
+ }
1887
+ async function signSpotSend(args) {
1888
+ const {
1889
+ wallet: wallet2,
1890
+ hyperliquidChain,
1891
+ signatureChainId,
1892
+ destination,
1893
+ token: token2,
1894
+ amount,
1895
+ time
1896
+ } = args;
1897
+ const domain = {
1898
+ name: "HyperliquidSignTransaction",
1899
+ version: "1",
1900
+ chainId: Number.parseInt(signatureChainId, 16),
1901
+ verifyingContract: ZERO_ADDRESS
1902
+ };
1903
+ const message = {
1904
+ hyperliquidChain,
1905
+ destination,
1906
+ token: token2,
1907
+ amount,
1908
+ time
1909
+ };
1910
+ const types = {
1911
+ "HyperliquidTransaction:SpotSend": [
1912
+ { name: "hyperliquidChain", type: "string" },
1913
+ { name: "destination", type: "string" },
1914
+ { name: "token", type: "string" },
1915
+ { name: "amount", type: "string" },
1916
+ { name: "time", type: "uint64" }
1917
+ ]
1918
+ };
1919
+ const signatureHex = await wallet2.walletClient.signTypedData({
1920
+ account: wallet2.account,
1921
+ domain,
1922
+ types,
1923
+ primaryType: "HyperliquidTransaction:SpotSend",
1924
+ message
1925
+ });
1926
+ return splitSignature(signatureHex);
1927
+ }
1928
+ async function signApproveBuilderFee(args) {
1929
+ const { wallet: wallet2, maxFeeRate, nonce, signatureChainId, isTestnet } = args;
1930
+ const hyperliquidChain = isTestnet ? "Testnet" : "Mainnet";
1931
+ const domain = {
1932
+ name: "HyperliquidSignTransaction",
1933
+ version: "1",
1934
+ chainId: Number.parseInt(signatureChainId, 16),
1935
+ verifyingContract: ZERO_ADDRESS
1936
+ };
1937
+ const message = {
1938
+ hyperliquidChain,
1939
+ maxFeeRate,
1940
+ builder: BUILDER_CODE.address,
1941
+ nonce
1942
+ };
1943
+ const types = {
1944
+ "HyperliquidTransaction:ApproveBuilderFee": [
1945
+ { name: "hyperliquidChain", type: "string" },
1946
+ { name: "maxFeeRate", type: "string" },
1947
+ { name: "builder", type: "address" },
1948
+ { name: "nonce", type: "uint64" }
1949
+ ]
1950
+ };
1951
+ const signatureHex = await wallet2.walletClient.signTypedData({
1952
+ account: wallet2.account,
1953
+ domain,
1954
+ types,
1955
+ primaryType: "HyperliquidTransaction:ApproveBuilderFee",
1956
+ message
1957
+ });
1958
+ return splitSignature(signatureHex);
1959
+ }
1960
+ function splitSignature(signature) {
1961
+ const cleaned = signature.slice(2);
1962
+ const rHex = `0x${cleaned.slice(0, 64)}`;
1963
+ const sHex = `0x${cleaned.slice(64, 128)}`;
1964
+ let v = parseInt(cleaned.slice(128, 130), 16);
1965
+ if (Number.isNaN(v)) {
1966
+ throw new Error("Invalid signature returned by wallet client.");
1967
+ }
1968
+ if (v < 27) {
1969
+ v += 27;
1970
+ }
1971
+ const normalizedV = v === 27 || v === 28 ? v : v % 2 ? 27 : 28;
1972
+ return {
1973
+ r: normalizeHex(rHex),
1974
+ s: normalizeHex(sHex),
1975
+ v: normalizedV
1976
+ };
1977
+ }
1978
+ function createL1ActionHash(args) {
1979
+ const { action, nonce, vaultAddress, expiresAfter } = args;
1980
+ const actionBytes = encode(action, { ignoreUndefined: true });
1981
+ const nonceBytes = toUint64Bytes(nonce);
1982
+ const vaultMarker = vaultAddress ? new Uint8Array([1]) : new Uint8Array([0]);
1983
+ const vaultBytes = vaultAddress ? hexToBytes(vaultAddress.slice(2)) : new Uint8Array();
1984
+ const hasExpiresAfter = typeof expiresAfter === "number";
1985
+ const expiresMarker = hasExpiresAfter ? new Uint8Array([0]) : new Uint8Array();
1986
+ const expiresBytes = hasExpiresAfter && expiresAfter !== void 0 ? toUint64Bytes(expiresAfter) : new Uint8Array();
1987
+ const bytes = concatBytes(
1988
+ actionBytes,
1989
+ nonceBytes,
1990
+ vaultMarker,
1991
+ vaultBytes,
1992
+ expiresMarker,
1993
+ expiresBytes
1994
+ );
1995
+ const hash = keccak_256(bytes);
1996
+ return `0x${bytesToHex(hash)}`;
1997
+ }
1998
+ function toUint64Bytes(value) {
1999
+ const bytes = new Uint8Array(8);
2000
+ new DataView(bytes.buffer).setBigUint64(0, BigInt(value));
2001
+ return bytes;
2002
+ }
2003
+ function getBridgeAddress(env) {
2004
+ const override = process.env.HYPERLIQUID_BRIDGE_ADDRESS;
2005
+ if (override?.trim()) {
2006
+ return normalizeAddress(override);
2007
+ }
2008
+ return HL_BRIDGE_ADDRESSES[env];
2009
+ }
2010
+ function getUsdcAddress(env) {
2011
+ const override = process.env.HYPERLIQUID_USDC_ADDRESS;
2012
+ if (override?.trim()) {
2013
+ return normalizeAddress(override);
2014
+ }
2015
+ return HL_USDC_ADDRESSES[env];
2016
+ }
2017
+ function getSignatureChainId(env) {
2018
+ const override = process.env.HYPERLIQUID_SIGNATURE_CHAIN_ID;
2019
+ const selected = override?.trim() || HL_SIGNATURE_CHAIN_ID[env];
2020
+ return normalizeHex(selected);
2021
+ }
2022
+ function assertPositiveNumber(value, label) {
2023
+ if (!Number.isFinite(value) || value <= 0) {
2024
+ throw new Error(`${label} must be a positive number.`);
2025
+ }
2026
+ }
2027
+
2028
+ // src/adapters/hyperliquid/exchange.ts
2029
+ var HyperliquidExchangeClient = class {
2030
+ constructor(args) {
2031
+ this.wallet = args.wallet;
2032
+ this.environment = args.environment ?? "mainnet";
2033
+ this.vaultAddress = args.vaultAddress;
2034
+ this.expiresAfter = args.expiresAfter;
2035
+ const resolvedNonceSource = args.walletNonceProvider ?? args.wallet.nonceSource ?? args.nonceSource;
2036
+ if (!resolvedNonceSource) {
2037
+ throw new Error(
2038
+ "Wallet nonce source is required for Hyperliquid exchange actions."
2039
+ );
2040
+ }
2041
+ this.nonceSource = resolvedNonceSource;
2042
+ }
2043
+ cancel(cancels) {
2044
+ return cancelHyperliquidOrders({
2045
+ wallet: this.wallet,
2046
+ cancels,
2047
+ environment: this.environment,
2048
+ vaultAddress: this.vaultAddress,
2049
+ expiresAfter: this.expiresAfter,
2050
+ nonceSource: this.nonceSource
2051
+ });
2052
+ }
2053
+ cancelByCloid(cancels) {
2054
+ return cancelHyperliquidOrdersByCloid({
2055
+ wallet: this.wallet,
2056
+ cancels,
2057
+ environment: this.environment,
2058
+ vaultAddress: this.vaultAddress,
2059
+ expiresAfter: this.expiresAfter,
2060
+ nonceSource: this.nonceSource
2061
+ });
2062
+ }
2063
+ cancelAll() {
2064
+ return cancelAllHyperliquidOrders({
2065
+ wallet: this.wallet,
2066
+ environment: this.environment,
2067
+ vaultAddress: this.vaultAddress,
2068
+ expiresAfter: this.expiresAfter,
2069
+ nonceSource: this.nonceSource
2070
+ });
2071
+ }
2072
+ scheduleCancel(time) {
2073
+ return scheduleHyperliquidCancel({
2074
+ wallet: this.wallet,
2075
+ time,
2076
+ environment: this.environment,
2077
+ vaultAddress: this.vaultAddress,
2078
+ expiresAfter: this.expiresAfter,
2079
+ nonceSource: this.nonceSource
2080
+ });
2081
+ }
2082
+ modify(modification) {
2083
+ return modifyHyperliquidOrder({
2084
+ wallet: this.wallet,
2085
+ modification,
2086
+ environment: this.environment,
2087
+ vaultAddress: this.vaultAddress,
2088
+ expiresAfter: this.expiresAfter,
2089
+ nonceSource: this.nonceSource
2090
+ });
2091
+ }
2092
+ batchModify(modifications) {
2093
+ return batchModifyHyperliquidOrders({
2094
+ wallet: this.wallet,
2095
+ modifications,
2096
+ environment: this.environment,
2097
+ vaultAddress: this.vaultAddress,
2098
+ expiresAfter: this.expiresAfter,
2099
+ nonceSource: this.nonceSource
2100
+ });
2101
+ }
2102
+ twapOrder(twap) {
2103
+ return placeHyperliquidTwapOrder({
2104
+ wallet: this.wallet,
2105
+ twap,
2106
+ environment: this.environment,
2107
+ vaultAddress: this.vaultAddress,
2108
+ expiresAfter: this.expiresAfter,
2109
+ nonceSource: this.nonceSource
2110
+ });
2111
+ }
2112
+ twapCancel(cancel) {
2113
+ return cancelHyperliquidTwapOrder({
2114
+ wallet: this.wallet,
2115
+ cancel,
2116
+ environment: this.environment,
2117
+ vaultAddress: this.vaultAddress,
2118
+ expiresAfter: this.expiresAfter,
2119
+ nonceSource: this.nonceSource
2120
+ });
2121
+ }
2122
+ updateLeverage(input) {
2123
+ return updateHyperliquidLeverage({
2124
+ wallet: this.wallet,
2125
+ input,
2126
+ environment: this.environment,
2127
+ vaultAddress: this.vaultAddress,
2128
+ expiresAfter: this.expiresAfter,
2129
+ nonceSource: this.nonceSource
2130
+ });
2131
+ }
2132
+ updateIsolatedMargin(input) {
2133
+ return updateHyperliquidIsolatedMargin({
2134
+ wallet: this.wallet,
2135
+ input,
2136
+ environment: this.environment,
2137
+ vaultAddress: this.vaultAddress,
2138
+ expiresAfter: this.expiresAfter,
2139
+ nonceSource: this.nonceSource
2140
+ });
2141
+ }
2142
+ reserveRequestWeight(weight) {
2143
+ return reserveHyperliquidRequestWeight({
2144
+ wallet: this.wallet,
2145
+ weight,
2146
+ environment: this.environment,
2147
+ vaultAddress: this.vaultAddress,
2148
+ expiresAfter: this.expiresAfter,
2149
+ nonceSource: this.nonceSource
2150
+ });
2151
+ }
2152
+ spotSend(params) {
2153
+ return sendHyperliquidSpot({
2154
+ wallet: this.wallet,
2155
+ environment: this.environment,
2156
+ nonceSource: this.nonceSource,
2157
+ ...params
2158
+ });
2159
+ }
2160
+ };
2161
+ async function cancelHyperliquidOrders(options) {
2162
+ options.cancels.forEach((c) => assertSymbol(c.symbol));
2163
+ const action = {
2164
+ type: "cancel",
2165
+ cancels: await withAssetIndexes(options, options.cancels, (idx, entry) => ({
2166
+ a: idx,
2167
+ o: entry.oid
2168
+ }))
2169
+ };
2170
+ return submitExchangeAction(options, action);
2171
+ }
2172
+ async function cancelHyperliquidOrdersByCloid(options) {
2173
+ options.cancels.forEach((c) => assertSymbol(c.symbol));
2174
+ const action = {
2175
+ type: "cancelByCloid",
2176
+ cancels: await withAssetIndexes(
2177
+ options,
2178
+ options.cancels,
2179
+ (idx, entry) => ({
2180
+ a: idx,
2181
+ c: normalizeAddress(entry.cloid)
2182
+ })
2183
+ )
2184
+ };
2185
+ return submitExchangeAction(options, action);
2186
+ }
2187
+ async function cancelAllHyperliquidOrders(options) {
2188
+ const action = { type: "cancelAll" };
2189
+ return submitExchangeAction(options, action);
2190
+ }
2191
+ async function scheduleHyperliquidCancel(options) {
2192
+ if (options.time !== null) {
2193
+ assertPositiveNumber(options.time, "time");
2194
+ }
2195
+ const action = { type: "scheduleCancel", time: options.time };
2196
+ return submitExchangeAction(options, action);
2197
+ }
2198
+ async function modifyHyperliquidOrder(options) {
2199
+ const { modification } = options;
2200
+ const order = await buildOrder(modification.order, options);
2201
+ const action = {
2202
+ type: "modify",
2203
+ oid: modification.oid,
2204
+ order
2205
+ };
2206
+ return submitExchangeAction(options, action);
2207
+ }
2208
+ async function batchModifyHyperliquidOrders(options) {
2209
+ options.modifications.forEach((m) => assertSymbol(m.order.symbol));
2210
+ const modifies = await Promise.all(
2211
+ options.modifications.map(async (mod) => ({
2212
+ oid: mod.oid,
2213
+ order: await buildOrder(mod.order, options)
2214
+ }))
2215
+ );
2216
+ const action = {
2217
+ type: "batchModify",
2218
+ modifies
2219
+ };
2220
+ return submitExchangeAction(options, action);
2221
+ }
2222
+ async function placeHyperliquidTwapOrder(options) {
2223
+ const { twap } = options;
2224
+ assertSymbol(twap.symbol);
2225
+ assertPositiveDecimal(twap.size, "size");
2226
+ assertPositiveNumber(twap.minutes, "minutes");
2227
+ const env = options.environment ?? "mainnet";
2228
+ const universe = await getUniverse({
2229
+ baseUrl: API_BASES[env],
2230
+ environment: env,
2231
+ fetcher: fetch
2232
+ });
2233
+ const asset = resolveAssetIndex(twap.symbol, universe);
2234
+ const action = {
2235
+ type: "twapOrder",
2236
+ twap: {
2237
+ a: asset,
2238
+ b: twap.side === "buy",
2239
+ s: toApiDecimal(twap.size),
2240
+ r: Boolean(twap.reduceOnly),
2241
+ m: twap.minutes,
2242
+ t: Boolean(twap.randomize)
2243
+ }
2244
+ };
2245
+ return submitExchangeAction(options, action);
2246
+ }
2247
+ async function cancelHyperliquidTwapOrder(options) {
2248
+ assertSymbol(options.cancel.symbol);
2249
+ const env = options.environment ?? "mainnet";
2250
+ const universe = await getUniverse({
2251
+ baseUrl: API_BASES[env],
2252
+ environment: env,
2253
+ fetcher: fetch
2254
+ });
2255
+ const asset = resolveAssetIndex(options.cancel.symbol, universe);
2256
+ const action = {
2257
+ type: "twapCancel",
2258
+ a: asset,
2259
+ t: options.cancel.twapId
2260
+ };
2261
+ return submitExchangeAction(options, action);
2262
+ }
2263
+ async function updateHyperliquidLeverage(options) {
2264
+ assertSymbol(options.input.symbol);
2265
+ assertPositiveNumber(options.input.leverage, "leverage");
2266
+ const env = options.environment ?? "mainnet";
2267
+ const universe = await getUniverse({
2268
+ baseUrl: API_BASES[env],
2269
+ environment: env,
2270
+ fetcher: fetch
2271
+ });
2272
+ const asset = resolveAssetIndex(options.input.symbol, universe);
2273
+ const action = {
2274
+ type: "updateLeverage",
2275
+ asset,
2276
+ isCross: options.input.leverageMode === "cross",
2277
+ leverage: options.input.leverage
2278
+ };
2279
+ return submitExchangeAction(options, action);
2280
+ }
2281
+ async function updateHyperliquidIsolatedMargin(options) {
2282
+ assertSymbol(options.input.symbol);
2283
+ assertPositiveNumber(options.input.ntli, "ntli");
2284
+ const env = options.environment ?? "mainnet";
2285
+ const universe = await getUniverse({
2286
+ baseUrl: API_BASES[env],
2287
+ environment: env,
2288
+ fetcher: fetch
2289
+ });
2290
+ const asset = resolveAssetIndex(options.input.symbol, universe);
2291
+ const action = {
2292
+ type: "updateIsolatedMargin",
2293
+ asset,
2294
+ isBuy: options.input.isBuy,
2295
+ ntli: options.input.ntli
2296
+ };
2297
+ return submitExchangeAction(options, action);
2298
+ }
2299
+ async function reserveHyperliquidRequestWeight(options) {
2300
+ assertPositiveNumber(options.weight, "weight");
2301
+ const action = {
2302
+ type: "reserveRequestWeight",
2303
+ weight: options.weight
2304
+ };
2305
+ return submitExchangeAction(options, action);
2306
+ }
2307
+ async function createHyperliquidSubAccount(options) {
2308
+ assertString(options.name, "name");
2309
+ const action = {
2310
+ type: "createSubAccount",
2311
+ name: options.name
2312
+ };
2313
+ return submitExchangeAction(options, action);
2314
+ }
2315
+ async function transferHyperliquidSubAccount(options) {
2316
+ assertString(options.subAccountUser, "subAccountUser");
2317
+ const usdScaled = normalizeUsdToInt(options.usd);
2318
+ const action = {
2319
+ type: "subAccountTransfer",
2320
+ subAccountUser: normalizeAddress(options.subAccountUser),
2321
+ isDeposit: Boolean(options.isDeposit),
2322
+ usd: usdScaled
2323
+ };
2324
+ return submitExchangeAction(options, action);
2325
+ }
2326
+ async function sendHyperliquidSpot(options) {
2327
+ const env = options.environment ?? "mainnet";
2328
+ if (!options.wallet.account || !options.wallet.walletClient) {
2329
+ throw new Error("Wallet with signing capability is required for spotSend.");
2330
+ }
2331
+ assertString(options.token, "token");
2332
+ assertPositiveDecimal(options.amount, "amount");
2333
+ const signatureChainId = getSignatureChainId(env);
2334
+ const hyperliquidChain = HL_CHAIN_LABEL[env];
2335
+ const nonce = options.nonce ?? options.nonceSource?.() ?? Date.now();
2336
+ const time = BigInt(nonce);
2337
+ const signature = await signSpotSend({
2338
+ wallet: options.wallet,
2339
+ hyperliquidChain,
2340
+ signatureChainId,
2341
+ destination: normalizeAddress(options.destination),
2342
+ token: options.token,
2343
+ amount: toApiDecimal(options.amount),
2344
+ time
2345
+ });
2346
+ const action = {
2347
+ type: "spotSend",
2348
+ hyperliquidChain,
2349
+ signatureChainId,
2350
+ destination: normalizeAddress(options.destination),
2351
+ token: options.token,
2352
+ amount: toApiDecimal(options.amount),
2353
+ time: nonce
2354
+ };
2355
+ return postExchange(env, { action, nonce, signature });
2356
+ }
2357
+ async function submitExchangeAction(options, action) {
2358
+ if (!options.wallet?.account || !options.wallet.walletClient) {
2359
+ throw new Error("Hyperliquid exchange actions require a signing wallet.");
2360
+ }
2361
+ const env = options.environment ?? "mainnet";
2362
+ const nonceSource = options.walletNonceProvider ?? options.wallet.nonceSource ?? options.nonceSource;
2363
+ if (!nonceSource && options.nonce === void 0) {
2364
+ throw new Error("Wallet nonce source is required for Hyperliquid exchange actions.");
2365
+ }
2366
+ const effectiveNonce = options.nonce ?? nonceSource?.();
2367
+ if (effectiveNonce === void 0) {
2368
+ throw new Error("Hyperliquid exchange actions require a nonce.");
2369
+ }
2370
+ const signature = await signL1Action({
2371
+ wallet: options.wallet,
2372
+ action,
2373
+ nonce: effectiveNonce,
2374
+ vaultAddress: options.vaultAddress ? normalizeAddress(options.vaultAddress) : void 0,
2375
+ expiresAfter: options.expiresAfter,
2376
+ isTestnet: env === "testnet"
2377
+ });
2378
+ const body = {
2379
+ action,
2380
+ nonce: effectiveNonce,
2381
+ signature
2382
+ };
2383
+ if (options.vaultAddress) {
2384
+ body.vaultAddress = normalizeAddress(options.vaultAddress);
2385
+ }
2386
+ if (typeof options.expiresAfter === "number") {
2387
+ body.expiresAfter = options.expiresAfter;
2388
+ }
2389
+ return postExchange(env, body);
2390
+ }
2391
+ async function withAssetIndexes(options, entries, mapper) {
2392
+ const env = options.environment ?? "mainnet";
2393
+ const universe = await getUniverse({
2394
+ baseUrl: API_BASES[env],
2395
+ environment: env,
2396
+ fetcher: fetch
2397
+ });
2398
+ return Promise.all(
2399
+ entries.map(async (entry) => {
2400
+ const assetIndex = resolveAssetIndex(entry.symbol, universe);
2401
+ return mapper(assetIndex, entry);
2402
+ })
2403
+ );
2404
+ }
2405
+ async function buildOrder(intent, options) {
2406
+ assertSymbol(intent.symbol);
2407
+ assertPositiveDecimal(intent.price, "price");
2408
+ assertPositiveDecimal(intent.size, "size");
2409
+ const env = options.environment ?? "mainnet";
2410
+ const universe = await getUniverse({
2411
+ baseUrl: API_BASES[env],
2412
+ environment: env,
2413
+ fetcher: fetch
2414
+ });
2415
+ const assetIndex = resolveAssetIndex(intent.symbol, universe);
2416
+ const limitOrTrigger = intent.trigger ? mapTrigger(intent.trigger) : {
2417
+ limit: {
2418
+ tif: intent.tif ?? "Ioc"
2419
+ }
2420
+ };
2421
+ return {
2422
+ a: assetIndex,
2423
+ b: intent.side === "buy",
2424
+ p: toApiDecimal(intent.price),
2425
+ s: toApiDecimal(intent.size),
2426
+ r: intent.reduceOnly ?? false,
2427
+ t: limitOrTrigger,
2428
+ ...intent.clientId ? {
2429
+ c: normalizeAddress(intent.clientId)
2430
+ } : {}
2431
+ };
2432
+ }
2433
+ function mapTrigger(trigger) {
2434
+ assertPositiveDecimal(trigger.triggerPx, "triggerPx");
2435
+ return {
2436
+ trigger: {
2437
+ isMarket: Boolean(trigger.isMarket),
2438
+ triggerPx: toApiDecimal(trigger.triggerPx),
2439
+ tpsl: trigger.tpsl
2440
+ }
2441
+ };
2442
+ }
2443
+ function assertSymbol(value) {
2444
+ assertString(value, "symbol");
2445
+ }
2446
+ function normalizeUsdToInt(value) {
2447
+ if (typeof value === "bigint") {
2448
+ if (value < 0n) {
2449
+ throw new Error("usd must be non-negative.");
2450
+ }
2451
+ return Number(value);
2452
+ }
2453
+ const parsed = typeof value === "string" ? Number.parseFloat(value) : Number(value);
2454
+ if (!Number.isFinite(parsed) || parsed < 0) {
2455
+ throw new Error("usd must be a non-negative number.");
2456
+ }
2457
+ return Math.round(parsed * 1e6);
2458
+ }
2459
+ function assertString(value, label) {
2460
+ if (typeof value !== "string" || !value.trim()) {
2461
+ throw new Error(`${label} must be a non-empty string.`);
2462
+ }
2463
+ }
2464
+ function assertPositiveDecimal(value, label) {
2465
+ if (typeof value === "number") {
2466
+ assertPositiveNumber(value, label);
2467
+ return;
2468
+ }
2469
+ if (typeof value === "bigint") {
2470
+ if (value <= 0n) {
2471
+ throw new Error(`${label} must be positive.`);
2472
+ }
2473
+ return;
2474
+ }
2475
+ assertString(value, label);
2476
+ }
2477
+ async function postExchange(env, body) {
2478
+ const response = await fetch(`${API_BASES[env]}/exchange`, {
2479
+ method: "POST",
2480
+ headers: { "content-type": "application/json" },
2481
+ body: JSON.stringify(body)
2482
+ });
2483
+ const json = await response.json().catch(() => null);
2484
+ if (!response.ok || !json) {
2485
+ throw new HyperliquidApiError(
2486
+ "Hyperliquid exchange action failed.",
2487
+ json ?? { status: response.status }
2488
+ );
2489
+ }
2490
+ if (json.status !== "ok") {
2491
+ throw new HyperliquidApiError("Hyperliquid exchange returned error.", json);
2492
+ }
2493
+ return json;
2494
+ }
2495
+
2496
+ // src/adapters/hyperliquid/info.ts
2497
+ async function postInfo(environment, payload) {
2498
+ const baseUrl = API_BASES[environment];
2499
+ const response = await fetch(`${baseUrl}/info`, {
2500
+ method: "POST",
2501
+ headers: { "content-type": "application/json" },
2502
+ body: JSON.stringify(payload)
2503
+ });
2504
+ const data = await response.json().catch(() => null);
2505
+ if (!response.ok) {
2506
+ throw new HyperliquidApiError(
2507
+ "Hyperliquid info request failed.",
2508
+ data ?? { status: response.status }
2509
+ );
2510
+ }
2511
+ return data;
2512
+ }
2513
+ var HyperliquidInfoClient = class {
2514
+ constructor(environment = "mainnet") {
2515
+ this.environment = environment;
2516
+ }
2517
+ meta() {
2518
+ return fetchHyperliquidMeta(this.environment);
2519
+ }
2520
+ metaAndAssetCtxs() {
2521
+ return fetchHyperliquidMetaAndAssetCtxs(this.environment);
2522
+ }
2523
+ spotMeta() {
2524
+ return fetchHyperliquidSpotMeta(this.environment);
2525
+ }
2526
+ spotMetaAndAssetCtxs() {
2527
+ return fetchHyperliquidSpotMetaAndAssetCtxs(this.environment);
2528
+ }
2529
+ assetCtxs() {
2530
+ return fetchHyperliquidAssetCtxs(this.environment);
2531
+ }
2532
+ spotAssetCtxs() {
2533
+ return fetchHyperliquidSpotAssetCtxs(this.environment);
2534
+ }
2535
+ openOrders(user) {
2536
+ return fetchHyperliquidOpenOrders({ user, environment: this.environment });
2537
+ }
2538
+ frontendOpenOrders(user) {
2539
+ return fetchHyperliquidFrontendOpenOrders({
2540
+ user,
2541
+ environment: this.environment
2542
+ });
2543
+ }
2544
+ orderStatus(user, oid) {
2545
+ return fetchHyperliquidOrderStatus({
2546
+ user,
2547
+ oid,
2548
+ environment: this.environment
2549
+ });
2550
+ }
2551
+ historicalOrders(user) {
2552
+ return fetchHyperliquidHistoricalOrders({
2553
+ user,
2554
+ environment: this.environment
2555
+ });
2556
+ }
2557
+ userFills(user) {
2558
+ return fetchHyperliquidUserFills({ user, environment: this.environment });
2559
+ }
2560
+ userFillsByTime(user, startTime, endTime) {
2561
+ return fetchHyperliquidUserFillsByTime({
2562
+ user,
2563
+ startTime,
2564
+ endTime,
2565
+ environment: this.environment
2566
+ });
2567
+ }
2568
+ userRateLimit(user) {
2569
+ return fetchHyperliquidUserRateLimit({
2570
+ user,
2571
+ environment: this.environment
2572
+ });
2573
+ }
2574
+ preTransferCheck(user, source) {
2575
+ return fetchHyperliquidPreTransferCheck({
2576
+ user,
2577
+ source,
2578
+ environment: this.environment
2579
+ });
2580
+ }
2581
+ spotClearinghouseState(user) {
2582
+ return fetchHyperliquidSpotClearinghouseState({
2583
+ user,
2584
+ environment: this.environment
2585
+ });
2586
+ }
2587
+ };
2588
+ async function fetchHyperliquidMeta(environment = "mainnet") {
2589
+ return postInfo(environment, { type: "meta" });
2590
+ }
2591
+ async function fetchHyperliquidMetaAndAssetCtxs(environment = "mainnet") {
2592
+ return postInfo(environment, { type: "metaAndAssetCtxs" });
2593
+ }
2594
+ async function fetchHyperliquidSpotMeta(environment = "mainnet") {
2595
+ return postInfo(environment, { type: "spotMeta" });
2596
+ }
2597
+ async function fetchHyperliquidSpotMetaAndAssetCtxs(environment = "mainnet") {
2598
+ return postInfo(environment, { type: "spotMetaAndAssetCtxs" });
2599
+ }
2600
+ async function fetchHyperliquidAssetCtxs(environment = "mainnet") {
2601
+ return postInfo(environment, { type: "assetCtxs" });
2602
+ }
2603
+ async function fetchHyperliquidSpotAssetCtxs(environment = "mainnet") {
2604
+ return postInfo(environment, { type: "spotAssetCtxs" });
2605
+ }
2606
+ async function fetchHyperliquidOpenOrders(params) {
2607
+ const env = params.environment ?? "mainnet";
2608
+ return postInfo(env, { type: "openOrders", user: normalizeAddress(params.user) });
2609
+ }
2610
+ async function fetchHyperliquidFrontendOpenOrders(params) {
2611
+ const env = params.environment ?? "mainnet";
2612
+ return postInfo(env, {
2613
+ type: "frontendOpenOrders",
2614
+ user: normalizeAddress(params.user)
2615
+ });
2616
+ }
2617
+ async function fetchHyperliquidOrderStatus(params) {
2618
+ const env = params.environment ?? "mainnet";
2619
+ return postInfo(env, {
2620
+ type: "orderStatus",
2621
+ user: normalizeAddress(params.user),
2622
+ oid: params.oid
2623
+ });
2624
+ }
2625
+ async function fetchHyperliquidHistoricalOrders(params) {
2626
+ const env = params.environment ?? "mainnet";
2627
+ return postInfo(env, {
2628
+ type: "historicalOrders",
2629
+ user: normalizeAddress(params.user)
2630
+ });
2631
+ }
2632
+ async function fetchHyperliquidUserFills(params) {
2633
+ const env = params.environment ?? "mainnet";
2634
+ return postInfo(env, {
2635
+ type: "userFills",
2636
+ user: normalizeAddress(params.user)
2637
+ });
2638
+ }
2639
+ async function fetchHyperliquidUserFillsByTime(params) {
2640
+ const env = params.environment ?? "mainnet";
2641
+ return postInfo(env, {
2642
+ type: "userFillsByTime",
2643
+ user: normalizeAddress(params.user),
2644
+ startTime: params.startTime,
2645
+ endTime: params.endTime
2646
+ });
2647
+ }
2648
+ async function fetchHyperliquidUserRateLimit(params) {
2649
+ const env = params.environment ?? "mainnet";
2650
+ return postInfo(env, {
2651
+ type: "userRateLimit",
2652
+ user: normalizeAddress(params.user)
2653
+ });
2654
+ }
2655
+ async function fetchHyperliquidPreTransferCheck(params) {
2656
+ const env = params.environment ?? "mainnet";
2657
+ return postInfo(env, {
2658
+ type: "preTransferCheck",
2659
+ user: normalizeAddress(params.user),
2660
+ source: normalizeAddress(params.source)
2661
+ });
2662
+ }
2663
+ async function fetchHyperliquidSpotClearinghouseState(params) {
2664
+ const env = params.environment ?? "mainnet";
2665
+ return postInfo(env, {
2666
+ type: "spotClearinghouseState",
2667
+ user: normalizeAddress(params.user)
2668
+ });
2669
+ }
2670
+
2671
+ // src/adapters/hyperliquid/index.ts
2672
+ async function placeHyperliquidOrder(options) {
2673
+ const {
2674
+ wallet: wallet2,
2675
+ orders,
2676
+ grouping = "na",
2677
+ environment,
2678
+ vaultAddress,
2679
+ expiresAfter,
2680
+ nonce
2681
+ } = options;
2682
+ const effectiveBuilder = BUILDER_CODE;
2683
+ if (!wallet2?.account || !wallet2.walletClient) {
2684
+ throw new Error(
2685
+ "Hyperliquid order signing requires a wallet with signing capabilities."
2686
+ );
2687
+ }
2688
+ if (!orders.length) {
2689
+ throw new Error("At least one order is required.");
2690
+ }
2691
+ const inferredEnvironment = environment ?? "mainnet";
2692
+ const resolvedBaseUrl = API_BASES[inferredEnvironment];
2693
+ const universe = await getUniverse({
2694
+ baseUrl: resolvedBaseUrl,
2695
+ environment: inferredEnvironment,
2696
+ fetcher: fetch
2697
+ });
2698
+ const preparedOrders = orders.map((intent) => {
2699
+ const assetIndex = resolveAssetIndex(intent.symbol, universe);
2700
+ const limitOrTrigger = intent.trigger ? {
2701
+ trigger: {
2702
+ isMarket: Boolean(intent.trigger.isMarket),
2703
+ triggerPx: toApiDecimal(intent.trigger.triggerPx),
2704
+ tpsl: intent.trigger.tpsl
2705
+ }
2706
+ } : {
2707
+ limit: {
2708
+ tif: intent.tif ?? "Ioc"
2709
+ }
2710
+ };
2711
+ const order = {
2712
+ a: assetIndex,
2713
+ b: intent.side === "buy",
2714
+ p: toApiDecimal(intent.price),
2715
+ s: toApiDecimal(intent.size),
2716
+ r: intent.reduceOnly ?? false,
2717
+ t: limitOrTrigger,
2718
+ ...intent.clientId ? {
2719
+ c: normalizeHex(intent.clientId)
2720
+ } : {}
2721
+ };
2722
+ return order;
2723
+ });
2724
+ const action = {
2725
+ type: "order",
2726
+ orders: preparedOrders,
2727
+ grouping
2728
+ };
2729
+ if (effectiveBuilder) {
2730
+ action.builder = {
2731
+ b: normalizeAddress(effectiveBuilder.address),
2732
+ f: effectiveBuilder.fee
2733
+ };
2734
+ }
2735
+ const effectiveNonce = nonce ?? Date.now();
2736
+ const signature = await signL1Action({
2737
+ wallet: wallet2,
2738
+ action,
2739
+ nonce: effectiveNonce,
2740
+ ...vaultAddress ? { vaultAddress } : {},
2741
+ ...typeof expiresAfter === "number" ? { expiresAfter } : {},
2742
+ isTestnet: inferredEnvironment === "testnet"
2743
+ });
2744
+ const body = {
2745
+ action,
2746
+ nonce: effectiveNonce,
2747
+ signature
2748
+ };
2749
+ if (vaultAddress) {
2750
+ body.vaultAddress = normalizeAddress(vaultAddress);
2751
+ }
2752
+ if (typeof expiresAfter === "number") {
2753
+ body.expiresAfter = expiresAfter;
2754
+ }
2755
+ const response = await fetch(`${resolvedBaseUrl}/exchange`, {
2756
+ method: "POST",
2757
+ headers: { "content-type": "application/json" },
2758
+ body: JSON.stringify(body)
2759
+ });
2760
+ const rawText = await response.text().catch(() => null);
2761
+ let parsed = null;
2762
+ if (rawText && rawText.length) {
2763
+ try {
2764
+ parsed = JSON.parse(rawText);
2765
+ } catch {
2766
+ parsed = rawText;
2767
+ }
2768
+ }
2769
+ const json = parsed && typeof parsed === "object" && "status" in parsed ? parsed : null;
2770
+ if (!response.ok || !json) {
2771
+ const detail = parsed?.error ?? parsed?.message ?? (typeof parsed === "string" ? parsed : rawText);
2772
+ const suffix = detail ? ` Detail: ${detail}` : "";
2773
+ throw new HyperliquidApiError(
2774
+ `Failed to submit Hyperliquid order.${suffix}`,
2775
+ parsed ?? rawText ?? { status: response.status }
2776
+ );
2777
+ }
2778
+ if (json.status !== "ok") {
2779
+ const detail = parsed?.error ?? rawText;
2780
+ throw new HyperliquidApiError(
2781
+ detail ? `Hyperliquid API returned an error status: ${detail}` : "Hyperliquid API returned an error status.",
2782
+ json
2783
+ );
2784
+ }
2785
+ const statuses = json.response?.data?.statuses ?? [];
2786
+ const errorStatuses = statuses.filter(
2787
+ (entry) => "error" in entry
2788
+ );
2789
+ if (errorStatuses.length) {
2790
+ const message = errorStatuses.map((entry) => entry.error).join(", ");
2791
+ throw new HyperliquidApiError(
2792
+ message || "Hyperliquid rejected the order.",
2793
+ json
2794
+ );
2795
+ }
2796
+ return json;
2797
+ }
2798
+ async function depositToHyperliquidBridge(options) {
2799
+ const { environment, amount, wallet: wallet2 } = options;
2800
+ const parsedAmount = Number(amount);
2801
+ if (!Number.isFinite(parsedAmount) || parsedAmount <= 0) {
2802
+ throw new Error("Deposit amount must be a positive number.");
2803
+ }
2804
+ if (parsedAmount < MIN_DEPOSIT_USDC) {
2805
+ throw new Error(`Minimum deposit is ${MIN_DEPOSIT_USDC} USDC.`);
2806
+ }
2807
+ if (!wallet2.account || !wallet2.walletClient) {
2808
+ throw new Error("Wallet with signing capability is required for deposit.");
2809
+ }
2810
+ const bridgeAddress = getBridgeAddress(environment);
2811
+ const usdcAddress = getUsdcAddress(environment);
2812
+ const amountUnits = parseUnits(amount, 6);
2813
+ if (!wallet2.walletClient || !wallet2.publicClient) {
2814
+ throw new Error(
2815
+ "Wallet client and public client are required for deposit."
2816
+ );
2817
+ }
2818
+ const walletClient = wallet2.walletClient;
2819
+ const publicClient = wallet2.publicClient;
2820
+ const data = encodeFunctionData({
2821
+ abi: erc20Abi,
2822
+ functionName: "transfer",
2823
+ args: [bridgeAddress, amountUnits]
2824
+ });
2825
+ const txHash = await walletClient.sendTransaction({
2826
+ account: wallet2.account,
2827
+ to: usdcAddress,
2828
+ data
2829
+ });
2830
+ await publicClient.waitForTransactionReceipt({ hash: txHash });
2831
+ return {
2832
+ txHash,
2833
+ amount: parsedAmount,
2834
+ amountUnits: amountUnits.toString(),
2835
+ environment,
2836
+ bridgeAddress
2837
+ };
2838
+ }
2839
+ async function withdrawFromHyperliquid(options) {
2840
+ const { environment, amount, destination, wallet: wallet2 } = options;
2841
+ const parsedAmount = Number(amount);
2842
+ if (!Number.isFinite(parsedAmount) || parsedAmount <= 0) {
2843
+ throw new Error("Withdraw amount must be a positive number.");
2844
+ }
2845
+ if (!wallet2.account || !wallet2.walletClient || !wallet2.publicClient) {
2846
+ throw new Error(
2847
+ "Wallet client and public client are required for withdraw."
2848
+ );
2849
+ }
2850
+ const signatureChainId = getSignatureChainId(environment);
2851
+ const hyperliquidChain = HL_CHAIN_LABEL[environment];
2852
+ const domain = {
2853
+ name: "HyperliquidSignTransaction",
2854
+ version: "1",
2855
+ chainId: Number.parseInt(signatureChainId, 16),
2856
+ verifyingContract: ZERO_ADDRESS
2857
+ };
2858
+ const time = BigInt(Date.now());
2859
+ const nonce = Number(time);
2860
+ const normalizedDestination = normalizeAddress(destination);
2861
+ const message = {
2862
+ hyperliquidChain,
2863
+ destination: normalizedDestination,
2864
+ amount: parsedAmount.toString(),
2865
+ time
2866
+ };
2867
+ const types = {
2868
+ "HyperliquidTransaction:Withdraw": [
2869
+ { name: "hyperliquidChain", type: "string" },
2870
+ { name: "destination", type: "string" },
2871
+ { name: "amount", type: "string" },
2872
+ { name: "time", type: "uint64" }
2873
+ ]
2874
+ };
2875
+ const signatureHex = await wallet2.walletClient.signTypedData({
2876
+ account: wallet2.account,
2877
+ domain,
2878
+ types,
2879
+ primaryType: "HyperliquidTransaction:Withdraw",
2880
+ message
2881
+ });
2882
+ const signature = splitSignature(signatureHex);
2883
+ const payload = {
2884
+ action: {
2885
+ type: "withdraw3",
2886
+ signatureChainId,
2887
+ hyperliquidChain,
2888
+ destination: normalizedDestination,
2889
+ amount: parsedAmount.toString(),
2890
+ time: nonce
2891
+ },
2892
+ nonce,
2893
+ signature
2894
+ };
2895
+ const endpoint = `${HL_ENDPOINT[environment]}/exchange`;
2896
+ const response = await fetch(endpoint, {
2897
+ method: "POST",
2898
+ headers: { "content-type": "application/json" },
2899
+ body: JSON.stringify(payload)
2900
+ });
2901
+ const json = await response.json().catch(() => null);
2902
+ if (!response.ok || json?.status !== "ok") {
2903
+ throw new Error(
2904
+ `Hyperliquid withdraw failed: ${json?.response ?? json?.error ?? response.statusText}`
2905
+ );
2906
+ }
2907
+ return {
2908
+ amount: parsedAmount,
2909
+ destination: normalizedDestination,
2910
+ environment,
2911
+ nonce,
2912
+ status: json.status ?? "ok"
2913
+ };
2914
+ }
2915
+ async function fetchHyperliquidClearinghouseState(params) {
2916
+ const { environment, walletAddress } = params;
2917
+ const response = await fetch(`${HL_ENDPOINT[environment]}/info`, {
2918
+ method: "POST",
2919
+ headers: { "content-type": "application/json" },
2920
+ body: JSON.stringify({ type: "clearinghouseState", user: walletAddress })
2921
+ });
2922
+ const data = await response.json().catch(() => null);
2923
+ return {
2924
+ ok: response.ok,
2925
+ data
2926
+ };
2927
+ }
2928
+ async function approveHyperliquidBuilderFee(options) {
2929
+ const { environment, wallet: wallet2, nonce, signatureChainId } = options;
2930
+ if (!wallet2?.account || !wallet2.walletClient) {
2931
+ throw new Error(
2932
+ "Hyperliquid builder approval requires a wallet with signing capabilities."
2933
+ );
2934
+ }
2935
+ const maxFeeRateValue = BUILDER_CODE.fee / 1e3;
2936
+ const formattedPercent = `${maxFeeRateValue}%`;
2937
+ const normalizedBuilder = normalizeAddress(BUILDER_CODE.address);
2938
+ const inferredEnvironment = environment ?? "mainnet";
2939
+ const resolvedBaseUrl = API_BASES[inferredEnvironment];
2940
+ const maxFeeRate = formattedPercent;
2941
+ const effectiveNonce = nonce ?? Date.now();
2942
+ const signatureNonce = BigInt(effectiveNonce);
2943
+ const signatureChainHex = signatureChainId ?? getSignatureChainId(inferredEnvironment);
2944
+ const approvalSignature = await signApproveBuilderFee({
2945
+ wallet: wallet2,
2946
+ maxFeeRate,
2947
+ nonce: signatureNonce,
2948
+ signatureChainId: signatureChainHex,
2949
+ isTestnet: inferredEnvironment === "testnet"
2950
+ });
2951
+ const action = {
2952
+ type: "approveBuilderFee",
2953
+ maxFeeRate,
2954
+ builder: normalizedBuilder,
2955
+ hyperliquidChain: HL_CHAIN_LABEL[inferredEnvironment],
2956
+ signatureChainId: signatureChainHex,
2957
+ nonce: effectiveNonce
2958
+ };
2959
+ const payload = {
2960
+ action,
2961
+ nonce: effectiveNonce,
2962
+ signature: approvalSignature
2963
+ };
2964
+ const response = await fetch(`${resolvedBaseUrl}/exchange`, {
2965
+ method: "POST",
2966
+ headers: { "content-type": "application/json" },
2967
+ body: JSON.stringify(payload)
2968
+ });
2969
+ const rawText = await response.text().catch(() => null);
2970
+ let parsed = null;
2971
+ if (rawText && rawText.length) {
2972
+ try {
2973
+ parsed = JSON.parse(rawText);
2974
+ } catch {
2975
+ parsed = rawText;
2976
+ }
2977
+ }
2978
+ const json = parsed && typeof parsed === "object" && "status" in parsed ? parsed : null;
2979
+ if (!response.ok || !json) {
2980
+ const detail = parsed?.error ?? parsed?.message ?? (typeof parsed === "string" ? parsed : rawText);
2981
+ const suffix = detail ? ` Detail: ${detail}` : "";
2982
+ throw new HyperliquidApiError(
2983
+ `Failed to submit builder approval.${suffix}`,
2984
+ parsed ?? rawText ?? { status: response.status }
2985
+ );
2986
+ }
2987
+ if (json.status !== "ok") {
2988
+ const detail = parsed?.error ?? rawText;
2989
+ throw new HyperliquidApiError(
2990
+ detail ? `Hyperliquid builder approval returned an error: ${detail}` : "Hyperliquid builder approval returned an error.",
2991
+ json
2992
+ );
2993
+ }
2994
+ return json;
2995
+ }
2996
+ async function getHyperliquidMaxBuilderFee(params) {
2997
+ const { environment, user } = params;
2998
+ const resolvedBaseUrl = API_BASES[environment];
2999
+ const response = await fetch(`${resolvedBaseUrl}/info`, {
3000
+ method: "POST",
3001
+ headers: { "content-type": "application/json" },
3002
+ body: JSON.stringify({
3003
+ type: "maxBuilderFee",
3004
+ user: normalizeAddress(user),
3005
+ builder: BUILDER_CODE.address
3006
+ })
3007
+ });
3008
+ const data = await response.json().catch(() => null);
3009
+ if (!response.ok) {
3010
+ throw new HyperliquidApiError(
3011
+ "Failed to query max builder fee.",
3012
+ data ?? { status: response.status }
3013
+ );
3014
+ }
3015
+ return data;
3016
+ }
3017
+ async function recordHyperliquidTermsAcceptance(input) {
3018
+ const { environment, walletAddress, storeOptions } = input;
3019
+ return store(
3020
+ {
3021
+ source: "hyperliquid",
3022
+ ref: `${environment}-terms-${Date.now()}`,
3023
+ status: "info",
3024
+ walletAddress,
3025
+ action: "terms",
3026
+ metadata: {
3027
+ environment,
3028
+ note: "Hyperliquid does not expose a terms endpoint; this records local acknowledgement only."
3029
+ }
3030
+ },
3031
+ storeOptions
3032
+ );
3033
+ }
3034
+ async function recordHyperliquidBuilderApproval(input) {
3035
+ const { environment, walletAddress, storeOptions } = input;
3036
+ const maxFeeRate = `${BUILDER_CODE.fee / 1e3}%`;
3037
+ return store(
3038
+ {
3039
+ source: "hyperliquid",
3040
+ ref: `${environment}-builder-${Date.now()}`,
3041
+ status: "info",
3042
+ walletAddress,
3043
+ action: "builder-approval",
3044
+ metadata: {
3045
+ environment,
3046
+ builder: BUILDER_CODE.address,
3047
+ maxFeeRate
3048
+ }
3049
+ },
3050
+ storeOptions
3051
+ );
3052
+ }
3053
+ var __hyperliquidInternals = {
3054
+ toApiDecimal,
3055
+ createL1ActionHash,
3056
+ splitSignature
3057
+ };
3058
+
1566
3059
  // src/ai/errors.ts
1567
3060
  var AIError = class extends Error {
1568
3061
  constructor(message, options) {
@@ -1607,7 +3100,7 @@ function assertFetchAvailable(fetchImplementation) {
1607
3100
  );
1608
3101
  }
1609
3102
  }
1610
- function resolveConfig(config = {}) {
3103
+ function resolveConfig2(config = {}) {
1611
3104
  const fetchImplementation = config.fetchImplementation ?? globalThis.fetch;
1612
3105
  assertFetchAvailable(fetchImplementation);
1613
3106
  const resolved = {
@@ -1848,7 +3341,7 @@ function extractTextPart(part, options) {
1848
3341
  // src/ai/client.ts
1849
3342
  var CHAT_COMPLETIONS_PATH = "/v1/chat/completions";
1850
3343
  function createAIClient(config = {}) {
1851
- const resolved = resolveConfig(config);
3344
+ const resolved = resolveConfig2(config);
1852
3345
  return {
1853
3346
  get config() {
1854
3347
  return resolved;
@@ -1863,7 +3356,7 @@ function createAIClient(config = {}) {
1863
3356
  };
1864
3357
  }
1865
3358
  async function generateText(options, clientConfig = {}) {
1866
- const resolved = resolveConfig(clientConfig);
3359
+ const resolved = resolveConfig2(clientConfig);
1867
3360
  const model = normalizeModelName(options.model ?? resolved.defaultModel);
1868
3361
  const payload = buildRequestPayload(options, model, {
1869
3362
  allowTools: isToolCallingSupported(model)
@@ -1929,7 +3422,7 @@ async function generateText(options, clientConfig = {}) {
1929
3422
  return result;
1930
3423
  }
1931
3424
  async function streamText(options, clientConfig = {}) {
1932
- const resolved = resolveConfig(clientConfig);
3425
+ const resolved = resolveConfig2(clientConfig);
1933
3426
  const model = normalizeModelName(options.model ?? resolved.defaultModel);
1934
3427
  const streamExtras = buildStreamMetadataExtras(options);
1935
3428
  const payload = buildRequestPayload(
@@ -2318,73 +3811,6 @@ function toAbortError(reason) {
2318
3811
  }
2319
3812
  return new AIAbortError(String(reason ?? "AI request aborted"));
2320
3813
  }
2321
-
2322
- // src/store/index.ts
2323
- var StoreError = class extends Error {
2324
- constructor(message, status, causeData) {
2325
- super(message);
2326
- this.status = status;
2327
- this.causeData = causeData;
2328
- this.name = "StoreError";
2329
- }
2330
- };
2331
- function resolveConfig2(options) {
2332
- const baseUrl = options?.baseUrl ?? process.env.BASE_URL;
2333
- const apiKey = options?.apiKey ?? process.env.OPENPOND_API_KEY;
2334
- if (!baseUrl) {
2335
- throw new StoreError("BASE_URL is required to store activity events");
2336
- }
2337
- if (!apiKey) {
2338
- throw new StoreError(
2339
- "OPENPOND_API_KEY is required to store activity events"
2340
- );
2341
- }
2342
- const normalizedBaseUrl = baseUrl.replace(/\/$/, "");
2343
- const fetchFn = options?.fetchFn ?? globalThis.fetch;
2344
- if (!fetchFn) {
2345
- throw new StoreError("Fetch is not available in this environment");
2346
- }
2347
- return { baseUrl: normalizedBaseUrl, apiKey, fetchFn };
2348
- }
2349
- async function store(input, options) {
2350
- const { baseUrl, apiKey, fetchFn } = resolveConfig2(options);
2351
- const url = `${baseUrl}/apps/positions/tx`;
2352
- let response;
2353
- try {
2354
- response = await fetchFn(url, {
2355
- method: "POST",
2356
- headers: {
2357
- "content-type": "application/json",
2358
- "openpond-api-key": apiKey
2359
- },
2360
- body: JSON.stringify(input)
2361
- });
2362
- } catch (error) {
2363
- throw new StoreError("Failed to reach store endpoint", void 0, error);
2364
- }
2365
- if (!response.ok) {
2366
- let body;
2367
- try {
2368
- body = await response.json();
2369
- } catch {
2370
- body = await response.text().catch(() => void 0);
2371
- }
2372
- throw new StoreError(
2373
- `Store request failed with status ${response.status}`,
2374
- response.status,
2375
- body
2376
- );
2377
- }
2378
- try {
2379
- const data = await response.json();
2380
- return {
2381
- id: data.id ?? "",
2382
- status: data.status ?? null
2383
- };
2384
- } catch {
2385
- return { id: "", status: null };
2386
- }
2387
- }
2388
3814
  var METADATA_SPEC_VERSION = "1.1.0";
2389
3815
  var McpAnnotationsSchema = z.object({
2390
3816
  title: z.string().optional(),
@@ -2526,7 +3952,7 @@ async function transpileWithEsbuild(options) {
2526
3952
  format: options.format,
2527
3953
  platform: "node",
2528
3954
  target: "node20",
2529
- logLevel: "warning",
3955
+ logLevel: options.logLevel ?? "warning",
2530
3956
  sourcesContent: false,
2531
3957
  sourcemap: false,
2532
3958
  loader: {
@@ -2540,13 +3966,16 @@ async function transpileWithEsbuild(options) {
2540
3966
  ".cjs": "js",
2541
3967
  ".json": "json"
2542
3968
  },
2543
- metafile: false,
3969
+ metafile: options.metafile ?? false,
2544
3970
  allowOverwrite: true,
2545
3971
  absWorkingDir: projectRoot
2546
3972
  };
2547
3973
  if (options.external && options.external.length > 0) {
2548
3974
  buildOptions.external = options.external;
2549
3975
  }
3976
+ if (options.outBase) {
3977
+ buildOptions.outbase = options.outBase;
3978
+ }
2550
3979
  if (!buildOptions.bundle) {
2551
3980
  buildOptions.packages = "external";
2552
3981
  }
@@ -2928,11 +4357,8 @@ async function loadAndValidateTools(toolsDir, options = {}) {
2928
4357
  throw new Error(`${file}: export exactly one of GET or POST`);
2929
4358
  }
2930
4359
  let normalizedSchedule = null;
2931
- if (hasGET) {
2932
- const schedule = toolModule?.profile?.schedule;
2933
- if (!schedule || typeof schedule?.cron !== "string" || schedule.cron.trim().length === 0) {
2934
- throw new Error(`${file}: GET tools require profile.schedule { cron }`);
2935
- }
4360
+ const schedule = toolModule?.profile?.schedule;
4361
+ if (hasGET && schedule && typeof schedule.cron === "string" && schedule.cron.trim().length > 0) {
2936
4362
  normalizedSchedule = normalizeScheduleExpression(schedule.cron, file);
2937
4363
  if (typeof schedule.enabled === "boolean") {
2938
4364
  normalizedSchedule.authoredEnabled = schedule.enabled;
@@ -2942,6 +4368,9 @@ async function loadAndValidateTools(toolsDir, options = {}) {
2942
4368
  if (!schema) {
2943
4369
  throw new Error(`${file}: POST tools must export a Zod schema as 'schema'`);
2944
4370
  }
4371
+ if (schedule && typeof schedule.cron === "string") {
4372
+ throw new Error(`${file}: POST tools must not define profile.schedule; use GET + cron for scheduled tasks.`);
4373
+ }
2945
4374
  }
2946
4375
  const httpHandlers = [...httpHandlersRaw];
2947
4376
  if (httpHandlers.length === 0) {
@@ -3227,6 +4656,6 @@ function timestamp() {
3227
4656
  return (/* @__PURE__ */ new Date()).toISOString().replace("T", " ").slice(0, 19);
3228
4657
  }
3229
4658
 
3230
- export { AIAbortError, AIError, AIFetchError, AIResponseError, DEFAULT_BASE_URL, DEFAULT_CHAIN, DEFAULT_FACILITATOR, DEFAULT_MODEL, DEFAULT_TIMEOUT_MS, DEFAULT_TOKENS, HTTP_METHODS2 as HTTP_METHODS, PAYMENT_HEADERS, SUPPORTED_CURRENCIES, StoreError, WEBSEARCH_TOOL_DEFINITION, WEBSEARCH_TOOL_NAME, X402BrowserClient, X402Client, X402PaymentRequiredError, chains, createAIClient, createDevServer, createMcpAdapter, createStdioServer, defineX402Payment, ensureTextContent, flattenMessageContent, generateMetadata, generateMetadataCommand, generateText, getModelConfig, getRpcUrl, getX402PaymentContext, isStreamingSupported, isToolCallingSupported, listModels, loadAndValidateTools, normalizeModelName, payX402, payX402WithWallet, registry, requireX402Payment, resolveConfig, resolveRuntimePath, resolveToolset, responseToToolResponse, store, streamText, tokens, validateCommand, wallet, walletToolkit, withX402Payment };
4659
+ export { AIAbortError, AIError, AIFetchError, AIResponseError, DEFAULT_BASE_URL, DEFAULT_CHAIN, DEFAULT_FACILITATOR, DEFAULT_MODEL, DEFAULT_TIMEOUT_MS, DEFAULT_TOKENS, HTTP_METHODS2 as HTTP_METHODS, HyperliquidApiError, HyperliquidBuilderApprovalError, HyperliquidExchangeClient, HyperliquidGuardError, HyperliquidInfoClient, HyperliquidTermsError, PAYMENT_HEADERS, SUPPORTED_CURRENCIES, StoreError, WEBSEARCH_TOOL_DEFINITION, WEBSEARCH_TOOL_NAME, X402BrowserClient, X402Client, X402PaymentRequiredError, __hyperliquidInternals, approveHyperliquidBuilderFee, batchModifyHyperliquidOrders, cancelAllHyperliquidOrders, cancelHyperliquidOrders, cancelHyperliquidOrdersByCloid, cancelHyperliquidTwapOrder, chains, createAIClient, createDevServer, createHyperliquidSubAccount, createMcpAdapter, createMonotonicNonceFactory, createStdioServer, defineX402Payment, depositToHyperliquidBridge, ensureTextContent, fetchHyperliquidAssetCtxs, fetchHyperliquidClearinghouseState, fetchHyperliquidFrontendOpenOrders, fetchHyperliquidHistoricalOrders, fetchHyperliquidMeta, fetchHyperliquidMetaAndAssetCtxs, fetchHyperliquidOpenOrders, fetchHyperliquidOrderStatus, fetchHyperliquidPreTransferCheck, fetchHyperliquidSpotAssetCtxs, fetchHyperliquidSpotClearinghouseState, fetchHyperliquidSpotMeta, fetchHyperliquidSpotMetaAndAssetCtxs, fetchHyperliquidUserFills, fetchHyperliquidUserFillsByTime, fetchHyperliquidUserRateLimit, flattenMessageContent, generateMetadata, generateMetadataCommand, generateText, getHyperliquidMaxBuilderFee, getModelConfig, getRpcUrl, getX402PaymentContext, isStreamingSupported, isToolCallingSupported, listModels, loadAndValidateTools, modifyHyperliquidOrder, normalizeModelName, payX402, payX402WithWallet, placeHyperliquidOrder, placeHyperliquidTwapOrder, recordHyperliquidBuilderApproval, recordHyperliquidTermsAcceptance, registry, requireX402Payment, reserveHyperliquidRequestWeight, resolveConfig2 as resolveConfig, resolveRuntimePath, resolveToolset, responseToToolResponse, retrieve, scheduleHyperliquidCancel, sendHyperliquidSpot, store, streamText, tokens, transferHyperliquidSubAccount, updateHyperliquidIsolatedMargin, updateHyperliquidLeverage, validateCommand, wallet, walletToolkit, withX402Payment, withdrawFromHyperliquid };
3231
4660
  //# sourceMappingURL=index.js.map
3232
4661
  //# sourceMappingURL=index.js.map