@zoralabs/cli 1.4.1 → 1.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.js +493 -171
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -5,7 +5,7 @@ import {
5
5
  } from "./chunk-WF24B44I.js";
6
6
 
7
7
  // src/index.tsx
8
- import { Command as Command17 } from "commander";
8
+ import { Command as Command18 } from "commander";
9
9
  import { ExitPromptError } from "@inquirer/core";
10
10
  import "fs";
11
11
  import { setApiBaseUrl } from "@zoralabs/coins-sdk";
@@ -173,6 +173,63 @@ function extractErrorMessage(error) {
173
173
  }
174
174
  return JSON.stringify(error);
175
175
  }
176
+ var MAX_SERIALIZE_DEPTH = 6;
177
+ function toSerializable(value, seen, depth) {
178
+ if (value === null) return null;
179
+ const type = typeof value;
180
+ if (type === "string" || type === "boolean") {
181
+ return value;
182
+ }
183
+ if (type === "number") {
184
+ return Number.isFinite(value) ? value : null;
185
+ }
186
+ if (type === "bigint") return value.toString();
187
+ if (type === "undefined" || type === "function" || type === "symbol") {
188
+ return null;
189
+ }
190
+ const obj = value;
191
+ if (seen.has(obj)) return "[Circular]";
192
+ if (depth >= MAX_SERIALIZE_DEPTH) return "[MaxDepth]";
193
+ if (value instanceof Date) {
194
+ return Number.isNaN(value.getTime()) ? null : value.toISOString();
195
+ }
196
+ seen.add(obj);
197
+ try {
198
+ if (Array.isArray(value)) {
199
+ return value.map((item) => toSerializable(item, seen, depth + 1));
200
+ }
201
+ const result = {};
202
+ if (value instanceof Error) {
203
+ result.name = value.name;
204
+ result.message = value.message;
205
+ if (value.stack) result.stack = value.stack;
206
+ }
207
+ for (const key of Object.keys(value)) {
208
+ if (key in result) continue;
209
+ let raw;
210
+ try {
211
+ raw = value[key];
212
+ } catch (getterError) {
213
+ result[key] = `[Unserializable: ${getterError instanceof Error ? getterError.message : String(getterError)}]`;
214
+ continue;
215
+ }
216
+ const t = typeof raw;
217
+ if (t === "undefined" || t === "function" || t === "symbol") continue;
218
+ result[key] = toSerializable(raw, seen, depth + 1);
219
+ }
220
+ return result;
221
+ } finally {
222
+ seen.delete(obj);
223
+ }
224
+ }
225
+ function serializeError(err) {
226
+ const serialized = toSerializable(err, /* @__PURE__ */ new WeakSet(), 0);
227
+ if (serialized !== null && typeof serialized === "object") {
228
+ if (Array.isArray(serialized)) return { value: serialized };
229
+ return serialized;
230
+ }
231
+ return { message: serialized === null ? String(err) : serialized };
232
+ }
176
233
  function bannedCoinMessage(address) {
177
234
  return `The coin at ${address} is unavailable because it violates the Zora terms of service.`;
178
235
  }
@@ -1070,8 +1127,8 @@ async function confirmAgentAction(opts) {
1070
1127
  }
1071
1128
 
1072
1129
  // src/lib/analytics.ts
1073
- import { PostHog } from "posthog-node";
1074
1130
  import { createHash, randomUUID } from "crypto";
1131
+ import { PostHog } from "posthog-node";
1075
1132
  import { privateKeyToAccount as privateKeyToAccount2 } from "viem/accounts";
1076
1133
 
1077
1134
  // src/lib/account/index.ts
@@ -1472,22 +1529,37 @@ var getClient = () => {
1472
1529
  }
1473
1530
  return client;
1474
1531
  };
1475
- var commonProperties = () => ({
1476
- cli_version: true ? "1.4.1" : "development",
1477
- os: process.platform,
1478
- arch: process.arch,
1479
- node_version: process.version
1480
- });
1481
- var hashApiKey = (key) => createHash("sha256").update(key).digest("hex").slice(0, 16);
1482
- var getWalletAddress = () => {
1532
+ var getWalletAddresses = () => {
1533
+ const addresses = {
1534
+ wallet: void 0,
1535
+ smartWallet: void 0
1536
+ };
1483
1537
  try {
1484
- const key = process.env.ZORA_PRIVATE_KEY || getPrivateKey();
1485
- if (!key) return void 0;
1486
- return privateKeyToAccount2(normalizeKey(key)).address;
1538
+ const privateKey = resolvePrivateKey();
1539
+ addresses.wallet = privateKeyToAccount2(normalizeKey(privateKey)).address;
1487
1540
  } catch {
1488
- return void 0;
1541
+ addresses.wallet = void 0;
1489
1542
  }
1543
+ try {
1544
+ const smartWalletAddress = resolveSmartWalletAddress();
1545
+ addresses.smartWallet = smartWalletAddress;
1546
+ } catch {
1547
+ addresses.smartWallet = void 0;
1548
+ }
1549
+ return addresses;
1550
+ };
1551
+ var commonProperties = () => {
1552
+ const addresses = getWalletAddresses();
1553
+ return {
1554
+ cli_version: true ? "1.5.0" : "development",
1555
+ os: process.platform,
1556
+ arch: process.arch,
1557
+ node_version: process.version,
1558
+ wallet_address: addresses.wallet,
1559
+ smart_wallet_address: addresses.smartWallet
1560
+ };
1490
1561
  };
1562
+ var hashApiKey = (key) => createHash("sha256").update(key).digest("hex").slice(0, 16);
1491
1563
  var identified = false;
1492
1564
  var identify = () => {
1493
1565
  try {
@@ -1495,20 +1567,37 @@ var identify = () => {
1495
1567
  identified = true;
1496
1568
  const id = getOrCreateDistinctId();
1497
1569
  const apiKey = getApiKey();
1498
- const walletAddress = getWalletAddress();
1499
- if (!apiKey && !walletAddress) {
1570
+ const { wallet: walletAddress, smartWallet: smartWalletAddress } = getWalletAddresses();
1571
+ if (!apiKey && !walletAddress && !smartWalletAddress) {
1500
1572
  return;
1501
1573
  }
1502
1574
  getClient().identify({
1503
1575
  distinctId: id,
1504
1576
  properties: {
1505
1577
  api_key_hash: apiKey ? hashApiKey(apiKey) : void 0,
1506
- wallet_address: walletAddress ?? void 0
1578
+ wallet_address: walletAddress ?? void 0,
1579
+ smart_wallet_address: smartWalletAddress ?? void 0
1507
1580
  }
1508
1581
  });
1509
1582
  } catch {
1510
1583
  }
1511
1584
  };
1585
+ var setPersonProperties = (properties) => {
1586
+ try {
1587
+ if (isDisabled()) return;
1588
+ const cleaned = Object.fromEntries(
1589
+ Object.entries(properties).filter(
1590
+ ([, value]) => value !== void 0 && value !== null && value !== ""
1591
+ )
1592
+ );
1593
+ if (Object.keys(cleaned).length === 0) return;
1594
+ getClient().identify({
1595
+ distinctId: getOrCreateDistinctId(),
1596
+ properties: cleaned
1597
+ });
1598
+ } catch {
1599
+ }
1600
+ };
1512
1601
  var track = (event, properties) => {
1513
1602
  try {
1514
1603
  if (isDisabled()) return;
@@ -1813,6 +1902,42 @@ import { createPublicClient as createPublicClient3, http as http3 } from "viem";
1813
1902
  import { base as base6 } from "viem/chains";
1814
1903
  import { privateKeyToAccount as privateKeyToAccount5 } from "viem/accounts";
1815
1904
 
1905
+ // src/lib/agent-harness.ts
1906
+ import { existsSync as existsSync2 } from "fs";
1907
+ import { join as join2 } from "path";
1908
+ var AGENT_HARNESS_ORDER = [
1909
+ "claude",
1910
+ "cursor",
1911
+ "windsurf",
1912
+ "openclaw",
1913
+ "hermes"
1914
+ ];
1915
+ var AGENT_HARNESS_SKILLS_DIRS = {
1916
+ claude: ".claude/skills",
1917
+ cursor: ".cursor/skills",
1918
+ windsurf: ".windsurf/skills",
1919
+ openclaw: ".openclaw/skills",
1920
+ hermes: ".hermes/skills"
1921
+ };
1922
+ var AGENT_HARNESS_ROOT_DIRS = {
1923
+ claude: ".claude",
1924
+ cursor: ".cursor",
1925
+ windsurf: ".windsurf",
1926
+ openclaw: ".openclaw",
1927
+ hermes: ".hermes"
1928
+ };
1929
+ var AGENT_HARNESS_TO_UAPI = {
1930
+ claude: "CLAUDE",
1931
+ cursor: "CURSOR",
1932
+ windsurf: "WINDSURF",
1933
+ openclaw: "OPENCLAW",
1934
+ hermes: "HERMES"
1935
+ };
1936
+ var detectAgentHarness = (cwd) => AGENT_HARNESS_ORDER.find(
1937
+ (agent) => existsSync2(join2(cwd, AGENT_HARNESS_ROOT_DIRS[agent]))
1938
+ );
1939
+ var mapAgentHarnessToUapi = (harness) => AGENT_HARNESS_TO_UAPI[harness];
1940
+
1816
1941
  // src/lib/privy-session.ts
1817
1942
  import { privateKeyToAccount as privateKeyToAccount4 } from "viem/accounts";
1818
1943
  var EXPIRY_SKEW_MS = 6e4;
@@ -2810,20 +2935,22 @@ async function onboardAgent(opts) {
2810
2935
  `Failed to save API key: ${fsErrorMessage(err, getConfigPath())}`
2811
2936
  );
2812
2937
  }
2813
- if (opts.username !== void 0 || opts.bio !== void 0 || opts.avatar !== void 0) {
2938
+ if (opts.username !== void 0 || opts.bio !== void 0 || opts.avatar !== void 0 || opts.agentHarness !== void 0) {
2814
2939
  const chosen = [
2815
2940
  opts.username !== void 0 ? "username" : void 0,
2816
2941
  opts.bio !== void 0 ? "bio" : void 0,
2817
- opts.avatar ? "avatar" : void 0
2942
+ opts.avatar ? "avatar" : void 0,
2943
+ opts.agentHarness !== void 0 ? "agent harness" : void 0
2818
2944
  ].filter((field) => field !== void 0);
2819
2945
  progress(
2820
2946
  "profile",
2821
2947
  `applying the chosen ${new Intl.ListFormat("en", { type: "conjunction" }).format(chosen)}`
2822
2948
  );
2823
- if (opts.username !== void 0 || opts.bio !== void 0) {
2949
+ if (opts.username !== void 0 || opts.bio !== void 0 || opts.agentHarness !== void 0) {
2824
2950
  profile = await updateAgentProfile(session.accessToken, {
2825
2951
  username: opts.username,
2826
- bio: opts.bio
2952
+ bio: opts.bio,
2953
+ ...opts.agentHarness ? { agentHarness: mapAgentHarnessToUapi(opts.agentHarness) } : {}
2827
2954
  });
2828
2955
  }
2829
2956
  if (opts.avatar) {
@@ -3224,6 +3351,7 @@ Re-running 'agent create' will mint another ${what} for it.`;
3224
3351
  appId: options.appId,
3225
3352
  origin: options.origin,
3226
3353
  chainId,
3354
+ agentHarness: detectAgentHarness(process.cwd()),
3227
3355
  rpcUrl: options.rpcUrl,
3228
3356
  dryRun: Boolean(options.dryRun),
3229
3357
  skipCoin: Boolean(options.skipCoin),
@@ -3283,6 +3411,7 @@ Re-running 'agent create' will mint another ${what} for it.`;
3283
3411
  set_ticker: options.ticker !== void 0,
3284
3412
  output_format: json ? "json" : "text"
3285
3413
  });
3414
+ setPersonProperties({ name: result.username });
3286
3415
  outputData(json, {
3287
3416
  json: {
3288
3417
  ...result,
@@ -3505,6 +3634,7 @@ agentCommand.command("connect-email").description(
3505
3634
  generated_wallet: resolved.generated,
3506
3635
  output_format: json ? "json" : "text"
3507
3636
  });
3637
+ setPersonProperties({ email });
3508
3638
  return outputData(json, {
3509
3639
  json: {
3510
3640
  email,
@@ -3600,6 +3730,7 @@ agentCommand.command("connect-email").description(
3600
3730
  generated_wallet: resolved.generated,
3601
3731
  output_format: json ? "json" : "text"
3602
3732
  });
3733
+ setPersonProperties({ email: result.email });
3603
3734
  outputData(json, {
3604
3735
  json: {
3605
3736
  email: result.email,
@@ -3711,6 +3842,9 @@ The old handle may be claimed by someone else, and links to it can break.`,
3711
3842
  updated_avatar: options.avatar !== void 0,
3712
3843
  output_format: json ? "json" : "text"
3713
3844
  });
3845
+ if (options.username !== void 0) {
3846
+ setPersonProperties({ name: profile.username });
3847
+ }
3714
3848
  const profileUrl = `https://zora.co/@${profile.username}`;
3715
3849
  outputData(json, {
3716
3850
  json: {
@@ -5947,7 +6081,8 @@ ${err instanceof Error ? err.stack || err.message : String(err)}
5947
6081
  slippage: slippagePct,
5948
6082
  output_format: json ? "json" : "static",
5949
6083
  success: false,
5950
- error_type: err instanceof Error ? err.constructor.name : "unknown"
6084
+ error_type: err instanceof Error ? err.constructor.name : "unknown",
6085
+ error: serializeError(err)
5951
6086
  });
5952
6087
  await shutdownAnalytics();
5953
6088
  return outputErrorAndExit(
@@ -5975,7 +6110,11 @@ ${err instanceof Error ? err.stack || err.message : String(err)}
5975
6110
  const now = /* @__PURE__ */ new Date();
5976
6111
  const updated = appendSpend(
5977
6112
  budget,
5978
- { at: now.toISOString(), usd: swapAmountUsd, skill: `buy ${coinSymbol}` },
6113
+ {
6114
+ at: now.toISOString(),
6115
+ usd: swapAmountUsd,
6116
+ skill: `buy ${coinSymbol}`
6117
+ },
5979
6118
  now
5980
6119
  );
5981
6120
  saveBudget(updated);
@@ -6012,11 +6151,10 @@ ${err instanceof Error ? err.stack || err.message : String(err)}
6012
6151
  });
6013
6152
  });
6014
6153
 
6015
- // src/commands/comment.ts
6154
+ // src/commands/claim.ts
6016
6155
  import confirm4 from "@inquirer/confirm";
6017
6156
  import {
6018
- getCoin as getCoin3,
6019
- getCoinComments,
6157
+ getProfile as getProfile2,
6020
6158
  prepareUserOperation,
6021
6159
  setApiKey as setApiKey3,
6022
6160
  submitUserOperation,
@@ -6024,7 +6162,207 @@ import {
6024
6162
  toUserOperationCalls
6025
6163
  } from "@zoralabs/coins-sdk";
6026
6164
  import { Command as Command5 } from "commander";
6027
- import { isAddress as isAddress4 } from "viem";
6165
+ import { formatUnits as formatUnits5, isAddress as isAddress4 } from "viem";
6166
+ var CREATOR_COIN_DECIMALS = 18;
6167
+ var CREATOR_COIN_VESTING_ABI = [
6168
+ {
6169
+ type: "function",
6170
+ name: "claimVesting",
6171
+ stateMutability: "nonpayable",
6172
+ inputs: [],
6173
+ outputs: [{ name: "", type: "uint256" }]
6174
+ },
6175
+ {
6176
+ type: "function",
6177
+ name: "getClaimableAmount",
6178
+ stateMutability: "view",
6179
+ inputs: [],
6180
+ outputs: [{ name: "", type: "uint256" }]
6181
+ }
6182
+ ];
6183
+ var claimCommand = new Command5("claim").description("Claim vested rewards from your creator coin").option(
6184
+ "--coin <address>",
6185
+ "Creator coin address to claim from (defaults to your own)"
6186
+ ).option("--yes", "Skip confirmation and execute directly").action(async function(opts) {
6187
+ const json = getJson(this);
6188
+ const apiKey = getApiKey();
6189
+ if (apiKey) {
6190
+ setApiKey3(apiKey);
6191
+ }
6192
+ const { privateKeyAccount, smartWalletAccount } = await resolveAccounts();
6193
+ const { publicClient, walletClient, bundlerClient } = createClients(
6194
+ privateKeyAccount,
6195
+ smartWalletAccount
6196
+ );
6197
+ if (!!smartWalletAccount && !bundlerClient) {
6198
+ return outputErrorAndExit(
6199
+ json,
6200
+ "Failed to obtain bundler client for your smart wallet. Please try again. If the problem persists, ensure your smart wallet is setup correctly."
6201
+ );
6202
+ }
6203
+ const walletAddress = smartWalletAccount?.address ?? privateKeyAccount.address;
6204
+ let coinAddress;
6205
+ if (opts.coin) {
6206
+ if (!isAddress4(opts.coin)) {
6207
+ return outputErrorAndExit(json, `Invalid --coin address: ${opts.coin}`);
6208
+ }
6209
+ coinAddress = opts.coin;
6210
+ } else {
6211
+ let resolved;
6212
+ try {
6213
+ const response = await getProfile2({ identifier: walletAddress });
6214
+ resolved = response?.data?.profile?.creatorCoin?.address;
6215
+ } catch (err) {
6216
+ return outputErrorAndExit(
6217
+ json,
6218
+ `Failed to look up your creator coin: ${err instanceof Error ? err.message : String(err)}`
6219
+ );
6220
+ }
6221
+ if (!resolved || !isAddress4(resolved)) {
6222
+ return outputErrorAndExit(
6223
+ json,
6224
+ "No creator coin found for your wallet.",
6225
+ "Create your creator coin on Zora first, or pass one with --coin <address>."
6226
+ );
6227
+ }
6228
+ coinAddress = resolved;
6229
+ }
6230
+ let claimable;
6231
+ try {
6232
+ claimable = await publicClient.readContract({
6233
+ abi: CREATOR_COIN_VESTING_ABI,
6234
+ address: coinAddress,
6235
+ functionName: "getClaimableAmount"
6236
+ });
6237
+ } catch (err) {
6238
+ return outputErrorAndExit(
6239
+ json,
6240
+ `Failed to read claimable rewards: ${err instanceof Error ? err.message : String(err)}`,
6241
+ "Make sure --coin points to a Zora creator coin."
6242
+ );
6243
+ }
6244
+ if (claimable === 0n) {
6245
+ track("cli_claim", {
6246
+ action: "nothing_to_claim",
6247
+ coin_address: coinAddress,
6248
+ output_format: json ? "json" : "static",
6249
+ success: true
6250
+ });
6251
+ if (json) {
6252
+ return outputJson({
6253
+ action: "claim",
6254
+ coin: coinAddress,
6255
+ claimable: "0",
6256
+ claimed: false
6257
+ });
6258
+ }
6259
+ console.log(`
6260
+ Nothing to claim yet for ${coinAddress}.`);
6261
+ console.log(" Vested rewards accrue over time \u2014 check back later.\n");
6262
+ return;
6263
+ }
6264
+ const claimableFormatted = formatAmountDisplay(
6265
+ claimable,
6266
+ CREATOR_COIN_DECIMALS
6267
+ );
6268
+ if (!opts.yes) {
6269
+ console.log("\n Claim creator coin rewards\n");
6270
+ console.log(` Coin ${coinAddress}`);
6271
+ console.log(` Claimable ${claimableFormatted}
6272
+ `);
6273
+ const ok = await confirm4({ message: "Confirm?", default: false });
6274
+ if (!ok) {
6275
+ console.error("Aborted.");
6276
+ return safeExit(SUCCESS);
6277
+ }
6278
+ }
6279
+ let txHash;
6280
+ try {
6281
+ if (smartWalletAccount) {
6282
+ const userOperation = await prepareUserOperation({
6283
+ bundlerClient,
6284
+ account: smartWalletAccount,
6285
+ calls: toUserOperationCalls([
6286
+ toGenericCall({
6287
+ abi: CREATOR_COIN_VESTING_ABI,
6288
+ address: coinAddress,
6289
+ functionName: "claimVesting"
6290
+ })
6291
+ ])
6292
+ });
6293
+ const receipt = await submitUserOperation({
6294
+ bundlerClient,
6295
+ account: smartWalletAccount,
6296
+ userOperation
6297
+ });
6298
+ if (!receipt.success) {
6299
+ throw new Error(
6300
+ `User operation reverted${receipt.reason ? `: ${receipt.reason}` : ""}`
6301
+ );
6302
+ }
6303
+ txHash = receipt.receipt.transactionHash;
6304
+ } else {
6305
+ txHash = await walletClient.writeContract({
6306
+ abi: CREATOR_COIN_VESTING_ABI,
6307
+ address: coinAddress,
6308
+ functionName: "claimVesting"
6309
+ });
6310
+ await publicClient.waitForTransactionReceipt({ hash: txHash });
6311
+ }
6312
+ } catch (err) {
6313
+ track("cli_claim", {
6314
+ coin_address: coinAddress,
6315
+ output_format: json ? "json" : "static",
6316
+ success: false,
6317
+ error_type: err instanceof Error ? err.constructor.name : "unknown"
6318
+ });
6319
+ await shutdownAnalytics();
6320
+ return outputErrorAndExit(
6321
+ json,
6322
+ `Claim failed: ${err instanceof Error ? err.message : String(err)}`,
6323
+ gasErrorSuggestion(err, smartWalletAccount ?? privateKeyAccount)
6324
+ );
6325
+ }
6326
+ if (json) {
6327
+ outputJson({
6328
+ action: "claim",
6329
+ coin: coinAddress,
6330
+ claimed: {
6331
+ amount: formatUnits5(claimable, CREATOR_COIN_DECIMALS),
6332
+ raw: claimable.toString()
6333
+ },
6334
+ tx: txHash
6335
+ });
6336
+ } else {
6337
+ console.log("\n Claimed creator coin rewards\n");
6338
+ console.log(` Coin ${coinAddress}`);
6339
+ console.log(` Claimed ${claimableFormatted}`);
6340
+ console.log(` Tx ${txHash}
6341
+ `);
6342
+ }
6343
+ track("cli_claim", {
6344
+ coin_address: coinAddress,
6345
+ amount: claimableFormatted,
6346
+ transactionHash: txHash,
6347
+ output_format: json ? "json" : "static",
6348
+ success: true,
6349
+ tx_hash: txHash
6350
+ });
6351
+ });
6352
+
6353
+ // src/commands/comment.ts
6354
+ import confirm5 from "@inquirer/confirm";
6355
+ import {
6356
+ getCoin as getCoin3,
6357
+ getCoinComments,
6358
+ prepareUserOperation as prepareUserOperation2,
6359
+ setApiKey as setApiKey4,
6360
+ submitUserOperation as submitUserOperation2,
6361
+ toGenericCall as toGenericCall2,
6362
+ toUserOperationCalls as toUserOperationCalls2
6363
+ } from "@zoralabs/coins-sdk";
6364
+ import { Command as Command6 } from "commander";
6365
+ import { isAddress as isAddress5 } from "viem";
6028
6366
 
6029
6367
  // src/lib/comments.ts
6030
6368
  var COMMENTS_ADDRESS = "0x7777777C2B3132e03a65721a41745C07170a5877";
@@ -6101,7 +6439,7 @@ var ZERO_ADDRESS = "0x0000000000000000000000000000000000000000";
6101
6439
  var resolveApiKey = () => {
6102
6440
  const apiKey = getApiKey();
6103
6441
  if (apiKey) {
6104
- setApiKey3(apiKey);
6442
+ setApiKey4(apiKey);
6105
6443
  }
6106
6444
  };
6107
6445
  async function resolveCoinTarget(json, typeOrId, identifier, command) {
@@ -6123,7 +6461,7 @@ async function resolveCoinTarget(json, typeOrId, identifier, command) {
6123
6461
  }
6124
6462
  resolveApiKey();
6125
6463
  if (parsed.kind === "address") {
6126
- if (!isAddress4(parsed.address)) {
6464
+ if (!isAddress5(parsed.address)) {
6127
6465
  return outputErrorAndExit(json, `Invalid address: ${parsed.address}`);
6128
6466
  }
6129
6467
  let name = parsed.address;
@@ -6178,12 +6516,12 @@ async function resolveCoinTarget(json, typeOrId, identifier, command) {
6178
6516
  }
6179
6517
  }
6180
6518
  async function commentViaSmartWallet(call, bundlerClient, account) {
6181
- const userOperation = await prepareUserOperation({
6519
+ const userOperation = await prepareUserOperation2({
6182
6520
  bundlerClient,
6183
6521
  account,
6184
- calls: toUserOperationCalls([toGenericCall(call)])
6522
+ calls: toUserOperationCalls2([toGenericCall2(call)])
6185
6523
  });
6186
- const receipt = await submitUserOperation({
6524
+ const receipt = await submitUserOperation2({
6187
6525
  bundlerClient,
6188
6526
  account,
6189
6527
  userOperation
@@ -6195,7 +6533,7 @@ async function commentViaSmartWallet(call, bundlerClient, account) {
6195
6533
  }
6196
6534
  return receipt.receipt.transactionHash;
6197
6535
  }
6198
- var commentCommand = new Command5("comment").description("Comment on a coin you hold").argument(
6536
+ var commentCommand = new Command6("comment").description("Comment on a coin you hold").argument(
6199
6537
  "[typeOrId]",
6200
6538
  "Type prefix (creator-coin, trend) or coin address/name"
6201
6539
  ).argument("[nameOrText]", "Coin name (with a type prefix) or comment text").argument("[text]", "Comment text when a type prefix is used").option("--referrer <address>", "Referrer address for spark rewards").option("--yes", "Skip confirmation and post directly").action(async function(typeOrId, nameOrText, text, opts) {
@@ -6210,7 +6548,7 @@ var commentCommand = new Command5("comment").description("Comment on a coin you
6210
6548
  'Usage: zora comment <coin> "your comment"'
6211
6549
  );
6212
6550
  }
6213
- if (opts.referrer && !isAddress4(opts.referrer)) {
6551
+ if (opts.referrer && !isAddress5(opts.referrer)) {
6214
6552
  return outputErrorAndExit(json, `Invalid --referrer: ${opts.referrer}`);
6215
6553
  }
6216
6554
  const coin = await resolveCoinTarget(
@@ -6296,7 +6634,7 @@ var commentCommand = new Command5("comment").description("Comment on a coin you
6296
6634
  console.log(` Cost ${isOwner ? "free (coin owner)" : "1 spark"}`);
6297
6635
  console.log(` Text ${commentText}
6298
6636
  `);
6299
- const ok = await confirm4({ message: "Post comment?", default: false });
6637
+ const ok = await confirm5({ message: "Post comment?", default: false });
6300
6638
  if (!ok) {
6301
6639
  console.error("Aborted.");
6302
6640
  return safeExit(SUCCESS);
@@ -6311,7 +6649,8 @@ var commentCommand = new Command5("comment").description("Comment on a coin you
6311
6649
  coin_address: coin.address,
6312
6650
  output_format: json ? "json" : "static",
6313
6651
  success: false,
6314
- error_type: err instanceof Error ? err.constructor.name : "unknown"
6652
+ error_type: err instanceof Error ? err.constructor.name : "unknown",
6653
+ error: serializeError(err)
6315
6654
  });
6316
6655
  await shutdownAnalytics();
6317
6656
  const rawMessage = err instanceof Error ? err.message : String(err);
@@ -6453,11 +6792,11 @@ No comments yet on ${coin.name}.
6453
6792
  });
6454
6793
 
6455
6794
  // src/commands/create.ts
6456
- import { Command as Command6 } from "commander";
6457
- import confirm5 from "@inquirer/confirm";
6795
+ import { Command as Command7 } from "commander";
6796
+ import confirm6 from "@inquirer/confirm";
6458
6797
  import input2 from "@inquirer/input";
6459
6798
  import select2 from "@inquirer/select";
6460
- import { existsSync as existsSync2, readFileSync as readFileSync3 } from "fs";
6799
+ import { existsSync as existsSync3, readFileSync as readFileSync3 } from "fs";
6461
6800
  import { basename as basename2, extname as extname2 } from "path";
6462
6801
  import { base as base7 } from "viem/chains";
6463
6802
  import {
@@ -6466,7 +6805,7 @@ import {
6466
6805
  createMetadataBuilder,
6467
6806
  createZoraUploaderForCreator,
6468
6807
  CreateConstants,
6469
- setApiKey as setApiKey4
6808
+ setApiKey as setApiKey5
6470
6809
  } from "@zoralabs/coins-sdk";
6471
6810
  var IMAGE_MIME_BY_EXT = {
6472
6811
  ".png": "image/png",
@@ -6522,7 +6861,7 @@ async function resolveField(value, {
6522
6861
  }
6523
6862
  return input2({ message, required });
6524
6863
  }
6525
- var createCommand = new Command6("create").description("Create a coin (post)").option("--name <name>", "Coin name").option("--symbol <symbol>", "Coin symbol (ticker)").option("--description <description>", "Coin description").option("--image <path>", "Path to a local image file to upload").option(
6864
+ var createCommand = new Command7("create").description("Create a coin (post)").option("--name <name>", "Coin name").option("--symbol <symbol>", "Coin symbol (ticker)").option("--description <description>", "Coin description").option("--image <path>", "Path to a local image file to upload").option(
6526
6865
  "--currency <currency>",
6527
6866
  "Backing currency: ZORA, ETH, CREATOR_COIN, CREATOR_COIN_OR_ZORA (prompts if omitted)"
6528
6867
  ).option("--yes", "Skip confirmation and create directly").action(async function(opts) {
@@ -6535,7 +6874,7 @@ var createCommand = new Command6("create").description("Create a coin (post)").o
6535
6874
  "Run 'zora auth configure' to set your API key."
6536
6875
  );
6537
6876
  }
6538
- setApiKey4(apiKey);
6877
+ setApiKey5(apiKey);
6539
6878
  const name = await resolveField(opts.name, {
6540
6879
  json,
6541
6880
  message: "Coin name:",
@@ -6562,7 +6901,7 @@ var createCommand = new Command6("create").description("Create a coin (post)").o
6562
6901
  flag: "--image"
6563
6902
  });
6564
6903
  const currency = await resolveCurrency(opts.currency, json);
6565
- if (!existsSync2(imagePath)) {
6904
+ if (!existsSync3(imagePath)) {
6566
6905
  return outputErrorAndExit(
6567
6906
  json,
6568
6907
  `Image file not found: ${imagePath}`,
@@ -6606,7 +6945,7 @@ var createCommand = new Command6("create").description("Create a coin (post)").o
6606
6945
  ` Creator ${creator} (${usingSmartWallet ? "smart wallet" : "EOA"})`
6607
6946
  );
6608
6947
  console.log("");
6609
- const ok = await confirm5({ message: "Confirm?", default: false });
6948
+ const ok = await confirm6({ message: "Confirm?", default: false });
6610
6949
  if (!ok) {
6611
6950
  console.error("Aborted.");
6612
6951
  return safeExit(SUCCESS);
@@ -6636,7 +6975,9 @@ var createCommand = new Command6("create").description("Create a coin (post)").o
6636
6975
  output_format: json ? "json" : "static",
6637
6976
  success: false,
6638
6977
  stage: "upload",
6639
- error_type: err instanceof Error ? err.constructor.name : "unknown"
6978
+ error_type: err instanceof Error ? err.constructor.name : "unknown",
6979
+ error_message: err instanceof Error ? err.message : String(err),
6980
+ error: serializeError(err)
6640
6981
  });
6641
6982
  await shutdownAnalytics();
6642
6983
  return outputErrorAndExit(
@@ -6671,7 +7012,9 @@ var createCommand = new Command6("create").description("Create a coin (post)").o
6671
7012
  output_format: json ? "json" : "static",
6672
7013
  success: false,
6673
7014
  stage: "deploy",
6674
- error_type: err instanceof Error ? err.constructor.name : "unknown"
7015
+ error_type: err instanceof Error ? err.constructor.name : "unknown",
7016
+ error_message: err instanceof Error ? err.message : String(err),
7017
+ error: serializeError(err)
6675
7018
  });
6676
7019
  await shutdownAnalytics();
6677
7020
  return outputErrorAndExit(
@@ -6715,8 +7058,8 @@ var createCommand = new Command6("create").description("Create a coin (post)").o
6715
7058
  });
6716
7059
 
6717
7060
  // src/commands/dm.ts
6718
- import { Command as Command7 } from "commander";
6719
- import { isAddress as isAddress6 } from "viem";
7061
+ import { Command as Command8 } from "commander";
7062
+ import { isAddress as isAddress7 } from "viem";
6720
7063
 
6721
7064
  // src/messaging/identity.ts
6722
7065
  import { hashMessage, toBytes } from "viem";
@@ -6858,24 +7201,24 @@ var createCliSmartWalletProvider = async (opts) => {
6858
7201
  };
6859
7202
 
6860
7203
  // src/messaging/uapi.ts
6861
- import { getAddress as getAddress4, isAddress as isAddress5 } from "viem";
7204
+ import { getAddress as getAddress4, isAddress as isAddress6 } from "viem";
6862
7205
 
6863
7206
  // src/lib/profile-cache.ts
6864
- import { existsSync as existsSync3, mkdirSync as mkdirSync2, readFileSync as readFileSync4, writeFileSync as writeFileSync2 } from "fs";
7207
+ import { existsSync as existsSync4, mkdirSync as mkdirSync2, readFileSync as readFileSync4, writeFileSync as writeFileSync2 } from "fs";
6865
7208
  import { homedir as homedir2, platform as platform3 } from "os";
6866
- import { dirname, join as join2 } from "path";
7209
+ import { dirname, join as join3 } from "path";
6867
7210
  var MAX_ENTRIES = 5e3;
6868
7211
  function cacheFile() {
6869
- const dir = platform3() === "win32" ? join2(
6870
- process.env.APPDATA ?? join2(homedir2(), "AppData", "Roaming"),
7212
+ const dir = platform3() === "win32" ? join3(
7213
+ process.env.APPDATA ?? join3(homedir2(), "AppData", "Roaming"),
6871
7214
  "zora"
6872
- ) : join2(homedir2(), ".config", "zora");
6873
- return join2(dir, "profiles.json");
7215
+ ) : join3(homedir2(), ".config", "zora");
7216
+ return join3(dir, "profiles.json");
6874
7217
  }
6875
7218
  function readProfileCache() {
6876
7219
  try {
6877
7220
  const file = cacheFile();
6878
- if (!existsSync3(file)) return {};
7221
+ if (!existsSync4(file)) return {};
6879
7222
  const parsed = JSON.parse(readFileSync4(file, "utf-8"));
6880
7223
  return parsed?.profiles ?? {};
6881
7224
  } catch {
@@ -6946,7 +7289,7 @@ var resolveHandleToAddress = async (handle) => {
6946
7289
  const wallet = profile.linkedWallets?.edges?.find(
6947
7290
  (e) => e.node?.walletType === "SMART_WALLET"
6948
7291
  )?.node?.walletAddress;
6949
- if (!wallet || !isAddress5(wallet)) return { ok: false, reason: "no-inbox" };
7292
+ if (!wallet || !isAddress6(wallet)) return { ok: false, reason: "no-inbox" };
6950
7293
  return { ok: true, address: getAddress4(wallet) };
6951
7294
  };
6952
7295
  var PROFILE_TTL_MS = 24 * 60 * 60 * 1e3;
@@ -7173,7 +7516,7 @@ var peerLabel = async (peer) => {
7173
7516
  }
7174
7517
  };
7175
7518
  var resolvePeer = async (json, value) => {
7176
- if (isAddress6(value)) return value;
7519
+ if (isAddress7(value)) return value;
7177
7520
  const result = await resolveHandleToAddress(value);
7178
7521
  if (result.ok) return result.address;
7179
7522
  const messages = {
@@ -7263,7 +7606,7 @@ var renderSummaries = (summaries, empty) => {
7263
7606
  ${preview}`);
7264
7607
  }
7265
7608
  };
7266
- var dmCommand = new Command7("dm").description("Read and respond to your Zora DMs").action(function() {
7609
+ var dmCommand = new Command8("dm").description("Read and respond to your Zora DMs").action(function() {
7267
7610
  this.outputHelp();
7268
7611
  });
7269
7612
  dmCommand.command("list").description("List active conversations").action(async function() {
@@ -7400,7 +7743,8 @@ dmCommand.command("send").description(
7400
7743
  track("cli_dm_send", {
7401
7744
  output_format: json ? "json" : "text",
7402
7745
  success: false,
7403
- denied: true
7746
+ denied: true,
7747
+ error: serializeError(err)
7404
7748
  });
7405
7749
  return outputErrorAndExit(
7406
7750
  json,
@@ -7493,9 +7837,9 @@ consentSubcommand("approve", "allowed", "Approve an inbound request");
7493
7837
  consentSubcommand("deny", "denied", "Deny an inbound request");
7494
7838
 
7495
7839
  // src/commands/explore.tsx
7496
- import { Command as Command8 } from "commander";
7840
+ import { Command as Command9 } from "commander";
7497
7841
  import {
7498
- setApiKey as setApiKey5,
7842
+ setApiKey as setApiKey6,
7499
7843
  getCoinsTopVolume24h,
7500
7844
  getCoinsMostValuable,
7501
7845
  getCoinsNew,
@@ -7694,7 +8038,7 @@ var STATIC_COLUMNS = [
7694
8038
  }
7695
8039
  ];
7696
8040
  var SORT_OPTIONS2 = Object.keys(SORT_LABELS).join(", ");
7697
- var exploreCommand = new Command8("explore").description("Browse top, new, and highest volume coins").option("--sort <sort>", `Sort by: ${SORT_OPTIONS2}`, "mcap").option(
8041
+ var exploreCommand = new Command9("explore").description("Browse top, new, and highest volume coins").option("--sort <sort>", `Sort by: ${SORT_OPTIONS2}`, "mcap").option(
7698
8042
  "--type <type>",
7699
8043
  "Filter by type: all, trend, creator-coin, post (availability varies by sort)",
7700
8044
  "creator-coin"
@@ -7733,7 +8077,7 @@ var exploreCommand = new Command8("explore").description("Browse top, new, and h
7733
8077
  }
7734
8078
  const apiKey = getApiKey();
7735
8079
  if (apiKey) {
7736
- setApiKey5(apiKey);
8080
+ setApiKey6(apiKey);
7737
8081
  }
7738
8082
  const queryFn = QUERY_MAP[sort][type];
7739
8083
  if (json) {
@@ -7828,9 +8172,9 @@ var exploreCommand = new Command8("explore").description("Browse top, new, and h
7828
8172
  });
7829
8173
 
7830
8174
  // src/commands/follow.ts
7831
- import { getProfile as getProfile2, setApiKey as setApiKey6 } from "@zoralabs/coins-sdk";
7832
- import { Command as Command9 } from "commander";
7833
- import { erc20Abi as erc20Abi3, isAddress as isAddress7 } from "viem";
8175
+ import { getProfile as getProfile3, setApiKey as setApiKey7 } from "@zoralabs/coins-sdk";
8176
+ import { Command as Command10 } from "commander";
8177
+ import { erc20Abi as erc20Abi3, isAddress as isAddress8 } from "viem";
7834
8178
 
7835
8179
  // src/lib/follow.ts
7836
8180
  var FOLLOW_MUTATION = "mutation CliFollow($followeeId: String!) { follow(followeeId: $followeeId) { handle profileId vcFollowingStatus } }";
@@ -7888,10 +8232,10 @@ function relationshipNote(status) {
7888
8232
  }
7889
8233
  async function requireCreatorCoinHolding(json, identifier) {
7890
8234
  const apiKey = getApiKey();
7891
- if (apiKey) setApiKey6(apiKey);
8235
+ if (apiKey) setApiKey7(apiKey);
7892
8236
  let profile;
7893
8237
  try {
7894
- const response = await getProfile2({ identifier });
8238
+ const response = await getProfile3({ identifier });
7895
8239
  profile = response?.data?.profile;
7896
8240
  } catch (err) {
7897
8241
  return outputErrorAndExit(
@@ -7908,7 +8252,7 @@ async function requireCreatorCoinHolding(json, identifier) {
7908
8252
  }
7909
8253
  const label = profile.handle && !isPlaceholderName(profile.handle) ? `@${profile.handle}` : identifier;
7910
8254
  const coinAddress = profile.creatorCoin?.address;
7911
- if (!coinAddress || !isAddress7(coinAddress)) {
8255
+ if (!coinAddress || !isAddress8(coinAddress)) {
7912
8256
  return outputErrorAndExit(
7913
8257
  json,
7914
8258
  `${label} doesn't have a creator coin yet, so there's nothing to buy.`,
@@ -7978,7 +8322,8 @@ async function runFollow(command, action, identifierArg) {
7978
8322
  action,
7979
8323
  output_format: json ? "json" : "static",
7980
8324
  success: false,
7981
- error_type: err instanceof Error ? err.constructor.name : "unknown"
8325
+ error_type: err instanceof Error ? err.constructor.name : "unknown",
8326
+ error: serializeError(err)
7982
8327
  });
7983
8328
  await shutdownAnalytics();
7984
8329
  const message = formatError(err);
@@ -8029,17 +8374,17 @@ async function runFollow(command, action, identifierArg) {
8029
8374
  }
8030
8375
  });
8031
8376
  }
8032
- var followCommand = new Command9("follow").description("Follow a Zora user whose creator coin you hold").argument("[identifier]", "Username (@handle), wallet address, or account id").action(async function(identifier) {
8377
+ var followCommand = new Command10("follow").description("Follow a Zora user whose creator coin you hold").argument("[identifier]", "Username (@handle), wallet address, or account id").action(async function(identifier) {
8033
8378
  await runFollow(this, "follow", identifier);
8034
8379
  });
8035
- var unfollowCommand = new Command9("unfollow").description("Unfollow a Zora user by username or address").argument("[identifier]", "Username (@handle), wallet address, or account id").action(async function(identifier) {
8380
+ var unfollowCommand = new Command10("unfollow").description("Unfollow a Zora user by username or address").argument("[identifier]", "Username (@handle), wallet address, or account id").action(async function(identifier) {
8036
8381
  await runFollow(this, "unfollow", identifier);
8037
8382
  });
8038
8383
 
8039
8384
  // src/commands/get.tsx
8040
- import { Command as Command10 } from "commander";
8385
+ import { Command as Command11 } from "commander";
8041
8386
  import { Box as Box12, Text as Text12 } from "ink";
8042
- import { setApiKey as setApiKey7, getCoinHolders, getCoinSwaps } from "@zoralabs/coins-sdk";
8387
+ import { setApiKey as setApiKey8, getCoinHolders, getCoinSwaps } from "@zoralabs/coins-sdk";
8043
8388
 
8044
8389
  // src/components/CoinDetail.tsx
8045
8390
  import { Box as Box7, Text as Text7 } from "ink";
@@ -8534,7 +8879,7 @@ function formatCoinJson(coin) {
8534
8879
  var resolveApiKey2 = () => {
8535
8880
  const apiKey = getApiKey();
8536
8881
  if (apiKey) {
8537
- setApiKey7(apiKey);
8882
+ setApiKey8(apiKey);
8538
8883
  }
8539
8884
  };
8540
8885
  var CoinResolutionError = class extends Error {
@@ -8663,7 +9008,7 @@ async function fetchRecentTrades(address) {
8663
9008
  return [];
8664
9009
  }
8665
9010
  }
8666
- var getCommand = new Command10("get").description("Look up a coin by address or name").argument("[typeOrId]", "Type prefix (creator-coin, trend) or identifier").argument(
9011
+ var getCommand = new Command11("get").description("Look up a coin by address or name").argument("[typeOrId]", "Type prefix (creator-coin, trend) or identifier").argument(
8667
9012
  "[identifier]",
8668
9013
  "Coin address (0x...) or name (when type prefix is given)"
8669
9014
  ).option("--live", "Interactive live-updating display (default)").option("--static", "Static snapshot").option(
@@ -9189,19 +9534,19 @@ getCommand.command("holders").description("Show top holders of a coin").argument
9189
9534
  });
9190
9535
 
9191
9536
  // src/commands/sell.ts
9192
- import confirm6 from "@inquirer/confirm";
9537
+ import confirm7 from "@inquirer/confirm";
9193
9538
  import {
9194
9539
  createQuote as createQuote2,
9195
9540
  getCoin as getCoin4,
9196
- setApiKey as setApiKey8,
9541
+ setApiKey as setApiKey9,
9197
9542
  tradeCoin as tradeCoin2,
9198
9543
  tradeCoinSmartWallet as tradeCoinSmartWallet2
9199
9544
  } from "@zoralabs/coins-sdk";
9200
- import { Command as Command11 } from "commander";
9545
+ import { Command as Command12 } from "commander";
9201
9546
  import {
9202
9547
  erc20Abi as erc20Abi4,
9203
- formatUnits as formatUnits5,
9204
- isAddress as isAddress8,
9548
+ formatUnits as formatUnits6,
9549
+ isAddress as isAddress9,
9205
9550
  parseUnits as parseUnits2
9206
9551
  } from "viem";
9207
9552
  function printSellQuote(output, info) {
@@ -9211,12 +9556,12 @@ function printSellQuote(output, info) {
9211
9556
  coin: info.coinSymbol,
9212
9557
  address: info.address,
9213
9558
  sell: {
9214
- amount: formatUnits5(info.amountIn, info.coinDecimals),
9559
+ amount: formatUnits6(info.amountIn, info.coinDecimals),
9215
9560
  raw: info.amountIn.toString(),
9216
9561
  symbol: info.coinSymbol
9217
9562
  },
9218
9563
  estimated: {
9219
- amount: formatUnits5(BigInt(info.quoteAmountOut), info.outputDecimals),
9564
+ amount: formatUnits6(BigInt(info.quoteAmountOut), info.outputDecimals),
9220
9565
  raw: info.quoteAmountOut,
9221
9566
  symbol: info.outputSymbol
9222
9567
  },
@@ -9236,7 +9581,7 @@ function printSellQuote(output, info) {
9236
9581
  `);
9237
9582
  }
9238
9583
  function printSellResult(output, info) {
9239
- const receivedAmount = formatUnits5(
9584
+ const receivedAmount = formatUnits6(
9240
9585
  info.receivedAmountOut,
9241
9586
  info.outputDecimals
9242
9587
  );
@@ -9250,7 +9595,7 @@ function printSellResult(output, info) {
9250
9595
  coin: info.coinSymbol,
9251
9596
  address: info.address,
9252
9597
  sold: {
9253
- amount: formatUnits5(info.amountIn, info.coinDecimals),
9598
+ amount: formatUnits6(info.amountIn, info.coinDecimals),
9254
9599
  raw: info.amountIn.toString(),
9255
9600
  symbol: info.coinSymbol
9256
9601
  },
@@ -9278,7 +9623,7 @@ function printSellResult(output, info) {
9278
9623
  console.log(` Tx ${info.txHash}
9279
9624
  `);
9280
9625
  }
9281
- var sellCommand = new Command11("sell").description("Sell a coin").argument(
9626
+ var sellCommand = new Command12("sell").description("Sell a coin").argument(
9282
9627
  "[typeOrId]",
9283
9628
  "Type prefix (creator-coin, trend) or coin address/name"
9284
9629
  ).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) {
@@ -9295,12 +9640,12 @@ var sellCommand = new Command11("sell").description("Sell a coin").argument(
9295
9640
  }
9296
9641
  const apiKey = getApiKey();
9297
9642
  if (apiKey) {
9298
- setApiKey8(apiKey);
9643
+ setApiKey9(apiKey);
9299
9644
  }
9300
9645
  let coinAddress;
9301
9646
  let earlyAccounts;
9302
9647
  if (parsed.kind === "address") {
9303
- if (!isAddress8(parsed.address)) {
9648
+ if (!isAddress9(parsed.address)) {
9304
9649
  return outputErrorAndExit(json, `Invalid address: ${parsed.address}`);
9305
9650
  }
9306
9651
  coinAddress = parsed.address;
@@ -9439,7 +9784,7 @@ var sellCommand = new Command11("sell").description("Sell a coin").argument(
9439
9784
  }
9440
9785
  if (debug) {
9441
9786
  console.error(
9442
- `[debug] $${usdVal} USD = ${formatUnits5(amountIn, coinDecimals)} ${coinSymbol} (coin price: $${coinPriceUsd2})`
9787
+ `[debug] $${usdVal} USD = ${formatUnits6(amountIn, coinDecimals)} ${coinSymbol} (coin price: $${coinPriceUsd2})`
9443
9788
  );
9444
9789
  }
9445
9790
  } else if (amountMode === "amount") {
@@ -9501,7 +9846,7 @@ var sellCommand = new Command11("sell").description("Sell a coin").argument(
9501
9846
  swapAmountUsd = parsePercentageLikeValue(opts.usd);
9502
9847
  } else if (coinPriceUsd !== null && coinPriceUsd > 0) {
9503
9848
  swapAmountUsd = Number(
9504
- (Number(formatUnits5(amountIn, coinDecimals)) * coinPriceUsd).toFixed(2)
9849
+ (Number(formatUnits6(amountIn, coinDecimals)) * coinPriceUsd).toFixed(2)
9505
9850
  );
9506
9851
  }
9507
9852
  const tradeParameters = {
@@ -9563,7 +9908,7 @@ ${err instanceof Error ? err.stack || err.message : String(err)}
9563
9908
  let receivedUsd;
9564
9909
  if (outputPriceUsd != null) {
9565
9910
  const outAmount = Number(
9566
- formatUnits5(BigInt(quoteAmountOut), outputToken.decimals)
9911
+ formatUnits6(BigInt(quoteAmountOut), outputToken.decimals)
9567
9912
  );
9568
9913
  receivedUsd = `~${formatUsd(outAmount * outputPriceUsd)}`;
9569
9914
  }
@@ -9614,7 +9959,7 @@ ${err instanceof Error ? err.stack || err.message : String(err)}
9614
9959
  slippagePct,
9615
9960
  receivedUsd
9616
9961
  });
9617
- const ok = await confirm6({
9962
+ const ok = await confirm7({
9618
9963
  message: "Confirm?",
9619
9964
  default: false
9620
9965
  });
@@ -9655,7 +10000,8 @@ ${err instanceof Error ? err.stack || err.message : String(err)}
9655
10000
  slippage: slippagePct,
9656
10001
  output_format: output,
9657
10002
  success: false,
9658
- error_type: err instanceof Error ? err.constructor.name : "unknown"
10003
+ error_type: err instanceof Error ? err.constructor.name : "unknown",
10004
+ error: serializeError(err)
9659
10005
  });
9660
10006
  await shutdownAnalytics();
9661
10007
  return outputErrorAndExit(
@@ -9683,7 +10029,7 @@ ${err instanceof Error ? err.stack || err.message : String(err)}
9683
10029
  }
9684
10030
  if (outputPriceUsd != null) {
9685
10031
  const actualAmount = Number(
9686
- formatUnits5(receivedAmountOut, outputToken.decimals)
10032
+ formatUnits6(receivedAmountOut, outputToken.decimals)
9687
10033
  );
9688
10034
  receivedUsd = `~${formatUsd(actualAmount * outputPriceUsd)}`;
9689
10035
  }
@@ -9722,13 +10068,13 @@ ${err instanceof Error ? err.stack || err.message : String(err)}
9722
10068
  });
9723
10069
 
9724
10070
  // src/commands/profile.tsx
9725
- import { Command as Command12 } from "commander";
10071
+ import { Command as Command13 } from "commander";
9726
10072
  import { Box as Box17, Text as Text17 } from "ink";
9727
10073
  import {
9728
10074
  getProfileCoins,
9729
10075
  getProfileBalances as getProfileBalances2,
9730
10076
  getWalletTradeActivity,
9731
- setApiKey as setApiKey9
10077
+ setApiKey as setApiKey10
9732
10078
  } from "@zoralabs/coins-sdk";
9733
10079
  import { privateKeyToAccount as privateKeyToAccount8 } from "viem/accounts";
9734
10080
 
@@ -10110,7 +10456,7 @@ import { jsx as jsx18, jsxs as jsxs17 } from "react/jsx-runtime";
10110
10456
  var resolveApiKey3 = () => {
10111
10457
  const apiKey = getApiKey();
10112
10458
  if (apiKey) {
10113
- setApiKey9(apiKey);
10459
+ setApiKey10(apiKey);
10114
10460
  }
10115
10461
  };
10116
10462
  var formatTradeJson2 = (trade, rank) => ({
@@ -10233,7 +10579,7 @@ var resolveIdentifier = (identifierArg, json) => {
10233
10579
  );
10234
10580
  }
10235
10581
  };
10236
- var profileCommand = new Command12("profile").description("View profile activity (posts, holdings, and trades)").argument(
10582
+ var profileCommand = new Command13("profile").description("View profile activity (posts, holdings, and trades)").argument(
10237
10583
  "[identifier]",
10238
10584
  "Wallet address or profile handle (defaults to your wallet)"
10239
10585
  ).option("--live", "Interactive live-updating display (default)").option("--static", "Static snapshot").option(
@@ -10775,20 +11121,20 @@ profileCommand.command("trades").description("View profile trade activity (buys
10775
11121
  });
10776
11122
 
10777
11123
  // src/commands/send.ts
10778
- import confirm7 from "@inquirer/confirm";
11124
+ import confirm8 from "@inquirer/confirm";
10779
11125
  import {
10780
- getProfile as getProfile3,
10781
- prepareUserOperation as prepareUserOperation2,
10782
- setApiKey as setApiKey10,
10783
- submitUserOperation as submitUserOperation2,
10784
- toGenericCall as toGenericCall2,
10785
- toUserOperationCalls as toUserOperationCalls2
11126
+ getProfile as getProfile4,
11127
+ prepareUserOperation as prepareUserOperation3,
11128
+ setApiKey as setApiKey11,
11129
+ submitUserOperation as submitUserOperation3,
11130
+ toGenericCall as toGenericCall3,
11131
+ toUserOperationCalls as toUserOperationCalls3
10786
11132
  } from "@zoralabs/coins-sdk";
10787
- import { Command as Command13 } from "commander";
11133
+ import { Command as Command14 } from "commander";
10788
11134
  import {
10789
11135
  erc20Abi as erc20Abi5,
10790
- formatUnits as formatUnits6,
10791
- isAddress as isAddress9,
11136
+ formatUnits as formatUnits7,
11137
+ isAddress as isAddress10,
10792
11138
  parseUnits as parseUnits3
10793
11139
  } from "viem";
10794
11140
  var SEND_AMOUNT_CHECKS = {
@@ -10801,12 +11147,12 @@ function isPlaceholderName2(name) {
10801
11147
  return name.startsWith("0x") || name.includes("\u2026") || name.includes("...");
10802
11148
  }
10803
11149
  async function resolveRecipient(identifier, json = false) {
10804
- const isIdentifierAddress = isAddress9(identifier);
11150
+ const isIdentifierAddress = isAddress10(identifier);
10805
11151
  try {
10806
- const response = await getProfile3({ identifier });
11152
+ const response = await getProfile4({ identifier });
10807
11153
  const profile = response?.data?.profile;
10808
11154
  const address = isIdentifierAddress ? identifier : profile?.publicWallet?.walletAddress;
10809
- if (!address || !isAddress9(address)) {
11155
+ if (!address || !isAddress10(address)) {
10810
11156
  return outputErrorAndExit(
10811
11157
  json,
10812
11158
  !address ? `No Zora profile or wallet found for "${identifier}".` : "Provide a valid 0x address or an existing Zora profile name."
@@ -10857,7 +11203,7 @@ function printSendResult(json, info) {
10857
11203
  coin: info.symbol,
10858
11204
  address: info.address,
10859
11205
  sent: {
10860
- amount: formatUnits6(info.amount, info.decimals),
11206
+ amount: formatUnits7(info.amount, info.decimals),
10861
11207
  raw: info.amount.toString(),
10862
11208
  symbol: info.symbol,
10863
11209
  amountUsd: info.amountUsd
@@ -10879,12 +11225,12 @@ function printSendResult(json, info) {
10879
11225
  `);
10880
11226
  }
10881
11227
  async function sendCallViaSmartWallet(call, bundlerClient, account) {
10882
- const userOperation = await prepareUserOperation2({
11228
+ const userOperation = await prepareUserOperation3({
10883
11229
  bundlerClient,
10884
11230
  account,
10885
- calls: toUserOperationCalls2([toGenericCall2(call)])
11231
+ calls: toUserOperationCalls3([toGenericCall3(call)])
10886
11232
  });
10887
- const receipt = await submitUserOperation2({
11233
+ const receipt = await submitUserOperation3({
10888
11234
  bundlerClient,
10889
11235
  account,
10890
11236
  userOperation
@@ -10896,7 +11242,7 @@ async function sendCallViaSmartWallet(call, bundlerClient, account) {
10896
11242
  }
10897
11243
  return receipt.receipt.transactionHash;
10898
11244
  }
10899
- var sendCommand = new Command13("send").description("Send coins or ETH to an address or Zora profile").argument(
11245
+ var sendCommand = new Command14("send").description("Send coins or ETH to an address or Zora profile").argument(
10900
11246
  "[typeOrId]",
10901
11247
  "Token (eth, usdc, zora), type prefix (creator-coin, trend), or coin address/name"
10902
11248
  ).argument("[identifier]", "Coin name (when type prefix is given)").option("--to <recipient>", "Recipient: address (0x...) or Zora profile name").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) {
@@ -10910,7 +11256,7 @@ var sendCommand = new Command13("send").description("Send coins or ETH to an add
10910
11256
  }
10911
11257
  const apiKey = getApiKey();
10912
11258
  if (apiKey) {
10913
- setApiKey10(apiKey);
11259
+ setApiKey11(apiKey);
10914
11260
  }
10915
11261
  const resolvedRecipient = await resolveRecipient(opts.to, json);
10916
11262
  if (resolvedRecipient.platformBlocked) {
@@ -11018,7 +11364,7 @@ var sendCommand = new Command13("send").description("Send coins or ETH to an add
11018
11364
  const ethPriceUsd = await fetchTokenPriceUsd(WETH_ADDRESS);
11019
11365
  if (ethPriceUsd != null) {
11020
11366
  amountUsd = Number(
11021
- (Number(formatUnits6(amount, 18)) * ethPriceUsd).toFixed(2)
11367
+ (Number(formatUnits7(amount, 18)) * ethPriceUsd).toFixed(2)
11022
11368
  );
11023
11369
  }
11024
11370
  if (!opts.yes) {
@@ -11029,7 +11375,7 @@ var sendCommand = new Command13("send").description("Send coins or ETH to an add
11029
11375
  amountUsd,
11030
11376
  recipient: resolvedRecipient
11031
11377
  });
11032
- const ok = await confirm7({ message: "Confirm?", default: false });
11378
+ const ok = await confirm8({ message: "Confirm?", default: false });
11033
11379
  if (!ok) {
11034
11380
  console.error("Aborted.");
11035
11381
  return safeExit(SUCCESS);
@@ -11070,7 +11416,8 @@ var sendCommand = new Command13("send").description("Send coins or ETH to an add
11070
11416
  asset: "eth",
11071
11417
  output_format: json ? "json" : "static",
11072
11418
  success: false,
11073
- error_type: err instanceof Error ? err.constructor.name : "unknown"
11419
+ error_type: err instanceof Error ? err.constructor.name : "unknown",
11420
+ error: serializeError(err)
11074
11421
  });
11075
11422
  await shutdownAnalytics();
11076
11423
  return outputErrorAndExit(
@@ -11275,7 +11622,7 @@ var sendCommand = new Command13("send").description("Send coins or ETH to an add
11275
11622
  const priceUsd = knownToken?.fixedPriceUsd ?? await fetchTokenPriceUsd(priceAddress);
11276
11623
  if (priceUsd != null) {
11277
11624
  amountUsd = Number(
11278
- (Number(formatUnits6(amount, decimals)) * priceUsd).toFixed(2)
11625
+ (Number(formatUnits7(amount, decimals)) * priceUsd).toFixed(2)
11279
11626
  );
11280
11627
  }
11281
11628
  if (!opts.yes) {
@@ -11286,7 +11633,7 @@ var sendCommand = new Command13("send").description("Send coins or ETH to an add
11286
11633
  amountUsd,
11287
11634
  recipient: resolvedRecipient
11288
11635
  });
11289
- const ok = await confirm7({ message: "Confirm?", default: false });
11636
+ const ok = await confirm8({ message: "Confirm?", default: false });
11290
11637
  if (!ok) {
11291
11638
  console.error("Aborted.");
11292
11639
  return safeExit(SUCCESS);
@@ -11338,7 +11685,8 @@ var sendCommand = new Command13("send").description("Send coins or ETH to an add
11338
11685
  coin_symbol: symbol,
11339
11686
  output_format: json ? "json" : "static",
11340
11687
  success: false,
11341
- error_type: err instanceof Error ? err.constructor.name : "unknown"
11688
+ error_type: err instanceof Error ? err.constructor.name : "unknown",
11689
+ error: serializeError(err)
11342
11690
  });
11343
11691
  await shutdownAnalytics();
11344
11692
  return outputErrorAndExit(
@@ -11390,7 +11738,7 @@ var sendCommand = new Command13("send").description("Send coins or ETH to an add
11390
11738
  });
11391
11739
 
11392
11740
  // src/commands/setup.tsx
11393
- import { Command as Command14 } from "commander";
11741
+ import { Command as Command15 } from "commander";
11394
11742
  import { Text as Text18, Box as Box18 } from "ink";
11395
11743
 
11396
11744
  // src/lib/strings.ts
@@ -11558,7 +11906,7 @@ ${BOLD}${DIM}[${step}/${total}]${RESET} ${BOLD}${title}${RESET}`
11558
11906
  console.log(`${DIM}${"\u2500".repeat(Math.max(cols, 20))}${RESET}
11559
11907
  `);
11560
11908
  }
11561
- var setupCommand = new Command14("setup").description("Guided first-time setup").option("--create", "Create a new wallet without prompting").option("--force", "Overwrite existing wallet without prompting").option("--yes", "Skip interactive prompt and execute directly").action(async function(options) {
11909
+ var setupCommand = new Command15("setup").description("Guided first-time setup").option("--create", "Create a new wallet without prompting").option("--force", "Overwrite existing wallet without prompting").option("--yes", "Skip interactive prompt and execute directly").action(async function(options) {
11562
11910
  const json = getJson(this);
11563
11911
  const nonInteractive = getYes(this);
11564
11912
  if (!json) stepLine(1, 3, "Set up wallet");
@@ -11695,9 +12043,9 @@ async function promptAndSaveApiKey(json, nonInteractive = false) {
11695
12043
  }
11696
12044
 
11697
12045
  // src/commands/skills.ts
11698
- import { Command as Command15 } from "commander";
11699
- import { writeFileSync as writeFileSync3, mkdirSync as mkdirSync3, existsSync as existsSync4 } from "fs";
11700
- import { resolve, join as join3 } from "path";
12046
+ import { Command as Command16 } from "commander";
12047
+ import { writeFileSync as writeFileSync3, mkdirSync as mkdirSync3 } from "fs";
12048
+ import { resolve, join as join4 } from "path";
11701
12049
 
11702
12050
  // src/generated/skill-content.ts
11703
12051
  var SKILL_CONTENT = {
@@ -11809,34 +12157,7 @@ var SKILLS = [
11809
12157
  description: "Read-only periodic portfolio and PnL digest, optionally delivered to the operator by DM"
11810
12158
  }
11811
12159
  ];
11812
- var AGENT_ORDER = [
11813
- "claude",
11814
- "cursor",
11815
- "windsurf",
11816
- "openclaw",
11817
- "hermes"
11818
- ];
11819
12160
  var SKILL_PREFIX = "zora-";
11820
- var AGENT_SKILLS_DIRS = {
11821
- claude: ".claude/skills",
11822
- cursor: ".cursor/skills",
11823
- windsurf: ".windsurf/skills",
11824
- openclaw: ".openclaw/skills",
11825
- hermes: ".hermes/skills"
11826
- };
11827
- var AGENT_ROOT_DIRS = {
11828
- claude: ".claude",
11829
- cursor: ".cursor",
11830
- windsurf: ".windsurf",
11831
- openclaw: ".openclaw",
11832
- hermes: ".hermes"
11833
- };
11834
- var detectAgent = (cwd) => {
11835
- for (const agent of AGENT_ORDER) {
11836
- if (existsSync4(join3(cwd, AGENT_ROOT_DIRS[agent]))) return agent;
11837
- }
11838
- return null;
11839
- };
11840
12161
  var getSkillContent = (name) => {
11841
12162
  const content = SKILL_CONTENT[name];
11842
12163
  if (content === void 0) {
@@ -11847,13 +12168,13 @@ var getSkillContent = (name) => {
11847
12168
  return content;
11848
12169
  };
11849
12170
  var writeSkill = (outDir, name) => {
11850
- const skillDir = join3(outDir, `${SKILL_PREFIX}${name}`);
12171
+ const skillDir = join4(outDir, `${SKILL_PREFIX}${name}`);
11851
12172
  mkdirSync3(skillDir, { recursive: true });
11852
- const outPath = join3(skillDir, "SKILL.md");
12173
+ const outPath = join4(skillDir, "SKILL.md");
11853
12174
  writeFileSync3(outPath, getSkillContent(name));
11854
12175
  return outPath;
11855
12176
  };
11856
- var skillsCommand = new Command15("skills").description(
12177
+ var skillsCommand = new Command16("skills").description(
11857
12178
  "Install pre-built agent skills \u2014 onboarding plus discovery, social, risk, and reporting strategies (run `skills list` to see them all)"
11858
12179
  ).action(function() {
11859
12180
  this.outputHelp();
@@ -11904,19 +12225,19 @@ skillsCommand.command("add [name]").description(
11904
12225
  outDir = resolve(dirFlag);
11905
12226
  resolvedAgent = "custom";
11906
12227
  } else if (agentFlag) {
11907
- if (!AGENT_SKILLS_DIRS[agentFlag]) {
12228
+ if (!AGENT_HARNESS_SKILLS_DIRS[agentFlag]) {
11908
12229
  return outputErrorAndExit(
11909
12230
  json,
11910
12231
  `Unknown agent: ${agentFlag}`,
11911
- `Supported: ${AGENT_ORDER.join(", ")}`
12232
+ `Supported: ${AGENT_HARNESS_ORDER.join(", ")}`
11912
12233
  );
11913
12234
  }
11914
- outDir = resolve(process.cwd(), AGENT_SKILLS_DIRS[agentFlag]);
12235
+ outDir = resolve(process.cwd(), AGENT_HARNESS_SKILLS_DIRS[agentFlag]);
11915
12236
  resolvedAgent = agentFlag;
11916
12237
  } else {
11917
- const detected = detectAgent(process.cwd());
12238
+ const detected = detectAgentHarness(process.cwd());
11918
12239
  resolvedAgent = detected ?? "claude";
11919
- outDir = resolve(process.cwd(), AGENT_SKILLS_DIRS[resolvedAgent]);
12240
+ outDir = resolve(process.cwd(), AGENT_HARNESS_SKILLS_DIRS[resolvedAgent]);
11920
12241
  }
11921
12242
  const requested = installAll ? SKILLS.map((s) => s.name) : [name];
11922
12243
  const invalid = requested.filter((n) => !SKILLS.some((s) => s.name === n));
@@ -11995,8 +12316,8 @@ Invoke by typing /${SKILL_PREFIX}${firstRequested} in your agent to get started.
11995
12316
  });
11996
12317
 
11997
12318
  // src/commands/wallet.ts
11998
- import { Command as Command16 } from "commander";
11999
- import { isAddress as isAddress10 } from "viem";
12319
+ import { Command as Command17 } from "commander";
12320
+ import { isAddress as isAddress11 } from "viem";
12000
12321
  import { privateKeyToAccount as privateKeyToAccount10 } from "viem/accounts";
12001
12322
  var resolvePrivateKey2 = () => {
12002
12323
  const envKey = process.env.ZORA_PRIVATE_KEY;
@@ -12012,15 +12333,15 @@ var resolvePrivateKey2 = () => {
12012
12333
  var resolveSmartWalletAddress3 = () => {
12013
12334
  const envAddress = process.env.ZORA_SMART_WALLET_ADDRESS;
12014
12335
  if (envAddress) {
12015
- return isAddress10(envAddress) ? { address: envAddress, source: "env" } : { invalid: true, source: "env" };
12336
+ return isAddress11(envAddress) ? { address: envAddress, source: "env" } : { invalid: true, source: "env" };
12016
12337
  }
12017
12338
  const fileAddress = getSmartWalletAddress();
12018
12339
  if (fileAddress !== void 0) {
12019
- return isAddress10(fileAddress) ? { address: fileAddress, source: "file" } : { invalid: true, source: "file" };
12340
+ return isAddress11(fileAddress) ? { address: fileAddress, source: "file" } : { invalid: true, source: "file" };
12020
12341
  }
12021
12342
  return void 0;
12022
12343
  };
12023
- var walletCommand = new Command16("wallet").description("Manage your Zora wallet").action(function() {
12344
+ var walletCommand = new Command17("wallet").description("Manage your Zora wallet").action(function() {
12024
12345
  this.outputHelp();
12025
12346
  });
12026
12347
  walletCommand.command("info").description("Show wallet address and storage location").action(function() {
@@ -12557,7 +12878,7 @@ import { jsx as jsx24 } from "react/jsx-runtime";
12557
12878
  if (process.env.ZORA_API_TARGET) {
12558
12879
  setApiBaseUrl(process.env.ZORA_API_TARGET);
12559
12880
  }
12560
- var version = true ? "1.4.1" : JSON.parse(
12881
+ var version = true ? "1.5.0" : JSON.parse(
12561
12882
  readFileSync5(new URL("../package.json", import.meta.url), "utf-8")
12562
12883
  ).version;
12563
12884
  function styledHelpWriteOut(showHeader) {
@@ -12577,7 +12898,7 @@ function styledHelpWriteOut(showHeader) {
12577
12898
  };
12578
12899
  }
12579
12900
  var buildProgram = () => {
12580
- const program2 = new Command17().name("zora").description("Trade what's trending. Run `zora setup` to get started.").version(version).option("--json", "Output as JSON (for scripts and automation)", false);
12901
+ const program2 = new Command18().name("zora").description("Trade what's trending. Run `zora setup` to get started.").version(version).option("--json", "Output as JSON (for scripts and automation)", false);
12581
12902
  const helpWidth = (process.stdout.columns || 80) - 4;
12582
12903
  program2.configureHelp({
12583
12904
  helpWidth,
@@ -12594,6 +12915,7 @@ var buildProgram = () => {
12594
12915
  program2.addCommand(authCommand);
12595
12916
  program2.addCommand(balanceCommand);
12596
12917
  program2.addCommand(buyCommand);
12918
+ program2.addCommand(claimCommand);
12597
12919
  program2.addCommand(commentCommand);
12598
12920
  program2.addCommand(createCommand);
12599
12921
  program2.addCommand(dmCommand);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zoralabs/cli",
3
- "version": "1.4.1",
3
+ "version": "1.5.0",
4
4
  "description": "Zora CLI tool",
5
5
  "type": "module",
6
6
  "bin": {