@zoralabs/cli 0.3.0 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +849 -396
- package/package.json +4 -3
package/dist/index.js
CHANGED
|
@@ -52,6 +52,12 @@ function apiErrorMessage(err) {
|
|
|
52
52
|
return "Zora is temporarily unavailable. Try again later.";
|
|
53
53
|
return formatError(err);
|
|
54
54
|
}
|
|
55
|
+
function bannedCoinMessage(address) {
|
|
56
|
+
return `The coin at ${address} is unavailable because it violates the Zora terms of service.`;
|
|
57
|
+
}
|
|
58
|
+
function bannedCoinBuyMessage(address) {
|
|
59
|
+
return `Unable to buy ${address} because it violates the Zora terms of service. Already own this coin? Run zora sell ${address} --all to exit your position.`;
|
|
60
|
+
}
|
|
55
61
|
function fsErrorMessage(err, path) {
|
|
56
62
|
if (!(err instanceof Error)) return String(err);
|
|
57
63
|
const code = err.code;
|
|
@@ -431,7 +437,7 @@ var getClient = () => {
|
|
|
431
437
|
return client;
|
|
432
438
|
};
|
|
433
439
|
var commonProperties = () => ({
|
|
434
|
-
cli_version: true ? "0.3.
|
|
440
|
+
cli_version: true ? "0.3.1" : "development",
|
|
435
441
|
os: process.platform,
|
|
436
442
|
arch: process.arch,
|
|
437
443
|
node_version: process.version
|
|
@@ -671,7 +677,7 @@ var Table = ({
|
|
|
671
677
|
|
|
672
678
|
// src/lib/format.ts
|
|
673
679
|
import { format, formatDistanceStrict } from "date-fns";
|
|
674
|
-
import {
|
|
680
|
+
import { formatUnits } from "viem";
|
|
675
681
|
function formatCompactUsd(value) {
|
|
676
682
|
if (!value || Number(value) === 0) return "$0";
|
|
677
683
|
return new Intl.NumberFormat("en-US", {
|
|
@@ -720,17 +726,28 @@ function formatCreatedAt(isoDate, now) {
|
|
|
720
726
|
if (isNaN(date.getTime())) return "-";
|
|
721
727
|
return `${formatRelativeTime(date, now)} (${formatAbsoluteTime(date)})`;
|
|
722
728
|
}
|
|
723
|
-
var
|
|
724
|
-
const
|
|
725
|
-
const parts =
|
|
726
|
-
if (!parts[1])
|
|
727
|
-
|
|
728
|
-
|
|
729
|
+
var formatAmountDisplay = (amount, decimals) => {
|
|
730
|
+
const formatted = formatUnits(amount, decimals);
|
|
731
|
+
const parts = formatted.split(".");
|
|
732
|
+
if (!parts[1]) {
|
|
733
|
+
return new Intl.NumberFormat("en-US", {
|
|
734
|
+
maximumFractionDigits: 2
|
|
735
|
+
}).format(Number(formatted));
|
|
736
|
+
}
|
|
737
|
+
const twoDecimal = `${parts[0]}.${parts[1].slice(0, 2)}`;
|
|
738
|
+
if (Number(twoDecimal) === 0 && amount > 0n) {
|
|
739
|
+
const sigIndex = parts[1].search(/[1-9]/);
|
|
740
|
+
const maxDecimals = sigIndex === -1 ? 6 : Math.min(sigIndex + 4, parts[1].length);
|
|
741
|
+
const truncated = `${parts[0]}.${parts[1].slice(0, maxDecimals)}`;
|
|
742
|
+
return new Intl.NumberFormat("en-US", {
|
|
743
|
+
maximumFractionDigits: maxDecimals
|
|
744
|
+
}).format(Number(truncated));
|
|
745
|
+
}
|
|
746
|
+
return new Intl.NumberFormat("en-US", {
|
|
747
|
+
maximumFractionDigits: 2
|
|
748
|
+
}).format(Number(formatted));
|
|
729
749
|
};
|
|
730
750
|
var truncateAddress = (address) => `${address.slice(0, 6)}\u2026${address.slice(-4)}`;
|
|
731
|
-
var formatCoinsDisplay = (coinsOut) => new Intl.NumberFormat("en-US", {
|
|
732
|
-
maximumFractionDigits: 2
|
|
733
|
-
}).format(Number(coinsOut));
|
|
734
751
|
|
|
735
752
|
// src/lib/balance-format.ts
|
|
736
753
|
var COIN_DECIMALS = 18;
|
|
@@ -961,8 +978,7 @@ var BalanceView = ({
|
|
|
961
978
|
const hints = [];
|
|
962
979
|
if (paginated && cursorHistory.length > 0) hints.push("\u2190 prev");
|
|
963
980
|
if (paginated && data?.pageInfo?.hasNextPage) hints.push("\u2192 next");
|
|
964
|
-
hints.push("r refresh");
|
|
965
|
-
if (autoRefresh) hints.push(`auto: ${secondsUntilRefresh}s`);
|
|
981
|
+
hints.push(autoRefresh ? `r refresh (${secondsUntilRefresh}s)` : "r refresh");
|
|
966
982
|
hints.push("q quit");
|
|
967
983
|
const footer = hints.join(" \xB7 ");
|
|
968
984
|
const showWallet = mode === "full" || mode === "wallet";
|
|
@@ -1017,7 +1033,7 @@ import { getTokenInfo } from "@zoralabs/coins-sdk";
|
|
|
1017
1033
|
import {
|
|
1018
1034
|
createPublicClient as createPublicClient2,
|
|
1019
1035
|
erc20Abi,
|
|
1020
|
-
formatUnits,
|
|
1036
|
+
formatUnits as formatUnits2,
|
|
1021
1037
|
http
|
|
1022
1038
|
} from "viem";
|
|
1023
1039
|
import { base as base2 } from "viem/chains";
|
|
@@ -1102,7 +1118,7 @@ var fetchWalletBalances = async (walletAddress) => {
|
|
|
1102
1118
|
});
|
|
1103
1119
|
const visible = resolved.filter((r) => r.balance > 0n || r.token.isNative);
|
|
1104
1120
|
const intermediate = visible.map(({ token, balance, priceUsd }) => {
|
|
1105
|
-
const human =
|
|
1121
|
+
const human = formatUnits2(balance, token.decimals);
|
|
1106
1122
|
const usdValue = priceUsd !== null ? Number(human) * priceUsd : null;
|
|
1107
1123
|
return { token, human, priceUsd, usdValue };
|
|
1108
1124
|
});
|
|
@@ -1527,10 +1543,10 @@ balanceCommand.command("coins").description("Show coin positions").option("--sor
|
|
|
1527
1543
|
// src/commands/buy.ts
|
|
1528
1544
|
import { Command as Command3 } from "commander";
|
|
1529
1545
|
import confirm2 from "@inquirer/confirm";
|
|
1530
|
-
import { parseUnits, formatUnits as
|
|
1546
|
+
import { parseUnits, formatUnits as formatUnits4, isAddress } from "viem";
|
|
1531
1547
|
import {
|
|
1532
1548
|
setApiKey as setApiKey2,
|
|
1533
|
-
getCoin,
|
|
1549
|
+
getCoin as getCoin2,
|
|
1534
1550
|
tradeCoin,
|
|
1535
1551
|
createTradeCall
|
|
1536
1552
|
} from "@zoralabs/coins-sdk";
|
|
@@ -1538,7 +1554,7 @@ import {
|
|
|
1538
1554
|
// src/lib/trade-helpers.ts
|
|
1539
1555
|
import {
|
|
1540
1556
|
parseEther,
|
|
1541
|
-
formatUnits as
|
|
1557
|
+
formatUnits as formatUnits3,
|
|
1542
1558
|
isAddressEqual,
|
|
1543
1559
|
parseEventLogs,
|
|
1544
1560
|
erc20Abi as erc20Abi2
|
|
@@ -1571,25 +1587,6 @@ var parsePercentageLikeValue = (value) => {
|
|
|
1571
1587
|
const parsed = Number(value);
|
|
1572
1588
|
return Number.isFinite(parsed) ? parsed : void 0;
|
|
1573
1589
|
};
|
|
1574
|
-
var formatAmountDisplay = (amount, decimals) => {
|
|
1575
|
-
const formatted = formatUnits2(amount, decimals);
|
|
1576
|
-
const parts = formatted.split(".");
|
|
1577
|
-
if (!parts[1]) {
|
|
1578
|
-
return new Intl.NumberFormat("en-US", {
|
|
1579
|
-
maximumFractionDigits: 2
|
|
1580
|
-
}).format(Number(formatted));
|
|
1581
|
-
}
|
|
1582
|
-
const twoDecimal = `${parts[0]}.${parts[1].slice(0, 2)}`;
|
|
1583
|
-
let maxDecimals = 2;
|
|
1584
|
-
if (Number(twoDecimal) === 0 && amount > 0n) {
|
|
1585
|
-
const sigIndex = parts[1].search(/[1-9]/);
|
|
1586
|
-
maxDecimals = sigIndex === -1 ? 6 : Math.min(sigIndex + 4, parts[1].length);
|
|
1587
|
-
}
|
|
1588
|
-
const truncated = `${parts[0]}.${parts[1].slice(0, maxDecimals)}`;
|
|
1589
|
-
return new Intl.NumberFormat("en-US", {
|
|
1590
|
-
maximumFractionDigits: maxDecimals
|
|
1591
|
-
}).format(Number(truncated));
|
|
1592
|
-
};
|
|
1593
1590
|
var getReceivedAmountFromReceipt = ({
|
|
1594
1591
|
receipt,
|
|
1595
1592
|
tokenAddress,
|
|
@@ -1655,12 +1652,12 @@ var printQuote = (json, info) => {
|
|
|
1655
1652
|
coin: info.coinSymbol,
|
|
1656
1653
|
address: info.address,
|
|
1657
1654
|
spend: {
|
|
1658
|
-
amount:
|
|
1655
|
+
amount: formatUnits3(info.amountIn, info.inputTokenDecimals),
|
|
1659
1656
|
raw: info.amountIn.toString(),
|
|
1660
1657
|
symbol: info.inputTokenSymbol
|
|
1661
1658
|
},
|
|
1662
1659
|
estimated: {
|
|
1663
|
-
amount:
|
|
1660
|
+
amount: formatUnits3(BigInt(info.amountOut), 18),
|
|
1664
1661
|
raw: info.amountOut,
|
|
1665
1662
|
symbol: info.coinSymbol
|
|
1666
1663
|
},
|
|
@@ -1668,29 +1665,33 @@ var printQuote = (json, info) => {
|
|
|
1668
1665
|
});
|
|
1669
1666
|
return;
|
|
1670
1667
|
}
|
|
1668
|
+
const spendFormatted = formatAmountDisplay(
|
|
1669
|
+
info.amountIn,
|
|
1670
|
+
info.inputTokenDecimals
|
|
1671
|
+
);
|
|
1672
|
+
const coinsFormatted = formatAmountDisplay(BigInt(info.amountOut), 18);
|
|
1671
1673
|
console.log(`
|
|
1672
|
-
Buy ${info.coinName}
|
|
1674
|
+
Buy \x1B[1m${info.coinName}\x1B[0m`);
|
|
1675
|
+
console.log(` ${info.coinType} \xB7 ${info.address}
|
|
1673
1676
|
`);
|
|
1674
|
-
console.log(` Amount ${info.
|
|
1675
|
-
console.log(` You get ~${
|
|
1677
|
+
console.log(` Amount ${spendFormatted} ${info.inputTokenSymbol}`);
|
|
1678
|
+
console.log(` You get ~${coinsFormatted} ${info.coinSymbol}`);
|
|
1676
1679
|
console.log(` Slippage ${info.slippagePct}%
|
|
1677
1680
|
`);
|
|
1678
1681
|
};
|
|
1679
1682
|
var printTradeResult = (json, info) => {
|
|
1680
|
-
const receivedAmount = formatUnits2(info.receivedAmountOut, 18);
|
|
1681
|
-
const receivedFormatted = formatCoinsDisplay(receivedAmount);
|
|
1682
1683
|
if (json) {
|
|
1683
1684
|
outputJson({
|
|
1684
1685
|
action: "buy",
|
|
1685
1686
|
coin: info.coinSymbol,
|
|
1686
1687
|
address: info.address,
|
|
1687
1688
|
spent: {
|
|
1688
|
-
amount:
|
|
1689
|
+
amount: formatUnits3(info.amountIn, info.inputTokenDecimals),
|
|
1689
1690
|
raw: info.amountIn.toString(),
|
|
1690
1691
|
symbol: info.inputTokenSymbol
|
|
1691
1692
|
},
|
|
1692
1693
|
received: {
|
|
1693
|
-
amount:
|
|
1694
|
+
amount: formatUnits3(info.receivedAmountOut, 18),
|
|
1694
1695
|
raw: info.receivedAmountOut.toString(),
|
|
1695
1696
|
symbol: info.coinSymbol
|
|
1696
1697
|
},
|
|
@@ -1698,21 +1699,233 @@ var printTradeResult = (json, info) => {
|
|
|
1698
1699
|
});
|
|
1699
1700
|
return;
|
|
1700
1701
|
}
|
|
1702
|
+
const spentFormatted = formatAmountDisplay(
|
|
1703
|
+
info.amountIn,
|
|
1704
|
+
info.inputTokenDecimals
|
|
1705
|
+
);
|
|
1706
|
+
const receivedFormatted = formatAmountDisplay(info.receivedAmountOut, 18);
|
|
1701
1707
|
console.log(`
|
|
1702
|
-
Bought ${info.coinName}
|
|
1708
|
+
Bought \x1B[1m${info.coinName}\x1B[0m`);
|
|
1709
|
+
console.log(` ${info.coinType} \xB7 ${info.address}
|
|
1703
1710
|
`);
|
|
1704
|
-
console.log(` Spent ${
|
|
1711
|
+
console.log(` Spent ${spentFormatted} ${info.inputTokenSymbol}`);
|
|
1705
1712
|
console.log(` Received ${receivedFormatted} ${info.coinSymbol}`);
|
|
1706
1713
|
console.log(` Tx ${info.txHash}
|
|
1707
1714
|
`);
|
|
1708
1715
|
};
|
|
1709
1716
|
|
|
1717
|
+
// src/lib/coin-ref.ts
|
|
1718
|
+
import { getCoin, getProfile, getTrend } from "@zoralabs/coins-sdk";
|
|
1719
|
+
var TYPE_KEYWORDS = /* @__PURE__ */ new Set(["creator-coin", "trend"]);
|
|
1720
|
+
var CoinArgError = class extends Error {
|
|
1721
|
+
suggestion;
|
|
1722
|
+
constructor(message, suggestion) {
|
|
1723
|
+
super(message);
|
|
1724
|
+
this.suggestion = suggestion;
|
|
1725
|
+
}
|
|
1726
|
+
};
|
|
1727
|
+
function parsePositionalCoinArgs(firstArg, secondArg) {
|
|
1728
|
+
if (TYPE_KEYWORDS.has(firstArg)) {
|
|
1729
|
+
if (!secondArg) {
|
|
1730
|
+
throw new CoinArgError(
|
|
1731
|
+
`Missing identifier after "${firstArg}".`,
|
|
1732
|
+
`Usage: zora <command> ${firstArg} <name>`
|
|
1733
|
+
);
|
|
1734
|
+
}
|
|
1735
|
+
return { kind: "typed", type: firstArg, identifier: secondArg };
|
|
1736
|
+
}
|
|
1737
|
+
if (firstArg.startsWith("0x")) {
|
|
1738
|
+
return { kind: "address", address: firstArg };
|
|
1739
|
+
}
|
|
1740
|
+
return { kind: "ambiguous-name", name: firstArg };
|
|
1741
|
+
}
|
|
1742
|
+
function coinArgsToRef(parsed) {
|
|
1743
|
+
switch (parsed.kind) {
|
|
1744
|
+
case "typed":
|
|
1745
|
+
return { kind: "prefixed", type: parsed.type, name: parsed.identifier };
|
|
1746
|
+
case "address":
|
|
1747
|
+
return { kind: "address", address: parsed.address };
|
|
1748
|
+
case "ambiguous-name":
|
|
1749
|
+
return { kind: "ambiguous", name: parsed.name };
|
|
1750
|
+
}
|
|
1751
|
+
}
|
|
1752
|
+
async function resolveAmbiguousName(name) {
|
|
1753
|
+
const [creatorResult, trendResult] = await Promise.all([
|
|
1754
|
+
resolveByCreatorName(name),
|
|
1755
|
+
resolveByTrendTicker(name)
|
|
1756
|
+
]);
|
|
1757
|
+
const creatorFound = creatorResult.kind === "found" ? creatorResult.coin : null;
|
|
1758
|
+
const trendFound = trendResult.kind === "found" ? trendResult.coin : null;
|
|
1759
|
+
if (creatorFound && trendFound) {
|
|
1760
|
+
return { kind: "ambiguous", creator: creatorFound, trend: trendFound };
|
|
1761
|
+
}
|
|
1762
|
+
if (creatorFound) {
|
|
1763
|
+
return { kind: "found", coin: creatorFound };
|
|
1764
|
+
}
|
|
1765
|
+
if (trendFound) {
|
|
1766
|
+
return { kind: "found", coin: trendFound };
|
|
1767
|
+
}
|
|
1768
|
+
return {
|
|
1769
|
+
kind: "not-found",
|
|
1770
|
+
message: `No coin found matching "${name}".`
|
|
1771
|
+
};
|
|
1772
|
+
}
|
|
1773
|
+
function formatAmbiguousError(name, creator, trend, command) {
|
|
1774
|
+
const creatorMcap = formatCompactUsd(creator.marketCap);
|
|
1775
|
+
const trendMcap = formatCompactUsd(trend.marketCap);
|
|
1776
|
+
return {
|
|
1777
|
+
message: [
|
|
1778
|
+
`Multiple coins match "${name}":`,
|
|
1779
|
+
` creator-coin ${creator.name} ${creatorMcap} mcap`,
|
|
1780
|
+
` trend ${trend.name} ${trendMcap} mcap`
|
|
1781
|
+
].join("\n"),
|
|
1782
|
+
suggestion: `Use: zora ${command} creator-coin ${name} or zora ${command} trend ${name}`
|
|
1783
|
+
};
|
|
1784
|
+
}
|
|
1785
|
+
var COIN_TYPE_MAP = {
|
|
1786
|
+
CONTENT: "post",
|
|
1787
|
+
CREATOR: "creator-coin",
|
|
1788
|
+
TREND: "trend"
|
|
1789
|
+
};
|
|
1790
|
+
function mapCoinType(raw) {
|
|
1791
|
+
if (!raw) return "unknown";
|
|
1792
|
+
return COIN_TYPE_MAP[raw] ?? "unknown";
|
|
1793
|
+
}
|
|
1794
|
+
function coinFromToken(token) {
|
|
1795
|
+
return {
|
|
1796
|
+
name: token.name ?? "Unknown",
|
|
1797
|
+
address: token.address ?? "",
|
|
1798
|
+
coinType: mapCoinType(token.coinType),
|
|
1799
|
+
marketCap: token.marketCap ?? "0",
|
|
1800
|
+
marketCapDelta24h: token.marketCapDelta24h ?? "0",
|
|
1801
|
+
volume24h: token.volume24h ?? "0",
|
|
1802
|
+
uniqueHolders: token.uniqueHolders ?? 0,
|
|
1803
|
+
createdAt: token.createdAt,
|
|
1804
|
+
creatorAddress: token.creatorAddress,
|
|
1805
|
+
creatorHandle: token.creatorProfile?.handle,
|
|
1806
|
+
platformBlocked: token.platformBlocked ?? false
|
|
1807
|
+
};
|
|
1808
|
+
}
|
|
1809
|
+
async function resolveByAddress(address) {
|
|
1810
|
+
const response = await getCoin({ address });
|
|
1811
|
+
if (response.error || !response.data?.zora20Token) {
|
|
1812
|
+
return {
|
|
1813
|
+
kind: "not-found",
|
|
1814
|
+
message: `No coin found at address ${address}`
|
|
1815
|
+
};
|
|
1816
|
+
}
|
|
1817
|
+
return { kind: "found", coin: coinFromToken(response.data.zora20Token) };
|
|
1818
|
+
}
|
|
1819
|
+
async function resolveByTrendTicker(ticker) {
|
|
1820
|
+
const response = await getTrend({ ticker });
|
|
1821
|
+
if (response.error || !response.data?.trendCoin) {
|
|
1822
|
+
return {
|
|
1823
|
+
kind: "not-found",
|
|
1824
|
+
message: `No trend coin found with ticker "${ticker}"`
|
|
1825
|
+
};
|
|
1826
|
+
}
|
|
1827
|
+
return { kind: "found", coin: coinFromToken(response.data.trendCoin) };
|
|
1828
|
+
}
|
|
1829
|
+
async function resolveByCreatorName(name) {
|
|
1830
|
+
const response = await getProfile({ identifier: name });
|
|
1831
|
+
if (response.error || !response.data?.profile) {
|
|
1832
|
+
return {
|
|
1833
|
+
kind: "not-found",
|
|
1834
|
+
message: `No creator found with name "${name}"`
|
|
1835
|
+
};
|
|
1836
|
+
}
|
|
1837
|
+
const profile = response.data.profile;
|
|
1838
|
+
if (!profile.creatorCoin) {
|
|
1839
|
+
return {
|
|
1840
|
+
kind: "not-found",
|
|
1841
|
+
message: `"${name}" does not have a creator coin`
|
|
1842
|
+
};
|
|
1843
|
+
}
|
|
1844
|
+
return resolveByAddress(profile.creatorCoin.address);
|
|
1845
|
+
}
|
|
1846
|
+
async function resolveCoin(ref) {
|
|
1847
|
+
switch (ref.kind) {
|
|
1848
|
+
case "address":
|
|
1849
|
+
return resolveByAddress(ref.address);
|
|
1850
|
+
case "prefixed":
|
|
1851
|
+
if (ref.type === "trend") {
|
|
1852
|
+
return resolveByTrendTicker(ref.name);
|
|
1853
|
+
}
|
|
1854
|
+
return resolveByCreatorName(ref.name);
|
|
1855
|
+
case "ambiguous":
|
|
1856
|
+
return resolveByCreatorName(ref.name);
|
|
1857
|
+
}
|
|
1858
|
+
}
|
|
1859
|
+
|
|
1710
1860
|
// src/commands/buy.ts
|
|
1711
|
-
var buyCommand = new Command3("buy").description("Buy a coin").argument(
|
|
1861
|
+
var buyCommand = new Command3("buy").description("Buy a coin").argument(
|
|
1862
|
+
"[typeOrId]",
|
|
1863
|
+
"Type prefix (creator-coin, trend) or coin address/name"
|
|
1864
|
+
).argument("[identifier]", "Coin name (when type prefix is given)").option("--eth <value>", "Buy with ETH amount").option("--usd <value>", "Buy with USD equivalent (use with --token)").option("--token <asset>", "Token to spend: eth, usdc, zora", "eth").option("--percent <value>", "Buy with percentage of ETH balance").option("--all", "Swap all ETH for coin").option("--quote", "Print quote and exit without trading").option("--yes", "Skip confirmation and execute directly").option("--slippage <pct>", "Slippage tolerance percent", "1").option("--debug", "Print full quote request/response JSON").action(async function(typeOrId, identifier, opts) {
|
|
1712
1865
|
const json = getJson(this);
|
|
1713
1866
|
const debug = opts.debug === true;
|
|
1714
|
-
|
|
1715
|
-
|
|
1867
|
+
let parsed;
|
|
1868
|
+
try {
|
|
1869
|
+
parsed = parsePositionalCoinArgs(typeOrId, identifier);
|
|
1870
|
+
} catch (err) {
|
|
1871
|
+
if (err instanceof CoinArgError) {
|
|
1872
|
+
outputErrorAndExit(json, err.message, err.suggestion);
|
|
1873
|
+
}
|
|
1874
|
+
throw err;
|
|
1875
|
+
}
|
|
1876
|
+
const apiKey = getApiKey();
|
|
1877
|
+
if (apiKey) {
|
|
1878
|
+
setApiKey2(apiKey);
|
|
1879
|
+
}
|
|
1880
|
+
let coinAddress;
|
|
1881
|
+
if (parsed.kind === "address") {
|
|
1882
|
+
if (!isAddress(parsed.address)) {
|
|
1883
|
+
outputErrorAndExit(json, `Invalid address: ${parsed.address}`);
|
|
1884
|
+
return;
|
|
1885
|
+
}
|
|
1886
|
+
coinAddress = parsed.address;
|
|
1887
|
+
} else if (parsed.kind === "ambiguous-name") {
|
|
1888
|
+
let ambResult;
|
|
1889
|
+
try {
|
|
1890
|
+
ambResult = await resolveAmbiguousName(parsed.name);
|
|
1891
|
+
} catch (err) {
|
|
1892
|
+
outputErrorAndExit(
|
|
1893
|
+
json,
|
|
1894
|
+
`Request failed: ${err instanceof Error ? err.message : String(err)}`
|
|
1895
|
+
);
|
|
1896
|
+
return;
|
|
1897
|
+
}
|
|
1898
|
+
if (ambResult.kind === "not-found") {
|
|
1899
|
+
outputErrorAndExit(json, ambResult.message);
|
|
1900
|
+
return;
|
|
1901
|
+
}
|
|
1902
|
+
if (ambResult.kind === "ambiguous") {
|
|
1903
|
+
const { message, suggestion } = formatAmbiguousError(
|
|
1904
|
+
parsed.name,
|
|
1905
|
+
ambResult.creator,
|
|
1906
|
+
ambResult.trend,
|
|
1907
|
+
"buy"
|
|
1908
|
+
);
|
|
1909
|
+
outputErrorAndExit(json, message, suggestion);
|
|
1910
|
+
return;
|
|
1911
|
+
}
|
|
1912
|
+
coinAddress = ambResult.coin.address;
|
|
1913
|
+
} else {
|
|
1914
|
+
const ref = coinArgsToRef(parsed);
|
|
1915
|
+
try {
|
|
1916
|
+
const result = await resolveCoin(ref);
|
|
1917
|
+
if (result.kind === "not-found") {
|
|
1918
|
+
outputErrorAndExit(json, result.message, result.suggestion);
|
|
1919
|
+
return;
|
|
1920
|
+
}
|
|
1921
|
+
coinAddress = result.coin.address;
|
|
1922
|
+
} catch (err) {
|
|
1923
|
+
outputErrorAndExit(
|
|
1924
|
+
json,
|
|
1925
|
+
`Request failed: ${err instanceof Error ? err.message : String(err)}`
|
|
1926
|
+
);
|
|
1927
|
+
return;
|
|
1928
|
+
}
|
|
1716
1929
|
}
|
|
1717
1930
|
const tokenKey = opts.token.toLowerCase();
|
|
1718
1931
|
if (!(tokenKey in BASE_TRADE_TOKENS)) {
|
|
@@ -1736,15 +1949,11 @@ var buyCommand = new Command3("buy").description("Buy a coin").argument("[addres
|
|
|
1736
1949
|
);
|
|
1737
1950
|
}
|
|
1738
1951
|
const slippage = slippagePct / 100;
|
|
1739
|
-
const apiKey = getApiKey();
|
|
1740
|
-
if (apiKey) {
|
|
1741
|
-
setApiKey2(apiKey);
|
|
1742
|
-
}
|
|
1743
1952
|
const account = resolveAccount(json);
|
|
1744
1953
|
const { publicClient, walletClient } = createClients(account);
|
|
1745
1954
|
let token;
|
|
1746
1955
|
try {
|
|
1747
|
-
const response = await
|
|
1956
|
+
const response = await getCoin2({ address: coinAddress });
|
|
1748
1957
|
token = response.data?.zora20Token;
|
|
1749
1958
|
} catch (err) {
|
|
1750
1959
|
outputErrorAndExit(json, `Failed to fetch coin: ${apiErrorMessage(err)}`);
|
|
@@ -1752,8 +1961,12 @@ var buyCommand = new Command3("buy").description("Buy a coin").argument("[addres
|
|
|
1752
1961
|
if (!token) {
|
|
1753
1962
|
outputErrorAndExit(json, `Coin not found: ${coinAddress}`);
|
|
1754
1963
|
}
|
|
1964
|
+
if (token.platformBlocked) {
|
|
1965
|
+
outputErrorAndExit(json, bannedCoinBuyMessage(coinAddress));
|
|
1966
|
+
}
|
|
1755
1967
|
const coinName = token.name;
|
|
1756
1968
|
const coinSymbol = token.symbol;
|
|
1969
|
+
const coinType = mapCoinType(token.coinType);
|
|
1757
1970
|
let amountIn;
|
|
1758
1971
|
if (amountMode === "usd") {
|
|
1759
1972
|
const usdVal = parsePercentageLikeValue(opts.usd);
|
|
@@ -1788,7 +2001,7 @@ var buyCommand = new Command3("buy").description("Buy a coin").argument("[addres
|
|
|
1788
2001
|
}
|
|
1789
2002
|
if (debug) {
|
|
1790
2003
|
console.error(
|
|
1791
|
-
`[debug] $${usdVal} USD = ${
|
|
2004
|
+
`[debug] $${usdVal} USD = ${formatUnits4(amountIn, inputToken.decimals)} ${inputToken.symbol} (price: $${priceUsd})`
|
|
1792
2005
|
);
|
|
1793
2006
|
}
|
|
1794
2007
|
} else if (amountMode === "eth") {
|
|
@@ -1841,7 +2054,7 @@ var buyCommand = new Command3("buy").description("Buy a coin").argument("[addres
|
|
|
1841
2054
|
if (isEth && balance <= gasReserve) {
|
|
1842
2055
|
outputErrorAndExit(
|
|
1843
2056
|
json,
|
|
1844
|
-
`Balance too low (${
|
|
2057
|
+
`Balance too low (${formatAmountDisplay(balance, 18)} ETH). Need >${formatAmountDisplay(GAS_RESERVE, 18)} ETH for gas.`
|
|
1845
2058
|
);
|
|
1846
2059
|
}
|
|
1847
2060
|
const spendableBalance = balance - gasReserve;
|
|
@@ -1871,7 +2084,7 @@ var buyCommand = new Command3("buy").description("Buy a coin").argument("[addres
|
|
|
1871
2084
|
const priceUsd = inputToken.fixedPriceUsd ?? await fetchTokenPriceUsd(inputToken.priceAddress);
|
|
1872
2085
|
if (priceUsd != null) {
|
|
1873
2086
|
swapAmountUsd = Number(
|
|
1874
|
-
(Number(
|
|
2087
|
+
(Number(formatUnits4(amountIn, inputToken.decimals)) * priceUsd).toFixed(2)
|
|
1875
2088
|
);
|
|
1876
2089
|
}
|
|
1877
2090
|
}
|
|
@@ -1926,25 +2139,19 @@ ${err instanceof Error ? err.stack || err.message : String(err)}
|
|
|
1926
2139
|
"Check the coin address is valid and try again. Use --debug for full error details."
|
|
1927
2140
|
);
|
|
1928
2141
|
}
|
|
1929
|
-
const
|
|
1930
|
-
|
|
1931
|
-
|
|
1932
|
-
|
|
1933
|
-
|
|
1934
|
-
|
|
2142
|
+
const quoteInfo = {
|
|
2143
|
+
coinName,
|
|
2144
|
+
coinSymbol,
|
|
2145
|
+
coinType,
|
|
2146
|
+
address: coinAddress,
|
|
2147
|
+
amountIn,
|
|
2148
|
+
inputTokenSymbol: inputToken.symbol,
|
|
2149
|
+
inputTokenDecimals: inputToken.decimals,
|
|
2150
|
+
amountOut,
|
|
2151
|
+
slippagePct
|
|
2152
|
+
};
|
|
1935
2153
|
if (opts.quote) {
|
|
1936
|
-
printQuote(json,
|
|
1937
|
-
coinName,
|
|
1938
|
-
coinSymbol,
|
|
1939
|
-
address: coinAddress,
|
|
1940
|
-
spendAmount: `${spendFormatted} ${inputToken.symbol}`,
|
|
1941
|
-
amountIn,
|
|
1942
|
-
inputTokenSymbol: inputToken.symbol,
|
|
1943
|
-
inputTokenDecimals: inputToken.decimals,
|
|
1944
|
-
coinsFormatted,
|
|
1945
|
-
amountOut,
|
|
1946
|
-
slippagePct
|
|
1947
|
-
});
|
|
2154
|
+
printQuote(json, quoteInfo);
|
|
1948
2155
|
track("cli_buy", {
|
|
1949
2156
|
action: "quote",
|
|
1950
2157
|
coin_address: coinAddress,
|
|
@@ -1960,18 +2167,7 @@ ${err instanceof Error ? err.stack || err.message : String(err)}
|
|
|
1960
2167
|
return;
|
|
1961
2168
|
}
|
|
1962
2169
|
if (!opts.yes) {
|
|
1963
|
-
printQuote(false,
|
|
1964
|
-
coinName,
|
|
1965
|
-
coinSymbol,
|
|
1966
|
-
address: coinAddress,
|
|
1967
|
-
spendAmount: `${spendFormatted} ${inputToken.symbol}`,
|
|
1968
|
-
amountIn,
|
|
1969
|
-
inputTokenSymbol: inputToken.symbol,
|
|
1970
|
-
inputTokenDecimals: inputToken.decimals,
|
|
1971
|
-
coinsFormatted,
|
|
1972
|
-
amountOut,
|
|
1973
|
-
slippagePct
|
|
1974
|
-
});
|
|
2170
|
+
printQuote(false, quoteInfo);
|
|
1975
2171
|
const ok = await confirm2({
|
|
1976
2172
|
message: "Confirm?",
|
|
1977
2173
|
default: false
|
|
@@ -2028,8 +2224,8 @@ ${err instanceof Error ? err.stack || err.message : String(err)}
|
|
|
2028
2224
|
printTradeResult(json, {
|
|
2029
2225
|
coinName,
|
|
2030
2226
|
coinSymbol,
|
|
2227
|
+
coinType,
|
|
2031
2228
|
address: coinAddress,
|
|
2032
|
-
spendAmount,
|
|
2033
2229
|
amountIn,
|
|
2034
2230
|
inputTokenSymbol: inputToken.symbol,
|
|
2035
2231
|
inputTokenDecimals: inputToken.decimals,
|
|
@@ -2063,9 +2259,6 @@ import {
|
|
|
2063
2259
|
getCoinsTopVolume24h,
|
|
2064
2260
|
getCoinsMostValuable,
|
|
2065
2261
|
getCoinsNew,
|
|
2066
|
-
getCoinsTopGainers,
|
|
2067
|
-
getCoinsLastTraded,
|
|
2068
|
-
getCoinsLastTradedUnique,
|
|
2069
2262
|
getExploreTopVolumeAll24h,
|
|
2070
2263
|
getExploreTopVolumeCreators24h,
|
|
2071
2264
|
getExploreNewAll,
|
|
@@ -2088,9 +2281,6 @@ var SORT_LABELS2 = {
|
|
|
2088
2281
|
mcap: "Top by Market Cap",
|
|
2089
2282
|
volume: "Top by 24h Volume",
|
|
2090
2283
|
new: "New",
|
|
2091
|
-
gainers: "Top Gainers (24h)",
|
|
2092
|
-
"last-traded": "Last Traded",
|
|
2093
|
-
"last-traded-unique": "Last Traded (Unique)",
|
|
2094
2284
|
trending: "Trending",
|
|
2095
2285
|
featured: "Featured"
|
|
2096
2286
|
};
|
|
@@ -2340,8 +2530,7 @@ var ExploreView = ({
|
|
|
2340
2530
|
hints.push("c copy address");
|
|
2341
2531
|
if (cursorHistory.length > 0) hints.push("\u2190 prev");
|
|
2342
2532
|
if (pageInfo?.hasNextPage) hints.push("\u2192 next");
|
|
2343
|
-
hints.push("r refresh");
|
|
2344
|
-
if (autoRefresh) hints.push(`auto: ${secondsUntilRefresh}s`);
|
|
2533
|
+
hints.push(autoRefresh ? `r refresh (${secondsUntilRefresh}s)` : "r refresh");
|
|
2345
2534
|
hints.push("q quit");
|
|
2346
2535
|
const footer = hints.join(" \xB7 ") + (copyFeedback ? ` ${copyFeedback}` : "");
|
|
2347
2536
|
return /* @__PURE__ */ jsx4(
|
|
@@ -2378,15 +2567,6 @@ var QUERY_MAP = {
|
|
|
2378
2567
|
"creator-coin": getCreatorCoins,
|
|
2379
2568
|
post: getCoinsNew
|
|
2380
2569
|
},
|
|
2381
|
-
gainers: {
|
|
2382
|
-
post: getCoinsTopGainers
|
|
2383
|
-
},
|
|
2384
|
-
"last-traded": {
|
|
2385
|
-
post: getCoinsLastTraded
|
|
2386
|
-
},
|
|
2387
|
-
"last-traded-unique": {
|
|
2388
|
-
post: getCoinsLastTradedUnique
|
|
2389
|
-
},
|
|
2390
2570
|
trending: {
|
|
2391
2571
|
all: getTrendingAll,
|
|
2392
2572
|
trend: getTrendingTrends,
|
|
@@ -2428,7 +2608,7 @@ var SORT_OPTIONS2 = Object.keys(SORT_LABELS2).join(", ");
|
|
|
2428
2608
|
var exploreCommand = new Command4("explore").description("Browse top, new, and highest volume coins").option("--sort <sort>", `Sort by: ${SORT_OPTIONS2}`, "mcap").option(
|
|
2429
2609
|
"--type <type>",
|
|
2430
2610
|
"Filter by type: all, trend, creator-coin, post (availability varies by sort)",
|
|
2431
|
-
"
|
|
2611
|
+
"creator-coin"
|
|
2432
2612
|
).option("--limit <n>", "Number of results (max 20)", "10").option("--after <cursor>", "Pagination cursor from a previous result").option("--live", "Interactive live-updating display (default)").option("--static", "Static snapshot").option(
|
|
2433
2613
|
"--refresh <seconds>",
|
|
2434
2614
|
"Auto-refresh interval in seconds, requires --live (min 5)",
|
|
@@ -2560,130 +2740,42 @@ var exploreCommand = new Command4("explore").description("Browse top, new, and h
|
|
|
2560
2740
|
import { Command as Command5 } from "commander";
|
|
2561
2741
|
import { setApiKey as setApiKey4 } from "@zoralabs/coins-sdk";
|
|
2562
2742
|
|
|
2563
|
-
// src/
|
|
2564
|
-
import {
|
|
2565
|
-
|
|
2566
|
-
|
|
2567
|
-
|
|
2568
|
-
|
|
2569
|
-
|
|
2570
|
-
|
|
2571
|
-
|
|
2572
|
-
|
|
2573
|
-
}
|
|
2574
|
-
|
|
2575
|
-
return {
|
|
2576
|
-
name: token.name ?? "Unknown",
|
|
2577
|
-
address: token.address ?? "",
|
|
2578
|
-
coinType: mapCoinType(token.coinType),
|
|
2579
|
-
marketCap: token.marketCap ?? "0",
|
|
2580
|
-
marketCapDelta24h: token.marketCapDelta24h ?? "0",
|
|
2581
|
-
volume24h: token.volume24h ?? "0",
|
|
2582
|
-
uniqueHolders: token.uniqueHolders ?? 0,
|
|
2583
|
-
createdAt: token.createdAt,
|
|
2584
|
-
creatorAddress: token.creatorAddress,
|
|
2585
|
-
creatorHandle: token.creatorProfile?.handle
|
|
2586
|
-
};
|
|
2743
|
+
// src/components/CoinDetail.tsx
|
|
2744
|
+
import { Box as Box5, Text as Text5 } from "ink";
|
|
2745
|
+
import { jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
2746
|
+
var LABEL_WIDTH = 18;
|
|
2747
|
+
function Row({
|
|
2748
|
+
label,
|
|
2749
|
+
children
|
|
2750
|
+
}) {
|
|
2751
|
+
return /* @__PURE__ */ jsxs5(Box5, { children: [
|
|
2752
|
+
/* @__PURE__ */ jsx6(Box5, { width: LABEL_WIDTH, flexShrink: 0, children: /* @__PURE__ */ jsx6(Text5, { dimColor: true, children: label }) }),
|
|
2753
|
+
/* @__PURE__ */ jsx6(Text5, { children })
|
|
2754
|
+
] });
|
|
2587
2755
|
}
|
|
2588
|
-
function
|
|
2589
|
-
|
|
2590
|
-
|
|
2591
|
-
|
|
2592
|
-
|
|
2593
|
-
|
|
2594
|
-
|
|
2595
|
-
|
|
2596
|
-
|
|
2597
|
-
|
|
2598
|
-
|
|
2599
|
-
}
|
|
2600
|
-
|
|
2601
|
-
|
|
2602
|
-
|
|
2603
|
-
|
|
2604
|
-
|
|
2605
|
-
|
|
2606
|
-
|
|
2607
|
-
|
|
2608
|
-
|
|
2609
|
-
}
|
|
2610
|
-
|
|
2611
|
-
const response = await getTrend({ ticker });
|
|
2612
|
-
if (response.error || !response.data?.trendCoin) {
|
|
2613
|
-
return {
|
|
2614
|
-
kind: "not-found",
|
|
2615
|
-
message: `No trend coin found with ticker "${ticker}"`
|
|
2616
|
-
};
|
|
2617
|
-
}
|
|
2618
|
-
return { kind: "found", coin: coinFromToken(response.data.trendCoin) };
|
|
2619
|
-
}
|
|
2620
|
-
async function resolveByCreatorName(name) {
|
|
2621
|
-
const response = await getProfile({ identifier: name });
|
|
2622
|
-
if (response.error || !response.data?.profile) {
|
|
2623
|
-
return {
|
|
2624
|
-
kind: "not-found",
|
|
2625
|
-
message: `No creator found with name "${name}"`
|
|
2626
|
-
};
|
|
2627
|
-
}
|
|
2628
|
-
const profile = response.data.profile;
|
|
2629
|
-
if (!profile.creatorCoin) {
|
|
2630
|
-
return {
|
|
2631
|
-
kind: "not-found",
|
|
2632
|
-
message: `"${name}" does not have a creator coin`
|
|
2633
|
-
};
|
|
2634
|
-
}
|
|
2635
|
-
return resolveByAddress(profile.creatorCoin.address);
|
|
2636
|
-
}
|
|
2637
|
-
async function resolveCoin(ref) {
|
|
2638
|
-
switch (ref.kind) {
|
|
2639
|
-
case "address":
|
|
2640
|
-
return resolveByAddress(ref.address);
|
|
2641
|
-
case "prefixed":
|
|
2642
|
-
if (ref.type === "trend") {
|
|
2643
|
-
return resolveByTrendTicker(ref.name);
|
|
2644
|
-
}
|
|
2645
|
-
return resolveByCreatorName(ref.name);
|
|
2646
|
-
case "ambiguous":
|
|
2647
|
-
return resolveByCreatorName(ref.name);
|
|
2648
|
-
}
|
|
2649
|
-
}
|
|
2650
|
-
|
|
2651
|
-
// src/components/CoinDetail.tsx
|
|
2652
|
-
import { Box as Box5, Text as Text5 } from "ink";
|
|
2653
|
-
import { jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
2654
|
-
var LABEL_WIDTH = 18;
|
|
2655
|
-
function Row({
|
|
2656
|
-
label,
|
|
2657
|
-
children
|
|
2658
|
-
}) {
|
|
2659
|
-
return /* @__PURE__ */ jsxs5(Box5, { children: [
|
|
2660
|
-
/* @__PURE__ */ jsx6(Box5, { width: LABEL_WIDTH, flexShrink: 0, children: /* @__PURE__ */ jsx6(Text5, { dimColor: true, children: label }) }),
|
|
2661
|
-
/* @__PURE__ */ jsx6(Text5, { children })
|
|
2662
|
-
] });
|
|
2663
|
-
}
|
|
2664
|
-
function CoinDetail({ coin }) {
|
|
2665
|
-
const change = formatMcapChange(coin.marketCap, coin.marketCapDelta24h);
|
|
2666
|
-
return /* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", paddingLeft: 1, children: [
|
|
2667
|
-
/* @__PURE__ */ jsxs5(Box5, { marginTop: 1, flexDirection: "column", children: [
|
|
2668
|
-
/* @__PURE__ */ jsx6(Text5, { bold: true, children: coin.name }),
|
|
2669
|
-
/* @__PURE__ */ jsxs5(Text5, { children: [
|
|
2670
|
-
coin.coinType,
|
|
2671
|
-
" ",
|
|
2672
|
-
"\xB7",
|
|
2673
|
-
" ",
|
|
2674
|
-
coin.address
|
|
2675
|
-
] })
|
|
2676
|
-
] }),
|
|
2677
|
-
/* @__PURE__ */ jsxs5(Box5, { marginTop: 1, flexDirection: "column", children: [
|
|
2678
|
-
/* @__PURE__ */ jsx6(Row, { label: "Market Cap", children: formatCompactUsd(coin.marketCap) }),
|
|
2679
|
-
/* @__PURE__ */ jsx6(Row, { label: "24h Volume", children: formatCompactUsd(coin.volume24h) }),
|
|
2680
|
-
/* @__PURE__ */ jsx6(Row, { label: "24h Change", children: /* @__PURE__ */ jsx6(Text5, { color: change.color, children: change.text }) }),
|
|
2681
|
-
/* @__PURE__ */ jsx6(Row, { label: "Holders", children: formatHolders(coin.uniqueHolders) }),
|
|
2682
|
-
coin.coinType === "post" && (coin.creatorHandle ?? coin.creatorAddress) && /* @__PURE__ */ jsx6(Row, { label: "Creator", children: coin.creatorHandle ?? coin.creatorAddress }),
|
|
2683
|
-
/* @__PURE__ */ jsx6(Row, { label: "Created", children: formatCreatedAt(coin.createdAt) })
|
|
2684
|
-
] }),
|
|
2685
|
-
/* @__PURE__ */ jsx6(Box5, { marginBottom: 1 })
|
|
2686
|
-
] });
|
|
2756
|
+
function CoinDetail({ coin }) {
|
|
2757
|
+
const change = formatMcapChange(coin.marketCap, coin.marketCapDelta24h);
|
|
2758
|
+
return /* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", paddingLeft: 1, children: [
|
|
2759
|
+
/* @__PURE__ */ jsxs5(Box5, { marginTop: 1, flexDirection: "column", children: [
|
|
2760
|
+
/* @__PURE__ */ jsx6(Text5, { bold: true, children: coin.name }),
|
|
2761
|
+
/* @__PURE__ */ jsxs5(Text5, { children: [
|
|
2762
|
+
coin.coinType,
|
|
2763
|
+
" ",
|
|
2764
|
+
"\xB7",
|
|
2765
|
+
" ",
|
|
2766
|
+
coin.address
|
|
2767
|
+
] })
|
|
2768
|
+
] }),
|
|
2769
|
+
/* @__PURE__ */ jsxs5(Box5, { marginTop: 1, flexDirection: "column", children: [
|
|
2770
|
+
/* @__PURE__ */ jsx6(Row, { label: "Market Cap", children: formatCompactUsd(coin.marketCap) }),
|
|
2771
|
+
/* @__PURE__ */ jsx6(Row, { label: "24h Volume", children: formatCompactUsd(coin.volume24h) }),
|
|
2772
|
+
/* @__PURE__ */ jsx6(Row, { label: "24h Change", children: /* @__PURE__ */ jsx6(Text5, { color: change.color, children: change.text }) }),
|
|
2773
|
+
/* @__PURE__ */ jsx6(Row, { label: "Holders", children: formatHolders(coin.uniqueHolders) }),
|
|
2774
|
+
coin.coinType === "post" && (coin.creatorHandle ?? coin.creatorAddress) && /* @__PURE__ */ jsx6(Row, { label: "Creator", children: coin.creatorHandle ?? coin.creatorAddress }),
|
|
2775
|
+
/* @__PURE__ */ jsx6(Row, { label: "Created", children: formatCreatedAt(coin.createdAt) })
|
|
2776
|
+
] }),
|
|
2777
|
+
/* @__PURE__ */ jsx6(Box5, { marginBottom: 1 })
|
|
2778
|
+
] });
|
|
2687
2779
|
}
|
|
2688
2780
|
|
|
2689
2781
|
// src/commands/get.tsx
|
|
@@ -2702,29 +2794,87 @@ function formatCoinJson(coin) {
|
|
|
2702
2794
|
creatorHandle: coin.creatorHandle ?? null
|
|
2703
2795
|
};
|
|
2704
2796
|
}
|
|
2705
|
-
|
|
2706
|
-
|
|
2797
|
+
function outputCoin(json, coin) {
|
|
2798
|
+
outputData(json, {
|
|
2799
|
+
json: formatCoinJson(coin),
|
|
2800
|
+
render: () => {
|
|
2801
|
+
renderOnce(/* @__PURE__ */ jsx7(CoinDetail, { coin }));
|
|
2802
|
+
}
|
|
2803
|
+
});
|
|
2804
|
+
}
|
|
2805
|
+
var getCommand = new Command5("get").description("Look up a coin by address or name").argument("[typeOrId]", "Type prefix (creator-coin, trend) or identifier").argument(
|
|
2806
|
+
"[identifier]",
|
|
2807
|
+
"Coin address (0x...) or name (when type prefix is given)"
|
|
2808
|
+
).action(async function(typeOrId, identifier) {
|
|
2707
2809
|
const json = getJson(this);
|
|
2708
|
-
|
|
2709
|
-
|
|
2710
|
-
|
|
2711
|
-
|
|
2712
|
-
|
|
2713
|
-
|
|
2714
|
-
|
|
2715
|
-
|
|
2716
|
-
if (type === "post" && !identifier.startsWith("0x")) {
|
|
2717
|
-
outputErrorAndExit(
|
|
2718
|
-
json,
|
|
2719
|
-
"Posts can only be looked up by address.",
|
|
2720
|
-
"Use: zora get 0x..."
|
|
2721
|
-
);
|
|
2810
|
+
let parsed;
|
|
2811
|
+
try {
|
|
2812
|
+
parsed = parsePositionalCoinArgs(typeOrId, identifier);
|
|
2813
|
+
} catch (err) {
|
|
2814
|
+
if (err instanceof CoinArgError) {
|
|
2815
|
+
outputErrorAndExit(json, err.message, err.suggestion);
|
|
2816
|
+
}
|
|
2817
|
+
throw err;
|
|
2722
2818
|
}
|
|
2723
|
-
const ref = parseCoinRef(identifier, opts.type);
|
|
2724
2819
|
const apiKey = getApiKey();
|
|
2725
2820
|
if (apiKey) {
|
|
2726
2821
|
setApiKey4(apiKey);
|
|
2727
2822
|
}
|
|
2823
|
+
if (parsed.kind === "ambiguous-name") {
|
|
2824
|
+
let ambResult;
|
|
2825
|
+
try {
|
|
2826
|
+
ambResult = await resolveAmbiguousName(parsed.name);
|
|
2827
|
+
} catch (err) {
|
|
2828
|
+
outputErrorAndExit(
|
|
2829
|
+
json,
|
|
2830
|
+
`Request failed: ${err instanceof Error ? err.message : String(err)}`
|
|
2831
|
+
);
|
|
2832
|
+
return;
|
|
2833
|
+
}
|
|
2834
|
+
if (ambResult.kind === "not-found") {
|
|
2835
|
+
outputErrorAndExit(json, ambResult.message);
|
|
2836
|
+
return;
|
|
2837
|
+
}
|
|
2838
|
+
if (ambResult.kind === "ambiguous") {
|
|
2839
|
+
if (json) {
|
|
2840
|
+
outputData(json, {
|
|
2841
|
+
json: {
|
|
2842
|
+
matches: [
|
|
2843
|
+
{ type: "creator-coin", ...formatCoinJson(ambResult.creator) },
|
|
2844
|
+
{ type: "trend", ...formatCoinJson(ambResult.trend) }
|
|
2845
|
+
],
|
|
2846
|
+
hint: `Use: zora get creator-coin ${parsed.name} or zora get trend ${parsed.name}`
|
|
2847
|
+
},
|
|
2848
|
+
render: () => {
|
|
2849
|
+
}
|
|
2850
|
+
});
|
|
2851
|
+
} else {
|
|
2852
|
+
outputCoin(false, ambResult.creator);
|
|
2853
|
+
console.log("");
|
|
2854
|
+
outputCoin(false, ambResult.trend);
|
|
2855
|
+
console.log(
|
|
2856
|
+
`
|
|
2857
|
+
\x1B[2mUse \`zora get creator-coin ${parsed.name}\` or \`zora get trend ${parsed.name}\` for a specific type.\x1B[0m`
|
|
2858
|
+
);
|
|
2859
|
+
}
|
|
2860
|
+
track("cli_get", {
|
|
2861
|
+
lookup_type: "name",
|
|
2862
|
+
found: true,
|
|
2863
|
+
ambiguous: true,
|
|
2864
|
+
output_format: json ? "json" : "text"
|
|
2865
|
+
});
|
|
2866
|
+
return;
|
|
2867
|
+
}
|
|
2868
|
+
outputCoin(json, ambResult.coin);
|
|
2869
|
+
track("cli_get", {
|
|
2870
|
+
lookup_type: "name",
|
|
2871
|
+
found: true,
|
|
2872
|
+
coin_type: ambResult.coin.coinType,
|
|
2873
|
+
output_format: json ? "json" : "text"
|
|
2874
|
+
});
|
|
2875
|
+
return;
|
|
2876
|
+
}
|
|
2877
|
+
const ref = coinArgsToRef(parsed);
|
|
2728
2878
|
let result;
|
|
2729
2879
|
try {
|
|
2730
2880
|
result = await resolveCoin(ref);
|
|
@@ -2732,29 +2882,20 @@ var getCommand = new Command5("get").description("Look up a coin by address or n
|
|
|
2732
2882
|
outputErrorAndExit(json, `Request failed: ${apiErrorMessage(err)}`);
|
|
2733
2883
|
return;
|
|
2734
2884
|
}
|
|
2735
|
-
if (type && result.kind === "found" && result.coin.coinType !== type) {
|
|
2736
|
-
outputErrorAndExit(
|
|
2737
|
-
json,
|
|
2738
|
-
`Coin at ${result.coin.address} is a ${result.coin.coinType}, not a ${type}.`,
|
|
2739
|
-
`Use: zora get ${result.coin.address} --type ${result.coin.coinType}`
|
|
2740
|
-
);
|
|
2741
|
-
return;
|
|
2742
|
-
}
|
|
2743
2885
|
if (result.kind === "not-found") {
|
|
2744
2886
|
outputErrorAndExit(json, result.message);
|
|
2745
2887
|
return;
|
|
2746
2888
|
}
|
|
2747
|
-
|
|
2748
|
-
json
|
|
2749
|
-
|
|
2750
|
-
|
|
2751
|
-
|
|
2752
|
-
});
|
|
2889
|
+
if (result.coin.platformBlocked) {
|
|
2890
|
+
outputErrorAndExit(json, bannedCoinMessage(result.coin.address));
|
|
2891
|
+
return;
|
|
2892
|
+
}
|
|
2893
|
+
outputCoin(json, result.coin);
|
|
2753
2894
|
track("cli_get", {
|
|
2754
|
-
lookup_type:
|
|
2755
|
-
coin_type_filter: type
|
|
2756
|
-
found:
|
|
2757
|
-
coin_type: result.
|
|
2895
|
+
lookup_type: typeOrId.startsWith("0x") ? "address" : "name",
|
|
2896
|
+
coin_type_filter: parsed.kind === "typed" ? parsed.type : null,
|
|
2897
|
+
found: true,
|
|
2898
|
+
coin_type: result.coin.coinType,
|
|
2758
2899
|
output_format: json ? "json" : "text"
|
|
2759
2900
|
});
|
|
2760
2901
|
});
|
|
@@ -2827,7 +2968,6 @@ var downsample = (values, maxWidth) => {
|
|
|
2827
2968
|
|
|
2828
2969
|
// src/commands/price-history.tsx
|
|
2829
2970
|
import { jsx as jsx9 } from "react/jsx-runtime";
|
|
2830
|
-
var VALID_TYPES2 = ["creator-coin", "post", "trend"];
|
|
2831
2971
|
var VALID_INTERVALS = ["1h", "24h", "1w", "1m", "ALL"];
|
|
2832
2972
|
var INTERVAL_TO_API_FIELD = {
|
|
2833
2973
|
"1h": "oneHour",
|
|
@@ -2868,54 +3008,7 @@ var fetchPriceHistory = async (address, interval) => {
|
|
|
2868
3008
|
price: Number(p.closePrice)
|
|
2869
3009
|
}));
|
|
2870
3010
|
};
|
|
2871
|
-
|
|
2872
|
-
"--interval <interval>",
|
|
2873
|
-
`Time range: ${VALID_INTERVALS.join(", ")}`,
|
|
2874
|
-
"1w"
|
|
2875
|
-
).action(async function(identifier, opts) {
|
|
2876
|
-
const json = getJson(this);
|
|
2877
|
-
const interval = opts.interval ?? "1w";
|
|
2878
|
-
if (!VALID_INTERVALS.includes(interval)) {
|
|
2879
|
-
outputErrorAndExit(
|
|
2880
|
-
json,
|
|
2881
|
-
`Invalid --interval value: ${interval}.`,
|
|
2882
|
-
`Supported: ${VALID_INTERVALS.join(", ")}`
|
|
2883
|
-
);
|
|
2884
|
-
}
|
|
2885
|
-
if (opts.type !== void 0 && !VALID_TYPES2.includes(opts.type)) {
|
|
2886
|
-
outputErrorAndExit(
|
|
2887
|
-
json,
|
|
2888
|
-
`Invalid --type value: ${opts.type}.`,
|
|
2889
|
-
`Supported: ${VALID_TYPES2.join(", ")}`
|
|
2890
|
-
);
|
|
2891
|
-
}
|
|
2892
|
-
if (opts.type === "post" && !identifier.startsWith("0x")) {
|
|
2893
|
-
outputErrorAndExit(
|
|
2894
|
-
json,
|
|
2895
|
-
"Posts can only be looked up by address.",
|
|
2896
|
-
"Use: zora price-history 0x..."
|
|
2897
|
-
);
|
|
2898
|
-
}
|
|
2899
|
-
const ref = parseCoinRef(identifier, opts.type);
|
|
2900
|
-
const apiKey = getApiKey();
|
|
2901
|
-
if (apiKey) {
|
|
2902
|
-
setApiKey5(apiKey);
|
|
2903
|
-
}
|
|
2904
|
-
let result;
|
|
2905
|
-
try {
|
|
2906
|
-
result = await resolveCoin(ref);
|
|
2907
|
-
} catch (err) {
|
|
2908
|
-
outputErrorAndExit(
|
|
2909
|
-
json,
|
|
2910
|
-
`Request failed: ${err instanceof Error ? err.message : String(err)}`
|
|
2911
|
-
);
|
|
2912
|
-
return;
|
|
2913
|
-
}
|
|
2914
|
-
if (result.kind === "not-found") {
|
|
2915
|
-
outputErrorAndExit(json, result.message, result.suggestion);
|
|
2916
|
-
return;
|
|
2917
|
-
}
|
|
2918
|
-
const { coin } = result;
|
|
3011
|
+
async function showPriceHistory(json, coin, interval) {
|
|
2919
3012
|
let prices;
|
|
2920
3013
|
try {
|
|
2921
3014
|
prices = await fetchPriceHistory(coin.address, interval);
|
|
@@ -2941,9 +3034,7 @@ var priceHistoryCommand = new Command6("price-history").description("Display pri
|
|
|
2941
3034
|
priceValues[0],
|
|
2942
3035
|
priceValues[priceValues.length - 1]
|
|
2943
3036
|
);
|
|
2944
|
-
const sparklineText = sparkline(
|
|
2945
|
-
downsample(priceValues, MAX_SPARKLINE_WIDTH)
|
|
2946
|
-
);
|
|
3037
|
+
const sparklineText = sparkline(downsample(priceValues, MAX_SPARKLINE_WIDTH));
|
|
2947
3038
|
outputData(json, {
|
|
2948
3039
|
json: {
|
|
2949
3040
|
coin: coin.name,
|
|
@@ -2974,11 +3065,139 @@ var priceHistoryCommand = new Command6("price-history").description("Display pri
|
|
|
2974
3065
|
);
|
|
2975
3066
|
}
|
|
2976
3067
|
});
|
|
3068
|
+
return prices.length;
|
|
3069
|
+
}
|
|
3070
|
+
var priceHistoryCommand = new Command6("price-history").description("Display price history for a coin").argument("[typeOrId]", "Type prefix (creator-coin, trend) or identifier").argument(
|
|
3071
|
+
"[identifier]",
|
|
3072
|
+
"Coin address (0x...) or name (when type prefix is given)"
|
|
3073
|
+
).option(
|
|
3074
|
+
"--interval <interval>",
|
|
3075
|
+
`Time range: ${VALID_INTERVALS.join(", ")}`,
|
|
3076
|
+
"1w"
|
|
3077
|
+
).action(async function(typeOrId, identifier, opts) {
|
|
3078
|
+
const json = getJson(this);
|
|
3079
|
+
const interval = opts.interval ?? "1w";
|
|
3080
|
+
if (!VALID_INTERVALS.includes(interval)) {
|
|
3081
|
+
outputErrorAndExit(
|
|
3082
|
+
json,
|
|
3083
|
+
`Invalid --interval value: ${interval}.`,
|
|
3084
|
+
`Supported: ${VALID_INTERVALS.join(", ")}`
|
|
3085
|
+
);
|
|
3086
|
+
}
|
|
3087
|
+
let parsed;
|
|
3088
|
+
try {
|
|
3089
|
+
parsed = parsePositionalCoinArgs(typeOrId, identifier);
|
|
3090
|
+
} catch (err) {
|
|
3091
|
+
if (err instanceof CoinArgError) {
|
|
3092
|
+
outputErrorAndExit(json, err.message, err.suggestion);
|
|
3093
|
+
}
|
|
3094
|
+
throw err;
|
|
3095
|
+
}
|
|
3096
|
+
const apiKey = getApiKey();
|
|
3097
|
+
if (apiKey) {
|
|
3098
|
+
setApiKey5(apiKey);
|
|
3099
|
+
}
|
|
3100
|
+
if (parsed.kind === "ambiguous-name") {
|
|
3101
|
+
let ambResult;
|
|
3102
|
+
try {
|
|
3103
|
+
ambResult = await resolveAmbiguousName(parsed.name);
|
|
3104
|
+
} catch (err) {
|
|
3105
|
+
outputErrorAndExit(
|
|
3106
|
+
json,
|
|
3107
|
+
`Request failed: ${err instanceof Error ? err.message : String(err)}`
|
|
3108
|
+
);
|
|
3109
|
+
return;
|
|
3110
|
+
}
|
|
3111
|
+
if (ambResult.kind === "not-found") {
|
|
3112
|
+
outputErrorAndExit(json, ambResult.message);
|
|
3113
|
+
return;
|
|
3114
|
+
}
|
|
3115
|
+
if (ambResult.kind === "ambiguous") {
|
|
3116
|
+
if (json) {
|
|
3117
|
+
const [creatorPrices, trendPrices] = await Promise.all([
|
|
3118
|
+
fetchPriceHistory(ambResult.creator.address, interval),
|
|
3119
|
+
fetchPriceHistory(ambResult.trend.address, interval)
|
|
3120
|
+
]);
|
|
3121
|
+
outputData(json, {
|
|
3122
|
+
json: {
|
|
3123
|
+
matches: [
|
|
3124
|
+
{
|
|
3125
|
+
type: "creator-coin",
|
|
3126
|
+
coin: ambResult.creator.name,
|
|
3127
|
+
prices: creatorPrices
|
|
3128
|
+
},
|
|
3129
|
+
{
|
|
3130
|
+
type: "trend",
|
|
3131
|
+
coin: ambResult.trend.name,
|
|
3132
|
+
prices: trendPrices
|
|
3133
|
+
}
|
|
3134
|
+
],
|
|
3135
|
+
hint: `Use: zora price-history creator-coin ${parsed.name} or zora price-history trend ${parsed.name}`
|
|
3136
|
+
},
|
|
3137
|
+
render: () => {
|
|
3138
|
+
}
|
|
3139
|
+
});
|
|
3140
|
+
} else {
|
|
3141
|
+
await showPriceHistory(
|
|
3142
|
+
false,
|
|
3143
|
+
ambResult.creator,
|
|
3144
|
+
interval
|
|
3145
|
+
);
|
|
3146
|
+
console.log("");
|
|
3147
|
+
await showPriceHistory(false, ambResult.trend, interval);
|
|
3148
|
+
console.log(
|
|
3149
|
+
`
|
|
3150
|
+
\x1B[2mUse \`zora price-history creator-coin ${parsed.name}\` or \`zora price-history trend ${parsed.name}\` for a specific type.\x1B[0m`
|
|
3151
|
+
);
|
|
3152
|
+
}
|
|
3153
|
+
track("cli_price_history", {
|
|
3154
|
+
lookup_type: "name",
|
|
3155
|
+
ambiguous: true,
|
|
3156
|
+
interval,
|
|
3157
|
+
output_format: json ? "json" : "text"
|
|
3158
|
+
});
|
|
3159
|
+
return;
|
|
3160
|
+
}
|
|
3161
|
+
const dataPoints2 = await showPriceHistory(
|
|
3162
|
+
json,
|
|
3163
|
+
ambResult.coin,
|
|
3164
|
+
interval
|
|
3165
|
+
);
|
|
3166
|
+
track("cli_price_history", {
|
|
3167
|
+
lookup_type: "name",
|
|
3168
|
+
coin_type: ambResult.coin.coinType,
|
|
3169
|
+
interval,
|
|
3170
|
+
data_points: dataPoints2,
|
|
3171
|
+
output_format: json ? "json" : "text"
|
|
3172
|
+
});
|
|
3173
|
+
return;
|
|
3174
|
+
}
|
|
3175
|
+
const ref = coinArgsToRef(parsed);
|
|
3176
|
+
let result;
|
|
3177
|
+
try {
|
|
3178
|
+
result = await resolveCoin(ref);
|
|
3179
|
+
} catch (err) {
|
|
3180
|
+
outputErrorAndExit(
|
|
3181
|
+
json,
|
|
3182
|
+
`Request failed: ${err instanceof Error ? err.message : String(err)}`
|
|
3183
|
+
);
|
|
3184
|
+
return;
|
|
3185
|
+
}
|
|
3186
|
+
if (result.kind === "not-found") {
|
|
3187
|
+
outputErrorAndExit(json, result.message, result.suggestion);
|
|
3188
|
+
return;
|
|
3189
|
+
}
|
|
3190
|
+
if (result.coin.platformBlocked) {
|
|
3191
|
+
outputErrorAndExit(json, bannedCoinMessage(result.coin.address));
|
|
3192
|
+
return;
|
|
3193
|
+
}
|
|
3194
|
+
const { coin } = result;
|
|
3195
|
+
const dataPoints = await showPriceHistory(json, coin, interval);
|
|
2977
3196
|
track("cli_price_history", {
|
|
2978
|
-
lookup_type:
|
|
3197
|
+
lookup_type: typeOrId.startsWith("0x") ? "address" : "name",
|
|
2979
3198
|
coin_type: coin.coinType,
|
|
2980
3199
|
interval,
|
|
2981
|
-
data_points:
|
|
3200
|
+
data_points: dataPoints,
|
|
2982
3201
|
output_format: json ? "json" : "text"
|
|
2983
3202
|
});
|
|
2984
3203
|
});
|
|
@@ -2988,7 +3207,7 @@ import { Command as Command7 } from "commander";
|
|
|
2988
3207
|
import confirm3 from "@inquirer/confirm";
|
|
2989
3208
|
import {
|
|
2990
3209
|
erc20Abi as erc20Abi3,
|
|
2991
|
-
formatUnits as
|
|
3210
|
+
formatUnits as formatUnits5,
|
|
2992
3211
|
isAddress as isAddress2,
|
|
2993
3212
|
parseUnits as parseUnits2
|
|
2994
3213
|
} from "viem";
|
|
@@ -3005,12 +3224,12 @@ function printSellQuote(output, info) {
|
|
|
3005
3224
|
coin: info.coinSymbol,
|
|
3006
3225
|
address: info.address,
|
|
3007
3226
|
sell: {
|
|
3008
|
-
amount:
|
|
3227
|
+
amount: formatUnits5(info.amountIn, info.coinDecimals),
|
|
3009
3228
|
raw: info.amountIn.toString(),
|
|
3010
3229
|
symbol: info.coinSymbol
|
|
3011
3230
|
},
|
|
3012
3231
|
estimated: {
|
|
3013
|
-
amount:
|
|
3232
|
+
amount: formatUnits5(BigInt(info.quoteAmountOut), info.outputDecimals),
|
|
3014
3233
|
raw: info.quoteAmountOut,
|
|
3015
3234
|
symbol: info.outputSymbol
|
|
3016
3235
|
},
|
|
@@ -3019,7 +3238,8 @@ function printSellQuote(output, info) {
|
|
|
3019
3238
|
return;
|
|
3020
3239
|
}
|
|
3021
3240
|
console.log(`
|
|
3022
|
-
Sell ${info.coinName}
|
|
3241
|
+
Sell \x1B[1m${info.coinName}\x1B[0m`);
|
|
3242
|
+
console.log(` ${info.coinType} \xB7 ${info.address}
|
|
3023
3243
|
`);
|
|
3024
3244
|
console.log(` Amount ${info.soldFormatted} ${info.coinSymbol}`);
|
|
3025
3245
|
console.log(
|
|
@@ -3029,7 +3249,7 @@ function printSellQuote(output, info) {
|
|
|
3029
3249
|
`);
|
|
3030
3250
|
}
|
|
3031
3251
|
function printSellResult(output, info) {
|
|
3032
|
-
const receivedAmount =
|
|
3252
|
+
const receivedAmount = formatUnits5(
|
|
3033
3253
|
info.receivedAmountOut,
|
|
3034
3254
|
info.outputDecimals
|
|
3035
3255
|
);
|
|
@@ -3043,7 +3263,7 @@ function printSellResult(output, info) {
|
|
|
3043
3263
|
coin: info.coinSymbol,
|
|
3044
3264
|
address: info.address,
|
|
3045
3265
|
sold: {
|
|
3046
|
-
amount:
|
|
3266
|
+
amount: formatUnits5(info.amountIn, info.coinDecimals),
|
|
3047
3267
|
raw: info.amountIn.toString(),
|
|
3048
3268
|
symbol: info.coinSymbol
|
|
3049
3269
|
},
|
|
@@ -3058,7 +3278,8 @@ function printSellResult(output, info) {
|
|
|
3058
3278
|
return;
|
|
3059
3279
|
}
|
|
3060
3280
|
console.log(`
|
|
3061
|
-
Sold ${info.coinName}
|
|
3281
|
+
Sold \x1B[1m${info.coinName}\x1B[0m`);
|
|
3282
|
+
console.log(` ${info.coinType} \xB7 ${info.address}
|
|
3062
3283
|
`);
|
|
3063
3284
|
console.log(` Sold ${info.soldFormatted} ${info.coinSymbol}`);
|
|
3064
3285
|
console.log(
|
|
@@ -3070,11 +3291,74 @@ function printSellResult(output, info) {
|
|
|
3070
3291
|
console.log(` Tx ${info.txHash}
|
|
3071
3292
|
`);
|
|
3072
3293
|
}
|
|
3073
|
-
var sellCommand = new Command7("sell").description("Sell a coin").argument(
|
|
3294
|
+
var sellCommand = new Command7("sell").description("Sell a coin").argument(
|
|
3295
|
+
"[typeOrId]",
|
|
3296
|
+
"Type prefix (creator-coin, trend) or coin address/name"
|
|
3297
|
+
).argument("[identifier]", "Coin name (when type prefix is given)").option("--amount <value>", "Sell specific number of coins").option("--usd <value>", "Sell USD equivalent worth of coins").option("--percent <value>", "Sell percentage of coin balance").option("--all", "Sell entire coin balance").option("--to <asset>", "Receive asset: eth, usdc, zora", "eth").option("--token <asset>", "Receive asset: eth, usdc, zora (alias for --to)").option("--quote", "Print quote and exit without trading").option("--yes", "Skip confirmation and execute directly").option("--slippage <pct>", "Slippage tolerance percent", "1").option("--debug", "Print full quote request/response JSON").action(async function(typeOrId, identifier, opts) {
|
|
3074
3298
|
const json = getJson(this);
|
|
3075
3299
|
const debug = opts.debug === true;
|
|
3076
|
-
|
|
3077
|
-
|
|
3300
|
+
let parsed;
|
|
3301
|
+
try {
|
|
3302
|
+
parsed = parsePositionalCoinArgs(typeOrId, identifier);
|
|
3303
|
+
} catch (err) {
|
|
3304
|
+
if (err instanceof CoinArgError) {
|
|
3305
|
+
outputErrorAndExit(json, err.message, err.suggestion);
|
|
3306
|
+
}
|
|
3307
|
+
throw err;
|
|
3308
|
+
}
|
|
3309
|
+
const apiKey = getApiKey();
|
|
3310
|
+
if (apiKey) {
|
|
3311
|
+
setApiKey6(apiKey);
|
|
3312
|
+
}
|
|
3313
|
+
let coinAddress;
|
|
3314
|
+
if (parsed.kind === "address") {
|
|
3315
|
+
if (!isAddress2(parsed.address)) {
|
|
3316
|
+
outputErrorAndExit(json, `Invalid address: ${parsed.address}`);
|
|
3317
|
+
return;
|
|
3318
|
+
}
|
|
3319
|
+
coinAddress = parsed.address;
|
|
3320
|
+
} else if (parsed.kind === "ambiguous-name") {
|
|
3321
|
+
let ambResult;
|
|
3322
|
+
try {
|
|
3323
|
+
ambResult = await resolveAmbiguousName(parsed.name);
|
|
3324
|
+
} catch (err) {
|
|
3325
|
+
outputErrorAndExit(
|
|
3326
|
+
json,
|
|
3327
|
+
`Request failed: ${err instanceof Error ? err.message : String(err)}`
|
|
3328
|
+
);
|
|
3329
|
+
return;
|
|
3330
|
+
}
|
|
3331
|
+
if (ambResult.kind === "not-found") {
|
|
3332
|
+
outputErrorAndExit(json, ambResult.message);
|
|
3333
|
+
return;
|
|
3334
|
+
}
|
|
3335
|
+
if (ambResult.kind === "ambiguous") {
|
|
3336
|
+
const { message, suggestion } = formatAmbiguousError(
|
|
3337
|
+
parsed.name,
|
|
3338
|
+
ambResult.creator,
|
|
3339
|
+
ambResult.trend,
|
|
3340
|
+
"sell"
|
|
3341
|
+
);
|
|
3342
|
+
outputErrorAndExit(json, message, suggestion);
|
|
3343
|
+
return;
|
|
3344
|
+
}
|
|
3345
|
+
coinAddress = ambResult.coin.address;
|
|
3346
|
+
} else {
|
|
3347
|
+
const ref = coinArgsToRef(parsed);
|
|
3348
|
+
try {
|
|
3349
|
+
const result = await resolveCoin(ref);
|
|
3350
|
+
if (result.kind === "not-found") {
|
|
3351
|
+
outputErrorAndExit(json, result.message, result.suggestion);
|
|
3352
|
+
return;
|
|
3353
|
+
}
|
|
3354
|
+
coinAddress = result.coin.address;
|
|
3355
|
+
} catch (err) {
|
|
3356
|
+
outputErrorAndExit(
|
|
3357
|
+
json,
|
|
3358
|
+
`Request failed: ${err instanceof Error ? err.message : String(err)}`
|
|
3359
|
+
);
|
|
3360
|
+
return;
|
|
3361
|
+
}
|
|
3078
3362
|
}
|
|
3079
3363
|
const output = json ? "json" : "static";
|
|
3080
3364
|
const outputAsset = opts.token ? opts.token.toLowerCase() : opts.to;
|
|
@@ -3099,10 +3383,6 @@ var sellCommand = new Command7("sell").description("Sell a coin").argument("[add
|
|
|
3099
3383
|
);
|
|
3100
3384
|
}
|
|
3101
3385
|
const slippage = slippagePct / 100;
|
|
3102
|
-
const apiKey = getApiKey();
|
|
3103
|
-
if (apiKey) {
|
|
3104
|
-
setApiKey6(apiKey);
|
|
3105
|
-
}
|
|
3106
3386
|
const account = resolveAccount(json);
|
|
3107
3387
|
const { publicClient, walletClient } = createClients(account);
|
|
3108
3388
|
let token;
|
|
@@ -3117,6 +3397,7 @@ var sellCommand = new Command7("sell").description("Sell a coin").argument("[add
|
|
|
3117
3397
|
}
|
|
3118
3398
|
const coinName = token.name;
|
|
3119
3399
|
const coinSymbol = token.symbol;
|
|
3400
|
+
const coinType = mapCoinType(token.coinType);
|
|
3120
3401
|
const coinDecimals = Number(token.decimals ?? 18);
|
|
3121
3402
|
let amountIn;
|
|
3122
3403
|
if (amountMode === "usd") {
|
|
@@ -3143,7 +3424,7 @@ var sellCommand = new Command7("sell").description("Sell a coin").argument("[add
|
|
|
3143
3424
|
}
|
|
3144
3425
|
if (debug) {
|
|
3145
3426
|
console.error(
|
|
3146
|
-
`[debug] $${usdVal} USD = ${
|
|
3427
|
+
`[debug] $${usdVal} USD = ${formatUnits5(amountIn, coinDecimals)} ${coinSymbol} (coin price: $${coinPriceUsd})`
|
|
3147
3428
|
);
|
|
3148
3429
|
}
|
|
3149
3430
|
} else if (amountMode === "amount") {
|
|
@@ -3198,7 +3479,7 @@ var sellCommand = new Command7("sell").description("Sell a coin").argument("[add
|
|
|
3198
3479
|
const coinPriceUsd = await fetchTokenPriceUsd(coinAddress);
|
|
3199
3480
|
if (coinPriceUsd !== null && coinPriceUsd > 0) {
|
|
3200
3481
|
swapAmountUsd = Number(
|
|
3201
|
-
(Number(
|
|
3482
|
+
(Number(formatUnits5(amountIn, coinDecimals)) * coinPriceUsd).toFixed(
|
|
3202
3483
|
2
|
|
3203
3484
|
)
|
|
3204
3485
|
);
|
|
@@ -3264,6 +3545,7 @@ ${err instanceof Error ? err.stack || err.message : String(err)}
|
|
|
3264
3545
|
printSellQuote(output, {
|
|
3265
3546
|
coinName,
|
|
3266
3547
|
coinSymbol,
|
|
3548
|
+
coinType,
|
|
3267
3549
|
address: coinAddress,
|
|
3268
3550
|
soldFormatted,
|
|
3269
3551
|
amountIn,
|
|
@@ -3293,6 +3575,7 @@ ${err instanceof Error ? err.stack || err.message : String(err)}
|
|
|
3293
3575
|
printSellQuote("static", {
|
|
3294
3576
|
coinName,
|
|
3295
3577
|
coinSymbol,
|
|
3578
|
+
coinType,
|
|
3296
3579
|
address: coinAddress,
|
|
3297
3580
|
soldFormatted,
|
|
3298
3581
|
amountIn,
|
|
@@ -3361,6 +3644,7 @@ ${err instanceof Error ? err.stack || err.message : String(err)}
|
|
|
3361
3644
|
printSellResult(output, {
|
|
3362
3645
|
coinName,
|
|
3363
3646
|
coinSymbol,
|
|
3647
|
+
coinType,
|
|
3364
3648
|
address: coinAddress,
|
|
3365
3649
|
amountIn,
|
|
3366
3650
|
coinDecimals,
|
|
@@ -3517,8 +3801,10 @@ var ProfileView = ({
|
|
|
3517
3801
|
] }) });
|
|
3518
3802
|
}
|
|
3519
3803
|
if (!data) return null;
|
|
3520
|
-
const hints = [
|
|
3521
|
-
|
|
3804
|
+
const hints = [
|
|
3805
|
+
"\u2190 \u2192 switch tab",
|
|
3806
|
+
autoRefresh ? `r refresh (${secondsUntilRefresh}s)` : "r refresh"
|
|
3807
|
+
];
|
|
3522
3808
|
hints.push("q quit");
|
|
3523
3809
|
const footer = hints.join(" \xB7 ");
|
|
3524
3810
|
const rankedPosts = data.posts.map((p, i) => ({ ...p, rank: i + 1 }));
|
|
@@ -3789,7 +4075,7 @@ import { Command as Command9 } from "commander";
|
|
|
3789
4075
|
import confirm4 from "@inquirer/confirm";
|
|
3790
4076
|
import {
|
|
3791
4077
|
erc20Abi as erc20Abi4,
|
|
3792
|
-
formatUnits as
|
|
4078
|
+
formatUnits as formatUnits6,
|
|
3793
4079
|
isAddress as isAddress3,
|
|
3794
4080
|
parseUnits as parseUnits3
|
|
3795
4081
|
} from "viem";
|
|
@@ -3799,7 +4085,7 @@ var SEND_AMOUNT_CHECKS = {
|
|
|
3799
4085
|
percent: (opts) => opts.percent !== void 0,
|
|
3800
4086
|
all: (opts) => opts.all === true
|
|
3801
4087
|
};
|
|
3802
|
-
var
|
|
4088
|
+
var KNOWN_TOKEN_NAMES = /* @__PURE__ */ new Set(["eth", "usdc", "zora"]);
|
|
3803
4089
|
function printSendPreview(info) {
|
|
3804
4090
|
const usdStr = info.amountUsd != null ? ` ($${info.amountUsd.toFixed(2)})` : "";
|
|
3805
4091
|
console.log(`
|
|
@@ -3820,7 +4106,7 @@ function printSendResult(json, info) {
|
|
|
3820
4106
|
coin: info.symbol,
|
|
3821
4107
|
address: info.address,
|
|
3822
4108
|
sent: {
|
|
3823
|
-
amount:
|
|
4109
|
+
amount: formatUnits6(info.amount, info.decimals),
|
|
3824
4110
|
raw: info.amount.toString(),
|
|
3825
4111
|
symbol: info.symbol,
|
|
3826
4112
|
amountUsd: info.amountUsd
|
|
@@ -3841,7 +4127,10 @@ function printSendResult(json, info) {
|
|
|
3841
4127
|
console.log(` Tx ${info.txHash}
|
|
3842
4128
|
`);
|
|
3843
4129
|
}
|
|
3844
|
-
var sendCommand = new Command9("send").description("Send coins or ETH to an address").argument(
|
|
4130
|
+
var sendCommand = new Command9("send").description("Send coins or ETH to an address").argument(
|
|
4131
|
+
"[typeOrId]",
|
|
4132
|
+
"Token (eth, usdc, zora), type prefix (creator-coin, trend), or coin address/name"
|
|
4133
|
+
).argument("[identifier]", "Coin name (when type prefix is given)").option("--to <address>", "Recipient address (0x...)").option("--amount <value>", "Send specific amount").option("--percent <value>", "Send percentage of balance (1-100)").option("--all", "Send entire balance").option("--yes", "Skip confirmation").action(async function(firstArg, secondArg, opts) {
|
|
3845
4134
|
const json = getJson(this);
|
|
3846
4135
|
if (!opts.to) {
|
|
3847
4136
|
outputErrorAndExit(
|
|
@@ -3858,24 +4147,15 @@ var sendCommand = new Command9("send").description("Send coins or ETH to an addr
|
|
|
3858
4147
|
);
|
|
3859
4148
|
}
|
|
3860
4149
|
const recipient = opts.to;
|
|
3861
|
-
if (opts.type !== void 0 && !VALID_TYPES3.includes(opts.type)) {
|
|
3862
|
-
outputErrorAndExit(
|
|
3863
|
-
json,
|
|
3864
|
-
`Invalid --type value: ${opts.type}.`,
|
|
3865
|
-
`Supported: ${VALID_TYPES3.join(", ")}`
|
|
3866
|
-
);
|
|
3867
|
-
}
|
|
3868
4150
|
const amountMode = getAmountMode(
|
|
3869
4151
|
json,
|
|
3870
4152
|
opts,
|
|
3871
4153
|
SEND_AMOUNT_CHECKS,
|
|
3872
4154
|
"--amount, --percent, or --all"
|
|
3873
4155
|
);
|
|
3874
|
-
const
|
|
4156
|
+
const isKnownToken = KNOWN_TOKEN_NAMES.has(firstArg.toLowerCase());
|
|
4157
|
+
const isEth = firstArg.toLowerCase() === "eth";
|
|
3875
4158
|
if (isEth) {
|
|
3876
|
-
if (opts.type) {
|
|
3877
|
-
outputErrorAndExit(json, "--type is not valid when sending ETH.");
|
|
3878
|
-
}
|
|
3879
4159
|
const account = resolveAccount(json);
|
|
3880
4160
|
const { publicClient, walletClient } = createClients(account);
|
|
3881
4161
|
const balance = await publicClient.getBalance({
|
|
@@ -3913,14 +4193,14 @@ var sendCommand = new Command9("send").description("Send coins or ETH to an addr
|
|
|
3913
4193
|
if (amount + GAS_RESERVE > balance) {
|
|
3914
4194
|
outputErrorAndExit(
|
|
3915
4195
|
json,
|
|
3916
|
-
`Insufficient balance. Have ${
|
|
4196
|
+
`Insufficient balance. Have ${formatAmountDisplay(balance, 18)} ETH (need to reserve ~${formatAmountDisplay(GAS_RESERVE, 18)} ETH for gas).`
|
|
3917
4197
|
);
|
|
3918
4198
|
}
|
|
3919
4199
|
} else {
|
|
3920
4200
|
if (balance <= GAS_RESERVE) {
|
|
3921
4201
|
outputErrorAndExit(
|
|
3922
4202
|
json,
|
|
3923
|
-
`Balance too low (${
|
|
4203
|
+
`Balance too low (${formatAmountDisplay(balance, 18)} ETH). Need >${formatAmountDisplay(GAS_RESERVE, 18)} ETH for gas.`
|
|
3924
4204
|
);
|
|
3925
4205
|
}
|
|
3926
4206
|
const spendable = balance - GAS_RESERVE;
|
|
@@ -3943,12 +4223,12 @@ var sendCommand = new Command9("send").description("Send coins or ETH to an addr
|
|
|
3943
4223
|
}
|
|
3944
4224
|
}
|
|
3945
4225
|
}
|
|
3946
|
-
const amountFormatted =
|
|
4226
|
+
const amountFormatted = formatAmountDisplay(amount, 18);
|
|
3947
4227
|
let amountUsd = null;
|
|
3948
4228
|
const ethPriceUsd = await fetchTokenPriceUsd(WETH_ADDRESS);
|
|
3949
4229
|
if (ethPriceUsd != null) {
|
|
3950
4230
|
amountUsd = Number(
|
|
3951
|
-
(Number(
|
|
4231
|
+
(Number(formatUnits6(amount, 18)) * ethPriceUsd).toFixed(2)
|
|
3952
4232
|
);
|
|
3953
4233
|
}
|
|
3954
4234
|
if (!opts.yes) {
|
|
@@ -4008,14 +4288,8 @@ var sendCommand = new Command9("send").description("Send coins or ETH to an addr
|
|
|
4008
4288
|
tx_hash: txHash
|
|
4009
4289
|
});
|
|
4010
4290
|
} else {
|
|
4011
|
-
const knownTokenKey =
|
|
4012
|
-
const knownToken = knownTokenKey !== "eth" && knownTokenKey in BASE_TRADE_TOKENS ? BASE_TRADE_TOKENS[knownTokenKey] : void 0;
|
|
4013
|
-
if (knownToken && opts.type) {
|
|
4014
|
-
outputErrorAndExit(
|
|
4015
|
-
json,
|
|
4016
|
-
`--type is not valid when sending ${knownToken.symbol}.`
|
|
4017
|
-
);
|
|
4018
|
-
}
|
|
4291
|
+
const knownTokenKey = firstArg.toLowerCase();
|
|
4292
|
+
const knownToken = isKnownToken && knownTokenKey !== "eth" && knownTokenKey in BASE_TRADE_TOKENS ? BASE_TRADE_TOKENS[knownTokenKey] : void 0;
|
|
4019
4293
|
let tokenAddress;
|
|
4020
4294
|
let tokenName;
|
|
4021
4295
|
if (knownToken) {
|
|
@@ -4027,21 +4301,60 @@ var sendCommand = new Command9("send").description("Send coins or ETH to an addr
|
|
|
4027
4301
|
if (apiKey) {
|
|
4028
4302
|
setApiKey8(apiKey);
|
|
4029
4303
|
}
|
|
4030
|
-
|
|
4031
|
-
let result;
|
|
4304
|
+
let parsed;
|
|
4032
4305
|
try {
|
|
4033
|
-
|
|
4306
|
+
parsed = parsePositionalCoinArgs(firstArg, secondArg);
|
|
4034
4307
|
} catch (err) {
|
|
4035
|
-
|
|
4036
|
-
json,
|
|
4037
|
-
|
|
4038
|
-
|
|
4308
|
+
if (err instanceof CoinArgError) {
|
|
4309
|
+
outputErrorAndExit(json, err.message, err.suggestion);
|
|
4310
|
+
}
|
|
4311
|
+
throw err;
|
|
4039
4312
|
}
|
|
4040
|
-
if (
|
|
4041
|
-
|
|
4313
|
+
if (parsed.kind === "ambiguous-name") {
|
|
4314
|
+
let ambResult;
|
|
4315
|
+
try {
|
|
4316
|
+
ambResult = await resolveAmbiguousName(parsed.name);
|
|
4317
|
+
} catch (err) {
|
|
4318
|
+
outputErrorAndExit(
|
|
4319
|
+
json,
|
|
4320
|
+
`Request failed: ${err instanceof Error ? err.message : String(err)}`
|
|
4321
|
+
);
|
|
4322
|
+
return;
|
|
4323
|
+
}
|
|
4324
|
+
if (ambResult.kind === "not-found") {
|
|
4325
|
+
outputErrorAndExit(json, ambResult.message);
|
|
4326
|
+
return;
|
|
4327
|
+
}
|
|
4328
|
+
if (ambResult.kind === "ambiguous") {
|
|
4329
|
+
const { message, suggestion } = formatAmbiguousError(
|
|
4330
|
+
parsed.name,
|
|
4331
|
+
ambResult.creator,
|
|
4332
|
+
ambResult.trend,
|
|
4333
|
+
"send"
|
|
4334
|
+
);
|
|
4335
|
+
outputErrorAndExit(json, message, suggestion);
|
|
4336
|
+
return;
|
|
4337
|
+
}
|
|
4338
|
+
tokenAddress = ambResult.coin.address;
|
|
4339
|
+
tokenName = ambResult.coin.name;
|
|
4340
|
+
} else {
|
|
4341
|
+
const ref = coinArgsToRef(parsed);
|
|
4342
|
+
try {
|
|
4343
|
+
const result = await resolveCoin(ref);
|
|
4344
|
+
if (result.kind === "not-found") {
|
|
4345
|
+
outputErrorAndExit(json, result.message, result.suggestion);
|
|
4346
|
+
return;
|
|
4347
|
+
}
|
|
4348
|
+
tokenAddress = result.coin.address;
|
|
4349
|
+
tokenName = result.coin.name;
|
|
4350
|
+
} catch (err) {
|
|
4351
|
+
outputErrorAndExit(
|
|
4352
|
+
json,
|
|
4353
|
+
`Request failed: ${err instanceof Error ? err.message : String(err)}`
|
|
4354
|
+
);
|
|
4355
|
+
return;
|
|
4356
|
+
}
|
|
4042
4357
|
}
|
|
4043
|
-
tokenAddress = result.coin.address;
|
|
4044
|
-
tokenName = result.coin.name;
|
|
4045
4358
|
}
|
|
4046
4359
|
const account = resolveAccount(json);
|
|
4047
4360
|
const { publicClient, walletClient } = createClients(account);
|
|
@@ -4139,7 +4452,7 @@ var sendCommand = new Command9("send").description("Send coins or ETH to an addr
|
|
|
4139
4452
|
const priceUsd = knownToken?.fixedPriceUsd ?? await fetchTokenPriceUsd(priceAddress);
|
|
4140
4453
|
if (priceUsd != null) {
|
|
4141
4454
|
amountUsd = Number(
|
|
4142
|
-
(Number(
|
|
4455
|
+
(Number(formatUnits6(amount, decimals)) * priceUsd).toFixed(2)
|
|
4143
4456
|
);
|
|
4144
4457
|
}
|
|
4145
4458
|
if (!opts.yes) {
|
|
@@ -4461,8 +4774,103 @@ walletCommand.command("export").description("Print the raw private key to stdout
|
|
|
4461
4774
|
});
|
|
4462
4775
|
});
|
|
4463
4776
|
|
|
4464
|
-
// src/components/
|
|
4777
|
+
// src/components/StyledHelp.tsx
|
|
4778
|
+
import { Text as Text10, Box as Box10 } from "ink";
|
|
4779
|
+
|
|
4780
|
+
// src/components/KeyValueTable.tsx
|
|
4465
4781
|
import { Text as Text9, Box as Box9 } from "ink";
|
|
4782
|
+
import { jsx as jsx12, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
4783
|
+
function KeyValueTable({
|
|
4784
|
+
rows,
|
|
4785
|
+
labelWidth
|
|
4786
|
+
}) {
|
|
4787
|
+
const pad = labelWidth ?? Math.max(0, ...rows.map((r) => r.label.length)) + 2;
|
|
4788
|
+
return /* @__PURE__ */ jsx12(Box9, { flexDirection: "column", children: rows.map((row, i) => /* @__PURE__ */ jsxs9(Text9, { children: [
|
|
4789
|
+
/* @__PURE__ */ jsx12(Text9, { bold: true, children: row.label.padEnd(pad) }),
|
|
4790
|
+
/* @__PURE__ */ jsx12(Text9, { dimColor: true, children: row.value })
|
|
4791
|
+
] }, i)) });
|
|
4792
|
+
}
|
|
4793
|
+
|
|
4794
|
+
// src/lib/parse-help.ts
|
|
4795
|
+
var DEFAULT_DESC_COLUMN = 38;
|
|
4796
|
+
var TWO_COLUMN_REGEX = /^(.+\S)([ \t]{2,})(\S.*)/m;
|
|
4797
|
+
function getDescriptionColumnOffset(sections) {
|
|
4798
|
+
for (const section of sections) {
|
|
4799
|
+
const match = section.content.match(TWO_COLUMN_REGEX);
|
|
4800
|
+
if (match) {
|
|
4801
|
+
return match[1].length + match[2].length;
|
|
4802
|
+
}
|
|
4803
|
+
}
|
|
4804
|
+
return DEFAULT_DESC_COLUMN;
|
|
4805
|
+
}
|
|
4806
|
+
function parseHelpSections(text) {
|
|
4807
|
+
const sections = [];
|
|
4808
|
+
let currentTitle = "";
|
|
4809
|
+
let currentLines = [];
|
|
4810
|
+
for (const line of text.split("\n")) {
|
|
4811
|
+
const match = line.match(/^([A-Z]\w+):(.*)/);
|
|
4812
|
+
if (match) {
|
|
4813
|
+
if (currentTitle) {
|
|
4814
|
+
const content = currentLines.join("\n").replace(/^\n+|\n+$/g, "");
|
|
4815
|
+
sections.push({ title: currentTitle, content });
|
|
4816
|
+
}
|
|
4817
|
+
currentTitle = match[1];
|
|
4818
|
+
currentLines = match[2].trim() ? [match[2].trim()] : [];
|
|
4819
|
+
} else if (currentTitle) {
|
|
4820
|
+
currentLines.push(line.startsWith(" ") ? line.slice(2) : line);
|
|
4821
|
+
}
|
|
4822
|
+
}
|
|
4823
|
+
if (currentTitle) {
|
|
4824
|
+
const content = currentLines.join("\n").replace(/^\n+|\n+$/g, "");
|
|
4825
|
+
sections.push({ title: currentTitle, content });
|
|
4826
|
+
}
|
|
4827
|
+
return sections.filter((s) => s.content);
|
|
4828
|
+
}
|
|
4829
|
+
|
|
4830
|
+
// src/components/StyledHelp.tsx
|
|
4831
|
+
import { jsx as jsx13, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
4832
|
+
function StyledHelp({
|
|
4833
|
+
sections,
|
|
4834
|
+
header
|
|
4835
|
+
}) {
|
|
4836
|
+
const descriptionColumnOffset = getDescriptionColumnOffset(sections);
|
|
4837
|
+
return /* @__PURE__ */ jsxs10(Box10, { flexDirection: "column", gap: 1, children: [
|
|
4838
|
+
header,
|
|
4839
|
+
sections.map((section, i) => {
|
|
4840
|
+
const hasTwoColumns = TWO_COLUMN_REGEX.test(section.content);
|
|
4841
|
+
const rows = hasTwoColumns ? section.content.split("\n").map((line) => {
|
|
4842
|
+
const m = line.match(TWO_COLUMN_REGEX);
|
|
4843
|
+
if (m)
|
|
4844
|
+
return {
|
|
4845
|
+
label: m[1],
|
|
4846
|
+
value: m[3][0].toUpperCase() + m[3].slice(1)
|
|
4847
|
+
};
|
|
4848
|
+
return { label: "", value: line.trimStart() };
|
|
4849
|
+
}) : null;
|
|
4850
|
+
return /* @__PURE__ */ jsxs10(
|
|
4851
|
+
Box10,
|
|
4852
|
+
{
|
|
4853
|
+
flexDirection: "column",
|
|
4854
|
+
borderStyle: "single",
|
|
4855
|
+
borderDimColor: true,
|
|
4856
|
+
paddingX: 1,
|
|
4857
|
+
paddingY: 1,
|
|
4858
|
+
children: [
|
|
4859
|
+
/* @__PURE__ */ jsx13(Text10, { bold: true, children: section.title }),
|
|
4860
|
+
rows ? /* @__PURE__ */ jsx13(KeyValueTable, { rows, labelWidth: descriptionColumnOffset }) : /* @__PURE__ */ jsx13(Text10, { children: section.content })
|
|
4861
|
+
]
|
|
4862
|
+
},
|
|
4863
|
+
i
|
|
4864
|
+
);
|
|
4865
|
+
})
|
|
4866
|
+
] });
|
|
4867
|
+
}
|
|
4868
|
+
|
|
4869
|
+
// src/components/StyledHelpHeader.tsx
|
|
4870
|
+
import { Text as Text12, Box as Box12 } from "ink";
|
|
4871
|
+
|
|
4872
|
+
// src/components/Zorb.tsx
|
|
4873
|
+
import { Text as Text11, Box as Box11 } from "ink";
|
|
4466
4874
|
|
|
4467
4875
|
// src/lib/zorb-pixels.ts
|
|
4468
4876
|
function supportsTruecolor() {
|
|
@@ -4607,7 +5015,7 @@ function generateZorbPixels(size) {
|
|
|
4607
5015
|
}
|
|
4608
5016
|
|
|
4609
5017
|
// src/components/Zorb.tsx
|
|
4610
|
-
import { jsx as
|
|
5018
|
+
import { jsx as jsx14, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
4611
5019
|
var LOWER_HALF_BLOCK = "\u2584";
|
|
4612
5020
|
var UPPER_HALF_BLOCK = "\u2580";
|
|
4613
5021
|
function rgbString([r, g, b]) {
|
|
@@ -4630,19 +5038,19 @@ function Zorb({ size = 20 }) {
|
|
|
4630
5038
|
const topIsBlack = isBlack(top);
|
|
4631
5039
|
const bottomIsBlack = isBlack(bottom);
|
|
4632
5040
|
if (topIsBlack && bottomIsBlack) {
|
|
4633
|
-
cells.push(/* @__PURE__ */
|
|
5041
|
+
cells.push(/* @__PURE__ */ jsx14(Text11, { children: " " }, x));
|
|
4634
5042
|
} else if (topIsBlack) {
|
|
4635
5043
|
cells.push(
|
|
4636
|
-
/* @__PURE__ */
|
|
5044
|
+
/* @__PURE__ */ jsx14(Text11, { color: rgbString(bottom), children: LOWER_HALF_BLOCK }, x)
|
|
4637
5045
|
);
|
|
4638
5046
|
} else if (bottomIsBlack) {
|
|
4639
5047
|
cells.push(
|
|
4640
|
-
/* @__PURE__ */
|
|
5048
|
+
/* @__PURE__ */ jsx14(Text11, { color: rgbString(top), children: UPPER_HALF_BLOCK }, x)
|
|
4641
5049
|
);
|
|
4642
5050
|
} else {
|
|
4643
5051
|
cells.push(
|
|
4644
|
-
/* @__PURE__ */
|
|
4645
|
-
|
|
5052
|
+
/* @__PURE__ */ jsx14(
|
|
5053
|
+
Text11,
|
|
4646
5054
|
{
|
|
4647
5055
|
backgroundColor: rgbString(top),
|
|
4648
5056
|
color: rgbString(bottom),
|
|
@@ -4653,25 +5061,66 @@ function Zorb({ size = 20 }) {
|
|
|
4653
5061
|
);
|
|
4654
5062
|
}
|
|
4655
5063
|
}
|
|
4656
|
-
rows.push(/* @__PURE__ */
|
|
5064
|
+
rows.push(/* @__PURE__ */ jsx14(Text11, { children: cells }, y));
|
|
4657
5065
|
}
|
|
4658
|
-
return /* @__PURE__ */
|
|
4659
|
-
/* @__PURE__ */
|
|
5066
|
+
return /* @__PURE__ */ jsxs11(Box11, { flexDirection: "column", children: [
|
|
5067
|
+
/* @__PURE__ */ jsx14(Text11, { children: " " }),
|
|
4660
5068
|
rows,
|
|
4661
|
-
/* @__PURE__ */
|
|
5069
|
+
/* @__PURE__ */ jsx14(Text11, { children: " " })
|
|
4662
5070
|
] });
|
|
4663
5071
|
}
|
|
4664
5072
|
|
|
5073
|
+
// src/components/StyledHelpHeader.tsx
|
|
5074
|
+
import { jsx as jsx15, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
5075
|
+
function StyledHelpHeader({
|
|
5076
|
+
sections
|
|
5077
|
+
}) {
|
|
5078
|
+
const descriptionColumnOffset = getDescriptionColumnOffset(sections);
|
|
5079
|
+
return /* @__PURE__ */ jsxs12(
|
|
5080
|
+
Box12,
|
|
5081
|
+
{
|
|
5082
|
+
flexDirection: "row",
|
|
5083
|
+
borderStyle: "single",
|
|
5084
|
+
borderDimColor: true,
|
|
5085
|
+
paddingX: 1,
|
|
5086
|
+
paddingY: 1,
|
|
5087
|
+
children: [
|
|
5088
|
+
/* @__PURE__ */ jsx15(Box12, { flexShrink: 0, width: descriptionColumnOffset, children: /* @__PURE__ */ jsx15(Zorb, { size: 20 }) }),
|
|
5089
|
+
/* @__PURE__ */ jsx15(Box12, { flexDirection: "column", flexGrow: 1, justifyContent: "center", children: /* @__PURE__ */ jsx15(Text12, { bold: true, children: "Zora CLI" }) })
|
|
5090
|
+
]
|
|
5091
|
+
}
|
|
5092
|
+
);
|
|
5093
|
+
}
|
|
5094
|
+
|
|
4665
5095
|
// src/index.tsx
|
|
4666
|
-
import { jsx as
|
|
5096
|
+
import { jsx as jsx16 } from "react/jsx-runtime";
|
|
4667
5097
|
if (process.env.ZORA_API_TARGET) {
|
|
4668
5098
|
setApiBaseUrl(process.env.ZORA_API_TARGET);
|
|
4669
5099
|
}
|
|
4670
|
-
var version = true ? "0.3.
|
|
5100
|
+
var version = true ? "0.3.1" : JSON.parse(
|
|
4671
5101
|
readFileSync2(new URL("../package.json", import.meta.url), "utf-8")
|
|
4672
5102
|
).version;
|
|
5103
|
+
function styledHelpWriteOut(showHeader) {
|
|
5104
|
+
return (str) => {
|
|
5105
|
+
if (supportsTruecolor()) {
|
|
5106
|
+
const sections = parseHelpSections(str);
|
|
5107
|
+
if (sections.length > 0) {
|
|
5108
|
+
const header = showHeader ? /* @__PURE__ */ jsx16(StyledHelpHeader, { sections }) : void 0;
|
|
5109
|
+
renderOnce(/* @__PURE__ */ jsx16(StyledHelp, { sections, header }));
|
|
5110
|
+
return;
|
|
5111
|
+
}
|
|
5112
|
+
}
|
|
5113
|
+
process.stdout.write(str);
|
|
5114
|
+
};
|
|
5115
|
+
}
|
|
4673
5116
|
var buildProgram = () => {
|
|
4674
|
-
const program2 = new Command12().name("zora").description("Zora
|
|
5117
|
+
const program2 = new Command12().name("zora").description("A developer CLI for the Zora platform").version(version).option("--json", "Output as JSON (for scripts and automation)", false);
|
|
5118
|
+
const helpWidth = (process.stdout.columns || 80) - 4;
|
|
5119
|
+
program2.configureHelp({ helpWidth });
|
|
5120
|
+
program2.configureOutput({ writeOut: styledHelpWriteOut(true) });
|
|
5121
|
+
program2.action(() => {
|
|
5122
|
+
program2.outputHelp();
|
|
5123
|
+
});
|
|
4675
5124
|
program2.addCommand(authCommand);
|
|
4676
5125
|
program2.addCommand(balanceCommand);
|
|
4677
5126
|
program2.addCommand(buyCommand);
|
|
@@ -4683,9 +5132,17 @@ var buildProgram = () => {
|
|
|
4683
5132
|
program2.addCommand(walletCommand);
|
|
4684
5133
|
program2.addCommand(sellCommand);
|
|
4685
5134
|
program2.addCommand(sendCommand);
|
|
5135
|
+
const applyToSubcommands = (parent) => {
|
|
5136
|
+
for (const cmd of parent.commands) {
|
|
5137
|
+
cmd.configureHelp({ helpWidth });
|
|
5138
|
+
cmd.configureOutput({ writeOut: styledHelpWriteOut(false) });
|
|
5139
|
+
applyToSubcommands(cmd);
|
|
5140
|
+
}
|
|
5141
|
+
};
|
|
5142
|
+
applyToSubcommands(program2);
|
|
4686
5143
|
program2.hook("preAction", (_thisCommand, actionCommand) => {
|
|
4687
5144
|
const expected = actionCommand.registeredArguments.length;
|
|
4688
|
-
if (expected > 0 && actionCommand.args.length
|
|
5145
|
+
if (expected > 0 && actionCommand.args.length === 0) {
|
|
4689
5146
|
actionCommand.outputHelp();
|
|
4690
5147
|
process.exit(1);
|
|
4691
5148
|
}
|
|
@@ -4694,10 +5151,6 @@ var buildProgram = () => {
|
|
|
4694
5151
|
};
|
|
4695
5152
|
var program = buildProgram();
|
|
4696
5153
|
if (!process.env.VITEST) {
|
|
4697
|
-
const showingHelp = process.argv.length <= 2 || process.argv.includes("--help") || process.argv.includes("-h");
|
|
4698
|
-
if (showingHelp && !process.argv.includes("--json") && supportsTruecolor()) {
|
|
4699
|
-
renderOnce(/* @__PURE__ */ jsx13(Zorb, { size: 20 }));
|
|
4700
|
-
}
|
|
4701
5154
|
console.warn(
|
|
4702
5155
|
"\x1B[33m\u26A0 Beta:\x1B[0m This CLI is in beta and should be used with caution."
|
|
4703
5156
|
);
|