@vultisig/cli 0.22.4 → 0.22.5

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 (3) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/dist/index.js +241 -1886
  3. package/package.json +3 -3
package/dist/index.js CHANGED
@@ -1449,980 +1449,6 @@ var init_formatUnits = __esm({
1449
1449
  }
1450
1450
  });
1451
1451
 
1452
- // ../../packages/lib/utils/dist/promise/isPromise.js
1453
- function isPromise(value) {
1454
- return !!value && typeof value.then === "function";
1455
- }
1456
- var init_isPromise = __esm({
1457
- "../../packages/lib/utils/dist/promise/isPromise.js"() {
1458
- }
1459
- });
1460
-
1461
- // ../../packages/lib/utils/dist/attempt.js
1462
- function attempt(input) {
1463
- if (typeof input === "function") {
1464
- try {
1465
- const result = input();
1466
- if (isPromise(result)) {
1467
- return attempt(result);
1468
- }
1469
- return { data: result };
1470
- } catch (error2) {
1471
- return { error: error2 };
1472
- }
1473
- } else {
1474
- return input.then((data) => ({ data }), (error2) => ({ error: error2 }));
1475
- }
1476
- }
1477
- function withFallback(result, fallback) {
1478
- if (isPromise(result)) {
1479
- return result.then((res) => {
1480
- if ("error" in res) {
1481
- return fallback;
1482
- }
1483
- return res.data;
1484
- });
1485
- }
1486
- if ("error" in result) {
1487
- return fallback;
1488
- }
1489
- return result.data;
1490
- }
1491
- var init_attempt = __esm({
1492
- "../../packages/lib/utils/dist/attempt.js"() {
1493
- init_isPromise();
1494
- }
1495
- });
1496
-
1497
- // ../../packages/lib/utils/dist/error/extractErrorMsg/index.js
1498
- var extractErrorMsg;
1499
- var init_extractErrorMsg = __esm({
1500
- "../../packages/lib/utils/dist/error/extractErrorMsg/index.js"() {
1501
- init_attempt();
1502
- extractErrorMsg = (err) => {
1503
- if (typeof err === "string") {
1504
- return err;
1505
- }
1506
- if (typeof err === "number" || typeof err === "boolean") {
1507
- return String(err);
1508
- }
1509
- if (typeof err === "object" && err && "message" in err) {
1510
- return extractErrorMsg(err.message);
1511
- }
1512
- return withFallback(attempt(() => JSON.stringify(err)), "Unknown Error");
1513
- };
1514
- }
1515
- });
1516
-
1517
- // ../../packages/lib/utils/dist/array/isEmpty/index.js
1518
- var isEmpty;
1519
- var init_isEmpty = __esm({
1520
- "../../packages/lib/utils/dist/array/isEmpty/index.js"() {
1521
- isEmpty = (items) => items.length === 0;
1522
- }
1523
- });
1524
-
1525
- // ../../packages/lib/utils/dist/promise/asyncFallbackChain/index.js
1526
- var asyncFallbackChain;
1527
- var init_asyncFallbackChain = __esm({
1528
- "../../packages/lib/utils/dist/promise/asyncFallbackChain/index.js"() {
1529
- init_isEmpty();
1530
- asyncFallbackChain = async (...functions) => {
1531
- if (isEmpty(functions)) {
1532
- throw new Error("No functions provided");
1533
- }
1534
- try {
1535
- const result = await functions[0]();
1536
- return result;
1537
- } catch (error2) {
1538
- if (functions.length <= 1) {
1539
- throw error2;
1540
- }
1541
- return asyncFallbackChain(...functions.slice(1));
1542
- }
1543
- };
1544
- }
1545
- });
1546
-
1547
- // ../../packages/lib/utils/dist/fetch/HttpResponseError.js
1548
- var HttpResponseError;
1549
- var init_HttpResponseError = __esm({
1550
- "../../packages/lib/utils/dist/fetch/HttpResponseError.js"() {
1551
- HttpResponseError = class extends Error {
1552
- status;
1553
- statusText;
1554
- url;
1555
- body;
1556
- constructor(opts) {
1557
- super(opts.message);
1558
- this.name = "HttpResponseError";
1559
- this.status = opts.status;
1560
- this.statusText = opts.statusText;
1561
- this.url = opts.url;
1562
- this.body = opts.body;
1563
- }
1564
- };
1565
- }
1566
- });
1567
-
1568
- // ../../packages/lib/utils/dist/fetch/assertFetchResponse.js
1569
- var assertFetchResponse;
1570
- var init_assertFetchResponse = __esm({
1571
- "../../packages/lib/utils/dist/fetch/assertFetchResponse.js"() {
1572
- init_extractErrorMsg();
1573
- init_asyncFallbackChain();
1574
- init_HttpResponseError();
1575
- assertFetchResponse = async (response) => {
1576
- if (!response.ok) {
1577
- const body = await asyncFallbackChain(async () => response.json(), async () => response.text(), async () => `HTTP ${response.status} ${response.statusText || "Error"}: Request failed for ${response.url}`);
1578
- const msg = extractErrorMsg(body);
1579
- throw new HttpResponseError({
1580
- message: msg,
1581
- status: response.status,
1582
- statusText: response.statusText,
1583
- url: response.url,
1584
- body
1585
- });
1586
- }
1587
- };
1588
- }
1589
- });
1590
-
1591
- // ../../packages/lib/utils/dist/record/getRecordKeys/index.js
1592
- var getRecordKeys;
1593
- var init_getRecordKeys = __esm({
1594
- "../../packages/lib/utils/dist/record/getRecordKeys/index.js"() {
1595
- getRecordKeys = (record) => {
1596
- return Object.keys(record);
1597
- };
1598
- }
1599
- });
1600
-
1601
- // ../../packages/lib/utils/dist/record/withoutUndefinedFields.js
1602
- function withoutUndefinedFields(record) {
1603
- const result = {};
1604
- getRecordKeys(record).forEach((key) => {
1605
- const typedKey = key;
1606
- const value = record[typedKey];
1607
- if (value !== void 0) {
1608
- result[typedKey] = value;
1609
- }
1610
- });
1611
- return result;
1612
- }
1613
- var init_withoutUndefinedFields = __esm({
1614
- "../../packages/lib/utils/dist/record/withoutUndefinedFields.js"() {
1615
- init_getRecordKeys();
1616
- }
1617
- });
1618
-
1619
- // ../../packages/lib/utils/dist/query/queryUrl.js
1620
- async function queryUrl(url, options = {}) {
1621
- const { responseType = "json", body, headers, method } = options;
1622
- const response = await fetch(url, withoutUndefinedFields({
1623
- method: method ?? (body ? "POST" : "GET"),
1624
- headers: withoutUndefinedFields({
1625
- ...headers,
1626
- "Content-Type": body ? "application/json" : void 0
1627
- }),
1628
- body: processBody(body)
1629
- }));
1630
- await assertFetchResponse(response);
1631
- if (responseType !== "none") {
1632
- return response[responseType]();
1633
- }
1634
- }
1635
- var processBody;
1636
- var init_queryUrl = __esm({
1637
- "../../packages/lib/utils/dist/query/queryUrl.js"() {
1638
- init_assertFetchResponse();
1639
- init_withoutUndefinedFields();
1640
- processBody = (body) => {
1641
- if (body === void 0) {
1642
- return void 0;
1643
- }
1644
- if (typeof body === "string") {
1645
- return body;
1646
- }
1647
- return JSON.stringify(body);
1648
- };
1649
- }
1650
- });
1651
-
1652
- // ../../packages/core/chain/dist/chains/cosmos/thor/lp/pools.js
1653
- var thorchainMidgardBaseUrl, POOL_ID_RE, assertValidPoolId, isValidPoolId, normalizePool, getThorchainPools;
1654
- var init_pools = __esm({
1655
- "../../packages/core/chain/dist/chains/cosmos/thor/lp/pools.js"() {
1656
- init_queryUrl();
1657
- thorchainMidgardBaseUrl = "https://gateway.liquify.com/chain/thorchain_midgard";
1658
- POOL_ID_RE = /^[A-Z0-9]+\.[A-Z0-9]+(-[A-Z0-9]+)?$/;
1659
- assertValidPoolId = (pool) => {
1660
- if (typeof pool !== "string" || pool.length === 0) {
1661
- throw new Error(`assertValidPoolId: pool id must be a non-empty string, got ${typeof pool} ${pool === "" ? '""' : ""}`);
1662
- }
1663
- if (!POOL_ID_RE.test(pool)) {
1664
- throw new Error(`assertValidPoolId: ${JSON.stringify(pool)} is not a valid THORChain pool id. Expected uppercase CHAIN.ASSET (e.g. "BTC.BTC") or CHAIN.ASSET-CONTRACT (e.g. "ETH.USDC-0XA0B86991C6218B36C1D19D4A2E9EB0CE3606EB48").`);
1665
- }
1666
- };
1667
- isValidPoolId = (pool) => {
1668
- if (typeof pool !== "string" || pool.length === 0)
1669
- return false;
1670
- return POOL_ID_RE.test(pool);
1671
- };
1672
- normalizePool = (raw) => ({
1673
- asset: raw.asset ?? "",
1674
- status: raw.status ?? "",
1675
- assetDepth: raw.assetDepth ?? "0",
1676
- runeDepth: raw.runeDepth ?? "0",
1677
- liquidityUnits: raw.liquidityUnits ?? "0",
1678
- volume24h: raw.volume24h ?? "0",
1679
- annualPercentageRate: raw.annualPercentageRate ?? "0"
1680
- });
1681
- getThorchainPools = async (options = {}) => {
1682
- const status = options.status === void 0 ? "available" : options.status;
1683
- const url = status === null ? `${thorchainMidgardBaseUrl}/v2/pools` : `${thorchainMidgardBaseUrl}/v2/pools?status=${encodeURIComponent(status)}`;
1684
- const raw = await queryUrl(url);
1685
- if (!Array.isArray(raw)) {
1686
- throw new Error(`getThorchainPools: expected an array from ${url}, got ${typeof raw}`);
1687
- }
1688
- return raw.map(normalizePool);
1689
- };
1690
- }
1691
- });
1692
-
1693
- // ../../packages/core/chain/dist/chains/cosmos/thor/lp/memo.js
1694
- var assertMemoSegmentSafe, addLpMemo, removeLpMemo;
1695
- var init_memo = __esm({
1696
- "../../packages/core/chain/dist/chains/cosmos/thor/lp/memo.js"() {
1697
- init_pools();
1698
- assertMemoSegmentSafe = (value, fieldName) => {
1699
- if (typeof value !== "string") {
1700
- throw new Error(`${fieldName} must be a string, got ${typeof value}`);
1701
- }
1702
- if (value.includes(":")) {
1703
- throw new Error(`${fieldName} must not contain \`:\` (would inject extra memo segments), got ${JSON.stringify(value)}`);
1704
- }
1705
- if (/\s/.test(value)) {
1706
- throw new Error(`${fieldName} must not contain whitespace, got ${JSON.stringify(value)}`);
1707
- }
1708
- };
1709
- addLpMemo = ({ pool, pairedAddress }) => {
1710
- assertValidPoolId(pool);
1711
- if (pairedAddress && pairedAddress.length > 0) {
1712
- assertMemoSegmentSafe(pairedAddress, "pairedAddress");
1713
- return `+:${pool}:${pairedAddress}`;
1714
- }
1715
- return `+:${pool}`;
1716
- };
1717
- removeLpMemo = ({ pool, basisPoints, withdrawToAsset }) => {
1718
- assertValidPoolId(pool);
1719
- if (!Number.isInteger(basisPoints) || basisPoints < 1 || basisPoints > 1e4) {
1720
- throw new Error(`removeLpMemo: basisPoints must be an integer in [1, 10000], got ${basisPoints}`);
1721
- }
1722
- if (withdrawToAsset && withdrawToAsset.length > 0) {
1723
- assertMemoSegmentSafe(withdrawToAsset, "withdrawToAsset");
1724
- return `-:${pool}:${basisPoints}:${withdrawToAsset}`;
1725
- }
1726
- return `-:${pool}:${basisPoints}`;
1727
- };
1728
- }
1729
- });
1730
-
1731
- // ../../packages/core/chain/dist/chains/cosmos/thor/lp/payload.js
1732
- var LP_REMOVE_DUST_RUNE_BASE_UNITS, isPositiveBaseUnitString, buildThorchainLpAddPayload, buildThorchainLpRemovePayload;
1733
- var init_payload = __esm({
1734
- "../../packages/core/chain/dist/chains/cosmos/thor/lp/payload.js"() {
1735
- init_memo();
1736
- LP_REMOVE_DUST_RUNE_BASE_UNITS = "2000000";
1737
- isPositiveBaseUnitString = (value) => /^\d+$/.test(value) && BigInt(value) > 0n;
1738
- buildThorchainLpAddPayload = ({ pool, amountRuneBaseUnits, pairedAddress }) => {
1739
- if (!isPositiveBaseUnitString(amountRuneBaseUnits)) {
1740
- throw new Error(`buildThorchainLpAddPayload: amountRuneBaseUnits must be a positive integer string, got ${amountRuneBaseUnits}`);
1741
- }
1742
- const memo = addLpMemo({ pool, pairedAddress });
1743
- return {
1744
- kind: "thorchain_lp_add",
1745
- chain: "THORChain",
1746
- denom: "rune",
1747
- amount: amountRuneBaseUnits,
1748
- memo,
1749
- pool,
1750
- ...pairedAddress ? { pairedAddress } : {}
1751
- };
1752
- };
1753
- buildThorchainLpRemovePayload = ({ pool, basisPoints, withdrawToAsset }) => {
1754
- if (!Number.isInteger(basisPoints) || basisPoints < 1 || basisPoints > 1e4) {
1755
- throw new Error(`buildThorchainLpRemovePayload: basisPoints must be an integer in [1, 10000], got ${basisPoints}`);
1756
- }
1757
- const memo = removeLpMemo({ pool, basisPoints, withdrawToAsset });
1758
- return {
1759
- kind: "thorchain_lp_remove",
1760
- chain: "THORChain",
1761
- denom: "rune",
1762
- amount: LP_REMOVE_DUST_RUNE_BASE_UNITS,
1763
- memo,
1764
- pool,
1765
- basisPoints,
1766
- ...withdrawToAsset ? { withdrawToAsset } : {}
1767
- };
1768
- };
1769
- }
1770
- });
1771
-
1772
- // ../../packages/core/chain/dist/Chain.js
1773
- var EthereumL2Chain, EvmChain, UtxoChain, cosmosChainsByKind, IbcEnabledCosmosChain, VaultBasedCosmosChain, CosmosChain, OtherChain, Chain9, UtxoBasedChain, defaultChains;
1774
- var init_Chain = __esm({
1775
- "../../packages/core/chain/dist/Chain.js"() {
1776
- EthereumL2Chain = {
1777
- Arbitrum: "Arbitrum",
1778
- Base: "Base",
1779
- Blast: "Blast",
1780
- Optimism: "Optimism",
1781
- Zksync: "Zksync",
1782
- Mantle: "Mantle"
1783
- };
1784
- EvmChain = {
1785
- ...EthereumL2Chain,
1786
- Avalanche: "Avalanche",
1787
- CronosChain: "CronosChain",
1788
- BSC: "BSC",
1789
- Ethereum: "Ethereum",
1790
- Polygon: "Polygon",
1791
- Hyperliquid: "Hyperliquid",
1792
- Sei: "Sei"
1793
- };
1794
- (function(UtxoChain2) {
1795
- UtxoChain2["Bitcoin"] = "Bitcoin";
1796
- UtxoChain2["BitcoinCash"] = "Bitcoin-Cash";
1797
- UtxoChain2["Litecoin"] = "Litecoin";
1798
- UtxoChain2["Dogecoin"] = "Dogecoin";
1799
- UtxoChain2["Dash"] = "Dash";
1800
- UtxoChain2["Zcash"] = "Zcash";
1801
- })(UtxoChain || (UtxoChain = {}));
1802
- cosmosChainsByKind = {
1803
- ibcEnabled: {
1804
- Cosmos: "Cosmos",
1805
- Osmosis: "Osmosis",
1806
- Dydx: "Dydx",
1807
- Kujira: "Kujira",
1808
- Terra: "Terra",
1809
- TerraClassic: "TerraClassic",
1810
- Noble: "Noble",
1811
- Akash: "Akash"
1812
- },
1813
- vaultBased: {
1814
- THORChain: "THORChain",
1815
- MayaChain: "MayaChain"
1816
- }
1817
- };
1818
- IbcEnabledCosmosChain = cosmosChainsByKind.ibcEnabled;
1819
- VaultBasedCosmosChain = cosmosChainsByKind.vaultBased;
1820
- CosmosChain = {
1821
- ...IbcEnabledCosmosChain,
1822
- ...VaultBasedCosmosChain
1823
- };
1824
- (function(OtherChain2) {
1825
- OtherChain2["Sui"] = "Sui";
1826
- OtherChain2["Solana"] = "Solana";
1827
- OtherChain2["Polkadot"] = "Polkadot";
1828
- OtherChain2["Bittensor"] = "Bittensor";
1829
- OtherChain2["Ton"] = "Ton";
1830
- OtherChain2["Ripple"] = "Ripple";
1831
- OtherChain2["Tron"] = "Tron";
1832
- OtherChain2["Cardano"] = "Cardano";
1833
- OtherChain2["QBTC"] = "QBTC";
1834
- })(OtherChain || (OtherChain = {}));
1835
- Chain9 = {
1836
- ...EvmChain,
1837
- ...UtxoChain,
1838
- ...CosmosChain,
1839
- ...OtherChain
1840
- };
1841
- UtxoBasedChain = [
1842
- ...Object.values(UtxoChain),
1843
- OtherChain.Cardano
1844
- ];
1845
- defaultChains = [
1846
- Chain9.Bitcoin,
1847
- Chain9.Ethereum,
1848
- Chain9.THORChain,
1849
- Chain9.Solana,
1850
- Chain9.BSC
1851
- ];
1852
- }
1853
- });
1854
-
1855
- // ../../packages/core/chain/dist/chains/cosmos/cosmosRpcUrl.js
1856
- var cosmosRpcUrl;
1857
- var init_cosmosRpcUrl = __esm({
1858
- "../../packages/core/chain/dist/chains/cosmos/cosmosRpcUrl.js"() {
1859
- cosmosRpcUrl = {
1860
- Cosmos: "https://cosmos-rest.publicnode.com",
1861
- Osmosis: "https://osmosis-rest.publicnode.com",
1862
- Dydx: "https://dydx-rest.publicnode.com",
1863
- Kujira: "https://kujira-rest.publicnode.com",
1864
- Terra: "https://terra-lcd.publicnode.com",
1865
- TerraClassic: "https://terra-classic-lcd.publicnode.com",
1866
- Noble: "https://noble-api.polkachu.com",
1867
- THORChain: "https://gateway.liquify.com/chain/thorchain_api",
1868
- MayaChain: "https://mayanode.mayachain.info",
1869
- Akash: "https://akash-rest.publicnode.com"
1870
- };
1871
- }
1872
- });
1873
-
1874
- // ../../packages/core/chain/dist/chains/cosmos/thor/lp/memberPool.js
1875
- var isNonZeroBaseUnit, normalizeMemberPool;
1876
- var init_memberPool = __esm({
1877
- "../../packages/core/chain/dist/chains/cosmos/thor/lp/memberPool.js"() {
1878
- isNonZeroBaseUnit = (value) => {
1879
- if (!value)
1880
- return false;
1881
- try {
1882
- return BigInt(value) > 0n;
1883
- } catch {
1884
- return false;
1885
- }
1886
- };
1887
- normalizeMemberPool = (raw) => ({
1888
- pool: raw.pool ?? "",
1889
- liquidityUnits: raw.liquidityUnits ?? "0",
1890
- runeAdded: raw.runeAdded ?? "0",
1891
- assetAdded: raw.assetAdded ?? "0",
1892
- runePending: raw.runePending ?? "0",
1893
- assetPending: raw.assetPending ?? "0",
1894
- runeAddress: raw.runeAddress ?? "",
1895
- assetAddress: raw.assetAddress ?? "",
1896
- dateLastAdded: raw.dateLastAdded ?? "0",
1897
- lastAddHeight: "",
1898
- isPending: isNonZeroBaseUnit(raw.runePending) || isNonZeroBaseUnit(raw.assetPending)
1899
- });
1900
- }
1901
- });
1902
-
1903
- // ../../packages/core/chain/dist/chains/cosmos/thor/lp/position.js
1904
- var isMidgardNotFoundError, getThorchainLpPosition, getThorchainLpPositionFromThornode;
1905
- var init_position = __esm({
1906
- "../../packages/core/chain/dist/chains/cosmos/thor/lp/position.js"() {
1907
- init_Chain();
1908
- init_cosmosRpcUrl();
1909
- init_HttpResponseError();
1910
- init_queryUrl();
1911
- init_memberPool();
1912
- init_pools();
1913
- isMidgardNotFoundError = (err) => err instanceof HttpResponseError && err.status === 404;
1914
- getThorchainLpPosition = async ({ thorAddress, pool }) => {
1915
- assertValidPoolId(pool);
1916
- const url = `${thorchainMidgardBaseUrl}/v2/member/${encodeURIComponent(thorAddress)}`;
1917
- let midgardNotFound = false;
1918
- let raw = {};
1919
- try {
1920
- raw = await queryUrl(url);
1921
- } catch (err) {
1922
- if (isMidgardNotFoundError(err)) {
1923
- midgardNotFound = true;
1924
- } else {
1925
- throw err;
1926
- }
1927
- }
1928
- if (!midgardNotFound) {
1929
- const pools = Array.isArray(raw.pools) ? raw.pools : [];
1930
- const found = pools.find((p) => p.pool === pool);
1931
- if (found)
1932
- return normalizeMemberPool(found);
1933
- }
1934
- return getThorchainLpPositionFromThornode({ thorAddress, pool });
1935
- };
1936
- getThorchainLpPositionFromThornode = async ({ thorAddress, pool }) => {
1937
- assertValidPoolId(pool);
1938
- const url = `${cosmosRpcUrl[Chain9.THORChain]}/thorchain/pool/${encodeURIComponent(pool)}/liquidity_provider/${encodeURIComponent(thorAddress)}`;
1939
- let raw;
1940
- try {
1941
- raw = await queryUrl(url);
1942
- } catch (err) {
1943
- if (err instanceof HttpResponseError && err.status === 404)
1944
- return null;
1945
- throw err;
1946
- }
1947
- const units = raw.units ?? "0";
1948
- const pendingRune = raw.pending_rune ?? "0";
1949
- const pendingAsset = raw.pending_asset ?? "0";
1950
- if (!isNonZeroBaseUnit(units) && !isNonZeroBaseUnit(pendingRune) && !isNonZeroBaseUnit(pendingAsset)) {
1951
- return null;
1952
- }
1953
- return {
1954
- pool: raw.asset ?? pool,
1955
- liquidityUnits: units,
1956
- // Thornode doesn't track historical added amounts — those are a
1957
- // Midgard-only enrichment. Surface them as 0; the caller can still
1958
- // act on units/pending.
1959
- runeAdded: "0",
1960
- assetAdded: "0",
1961
- runePending: pendingRune,
1962
- assetPending: pendingAsset,
1963
- runeAddress: raw.rune_address ?? thorAddress,
1964
- assetAddress: raw.asset_address ?? "",
1965
- // Thornode exposes the last-add block height, not a Unix timestamp.
1966
- // Keep `dateLastAdded` semantically Unix-seconds-or-0 and expose the
1967
- // block height via the dedicated `lastAddHeight` field so lockup
1968
- // checks can use either source.
1969
- dateLastAdded: "0",
1970
- lastAddHeight: typeof raw.last_add_height === "number" ? String(raw.last_add_height) : "",
1971
- isPending: isNonZeroBaseUnit(pendingRune) || isNonZeroBaseUnit(pendingAsset)
1972
- };
1973
- };
1974
- }
1975
- });
1976
-
1977
- // ../../packages/core/chain/dist/chains/cosmos/thor/lp/validation.js
1978
- var extractPoolStatus, poolPauseMimirKey, getThorchainMimir, assertPoolDepositable;
1979
- var init_validation = __esm({
1980
- "../../packages/core/chain/dist/chains/cosmos/thor/lp/validation.js"() {
1981
- init_Chain();
1982
- init_cosmosRpcUrl();
1983
- init_queryUrl();
1984
- init_pools();
1985
- extractPoolStatus = (raw) => {
1986
- if (raw && typeof raw === "object" && "status" in raw) {
1987
- const status = raw.status;
1988
- return typeof status === "string" ? status : void 0;
1989
- }
1990
- return void 0;
1991
- };
1992
- poolPauseMimirKey = (pool) => {
1993
- const dotIdx = pool.indexOf(".");
1994
- if (dotIdx <= 0 || dotIdx >= pool.length - 1) {
1995
- throw new Error(`poolPauseMimirKey: invalid pool id ${pool}`);
1996
- }
1997
- const chain = pool.slice(0, dotIdx);
1998
- const asset = pool.slice(dotIdx + 1);
1999
- return `PAUSELPDEPOSIT-${chain}-${asset}`;
2000
- };
2001
- getThorchainMimir = async () => {
2002
- const url = `${cosmosRpcUrl[Chain9.THORChain]}/thorchain/mimir`;
2003
- const raw = await queryUrl(url);
2004
- if (!raw || typeof raw !== "object") {
2005
- throw new Error(`getThorchainMimir: unexpected response shape from ${url}`);
2006
- }
2007
- const out = {};
2008
- for (const [k, v] of Object.entries(raw)) {
2009
- if (typeof v === "number" && Number.isFinite(v)) {
2010
- out[k] = v;
2011
- } else if (typeof v === "string" && /^-?\d+$/.test(v)) {
2012
- out[k] = Number(v);
2013
- }
2014
- }
2015
- return out;
2016
- };
2017
- assertPoolDepositable = async (pool) => {
2018
- assertValidPoolId(pool);
2019
- const [poolRaw, mimir] = await Promise.all([
2020
- queryUrl(`${cosmosRpcUrl[Chain9.THORChain]}/thorchain/pool/${encodeURIComponent(pool)}`),
2021
- getThorchainMimir()
2022
- ]);
2023
- const status = extractPoolStatus(poolRaw);
2024
- if (status === void 0) {
2025
- throw new Error(`assertPoolDepositable: pool ${pool} response from thornode did not include a string \`status\` field`);
2026
- }
2027
- if (status !== "Available") {
2028
- throw new Error(`assertPoolDepositable: pool ${pool} status is ${status}, must be Available for LP add`);
2029
- }
2030
- const pauseKey = poolPauseMimirKey(pool);
2031
- const pauseValue = mimir[pauseKey];
2032
- if (typeof pauseValue === "number" && pauseValue > 0) {
2033
- throw new Error(`assertPoolDepositable: pool ${pool} has LP deposits paused on-chain via mimir ${pauseKey}=${pauseValue}. THORChain validators have disabled new adds for this pool; any tx would be rejected at handler execution time.`);
2034
- }
2035
- };
2036
- }
2037
- });
2038
-
2039
- // ../../packages/core/chain/dist/chains/cosmos/thor/thorchainLp.js
2040
- var thorchainLpChainCode;
2041
- var init_thorchainLp = __esm({
2042
- "../../packages/core/chain/dist/chains/cosmos/thor/thorchainLp.js"() {
2043
- init_Chain();
2044
- thorchainLpChainCode = {
2045
- [Chain9.Avalanche]: "AVAX",
2046
- [Chain9.Base]: "BASE",
2047
- [Chain9.BitcoinCash]: "BCH",
2048
- [Chain9.BSC]: "BSC",
2049
- [Chain9.Bitcoin]: "BTC",
2050
- [Chain9.Dash]: "DASH",
2051
- [Chain9.Dogecoin]: "DOGE",
2052
- [Chain9.Ethereum]: "ETH",
2053
- [Chain9.Cosmos]: "GAIA",
2054
- [Chain9.Kujira]: "KUJI",
2055
- [Chain9.Litecoin]: "LTC",
2056
- [Chain9.THORChain]: "THOR",
2057
- [Chain9.Tron]: "TRON",
2058
- [Chain9.Ripple]: "XRP",
2059
- [Chain9.Arbitrum]: "ARB",
2060
- [Chain9.Zcash]: "ZEC"
2061
- };
2062
- }
2063
- });
2064
-
2065
- // ../../packages/core/chain/dist/chains/cosmos/thor/lp/lpChainMap.js
2066
- var lpChainMap, chainPrefixToChain, chainToLpPrefix;
2067
- var init_lpChainMap = __esm({
2068
- "../../packages/core/chain/dist/chains/cosmos/thor/lp/lpChainMap.js"() {
2069
- init_thorchainLp();
2070
- lpChainMap = Object.freeze(Object.entries(thorchainLpChainCode).reduce((acc, [chainKey, prefix]) => {
2071
- if (prefix) {
2072
- acc[prefix] = chainKey;
2073
- }
2074
- return acc;
2075
- }, {}));
2076
- chainPrefixToChain = (prefix) => lpChainMap[prefix.toUpperCase()];
2077
- chainToLpPrefix = (chain) => thorchainLpChainCode[chain];
2078
- }
2079
- });
2080
-
2081
- // ../../packages/core/chain/dist/chains/cosmos/thor/lp/pairing.js
2082
- var resolvePairedAddressForLpAdd;
2083
- var init_pairing = __esm({
2084
- "../../packages/core/chain/dist/chains/cosmos/thor/lp/pairing.js"() {
2085
- init_Chain();
2086
- init_lpChainMap();
2087
- init_pools();
2088
- resolvePairedAddressForLpAdd = ({ pool, side, vaultAddresses }) => {
2089
- assertValidPoolId(pool);
2090
- const [chainPrefix] = pool.split(".");
2091
- if (!chainPrefix)
2092
- return void 0;
2093
- const assetChain = chainPrefixToChain(chainPrefix);
2094
- if (!assetChain)
2095
- return void 0;
2096
- if (side === "asset") {
2097
- return vaultAddresses[Chain9.THORChain];
2098
- }
2099
- return vaultAddresses[assetChain];
2100
- };
2101
- }
2102
- });
2103
-
2104
- // ../../packages/core/chain/dist/chains/cosmos/thor/lp/math.js
2105
- var assertBaseUnitString, getLiquidityUnits, getPoolShare, getLpAddSlippage, estimateLpAdd;
2106
- var init_math = __esm({
2107
- "../../packages/core/chain/dist/chains/cosmos/thor/lp/math.js"() {
2108
- init_Chain();
2109
- init_cosmosRpcUrl();
2110
- init_queryUrl();
2111
- init_pools();
2112
- assertBaseUnitString = (value, fieldName) => {
2113
- if (typeof value !== "string" || value.length === 0) {
2114
- throw new Error(`${fieldName} must be a non-empty base-unit string, got ${typeof value === "string" ? JSON.stringify(value) : typeof value}`);
2115
- }
2116
- if (!/^\d+$/.test(value)) {
2117
- throw new Error(`${fieldName} must be a non-negative integer base-unit string, got ${JSON.stringify(value)}`);
2118
- }
2119
- return BigInt(value);
2120
- };
2121
- getLiquidityUnits = ({ pool, assetAmountBaseUnit, runeAmountBaseUnit }) => {
2122
- const P = assertBaseUnitString(pool.poolUnits, "pool.poolUnits");
2123
- const R = assertBaseUnitString(pool.runeDepth, "pool.runeDepth");
2124
- const A = assertBaseUnitString(pool.assetDepth, "pool.assetDepth");
2125
- const r = assertBaseUnitString(runeAmountBaseUnit, "runeAmountBaseUnit");
2126
- const a = assertBaseUnitString(assetAmountBaseUnit, "assetAmountBaseUnit");
2127
- if (R === 0n || A === 0n || P === 0n) {
2128
- return "0";
2129
- }
2130
- const numerator = P * (R * a + r * A);
2131
- const denominator = 2n * R * A;
2132
- return (numerator / denominator).toString();
2133
- };
2134
- getPoolShare = ({ pool, liquidityUnits }) => {
2135
- const P = assertBaseUnitString(pool.poolUnits, "pool.poolUnits");
2136
- const L = assertBaseUnitString(liquidityUnits, "liquidityUnits");
2137
- if (P === 0n || L === 0n) {
2138
- return { poolShareDecimal: "0" };
2139
- }
2140
- const totalAfter = P + L;
2141
- const SCALE = 10n ** 18n;
2142
- const scaled = L * SCALE / totalAfter;
2143
- const decimal = scaled.toString().padStart(19, "0");
2144
- const intPart = decimal.slice(0, -18) || "0";
2145
- const fracPart = decimal.slice(-18).replace(/0+$/, "");
2146
- return {
2147
- poolShareDecimal: fracPart.length > 0 ? `${intPart}.${fracPart}` : intPart
2148
- };
2149
- };
2150
- getLpAddSlippage = ({ pool, assetAmountBaseUnit, runeAmountBaseUnit }) => {
2151
- const R = assertBaseUnitString(pool.runeDepth, "pool.runeDepth");
2152
- const A = assertBaseUnitString(pool.assetDepth, "pool.assetDepth");
2153
- const r = assertBaseUnitString(runeAmountBaseUnit, "runeAmountBaseUnit");
2154
- const a = assertBaseUnitString(assetAmountBaseUnit, "assetAmountBaseUnit");
2155
- if (R === 0n || A === 0n) {
2156
- return { decimalPercent: "0", slippageInRuneBaseUnit: "0" };
2157
- }
2158
- const ra = R * a;
2159
- const ar = A * r;
2160
- const numerator = ra > ar ? ra - ar : ar - ra;
2161
- const denominator = A * r + R * A;
2162
- if (denominator === 0n) {
2163
- return { decimalPercent: "0", slippageInRuneBaseUnit: "0" };
2164
- }
2165
- const SCALE = 10n ** 18n;
2166
- const scaled = numerator * SCALE / denominator;
2167
- const decimal = scaled.toString().padStart(19, "0");
2168
- const intPart = decimal.slice(0, -18) || "0";
2169
- const fracPart = decimal.slice(-18).replace(/0+$/, "");
2170
- const decimalPercent = fracPart.length > 0 ? `${intPart}.${fracPart}` : intPart;
2171
- const imbalanceNumerator = ra > ar ? ra - ar : ar - ra;
2172
- const imbalanceInRune = A === 0n ? 0n : imbalanceNumerator / (2n * A);
2173
- const slippageInRune = imbalanceInRune * scaled / SCALE;
2174
- return {
2175
- decimalPercent,
2176
- slippageInRuneBaseUnit: slippageInRune.toString()
2177
- };
2178
- };
2179
- estimateLpAdd = async ({ pool, assetAmountBaseUnit, runeAmountBaseUnit, thornodeBaseUrl }) => {
2180
- assertValidPoolId(pool);
2181
- const base = thornodeBaseUrl ?? cosmosRpcUrl[Chain9.THORChain];
2182
- const url = `${base}/thorchain/pool/${encodeURIComponent(pool)}`;
2183
- const raw = await queryUrl(url);
2184
- if (!raw || typeof raw !== "object" || typeof raw.balance_asset !== "string" || typeof raw.balance_rune !== "string") {
2185
- throw new Error(`estimateLpAdd: pool ${pool} response from ${url} missing balance fields`);
2186
- }
2187
- const poolUnitsRaw = raw.pool_units ?? raw.LP_units;
2188
- if (typeof poolUnitsRaw !== "string" || poolUnitsRaw.length === 0) {
2189
- throw new Error(`estimateLpAdd: pool ${pool} response from ${url} missing pool_units / LP_units`);
2190
- }
2191
- const poolState = {
2192
- assetDepth: raw.balance_asset,
2193
- runeDepth: raw.balance_rune,
2194
- poolUnits: poolUnitsRaw
2195
- };
2196
- const liquidityUnits = getLiquidityUnits({
2197
- pool: poolState,
2198
- assetAmountBaseUnit,
2199
- runeAmountBaseUnit
2200
- });
2201
- const share = getPoolShare({
2202
- pool: poolState,
2203
- liquidityUnits
2204
- });
2205
- const slip = getLpAddSlippage({
2206
- pool: poolState,
2207
- assetAmountBaseUnit,
2208
- runeAmountBaseUnit
2209
- });
2210
- const R = BigInt(poolState.runeDepth);
2211
- const A = BigInt(poolState.assetDepth);
2212
- const P = BigInt(poolState.poolUnits);
2213
- const r = BigInt(runeAmountBaseUnit);
2214
- const a = BigInt(assetAmountBaseUnit);
2215
- const L = BigInt(liquidityUnits);
2216
- const totalAfter = P + L;
2217
- const runeDepthAfter = R + r;
2218
- const assetDepthAfter = A + a;
2219
- const runeShareBaseUnit = totalAfter === 0n ? "0" : (runeDepthAfter * L / totalAfter).toString();
2220
- const assetShareBaseUnit = totalAfter === 0n ? "0" : (assetDepthAfter * L / totalAfter).toString();
2221
- return {
2222
- liquidityUnits,
2223
- poolShareDecimal: share.poolShareDecimal,
2224
- runeShareBaseUnit,
2225
- assetShareBaseUnit,
2226
- slippageDecimal: slip.decimalPercent,
2227
- slippageRuneBaseUnit: slip.slippageInRuneBaseUnit
2228
- };
2229
- };
2230
- }
2231
- });
2232
-
2233
- // ../../packages/core/chain/dist/chains/cosmos/thor/lp/positions.js
2234
- var getThorchainLpPositions;
2235
- var init_positions = __esm({
2236
- "../../packages/core/chain/dist/chains/cosmos/thor/lp/positions.js"() {
2237
- init_HttpResponseError();
2238
- init_queryUrl();
2239
- init_memberPool();
2240
- init_pools();
2241
- getThorchainLpPositions = async ({ thorAddress }) => {
2242
- const url = `${thorchainMidgardBaseUrl}/v2/member/${encodeURIComponent(thorAddress)}`;
2243
- let raw;
2244
- try {
2245
- raw = await queryUrl(url);
2246
- } catch (err) {
2247
- if (err instanceof HttpResponseError && err.status === 404)
2248
- return [];
2249
- throw err;
2250
- }
2251
- if (!raw || typeof raw !== "object") {
2252
- throw new Error(`getThorchainLpPositions: unexpected Midgard response shape from ${url}`);
2253
- }
2254
- if (raw.pools === void 0) {
2255
- return [];
2256
- }
2257
- if (!Array.isArray(raw.pools)) {
2258
- throw new Error(`getThorchainLpPositions: Midgard response ${url} has non-array \`pools\` field`);
2259
- }
2260
- return raw.pools.map(normalizeMemberPool);
2261
- };
2262
- }
2263
- });
2264
-
2265
- // ../../packages/core/chain/dist/chains/cosmos/thor/lp/lockup.js
2266
- var THORCHAIN_BLOCK_TIME_SECONDS, getThorchainLpLockupSeconds, getLpWithdrawReadiness;
2267
- var init_lockup = __esm({
2268
- "../../packages/core/chain/dist/chains/cosmos/thor/lp/lockup.js"() {
2269
- init_validation();
2270
- THORCHAIN_BLOCK_TIME_SECONDS = 6;
2271
- getThorchainLpLockupSeconds = async () => {
2272
- const mimir = await getThorchainMimir();
2273
- const blocks = mimir["LIQUIDITYLOCKUPBLOCKS"];
2274
- if (typeof blocks !== "number" || !Number.isFinite(blocks) || blocks < 0) {
2275
- throw new Error(`getThorchainLpLockupSeconds: mimir did not include a valid LIQUIDITYLOCKUPBLOCKS value`);
2276
- }
2277
- return blocks * THORCHAIN_BLOCK_TIME_SECONDS;
2278
- };
2279
- getLpWithdrawReadiness = async ({ position, lockupSeconds: providedLockupSeconds, nowUnix = Math.floor(Date.now() / 1e3) }) => {
2280
- const lockupSeconds = providedLockupSeconds ?? await getThorchainLpLockupSeconds();
2281
- const lastAdded = Number(position.dateLastAdded);
2282
- if (!Number.isFinite(lastAdded) || lastAdded <= 0) {
2283
- return {
2284
- isWithdrawable: true,
2285
- unlockAtUnix: 0,
2286
- remainingSeconds: 0
2287
- };
2288
- }
2289
- const unlockAtUnix = lastAdded + lockupSeconds;
2290
- const remainingSeconds = Math.max(unlockAtUnix - nowUnix, 0);
2291
- return {
2292
- isWithdrawable: remainingSeconds === 0,
2293
- unlockAtUnix,
2294
- remainingSeconds
2295
- };
2296
- };
2297
- }
2298
- });
2299
-
2300
- // ../../packages/core/chain/dist/chains/cosmos/thor/getThorchainInboundAddress.js
2301
- var getThorchainInboundAddress_exports = {};
2302
- __export(getThorchainInboundAddress_exports, {
2303
- getThorchainInboundAddress: () => getThorchainInboundAddress
2304
- });
2305
- var thorchainInboundAddressApi, getThorchainInboundAddress;
2306
- var init_getThorchainInboundAddress = __esm({
2307
- "../../packages/core/chain/dist/chains/cosmos/thor/getThorchainInboundAddress.js"() {
2308
- init_queryUrl();
2309
- init_Chain();
2310
- init_cosmosRpcUrl();
2311
- thorchainInboundAddressApi = `${cosmosRpcUrl[Chain9.THORChain]}/thorchain/inbound_addresses`;
2312
- getThorchainInboundAddress = () => queryUrl(thorchainInboundAddressApi);
2313
- }
2314
- });
2315
-
2316
- // ../../packages/core/chain/dist/chains/cosmos/thor/lp/halts.js
2317
- var buildStatus, getThorchainLpHaltStatusAll, getThorchainLpHaltStatus, getThorchainLpPoolPauseStatus;
2318
- var init_halts = __esm({
2319
- "../../packages/core/chain/dist/chains/cosmos/thor/lp/halts.js"() {
2320
- init_getThorchainInboundAddress();
2321
- init_validation();
2322
- buildStatus = (raw) => {
2323
- const reasons = [];
2324
- if (raw.halted)
2325
- reasons.push(`${raw.chain} chain is halted`);
2326
- if (raw.global_trading_paused)
2327
- reasons.push("global trading paused");
2328
- if (raw.chain_trading_paused)
2329
- reasons.push(`${raw.chain} chain trading paused`);
2330
- if (raw.chain_lp_actions_paused)
2331
- reasons.push(`${raw.chain} LP actions paused`);
2332
- const depositable = !raw.halted && !raw.chain_lp_actions_paused && !raw.chain_trading_paused && !raw.global_trading_paused;
2333
- const withdrawable = !raw.halted && !raw.chain_lp_actions_paused;
2334
- return {
2335
- chain: raw.chain,
2336
- depositable,
2337
- withdrawable,
2338
- reasons,
2339
- raw: {
2340
- halted: raw.halted,
2341
- chain_trading_paused: raw.chain_trading_paused,
2342
- chain_lp_actions_paused: raw.chain_lp_actions_paused,
2343
- global_trading_paused: raw.global_trading_paused
2344
- }
2345
- };
2346
- };
2347
- getThorchainLpHaltStatusAll = async () => {
2348
- const addresses = await getThorchainInboundAddress();
2349
- return addresses.map((a) => buildStatus({
2350
- chain: a.chain,
2351
- halted: a.halted,
2352
- chain_trading_paused: a.chain_trading_paused,
2353
- chain_lp_actions_paused: a.chain_lp_actions_paused,
2354
- global_trading_paused: a.global_trading_paused
2355
- }));
2356
- };
2357
- getThorchainLpHaltStatus = async (chain) => {
2358
- const all = await getThorchainLpHaltStatusAll();
2359
- const upper = chain.toUpperCase();
2360
- const match = all.find((s) => s.chain.toUpperCase() === upper);
2361
- if (!match) {
2362
- throw new Error(`getThorchainLpHaltStatus: chain ${chain} not found in inbound_addresses`);
2363
- }
2364
- return match;
2365
- };
2366
- getThorchainLpPoolPauseStatus = async (pool) => {
2367
- const mimir = await getThorchainMimir();
2368
- const mimirKey = poolPauseMimirKey(pool);
2369
- const mimirValue = mimir[mimirKey];
2370
- if (typeof mimirValue === "number" && mimirValue > 0) {
2371
- return { paused: true, mimirKey, mimirValue };
2372
- }
2373
- return { paused: false };
2374
- };
2375
- }
2376
- });
2377
-
2378
- // ../../packages/core/chain/dist/chains/cosmos/thor/lp/index.js
2379
- var lp_exports = {};
2380
- __export(lp_exports, {
2381
- THORCHAIN_BLOCK_TIME_SECONDS: () => THORCHAIN_BLOCK_TIME_SECONDS,
2382
- addLpMemo: () => addLpMemo,
2383
- assertPoolDepositable: () => assertPoolDepositable,
2384
- assertValidPoolId: () => assertValidPoolId,
2385
- buildThorchainLpAddPayload: () => buildThorchainLpAddPayload,
2386
- buildThorchainLpRemovePayload: () => buildThorchainLpRemovePayload,
2387
- chainPrefixToChain: () => chainPrefixToChain,
2388
- chainToLpPrefix: () => chainToLpPrefix,
2389
- estimateLpAdd: () => estimateLpAdd,
2390
- getLiquidityUnits: () => getLiquidityUnits,
2391
- getLpAddSlippage: () => getLpAddSlippage,
2392
- getLpWithdrawReadiness: () => getLpWithdrawReadiness,
2393
- getPoolShare: () => getPoolShare,
2394
- getThorchainLpHaltStatus: () => getThorchainLpHaltStatus,
2395
- getThorchainLpHaltStatusAll: () => getThorchainLpHaltStatusAll,
2396
- getThorchainLpLockupSeconds: () => getThorchainLpLockupSeconds,
2397
- getThorchainLpPoolPauseStatus: () => getThorchainLpPoolPauseStatus,
2398
- getThorchainLpPosition: () => getThorchainLpPosition,
2399
- getThorchainLpPositionFromThornode: () => getThorchainLpPositionFromThornode,
2400
- getThorchainLpPositions: () => getThorchainLpPositions,
2401
- getThorchainMimir: () => getThorchainMimir,
2402
- getThorchainPools: () => getThorchainPools,
2403
- isValidPoolId: () => isValidPoolId,
2404
- lpChainMap: () => lpChainMap,
2405
- poolPauseMimirKey: () => poolPauseMimirKey,
2406
- removeLpMemo: () => removeLpMemo,
2407
- resolvePairedAddressForLpAdd: () => resolvePairedAddressForLpAdd,
2408
- thorchainMidgardBaseUrl: () => thorchainMidgardBaseUrl
2409
- });
2410
- var init_lp = __esm({
2411
- "../../packages/core/chain/dist/chains/cosmos/thor/lp/index.js"() {
2412
- init_memo();
2413
- init_payload();
2414
- init_pools();
2415
- init_position();
2416
- init_validation();
2417
- init_pairing();
2418
- init_lpChainMap();
2419
- init_math();
2420
- init_positions();
2421
- init_lockup();
2422
- init_halts();
2423
- }
2424
- });
2425
-
2426
1452
  // src/index.ts
2427
1453
  import "dotenv/config";
2428
1454
  import { promises as fs4 } from "node:fs";
@@ -4514,8 +3540,9 @@ async function executeVaults(ctx2) {
4514
3540
  spinner.succeed("Vaults loaded");
4515
3541
  if (isJsonOutput()) {
4516
3542
  const activeVault2 = ctx2.getActiveVault();
3543
+ const sorted = [...vaults].sort((a, b) => a.id === activeVault2?.id ? -1 : b.id === activeVault2?.id ? 1 : 0);
4517
3544
  outputJson({
4518
- vaults: vaults.map((v) => ({
3545
+ vaults: sorted.map((v) => ({
4519
3546
  id: v.id,
4520
3547
  name: v.name,
4521
3548
  type: v.type,
@@ -5824,10 +4851,10 @@ async function authenticateVault(client, vault, password, maxAttempts = 3) {
5824
4851
  });
5825
4852
  const messageHash = computePersonalSignHash(authMessage);
5826
4853
  let lastError = null;
5827
- for (let attempt2 = 1; attempt2 <= maxAttempts; attempt2++) {
4854
+ for (let attempt = 1; attempt <= maxAttempts; attempt++) {
5828
4855
  try {
5829
- if (attempt2 > 1) {
5830
- process.stderr.write(` Retry ${attempt2}/${maxAttempts}...
4856
+ if (attempt > 1) {
4857
+ process.stderr.write(` Retry ${attempt}/${maxAttempts}...
5831
4858
  `);
5832
4859
  }
5833
4860
  const signature = await vault.signBytes({ data: Buffer.from(messageHash), chain: Chain7.Ethereum }, {});
@@ -5844,7 +4871,7 @@ async function authenticateVault(client, vault, password, maxAttempts = 3) {
5844
4871
  };
5845
4872
  } catch (err) {
5846
4873
  lastError = err;
5847
- if (attempt2 < maxAttempts && err.message?.includes("timeout")) {
4874
+ if (attempt < maxAttempts && err.message?.includes("timeout")) {
5848
4875
  continue;
5849
4876
  }
5850
4877
  throw err;
@@ -6369,7 +5396,7 @@ function getNativeTokenDecimals(chain) {
6369
5396
  }
6370
5397
 
6371
5398
  // src/agent/executor.ts
6372
- import { Chain as Chain10, evmCall, Vultisig as VultisigSdk } from "@vultisig/sdk";
5399
+ import { Chain as Chain9, Vultisig as VultisigSdk } from "@vultisig/sdk";
6373
5400
 
6374
5401
  // ../../node_modules/viem/_esm/index.js
6375
5402
  init_formatUnits();
@@ -6529,29 +5556,6 @@ function sleep2(ms) {
6529
5556
  return new Promise((resolve) => setTimeout(resolve, ms));
6530
5557
  }
6531
5558
 
6532
- // src/agent/types.ts
6533
- var AUTO_EXECUTE_ACTIONS = /* @__PURE__ */ new Set([
6534
- "vault_chain",
6535
- "vault_coin",
6536
- "address_book",
6537
- "get_address_book",
6538
- "get_balances",
6539
- "search_token",
6540
- "list_vaults",
6541
- "build_swap_tx",
6542
- "build_send_tx",
6543
- "build_custom_tx",
6544
- "build_tx",
6545
- "sign_tx",
6546
- "sign_typed_data",
6547
- "read_evm_contract",
6548
- "scan_tx",
6549
- "thorchain_pool_info",
6550
- "thorchain_add_liquidity",
6551
- "thorchain_remove_liquidity"
6552
- ]);
6553
- var PASSWORD_REQUIRED_ACTIONS = /* @__PURE__ */ new Set(["sign_tx", "sign_typed_data", "build_custom_tx"]);
6554
-
6555
5559
  // src/agent/executor.ts
6556
5560
  var EVM_CHAINS = /* @__PURE__ */ new Set([
6557
5561
  "Ethereum",
@@ -6583,7 +5587,7 @@ var EVM_GAS_RPC = {
6583
5587
  Hyperliquid: "https://rpc.hyperliquid.xyz/evm",
6584
5588
  Sei: "https://evm-rpc.sei-apis.com"
6585
5589
  };
6586
- var AgentExecutor = class _AgentExecutor {
5590
+ var AgentExecutor = class {
6587
5591
  vault;
6588
5592
  /** Owning SDK (optional); used for address book backed by app storage */
6589
5593
  vultisig;
@@ -6638,7 +5642,7 @@ var AgentExecutor = class _AgentExecutor {
6638
5642
  `);
6639
5643
  return false;
6640
5644
  }
6641
- const chain = resolveChainFromTxReady(txReadyData) || Chain10.Ethereum;
5645
+ const chain = resolveChainFromTxReady(txReadyData) || Chain9.Ethereum;
6642
5646
  this.pendingPayloads.clear();
6643
5647
  this.pendingPayloads.set("latest", {
6644
5648
  payload: { __serverTx: true, ...txReadyData },
@@ -6656,137 +5660,78 @@ var AgentExecutor = class _AgentExecutor {
6656
5660
  hasPendingTransaction() {
6657
5661
  return this.pendingPayloads.has("latest");
6658
5662
  }
6659
- shouldAutoExecute(action) {
6660
- return action.auto_execute === true || AUTO_EXECUTE_ACTIONS.has(action.type);
6661
- }
6662
- requiresPassword(action) {
6663
- return PASSWORD_REQUIRED_ACTIONS.has(action.type);
6664
- }
6665
5663
  /**
6666
- * Execute a single action and return the result.
5664
+ * Wrap a per-tool handler body with normalised success/failure → RecentAction
5665
+ * conversion. Replaces the legacy executeAction → ActionResult adapter that
5666
+ * the dispatch chokepoint used before this refactor.
6667
5667
  */
6668
- async executeAction(action) {
5668
+ async runTool(toolName, body) {
6669
5669
  try {
6670
- const data = await this.dispatch(action);
6671
- return {
6672
- action: action.type,
6673
- action_id: action.id,
6674
- success: true,
6675
- data
6676
- };
5670
+ const data = await body();
5671
+ return { tool: toolName, success: true, data };
6677
5672
  } catch (err) {
6678
5673
  const { code, message } = normalizeAgentError(err);
6679
- return {
6680
- action: action.type,
6681
- action_id: action.id,
6682
- success: false,
6683
- error: message,
6684
- code
6685
- };
6686
- }
6687
- }
6688
- async dispatch(action) {
6689
- if (this.verbose) process.stderr.write(`[dispatch] action.type=${action.type} action.id=${action.id}
6690
- `);
6691
- const params = action.params || {};
6692
- switch (action.type) {
6693
- case "get_balances":
6694
- return this.getBalances(params);
6695
- case "vault_chain":
6696
- return this.vaultChain(params);
6697
- case "vault_coin":
6698
- return this.vaultCoin(params);
6699
- case "build_send_tx":
6700
- return this.buildSendTx(params);
6701
- case "build_swap_tx":
6702
- return this.buildSwapTx(params);
6703
- case "build_tx":
6704
- case "build_custom_tx":
6705
- return this.buildTx(params);
6706
- case "sign_tx":
6707
- return this.signTx(params);
6708
- case "get_address_book":
6709
- return this.getAddressBook(params);
6710
- case "address_book":
6711
- return this.addressBook(params);
6712
- case "search_token":
6713
- return this.searchToken(params);
6714
- case "list_vaults":
6715
- return this.listVaults();
6716
- case "sign_typed_data":
6717
- return this.signTypedData(params);
6718
- case "scan_tx":
6719
- return this.scanTx(params);
6720
- case "read_evm_contract":
6721
- return this.readEvmContract(params);
6722
- case "thorchain_pool_info":
6723
- return this.thorchainPoolInfo(params);
6724
- case "thorchain_add_liquidity":
6725
- return this.thorchainAddLiquidity(params);
6726
- case "thorchain_remove_liquidity":
6727
- return this.thorchainRemoveLiquidity(params);
6728
- default:
6729
- throw new Error(
6730
- `Action type '${action.type}' is not implemented locally. The backend may handle this action server-side.`
6731
- );
6732
- }
6733
- }
6734
- // ============================================================================
6735
- // Balance & Portfolio
6736
- // ============================================================================
6737
- async getBalances(params) {
6738
- const chainFilter = params.chain;
6739
- const tickerFilter = params.ticker;
6740
- const balanceRecord = await this.vault.balances();
6741
- let entries = Object.entries(balanceRecord).map(([key, b]) => ({
6742
- chain: b.chainId || key.split(":")[0] || "",
6743
- symbol: b.symbol || "",
6744
- amount: b.formattedAmount || b.amount?.toString() || "0",
6745
- decimals: b.decimals || 18,
6746
- raw_amount: b.amount?.toString()
6747
- }));
6748
- if (chainFilter) {
6749
- const chain = resolveChain(chainFilter);
6750
- if (chain) {
6751
- entries = entries.filter((b) => b.chain.toLowerCase() === chain.toLowerCase());
6752
- }
5674
+ return { tool: toolName, success: false, data: { error: message, code } };
6753
5675
  }
6754
- if (tickerFilter) {
6755
- entries = entries.filter((b) => b.symbol.toLowerCase() === tickerFilter.toLowerCase());
6756
- }
6757
- return { balances: entries };
6758
5676
  }
6759
5677
  // ============================================================================
6760
5678
  // Chain & Token Management
6761
5679
  // ============================================================================
6762
5680
  // vault_chain dispatcher — backend shape:
6763
5681
  // { action: "add" | "remove", chains: [{ chain }] }
6764
- // Single-chain (`chain` only) and legacy string arrays are tolerated for
6765
- // forward compatibility / hand-rolled callers.
6766
- async vaultChain(params) {
6767
- const action = params.action;
6768
- switch (action) {
6769
- case "add":
6770
- return this.addChainImpl(params);
6771
- case "remove":
6772
- return this.removeChainImpl(params);
6773
- default:
6774
- throw new Error(`vault_chain: unknown action: ${action ?? "(missing)"}`);
6775
- }
5682
+ // Discriminator wrapper: routes to addChain / removeChain so the resulting
5683
+ // RecentAction is tagged tool: 'vault_chain' (matching what the agent emits)
5684
+ // rather than the per-action method's tool name.
5685
+ async vaultChain(toolCallId, input) {
5686
+ return this.runTool("vault_chain", async () => {
5687
+ const action = input.action;
5688
+ switch (action) {
5689
+ case "add":
5690
+ return this.addChainImpl(input);
5691
+ case "remove":
5692
+ return this.removeChainImpl(input);
5693
+ default:
5694
+ throw new Error(`vault_chain: unknown action: ${action ?? "(missing)"}`);
5695
+ }
5696
+ });
6776
5697
  }
6777
5698
  // vault_coin dispatcher — backend shape:
6778
- // { action: "add" | "remove", coins: [{ chain, ticker, contract_address?, decimals?, ... }] }
6779
- async vaultCoin(params) {
6780
- const action = params.action;
6781
- switch (action) {
6782
- case "add":
6783
- return this.addCoinImpl(params);
6784
- case "remove":
6785
- return this.removeCoinImpl(params);
6786
- default:
6787
- throw new Error(`vault_coin: unknown action: ${action ?? "(missing)"}`);
6788
- }
5699
+ // { action: "add" | "remove", coins: [{ chain, ticker, contract_address?, ... }] }
5700
+ async vaultCoin(toolCallId, input) {
5701
+ return this.runTool("vault_coin", async () => {
5702
+ const action = input.action;
5703
+ switch (action) {
5704
+ case "add":
5705
+ return this.addCoinImpl(input);
5706
+ case "remove":
5707
+ return this.removeCoinImpl(input);
5708
+ default:
5709
+ throw new Error(`vault_coin: unknown action: ${action ?? "(missing)"}`);
5710
+ }
5711
+ });
5712
+ }
5713
+ // address_book dispatcher — backend shape:
5714
+ // { action: "add" | "remove", entry: { name, chain, address } }
5715
+ async addressBook(toolCallId, input) {
5716
+ return this.runTool("address_book", async () => {
5717
+ const action = input.action;
5718
+ switch (action) {
5719
+ case "add":
5720
+ return this.addAddressBookImpl(input);
5721
+ case "remove":
5722
+ return this.removeAddressBookImpl(input);
5723
+ default:
5724
+ throw new Error(`address_book: unknown action: ${action ?? "(missing)"}`);
5725
+ }
5726
+ });
5727
+ }
5728
+ async addChain(_toolCallId, input) {
5729
+ return this.runTool("add_chain", () => this.addChainImpl(input));
6789
5730
  }
5731
+ // Backend `vault_chain { action: "add", chains: [...] }` and legacy
5732
+ // single-chain calls both flow through this impl. The public `addChain`
5733
+ // wrapper above tags results as `tool: 'add_chain'`; the new `vaultChain`
5734
+ // wrapper (above) tags them as `tool: 'vault_chain'`.
6790
5735
  async addChainImpl(params) {
6791
5736
  const chains = params.chains;
6792
5737
  if (chains && Array.isArray(chains)) {
@@ -6839,7 +5784,7 @@ var AgentExecutor = class _AgentExecutor {
6839
5784
  id: t.contract_address || t.contractAddress || "",
6840
5785
  symbol: symbol2,
6841
5786
  name: t.name || symbol2,
6842
- decimals: t.decimals || 18,
5787
+ decimals: t.decimals ?? 18,
6843
5788
  contractAddress: t.contract_address || t.contractAddress,
6844
5789
  chainId: chain2.toString()
6845
5790
  });
@@ -6855,7 +5800,7 @@ var AgentExecutor = class _AgentExecutor {
6855
5800
  id: params.contract_address || params.contractAddress || "",
6856
5801
  symbol,
6857
5802
  name: params.name || symbol,
6858
- decimals: params.decimals || 18,
5803
+ decimals: params.decimals ?? 18,
6859
5804
  contractAddress: params.contract_address || params.contractAddress,
6860
5805
  chainId: chain.toString()
6861
5806
  });
@@ -6889,457 +5834,42 @@ var AgentExecutor = class _AgentExecutor {
6889
5834
  await this.vault.removeToken(chain, tokenId);
6890
5835
  return { chain: chain.toString(), removed: true };
6891
5836
  }
6892
- // ============================================================================
6893
- // Transaction Building
6894
- // ============================================================================
6895
- async buildSendTx(params) {
6896
- const chainName = params.chain || params.from_chain;
6897
- const chain = resolveChain(chainName);
6898
- if (!chain) throw new Error(`Unknown chain: ${chainName}`);
6899
- const symbol = params.symbol || params.ticker;
6900
- const toAddress = params.address || params.to || params.destination;
6901
- const amountStr = params.amount;
6902
- if (!toAddress) throw new Error("Destination address is required");
6903
- if (!amountStr) throw new Error("Amount is required");
6904
- await this.acquireEvmLockIfNeeded(chain);
6905
- try {
6906
- const address = await this.vault.address(chain);
6907
- const balance = await this.vault.balance(chain, params.token_id);
6908
- const coin = {
6909
- chain,
6910
- address,
6911
- decimals: balance.decimals,
6912
- ticker: symbol || balance.symbol,
6913
- id: params.token_id
6914
- };
6915
- const amount = parseAmount(amountStr, balance.decimals);
6916
- const memo = params.memo;
6917
- const payload = await this.vault.prepareSendTx({
6918
- coin,
6919
- receiver: toAddress,
6920
- amount,
6921
- memo
6922
- });
6923
- await this.patchEvmNonce(chain, payload);
6924
- const messageHashes = await this.vault.extractMessageHashes(payload);
6925
- this.pendingPayloads.clear();
6926
- const payloadId = `tx_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
6927
- this.pendingPayloads.set(payloadId, {
6928
- payload,
6929
- coin,
6930
- chain,
6931
- timestamp: Date.now()
6932
- });
6933
- this.pendingPayloads.set("latest", {
6934
- payload,
6935
- coin,
6936
- chain,
6937
- timestamp: Date.now()
6938
- });
6939
- return {
6940
- keysign_payload: payloadId,
6941
- from_chain: chain.toString(),
6942
- from_symbol: coin.ticker,
6943
- amount: amountStr,
6944
- sender: address,
6945
- destination: toAddress,
6946
- memo: memo || void 0,
6947
- message_hashes: messageHashes,
6948
- tx_details: {
6949
- chain: chain.toString(),
6950
- from: address,
6951
- to: toAddress,
6952
- amount: amountStr,
6953
- symbol: coin.ticker
6954
- }
6955
- };
6956
- } catch (err) {
6957
- await this.releaseEvmLock(chain);
6958
- throw err;
6959
- }
5837
+ async removeChain(_toolCallId, input) {
5838
+ return this.runTool("remove_chain", () => this.removeChainImpl(input));
6960
5839
  }
6961
- async buildSwapTx(params) {
6962
- if (this.verbose)
6963
- process.stderr.write(`[build_swap_tx] called with params: ${JSON.stringify(params).slice(0, 500)}
6964
- `);
6965
- const fromChainName = params.from_chain || params.chain;
6966
- const toChainName = params.to_chain;
6967
- const fromChain = resolveChain(fromChainName);
6968
- const toChain = toChainName ? resolveChain(toChainName) : null;
6969
- if (!fromChain) throw new Error(`Unknown from_chain: ${fromChainName}`);
6970
- await this.acquireEvmLockIfNeeded(fromChain);
6971
- try {
6972
- const amountStr = params.amount;
6973
- const fromSymbol = params.from_symbol || params.from_token || "";
6974
- const toSymbol = params.to_symbol || params.to_token || "";
6975
- const fromToken = params.from_contract || params.from_token_id;
6976
- const toToken = params.to_contract || params.to_token_id;
6977
- const fromCoin = { chain: fromChain, token: fromToken || void 0 };
6978
- const toCoin = {
6979
- chain: toChain || fromChain,
6980
- token: toToken || void 0
6981
- };
6982
- const quote = await this.vault.getSwapQuote({
6983
- fromCoin,
6984
- toCoin,
6985
- amount: amountStr
6986
- });
6987
- const swapResult = await this.vault.prepareSwapTx({
6988
- fromCoin,
6989
- toCoin,
6990
- amount: amountStr,
6991
- swapQuote: quote,
6992
- autoApprove: true
6993
- });
6994
- const chain = fromChain;
6995
- const payload = swapResult.keysignPayload;
6996
- await this.patchEvmNonce(chain, payload);
6997
- const messageHashes = await this.vault.extractMessageHashes(payload);
6998
- this.pendingPayloads.clear();
6999
- const payloadId = `swap_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
7000
- this.pendingPayloads.set(payloadId, {
7001
- payload,
7002
- coin: { chain, address: "", decimals: 18, ticker: fromSymbol },
7003
- chain,
7004
- timestamp: Date.now()
7005
- });
7006
- this.pendingPayloads.set("latest", {
7007
- payload,
7008
- coin: { chain, address: "", decimals: 18, ticker: fromSymbol },
7009
- chain,
7010
- timestamp: Date.now()
7011
- });
7012
- return {
7013
- keysign_payload: payloadId,
7014
- from_chain: fromChain.toString(),
7015
- to_chain: (toChain || fromChain).toString(),
7016
- from_symbol: fromSymbol,
7017
- to_symbol: toSymbol,
7018
- amount: amountStr,
7019
- estimated_output: quote.estimatedOutput?.toString(),
7020
- provider: quote.provider,
7021
- message_hashes: messageHashes
7022
- };
7023
- } catch (err) {
7024
- await this.releaseEvmLock(fromChain);
7025
- throw err;
7026
- }
5840
+ async addCoin(_toolCallId, input) {
5841
+ return this.runTool("add_coin", () => this.addCoinImpl(input));
5842
+ }
5843
+ async removeCoin(_toolCallId, input) {
5844
+ return this.runTool("remove_coin", () => this.removeCoinImpl(input));
7027
5845
  }
7028
5846
  // ============================================================================
7029
- // THORChain LP (RUNE-side asym add / remove via prepareSendTx + memo)
5847
+ // Transaction Signing
7030
5848
  // ============================================================================
7031
5849
  /**
7032
- * Pool stats from Midgard (no signing). Optional `pool` filters to one row.
5850
+ * Sign and broadcast a transaction previously buffered by
5851
+ * {@link storeServerTransaction} via the `tx_ready` SSE channel. Returns
5852
+ * a `RecentAction` to be flushed in the next `context.recent_actions`.
5853
+ *
5854
+ * Replaces the legacy `signTx(action.params)` path: there is no longer an
5855
+ * action wrapper, no `keysign_payload` lookup (the buffer always uses
5856
+ * the `'latest'` slot), and no SDK-built keysignPayload branch (the live
5857
+ * client-side tools no longer produce SDK-built payloads — those went
5858
+ * away with `buildSendTx`/`buildSwapTx`).
7033
5859
  */
7034
- async thorchainPoolInfo(params) {
7035
- const { assertValidPoolId: assertValidPoolId2, getThorchainPools: getThorchainPools2, thorchainMidgardBaseUrl: thorchainMidgardBaseUrl2 } = await Promise.resolve().then(() => (init_lp(), lp_exports));
7036
- const statusRaw = params.status;
7037
- let poolFetchOpts = {};
7038
- if (statusRaw === null || String(statusRaw).toLowerCase() === "all") {
7039
- poolFetchOpts = { status: null };
7040
- } else if (statusRaw !== void 0) {
7041
- poolFetchOpts = { status: String(statusRaw) };
7042
- }
7043
- const pools = await getThorchainPools2(poolFetchOpts);
7044
- const poolArg = params.pool;
7045
- if (poolArg) {
7046
- const normalized = poolArg.trim().toUpperCase();
7047
- assertValidPoolId2(normalized);
7048
- const row = pools.find((p) => p.asset.toUpperCase() === normalized);
7049
- return {
7050
- found: !!row,
7051
- pool_id: normalized,
7052
- summary: row ?? null,
7053
- midgard: thorchainMidgardBaseUrl2
7054
- };
7055
- }
7056
- const limitRaw = params.limit;
7057
- const limit = Math.min(500, Math.max(1, typeof limitRaw === "number" ? limitRaw : Number(limitRaw) || 80));
7058
- return {
7059
- pools: pools.slice(0, limit),
7060
- total: pools.length,
7061
- midgard: thorchainMidgardBaseUrl2
7062
- };
7063
- }
7064
- async thorchainAddLiquidity(params) {
7065
- const { assertValidPoolId: assertValidPoolId2, buildThorchainLpAddPayload: buildThorchainLpAddPayload2, resolvePairedAddressForLpAdd: resolvePairedAddressForLpAdd2 } = await Promise.resolve().then(() => (init_lp(), lp_exports));
7066
- const { getThorchainInboundAddress: getThorchainInboundAddress2 } = await Promise.resolve().then(() => (init_getThorchainInboundAddress(), getThorchainInboundAddress_exports));
7067
- const pool = this.normalizeThorchainPoolId(params.pool, assertValidPoolId2);
7068
- const amountStr = String(params.amount ?? "").trim();
7069
- if (!amountStr) {
7070
- throw new Error('amount is required (RUNE amount as a decimal string, e.g. "0.25")');
7071
- }
7072
- if (!/^\d+(\.\d+)?$/.test(amountStr)) {
7073
- throw new Error('amount must be a positive decimal string (no sign or scientific notation), e.g. "0.25"');
7074
- }
7075
- const [, frac = ""] = amountStr.split(".");
7076
- if (frac.length > 8) {
7077
- throw new Error("RUNE amount supports at most 8 decimal places");
7078
- }
7079
- const amountRuneBaseUnits = parseAmount(amountStr, 8);
7080
- if (amountRuneBaseUnits <= 0n) {
7081
- throw new Error("amount must be greater than zero");
7082
- }
7083
- let pairedAddress = params.paired_address?.trim() || void 0;
7084
- const autoPairRaw = params.auto_pair ?? params.autoPair;
7085
- const autoPairDisabled = autoPairRaw === false || autoPairRaw === 0 || typeof autoPairRaw === "string" && ["false", "0"].includes(autoPairRaw.toLowerCase());
7086
- const autoPair = !pairedAddress && !autoPairDisabled;
7087
- if (autoPair) {
7088
- const vaultAddresses = await this.buildVaultAddressMap();
7089
- pairedAddress = resolvePairedAddressForLpAdd2({
7090
- pool,
7091
- side: "rune",
7092
- vaultAddresses
7093
- }) || void 0;
7094
- }
7095
- const lpPayload = buildThorchainLpAddPayload2({
7096
- pool,
7097
- amountRuneBaseUnits: amountRuneBaseUnits.toString(),
7098
- ...pairedAddress ? { pairedAddress } : {}
7099
- });
7100
- const receiver = await this.getThorchainNativeInboundAddress(getThorchainInboundAddress2);
7101
- const address = await this.vault.address(Chain10.THORChain);
7102
- const coin = {
7103
- chain: Chain10.THORChain,
7104
- address,
7105
- decimals: 8,
7106
- ticker: "RUNE"
7107
- };
7108
- const payload = await this.vault.prepareSendTx({
7109
- coin,
7110
- receiver,
7111
- amount: BigInt(lpPayload.amount),
7112
- memo: lpPayload.memo
7113
- });
7114
- const messageHashes = await this.vault.extractMessageHashes(payload);
7115
- this.pendingPayloads.clear();
7116
- const payloadId = `tc_lp_add_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
7117
- this.pendingPayloads.set(payloadId, {
7118
- payload,
7119
- coin,
7120
- chain: Chain10.THORChain,
7121
- timestamp: Date.now()
7122
- });
7123
- this.pendingPayloads.set("latest", {
7124
- payload,
7125
- coin,
7126
- chain: Chain10.THORChain,
7127
- timestamp: Date.now()
7128
- });
7129
- return {
7130
- keysign_payload: payloadId,
7131
- chain: "THORChain",
7132
- pool: lpPayload.pool,
7133
- memo: lpPayload.memo,
7134
- amount_rune: amountStr,
7135
- paired_address: pairedAddress,
7136
- inbound_receiver: receiver,
7137
- sender: address,
7138
- message_hashes: messageHashes
7139
- };
7140
- }
7141
- async thorchainRemoveLiquidity(params) {
7142
- const { assertValidPoolId: assertValidPoolId2, buildThorchainLpRemovePayload: buildThorchainLpRemovePayload2 } = await Promise.resolve().then(() => (init_lp(), lp_exports));
7143
- const { getThorchainInboundAddress: getThorchainInboundAddress2 } = await Promise.resolve().then(() => (init_getThorchainInboundAddress(), getThorchainInboundAddress_exports));
7144
- const pool = this.normalizeThorchainPoolId(params.pool, assertValidPoolId2);
7145
- let basisPoints;
7146
- if (params.basis_points != null) {
7147
- basisPoints = Number(params.basis_points);
7148
- } else if (params.basisPoints != null) {
7149
- basisPoints = Number(params.basisPoints);
7150
- }
7151
- if (basisPoints == null && params.withdraw_percent != null) {
7152
- const pct = Number(params.withdraw_percent);
7153
- if (Number.isFinite(pct)) {
7154
- basisPoints = Math.round(pct * 100);
7155
- }
7156
- }
7157
- if (basisPoints == null || !Number.isInteger(basisPoints)) {
7158
- throw new Error("basis_points (integer 1\u201310000) or withdraw_percent (0.01\u2013100, maps to basis points) is required");
7159
- }
7160
- let withdrawToAsset = params.withdraw_to_asset?.trim();
7161
- if (!withdrawToAsset && params.withdrawToAsset) {
7162
- withdrawToAsset = String(params.withdrawToAsset).trim();
7163
- }
7164
- if (withdrawToAsset) {
7165
- withdrawToAsset = withdrawToAsset.toUpperCase();
7166
- }
7167
- const lpPayload = buildThorchainLpRemovePayload2({
7168
- pool,
7169
- basisPoints,
7170
- ...withdrawToAsset ? { withdrawToAsset } : {}
7171
- });
7172
- const receiver = await this.getThorchainNativeInboundAddress(getThorchainInboundAddress2);
7173
- const address = await this.vault.address(Chain10.THORChain);
7174
- const coin = {
7175
- chain: Chain10.THORChain,
7176
- address,
7177
- decimals: 8,
7178
- ticker: "RUNE"
7179
- };
7180
- const payload = await this.vault.prepareSendTx({
7181
- coin,
7182
- receiver,
7183
- amount: BigInt(lpPayload.amount),
7184
- memo: lpPayload.memo
7185
- });
7186
- const messageHashes = await this.vault.extractMessageHashes(payload);
7187
- this.pendingPayloads.clear();
7188
- const payloadId = `tc_lp_rm_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
7189
- this.pendingPayloads.set(payloadId, {
7190
- payload,
7191
- coin,
7192
- chain: Chain10.THORChain,
7193
- timestamp: Date.now()
7194
- });
7195
- this.pendingPayloads.set("latest", {
7196
- payload,
7197
- coin,
7198
- chain: Chain10.THORChain,
7199
- timestamp: Date.now()
7200
- });
7201
- return {
7202
- keysign_payload: payloadId,
7203
- chain: "THORChain",
7204
- pool: lpPayload.pool,
7205
- memo: lpPayload.memo,
7206
- basis_points: basisPoints,
7207
- withdraw_to_asset: withdrawToAsset || void 0,
7208
- dust_rune_base_units: lpPayload.amount,
7209
- inbound_receiver: receiver,
7210
- sender: address,
7211
- message_hashes: messageHashes
7212
- };
7213
- }
7214
- normalizeThorchainPoolId(raw, assertValidPoolId2) {
7215
- const pool = String(raw ?? "").trim();
7216
- if (!pool) {
7217
- throw new Error('pool is required (e.g. "BTC.BTC")');
7218
- }
7219
- const upper = pool.toUpperCase();
7220
- assertValidPoolId2(upper);
7221
- return upper;
7222
- }
7223
- async buildVaultAddressMap() {
7224
- const map = {};
7225
- for (const c of this.vault.chains) {
7226
- try {
7227
- map[c] = await this.vault.address(c);
7228
- } catch {
7229
- }
7230
- }
7231
- return map;
7232
- }
7233
- /** THORChain protocol vault for native RUNE deposits (SWAP/LP memos). Matches SDK e2e fixture. */
7234
- static THORCHAIN_RUNE_DEPOSIT_ADDRESS = "thor1g98cy3n9mmjrpn0sxmn63lztelera37n8n67c0";
7235
- async getThorchainNativeInboundAddress(getInbound) {
7236
- const rows = await getInbound();
7237
- const thor = rows.find((r) => r.chain.toUpperCase() === "THOR");
7238
- if (thor?.address) {
7239
- return thor.address;
7240
- }
7241
- if (this.verbose) {
7242
- process.stderr.write(
7243
- `[thorchain_lp] THOR inbound row missing; using static RUNE deposit vault ${_AgentExecutor.THORCHAIN_RUNE_DEPOSIT_ADDRESS}
7244
- `
7245
- );
7246
- }
7247
- return _AgentExecutor.THORCHAIN_RUNE_DEPOSIT_ADDRESS;
7248
- }
7249
- async buildTx(params) {
7250
- if (params.function_name && params.contract_address) {
7251
- return this.buildContractCallTx(params);
7252
- }
7253
- if (params.data || params.calldata || params.hex_payload) {
7254
- const txData = {
7255
- to: params.to || params.address || params.contract,
7256
- value: params.value || "0",
7257
- data: params.data || params.calldata || params.hex_payload,
7258
- chain: params.chain,
7259
- chain_id: params.chain_id
7260
- };
7261
- const stored = this.storeServerTransaction({
7262
- tx: txData,
7263
- chain: params.chain,
7264
- from_chain: params.chain
7265
- });
5860
+ async signTxFromBuffer(_toolCallId) {
5861
+ return this.runTool("sign_tx", async () => {
5862
+ if (this.verbose)
5863
+ process.stderr.write(`[sign_tx] pendingPayloads keys: ${[...this.pendingPayloads.keys()].join(", ")}
5864
+ `);
5865
+ const stored = this.pendingPayloads.get("latest");
7266
5866
  if (!stored) {
7267
- throw new Error("Could not stage calldata transaction for signing (invalid or empty tx payload)");
5867
+ throw new Error("No pending transaction to sign. Build a transaction first.");
5868
+ }
5869
+ const { payload, chain } = stored;
5870
+ if (!payload.__serverTx) {
5871
+ throw new Error("Pending transaction is not a server-built tx (no __serverTx flag).");
7268
5872
  }
7269
- const chain = resolveChain(params.chain) || Chain10.Ethereum;
7270
- const address = await this.vault.address(chain);
7271
- return {
7272
- status: "ready",
7273
- chain: chain.toString(),
7274
- from: address,
7275
- to: txData.to,
7276
- value: txData.value,
7277
- has_calldata: true,
7278
- message: "Transaction built. Ready to sign."
7279
- };
7280
- }
7281
- if (params.contract_address && !params.function_name) {
7282
- const provided = Object.keys(params).join(", ");
7283
- throw new Error(
7284
- `build_custom_tx requires function_name and params for contract calls. Got: ${provided}. Missing: function_name, params.`
7285
- );
7286
- }
7287
- throw new Error(
7288
- `build_custom_tx: unrecognized params shape. Expected function_name + contract_address for ABI-encoding. Server-built calldata should arrive via tx_ready, not via action params. Got keys: ${Object.keys(params).join(", ")}`
7289
- );
7290
- }
7291
- /**
7292
- * Build, sign, and broadcast an EVM contract call transaction from structured params.
7293
- * Encodes function_name + typed params into ABI calldata, then signs via signServerTx.
7294
- */
7295
- async buildContractCallTx(params) {
7296
- const chainName = params.chain || "Ethereum";
7297
- const chain = resolveChain(chainName);
7298
- if (!chain) throw new Error(`Unknown chain: ${chainName}`);
7299
- const contractAddress = params.contract_address;
7300
- const functionName = params.function_name;
7301
- const typedParams = params.params;
7302
- const value = params.value || "0";
7303
- const calldata = await encodeContractCall(functionName, typedParams || []);
7304
- if (this.verbose)
7305
- process.stderr.write(
7306
- `[build_contract_tx] ${functionName}(${(typedParams || []).map((p) => p.type).join(",")}) on ${contractAddress} chain=${chain}
7307
- `
7308
- );
7309
- const serverTxData = {
7310
- __serverTx: true,
7311
- tx: {
7312
- to: contractAddress,
7313
- value,
7314
- data: calldata
7315
- },
7316
- chain: chainName,
7317
- from_chain: chainName
7318
- };
7319
- this.pendingPayloads.set("latest", {
7320
- payload: serverTxData,
7321
- coin: { chain, address: "", decimals: 18, ticker: "" },
7322
- chain,
7323
- timestamp: Date.now()
7324
- });
7325
- return this.signServerTx(serverTxData, chain, { chain: chainName });
7326
- }
7327
- // ============================================================================
7328
- // Transaction Signing
7329
- // ============================================================================
7330
- async signTx(params) {
7331
- if (this.verbose) process.stderr.write(`[sign_tx] params: ${JSON.stringify(params).slice(0, 500)}
7332
- `);
7333
- if (this.verbose)
7334
- process.stderr.write(`[sign_tx] pendingPayloads keys: ${[...this.pendingPayloads.keys()].join(", ")}
7335
- `);
7336
- const payloadId = params.keysign_payload || params.payload_id || "latest";
7337
- const stored = this.pendingPayloads.get(payloadId);
7338
- if (!stored) {
7339
- throw new Error("No pending transaction to sign. Build a transaction first.");
7340
- }
7341
- const { payload, chain } = stored;
7342
- if (payload.__serverTx) {
7343
5873
  let result;
7344
5874
  if (chain === "Solana" && (payload.swap_tx || payload.provider)) {
7345
5875
  try {
@@ -7354,56 +5884,10 @@ var AgentExecutor = class _AgentExecutor {
7354
5884
  }
7355
5885
  }
7356
5886
  }
7357
- if (!result) result = await this.signServerTx(payload, chain, params);
5887
+ if (!result) result = await this.signServerTx(payload, chain, {});
7358
5888
  if (payload.sequence_id) result.sequence_id = payload.sequence_id;
7359
5889
  return result;
7360
- }
7361
- return this.signSdkTx(payload, chain, payloadId);
7362
- }
7363
- /**
7364
- * Sign and broadcast an SDK-built transaction (keysign payload from local build methods).
7365
- */
7366
- async signSdkTx(payload, chain, _payloadId) {
7367
- try {
7368
- if (this.vault.isEncrypted && !this.vault.isUnlocked?.()) {
7369
- if (this.password) {
7370
- await this.vault.unlock?.(this.password);
7371
- }
7372
- }
7373
- await this.patchEvmGas(chain, payload);
7374
- const messageHashes = await this.vault.extractMessageHashes(payload);
7375
- const signature = await this.vault.sign(
7376
- {
7377
- transaction: payload,
7378
- chain: payload.coin?.chain || chain,
7379
- messageHashes
7380
- },
7381
- {}
7382
- );
7383
- const txHash = await this.vault.broadcastTx({
7384
- chain,
7385
- keysignPayload: payload,
7386
- signature
7387
- });
7388
- this.evmLastBroadcast.set(chain.toString(), Date.now());
7389
- try {
7390
- this.recordEvmNonceFromPayload(chain, payload, messageHashes.length);
7391
- } catch (nonceErr) {
7392
- console.warn(`[nonce] failed to persist nonce for ${chain}:`, nonceErr);
7393
- }
7394
- await this.releaseEvmLock(chain);
7395
- this.pendingPayloads.clear();
7396
- const explorerUrl = VultisigSdk.getTxExplorerUrl(chain, txHash);
7397
- return {
7398
- tx_hash: txHash,
7399
- chain: chain.toString(),
7400
- status: "pending",
7401
- explorer_url: explorerUrl
7402
- };
7403
- } catch (err) {
7404
- await this.releaseEvmLock(chain);
7405
- throw err;
7406
- }
5890
+ });
7407
5891
  }
7408
5892
  /**
7409
5893
  * Sign and broadcast a server-built transaction (raw EVM tx from tx_ready SSE).
@@ -7769,37 +6253,39 @@ var AgentExecutor = class _AgentExecutor {
7769
6253
  * - Payloads array: { payloads: [{id, domain, types, message, primaryType, chain}, ...] }
7770
6254
  * Used by Polymarket which requires signing both an Order and a ClobAuth.
7771
6255
  */
7772
- async signTypedData(params) {
7773
- if (this.vault.isEncrypted && !this.vault.isUnlocked?.()) {
7774
- if (this.password) {
7775
- await this.vault.unlock?.(this.password);
6256
+ async signTypedData(_toolCallId, input) {
6257
+ return this.runTool("sign_typed_data", async () => {
6258
+ if (this.vault.isEncrypted && !this.vault.isUnlocked?.()) {
6259
+ if (this.password) {
6260
+ await this.vault.unlock?.(this.password);
6261
+ }
7776
6262
  }
7777
- }
7778
- const payloads = params.payloads;
7779
- if (payloads && Array.isArray(payloads)) {
7780
- if (this.verbose) process.stderr.write(`[sign_typed_data] payloads mode, ${payloads.length} items
6263
+ const payloads = input.payloads;
6264
+ if (payloads && Array.isArray(payloads)) {
6265
+ if (this.verbose) process.stderr.write(`[sign_typed_data] payloads mode, ${payloads.length} items
7781
6266
  `);
7782
- const signatures = [];
7783
- for (let i = 0; i < payloads.length; i++) {
7784
- const payload = payloads[i];
7785
- const id = payload.id || payload.name || "default";
7786
- if (i > 0) {
7787
- if (this.verbose) process.stderr.write(`[sign_typed_data] waiting 5s between MPC sessions...
6267
+ const signatures = [];
6268
+ for (let i = 0; i < payloads.length; i++) {
6269
+ const payload = payloads[i];
6270
+ const id = payload.id || payload.name || "default";
6271
+ if (i > 0) {
6272
+ if (this.verbose) process.stderr.write(`[sign_typed_data] waiting 5s between MPC sessions...
7788
6273
  `);
7789
- await new Promise((r) => setTimeout(r, 5e3));
7790
- }
7791
- const sig = await this.signSingleTypedData(payload);
7792
- signatures.push({ id, ...sig });
7793
- if (this.verbose) process.stderr.write(`[sign_typed_data] signed payload "${id}"
6274
+ await new Promise((r) => setTimeout(r, 5e3));
6275
+ }
6276
+ const sig = await this.signSingleTypedData(payload);
6277
+ signatures.push({ id, ...sig });
6278
+ if (this.verbose) process.stderr.write(`[sign_typed_data] signed payload "${id}"
7794
6279
  `);
6280
+ }
6281
+ return {
6282
+ signatures,
6283
+ pm_order_ref: input.pm_order_ref,
6284
+ auto_submit: !!(input.__pm_auto_submit || input.auto_submit)
6285
+ };
7795
6286
  }
7796
- return {
7797
- signatures,
7798
- pm_order_ref: params.pm_order_ref,
7799
- auto_submit: !!(params.__pm_auto_submit || params.auto_submit)
7800
- };
7801
- }
7802
- return this.signSingleTypedData(params);
6287
+ return this.signSingleTypedData(input);
6288
+ });
7803
6289
  }
7804
6290
  /**
7805
6291
  * Sign a single EIP-712 typed data object.
@@ -7819,11 +6305,11 @@ var AgentExecutor = class _AgentExecutor {
7819
6305
  `);
7820
6306
  const chainName = params.chain;
7821
6307
  const chainId = domain.chainId;
7822
- let chain = Chain10.Ethereum;
6308
+ let chain = Chain9.Ethereum;
7823
6309
  if (chainName) {
7824
- chain = resolveChain(chainName) || Chain10.Ethereum;
6310
+ chain = resolveChain(chainName) || Chain9.Ethereum;
7825
6311
  } else if (chainId) {
7826
- chain = resolveChainId(chainId) || Chain10.Ethereum;
6312
+ chain = resolveChainId(chainId) || Chain9.Ethereum;
7827
6313
  }
7828
6314
  const sigResult = await this.vault.signBytes({
7829
6315
  data: eip712Hash,
@@ -7848,33 +6334,20 @@ var AgentExecutor = class _AgentExecutor {
7848
6334
  }
7849
6335
  // ============================================================================
7850
6336
  // Address Book
6337
+ //
6338
+ // Live client-side tools — server-side `address_book_*` runs through MCP
6339
+ // for read; mutating writes have no local implementation yet.
7851
6340
  // ============================================================================
7852
- async getAddressBook(params) {
7853
- if (!this.vultisig) {
7854
- throw new Error(
7855
- "get_address_book requires the CLI SDK instance. Ensure AgentConfig.vultisig is set when creating the session."
7856
- );
7857
- }
7858
- const chainName = params.chain || params.chain_name;
7859
- const chain = chainName ? resolveChain(chainName) : void 0;
7860
- if (chainName && !chain) {
7861
- throw new Error(`Unknown chain: ${chainName}`);
7862
- }
7863
- return await this.vultisig.getAddressBook(chain);
6341
+ async addressBookAdd(_toolCallId, input) {
6342
+ return this.runTool("address_book_add", () => this.addAddressBookImpl(input));
7864
6343
  }
7865
- // address_book dispatcher — backend shape:
7866
- // { action: "add" | "remove", entry: { name, chain, address } }
7867
- async addressBook(params) {
7868
- const action = params.action;
7869
- switch (action) {
7870
- case "add":
7871
- return this.addAddressBookImpl(params);
7872
- case "remove":
7873
- return this.removeAddressBookImpl(params);
7874
- default:
7875
- throw new Error(`address_book: unknown action: ${action ?? "(missing)"}`);
7876
- }
6344
+ async addressBookRemove(_toolCallId, input) {
6345
+ return this.runTool("address_book_remove", () => this.removeAddressBookImpl(input));
7877
6346
  }
6347
+ // Backend `address_book { action: "add", entry: {...} }` flows through
6348
+ // this impl. The public `addressBookAdd` wrapper above tags results as
6349
+ // `tool: 'address_book_add'`; the new `addressBook` wrapper tags them as
6350
+ // `tool: 'address_book'` (matching the discriminator tool the backend emits).
7878
6351
  async addAddressBookImpl(params) {
7879
6352
  if (!this.vultisig) {
7880
6353
  throw new Error(
@@ -7938,117 +6411,14 @@ var AgentExecutor = class _AgentExecutor {
7938
6411
  await this.vultisig.removeAddressBookEntry([{ chain, address }]);
7939
6412
  return { removed: { chain: chain.toString(), address } };
7940
6413
  }
7941
- // ============================================================================
7942
- // Token Search & Other
7943
- // ============================================================================
7944
- async searchToken(params) {
7945
- const query = String(params.query ?? params.q ?? "").trim().toLowerCase();
7946
- if (!query) {
7947
- return { tokens: [] };
7948
- }
7949
- const limit = 20;
7950
- const chainName = params.chain;
7951
- const tokenMatchesQuery = (t) => {
7952
- const tick = t.ticker.toLowerCase();
7953
- const addr = (t.contractAddress ?? "").toLowerCase();
7954
- const pid = (t.priceProviderId ?? "").toLowerCase();
7955
- return tick.includes(query) || addr.includes(query) || pid.includes(query);
7956
- };
7957
- if (chainName) {
7958
- const chain = resolveChain(chainName);
7959
- if (!chain) throw new Error(`Unknown chain: ${chainName}`);
7960
- const tokens = VultisigSdk.getKnownTokens(chain).filter(tokenMatchesQuery).slice(0, limit);
7961
- return { tokens };
7962
- }
7963
- const out = [];
7964
- for (const c of Object.values(Chain10)) {
7965
- for (const t of VultisigSdk.getKnownTokens(c)) {
7966
- if (!tokenMatchesQuery(t)) continue;
7967
- out.push(t);
7968
- if (out.length >= limit) return { tokens: out };
7969
- }
7970
- }
7971
- return { tokens: out };
7972
- }
7973
- async listVaults() {
7974
- return {
7975
- vaults: [
7976
- {
7977
- name: this.vault.name,
7978
- id: this.vault.id,
7979
- type: this.vault.type,
7980
- chains: this.vault.chains.map((c) => c.toString())
7981
- }
7982
- ]
7983
- };
7984
- }
7985
- async scanTx(_params) {
7986
- throw new Error("scan_tx is not yet implemented locally. The backend may handle this action server-side.");
7987
- }
7988
- async readEvmContract(params) {
7989
- const chainName = params.chain;
7990
- if (!chainName) throw new Error("read_evm_contract requires chain");
7991
- const contractRaw = params.contract_address || params.contractAddress;
7992
- if (!contractRaw) throw new Error("read_evm_contract requires contract_address");
7993
- const functionName = params.function_name || params.functionName;
7994
- if (!functionName) throw new Error("read_evm_contract requires function_name");
7995
- const chain = resolveChain(chainName);
7996
- if (!chain) throw new Error(`Unknown chain: ${chainName}`);
7997
- if (!EVM_CHAINS.has(chain)) {
7998
- throw new Error(`read_evm_contract only supports EVM chains (got ${chain})`);
7999
- }
8000
- const callParams = params.params ?? [];
8001
- const data = await encodeContractCall(functionName, callParams);
8002
- const addr = contractRaw.startsWith("0x") ? contractRaw : `0x${contractRaw}`;
8003
- const to = addr;
8004
- const from = params.from;
8005
- const result = await evmCall(chain, { to, data, from });
8006
- return { result };
8007
- }
8008
6414
  };
8009
- async function encodeContractCall(functionName, params) {
8010
- const baseName = functionName.includes("(") ? functionName.split("(")[0] : functionName;
8011
- const types = params.map((p) => p.type);
8012
- const sig = `${baseName}(${types.join(",")})`;
8013
- const selector = await keccak256Selector(sig);
8014
- let encoded = "";
8015
- for (const param of params) {
8016
- encoded += abiEncodeParam(param.type, param.value);
8017
- }
8018
- return "0x" + selector + encoded;
8019
- }
8020
- async function keccak256Selector(sig) {
8021
- const { keccak_256: keccak_2562 } = await Promise.resolve().then(() => (init_sha3(), sha3_exports));
8022
- const hash = keccak_2562(new TextEncoder().encode(sig));
8023
- return Buffer.from(hash).toString("hex").slice(0, 8);
8024
- }
8025
- function abiEncodeParam(type, value) {
8026
- if (type === "address") {
8027
- const addr = value.startsWith("0x") ? value.slice(2) : value;
8028
- return addr.toLowerCase().padStart(64, "0");
8029
- }
8030
- if (type.startsWith("uint") || type.startsWith("int")) {
8031
- const n = BigInt(value);
8032
- const hex = n.toString(16);
8033
- return hex.padStart(64, "0");
8034
- }
8035
- if (type === "bool") {
8036
- return (value === "true" || value === "1" ? "1" : "0").padStart(64, "0");
8037
- }
8038
- if (type === "bytes32") {
8039
- const b2 = value.startsWith("0x") ? value.slice(2) : value;
8040
- return b2.padEnd(64, "0");
8041
- }
8042
- const b = value.startsWith("0x") ? value.slice(2) : Buffer.from(value).toString("hex");
8043
- return b.padStart(64, "0");
8044
- }
8045
6415
  function resolveChain(name) {
8046
6416
  if (!name) return null;
8047
- if (Object.values(Chain10).includes(name)) {
6417
+ if (Object.values(Chain9).includes(name)) {
8048
6418
  return name;
8049
6419
  }
8050
6420
  const lower = name.toLowerCase();
8051
- for (const [, value] of Object.entries(Chain10)) {
6421
+ for (const [, value] of Object.entries(Chain9)) {
8052
6422
  if (typeof value === "string" && value.toLowerCase() === lower) {
8053
6423
  return value;
8054
6424
  }
@@ -8074,16 +6444,11 @@ function resolveChain(name) {
8074
6444
  xrp: "Ripple"
8075
6445
  };
8076
6446
  const aliased = aliases[lower];
8077
- if (aliased && Object.values(Chain10).includes(aliased)) {
6447
+ if (aliased && Object.values(Chain9).includes(aliased)) {
8078
6448
  return aliased;
8079
6449
  }
8080
6450
  return null;
8081
6451
  }
8082
- function parseAmount(amountStr, decimals) {
8083
- const [whole, frac = ""] = amountStr.split(".");
8084
- const paddedFrac = frac.slice(0, decimals).padEnd(decimals, "0");
8085
- return BigInt(whole || "0") * 10n ** BigInt(decimals) + BigInt(paddedFrac || "0");
8086
- }
8087
6452
  function resolveChainFromTxReady(txReadyData) {
8088
6453
  if (txReadyData.chain) {
8089
6454
  const chain = resolveChain(txReadyData.chain);
@@ -8119,16 +6484,16 @@ function resolveChainId(chainId) {
8119
6484
  const id = typeof chainId === "string" ? parseInt(chainId, 10) : chainId;
8120
6485
  if (isNaN(id)) return null;
8121
6486
  const chainIdMap = {
8122
- 1: Chain10.Ethereum,
8123
- 56: Chain10.BSC,
8124
- 137: Chain10.Polygon,
8125
- 43114: Chain10.Avalanche,
8126
- 42161: Chain10.Arbitrum,
8127
- 10: Chain10.Optimism,
8128
- 8453: Chain10.Base,
8129
- 81457: Chain10.Blast,
8130
- 324: Chain10.Zksync,
8131
- 25: Chain10.CronosChain
6487
+ 1: Chain9.Ethereum,
6488
+ 56: Chain9.BSC,
6489
+ 137: Chain9.Polygon,
6490
+ 43114: Chain9.Avalanche,
6491
+ 42161: Chain9.Arbitrum,
6492
+ 10: Chain9.Optimism,
6493
+ 8453: Chain9.Base,
6494
+ 81457: Chain9.Blast,
6495
+ 324: Chain9.Zksync,
6496
+ 25: Chain9.CronosChain
8132
6497
  };
8133
6498
  return chainIdMap[id] || null;
8134
6499
  }
@@ -8507,22 +6872,14 @@ import { existsSync, mkdirSync as mkdirSync2, readFileSync as readFileSync2, wri
8507
6872
  import { homedir as homedir2 } from "node:os";
8508
6873
  import { join as join2 } from "node:path";
8509
6874
  import { MemoryStorage, PushNotificationService } from "@vultisig/sdk";
6875
+ var PASSWORD_REQUIRED_TOOLS = /* @__PURE__ */ new Set(["sign_typed_data", "sign_tx"]);
8510
6876
  var CLIENT_SIDE_TOOL_DISPATCH = {
8511
- sign_typed_data: "sign_typed_data",
8512
- vault_coin: "vault_coin",
8513
- vault_chain: "vault_chain",
8514
- address_book: "address_book"
6877
+ sign_typed_data: (ex, id, input) => ex.signTypedData(id, input),
6878
+ vault_coin: (ex, id, input) => ex.vaultCoin(id, input),
6879
+ vault_chain: (ex, id, input) => ex.vaultChain(id, input),
6880
+ address_book: (ex, id, input) => ex.addressBook(id, input)
8515
6881
  };
8516
6882
  var MAX_MESSAGE_LOOP_DEPTH = 16;
8517
- function actionResultToRecentAction(r) {
8518
- if (r.success) {
8519
- return { tool: r.action, success: true, data: r.data ?? {} };
8520
- }
8521
- const data = { ...r.data ?? {} };
8522
- if (r.error) data.error = r.error;
8523
- if (r.code) data.code = r.code;
8524
- return { tool: r.action, success: false, data };
8525
- }
8526
6883
  var AgentSession = class {
8527
6884
  client;
8528
6885
  vault;
@@ -8779,21 +7136,22 @@ var AgentSession = class {
8779
7136
  `[session] ${serverTxStoredFromStream} stored server tx from tx_ready, signing client-side
8780
7137
  `
8781
7138
  );
8782
- const signAction = {
8783
- id: `tx_sign_${Date.now()}`,
8784
- type: "sign_tx",
8785
- title: "Sign transaction",
8786
- params: {},
8787
- auto_execute: true
8788
- };
8789
- const results = await this.executeActions([signAction], ui);
8790
- if (results.length > 0) {
8791
- for (const result of results) {
8792
- this.pendingToolResults.push(actionResultToRecentAction(result));
8793
- }
8794
- await this.processMessageLoop(null, ui, depth + 1);
8795
- return;
7139
+ const signToolCallId = `tx_sign_${Date.now()}`;
7140
+ const recent = await this.runPasswordGatedTool(
7141
+ "sign_tx",
7142
+ signToolCallId,
7143
+ ui,
7144
+ () => this.executor.signTxFromBuffer(signToolCallId)
7145
+ );
7146
+ this.pendingToolResults.push(recent);
7147
+ if (recent.success && recent.data) {
7148
+ const txHash = recent.data.tx_hash;
7149
+ const chain = recent.data.chain;
7150
+ const explorerUrl = recent.data.explorer_url;
7151
+ if (txHash) ui.onTxStatus(txHash, chain || "", "pending", explorerUrl);
8796
7152
  }
7153
+ await this.processMessageLoop(null, ui, depth + 1);
7154
+ return;
8797
7155
  }
8798
7156
  if (this.pendingToolResults.length > 0) {
8799
7157
  await this.processMessageLoop(null, ui, depth + 1);
@@ -8801,12 +7159,59 @@ var AgentSession = class {
8801
7159
  }
8802
7160
  ui.onDone();
8803
7161
  }
8804
- // Routes client-side tool calls through executeAction. Missing registry
7162
+ /**
7163
+ * Wrap a per-tool dispatch with the password-prompt gate (for tools in
7164
+ * {@link PASSWORD_REQUIRED_TOOLS}) and `ui.onToolCall` /
7165
+ * `ui.onToolResult` lifecycle events. Returns the `RecentAction` produced
7166
+ * by the executor (or a synthetic failure `RecentAction` if the password
7167
+ * prompt was declined).
7168
+ */
7169
+ async runPasswordGatedTool(toolName, toolCallId, ui, body, input) {
7170
+ let promptedPassword;
7171
+ if (PASSWORD_REQUIRED_TOOLS.has(toolName) && !this.config.password) {
7172
+ try {
7173
+ promptedPassword = await ui.requestPassword();
7174
+ this.executor.setPassword(promptedPassword);
7175
+ } catch {
7176
+ const failure = {
7177
+ tool: toolName,
7178
+ success: false,
7179
+ data: { error: "Password not provided", code: "PASSWORD_REQUIRED" /* PASSWORD_REQUIRED */ }
7180
+ };
7181
+ ui.onToolCall(toolCallId, toolName, input);
7182
+ ui.onToolResult(
7183
+ toolCallId,
7184
+ toolName,
7185
+ false,
7186
+ failure.data,
7187
+ "Password not provided",
7188
+ "PASSWORD_REQUIRED" /* PASSWORD_REQUIRED */
7189
+ );
7190
+ return failure;
7191
+ }
7192
+ }
7193
+ ui.onToolCall(toolCallId, toolName, input);
7194
+ let recent;
7195
+ try {
7196
+ recent = await body();
7197
+ } catch (err) {
7198
+ const message = err instanceof Error ? err.message : String(err);
7199
+ recent = { tool: toolName, success: false, data: { error: message } };
7200
+ }
7201
+ const errorMsg = recent.data?.error ?? void 0;
7202
+ const errorCode = recent.data?.code ?? void 0;
7203
+ ui.onToolResult(toolCallId, toolName, recent.success, recent.data, errorMsg, errorCode);
7204
+ if (promptedPassword && recent.success) {
7205
+ this.config.password = promptedPassword;
7206
+ }
7207
+ return recent;
7208
+ }
7209
+ // Routes client-side tool calls through the per-tool registry. Missing
8805
7210
  // entries surface as a visible `[cli] unimplemented` warning + failure
8806
7211
  // RecentAction (never silent).
8807
7212
  async dispatchClientSideTool(toolCallId, toolName, input, ui) {
8808
- const actionType = CLIENT_SIDE_TOOL_DISPATCH[toolName];
8809
- if (!actionType) {
7213
+ const handler = CLIENT_SIDE_TOOL_DISPATCH[toolName];
7214
+ if (!handler) {
8810
7215
  process.stderr.write(`[cli] unimplemented client-side tool: ${toolName}
8811
7216
  `);
8812
7217
  this.pendingToolResults.push({
@@ -8816,76 +7221,26 @@ var AgentSession = class {
8816
7221
  });
8817
7222
  return;
8818
7223
  }
8819
- const action = {
8820
- id: toolCallId,
8821
- type: actionType,
8822
- title: toolName,
8823
- params: input,
8824
- auto_execute: true
8825
- };
7224
+ let recent;
8826
7225
  try {
8827
- const results = await this.executeActions([action], ui);
8828
- const result = results[0];
8829
- if (result) {
8830
- const recent = actionResultToRecentAction(result);
8831
- if (recent.data === void 0) recent.data = {};
8832
- for (const key of Object.keys(input)) {
8833
- if (key.startsWith("__") || key === "pm_order_ref") {
8834
- recent.data[key] = input[key];
8835
- }
8836
- }
8837
- this.pendingToolResults.push(recent);
8838
- }
7226
+ recent = await this.runPasswordGatedTool(
7227
+ toolName,
7228
+ toolCallId,
7229
+ ui,
7230
+ () => handler(this.executor, toolCallId, input),
7231
+ input
7232
+ );
8839
7233
  } catch (err) {
8840
7234
  const message = err instanceof Error ? err.message : String(err);
8841
- this.pendingToolResults.push({
8842
- tool: toolName,
8843
- success: false,
8844
- data: { error: message }
8845
- });
7235
+ recent = { tool: toolName, success: false, data: { error: message } };
8846
7236
  }
8847
- }
8848
- /**
8849
- * Execute a list of actions, handling password requirements.
8850
- */
8851
- async executeActions(actions, ui) {
8852
- const results = [];
8853
- for (const action of actions) {
8854
- if (!this.executor.shouldAutoExecute(action)) {
8855
- continue;
8856
- }
8857
- if (PASSWORD_REQUIRED_ACTIONS.has(action.type)) {
8858
- if (!this.config.password) {
8859
- try {
8860
- const password = await ui.requestPassword();
8861
- this.executor.setPassword(password);
8862
- this.config.password = password;
8863
- } catch {
8864
- results.push({
8865
- action: action.type,
8866
- action_id: action.id,
8867
- success: false,
8868
- error: "Password not provided",
8869
- code: "PASSWORD_REQUIRED" /* PASSWORD_REQUIRED */
8870
- });
8871
- continue;
8872
- }
8873
- }
8874
- }
8875
- ui.onToolCall(action.id, action.type, action.params);
8876
- const result = await this.executor.executeAction(action);
8877
- results.push(result);
8878
- ui.onToolResult(action.id, action.type, result.success, result.data, result.error, result.code);
8879
- if (action.type === "sign_tx" && result.success && result.data) {
8880
- const txHash = result.data.tx_hash;
8881
- const chain = result.data.chain;
8882
- const explorerUrl = result.data.explorer_url;
8883
- if (txHash) {
8884
- ui.onTxStatus(txHash, chain, "pending", explorerUrl);
8885
- }
7237
+ if (recent.data === void 0) recent.data = {};
7238
+ for (const key of Object.keys(input)) {
7239
+ if (key.startsWith("__") || key === "pm_order_ref") {
7240
+ recent.data[key] = input[key];
8886
7241
  }
8887
7242
  }
8888
- return results;
7243
+ this.pendingToolResults.push(recent);
8889
7244
  }
8890
7245
  /**
8891
7246
  * Cancel the current operation.
@@ -9503,7 +7858,7 @@ var cachedVersion = null;
9503
7858
  function getVersion() {
9504
7859
  if (cachedVersion) return cachedVersion;
9505
7860
  if (true) {
9506
- cachedVersion = "0.22.4";
7861
+ cachedVersion = "0.22.5";
9507
7862
  return cachedVersion;
9508
7863
  }
9509
7864
  try {
@@ -9786,7 +8141,7 @@ function readArgValue(args, optionName) {
9786
8141
  }
9787
8142
 
9788
8143
  // src/interactive/completer.ts
9789
- import { Chain as Chain11 } from "@vultisig/sdk";
8144
+ import { Chain as Chain10 } from "@vultisig/sdk";
9790
8145
  import fs3 from "fs";
9791
8146
  import path3 from "path";
9792
8147
  var COMMANDS = [
@@ -9930,7 +8285,7 @@ function completeVaultName(ctx2, partial) {
9930
8285
  return [show, partial];
9931
8286
  }
9932
8287
  function completeChainName(partial) {
9933
- const allChains = Object.values(Chain11);
8288
+ const allChains = Object.values(Chain10);
9934
8289
  const partialLower = partial.toLowerCase();
9935
8290
  const matches = allChains.filter((chain) => chain.toLowerCase().startsWith(partialLower));
9936
8291
  matches.sort();
@@ -9938,7 +8293,7 @@ function completeChainName(partial) {
9938
8293
  return [show, partial];
9939
8294
  }
9940
8295
  function findChainByName(name) {
9941
- const allChains = Object.values(Chain11);
8296
+ const allChains = Object.values(Chain10);
9942
8297
  const nameLower = name.toLowerCase();
9943
8298
  const found = allChains.find((chain) => chain.toLowerCase() === nameLower);
9944
8299
  return found ? found : null;