@zeroxyz/cli 1.16.0 → 1.18.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 +258 -26
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -78449,7 +78449,7 @@ init_esm_shims();
78449
78449
  // ../sdk/dist/index.js
78450
78450
  init_esm_shims();
78451
78451
 
78452
- // ../sdk/dist/chunk-A7WZYQXS.js
78452
+ // ../sdk/dist/chunk-KDWESC42.js
78453
78453
  init_esm_shims();
78454
78454
 
78455
78455
  // ../../node_modules/.pnpm/viem@2.52.2_bufferutil@4.1.0_typescript@5.9.3_utf-8-validate@6.0.6_zod@4.3.6/node_modules/viem/_esm/index.js
@@ -143831,7 +143831,7 @@ config(en_default2());
143831
143831
  // ../../node_modules/.pnpm/zod@4.3.6/node_modules/zod/index.js
143832
143832
  var zod_default = external_exports3;
143833
143833
 
143834
- // ../sdk/dist/chunk-A7WZYQXS.js
143834
+ // ../sdk/dist/chunk-KDWESC42.js
143835
143835
  var createManagedAccount = (client, address2) => toAccount({
143836
143836
  address: address2,
143837
143837
  async signMessage({ message: message2 }) {
@@ -144000,16 +144000,6 @@ var extractInputEnvelope = (bodySchema, method) => {
144000
144000
  const isGetLike = upperMethod === "GET" || upperMethod === "DELETE";
144001
144001
  return isGetLike ? { queryParams: root } : { body: root };
144002
144002
  };
144003
- var unwrapTransportEnvelope = (request22) => {
144004
- const input = asSchemaNode(asSchemaNode(request22)?.input);
144005
- if (!input || input.type !== "http") return request22;
144006
- const body = input.body;
144007
- const hasBody = body !== void 0 && body !== null && !(typeof body === "object" && Object.keys(body).length === 0);
144008
- if (hasBody) return body;
144009
- const qp = asSchemaNode(input.queryParams);
144010
- if (qp && Object.keys(qp).length > 0) return qp;
144011
- return null;
144012
- };
144013
144003
  var GET_LIKE = /* @__PURE__ */ new Set(["GET", "HEAD", "DELETE"]);
144014
144004
  var appendQueryParams = (url4, params) => {
144015
144005
  const entries = Object.entries(params).filter(([, v]) => v != null);
@@ -144398,6 +144388,7 @@ var pickSessionCloseAmount = (receipt, openTimeCumulative) => {
144398
144388
  if (receipt.metered === true) return fromReceipt;
144399
144389
  return fromReceipt > openTimeCumulative ? fromReceipt : openTimeCumulative;
144400
144390
  };
144391
+ var isMeteredZeroReceipt = (receipt) => receipt?.metered === true && BigInt(receipt.acceptedCumulative) === 0n && BigInt(receipt.spent) === 0n;
144401
144392
  var raceWithSignal = (p, signal, client) => {
144402
144393
  if (!signal) return p;
144403
144394
  if (signal.aborted) {
@@ -144971,7 +144962,7 @@ var Payments = class {
144971
144962
  }
144972
144963
  const receipt = readSessionReceipt(response);
144973
144964
  let closeAmount = pickSessionCloseAmount(receipt, openTimeCumulative);
144974
- if (closeAmount === 0n && channelEntry.cumulativeAmount > 0n) {
144965
+ if (closeAmount === 0n && channelEntry.cumulativeAmount > 0n && !isMeteredZeroReceipt(receipt)) {
144975
144966
  closeAmount = channelEntry.cumulativeAmount;
144976
144967
  }
144977
144968
  const reconcileAmount = receipt && isUintString(receipt.acceptedCumulative) ? receipt.acceptedCumulative : closeAmount.toString();
@@ -144988,7 +144979,7 @@ var Payments = class {
144988
144979
  capturedAmount,
144989
144980
  cause
144990
144981
  });
144991
- if (closeAmount === 0n) {
144982
+ if (closeAmount === 0n && !isMeteredZeroReceipt(receipt)) {
144992
144983
  throw closeFailed(
144993
144984
  `Refusing to sign zero close credential for channel ${channelId} \u2014 neither receipt nor channelEntry produced a nonzero cumulativeAmount. Query escrow directly to recover; check logger for an earlier 'non-bigint cumulativeAmount' warning.`
144994
144985
  );
@@ -145757,7 +145748,7 @@ var clientFetch = async (client, url4, opts = {}) => {
145757
145748
  return result;
145758
145749
  };
145759
145750
  var package_default = {
145760
- version: "0.10.0"
145751
+ version: "0.12.0"
145761
145752
  };
145762
145753
  var SDK_VERSION2 = package_default.version;
145763
145754
  var agentAuthMetadataSchema = external_exports3.object({
@@ -146243,6 +146234,7 @@ var userWalletDtoSchema = external_exports3.object({
146243
146234
  source: external_exports3.enum(["self_custody", "privy_embedded"]),
146244
146235
  isPrimary: external_exports3.boolean(),
146245
146236
  linkedAt: external_exports3.union([external_exports3.string(), external_exports3.date()]).nullable().optional(),
146237
+ importedAt: external_exports3.union([external_exports3.string(), external_exports3.date()]).nullable().optional(),
146246
146238
  delegationGranted: external_exports3.boolean(),
146247
146239
  signerQuorumId: external_exports3.string().nullable(),
146248
146240
  // Per-transaction USDC cap in base units (6 dp). null = unlimited, 0 = free-only.
@@ -146635,6 +146627,12 @@ var capabilityResponseSchema = external_exports3.object({
146635
146627
  bodySchema: external_exports3.record(external_exports3.string(), external_exports3.unknown()).nullable(),
146636
146628
  responseSchema: external_exports3.record(external_exports3.string(), external_exports3.unknown()).nullable(),
146637
146629
  example: external_exports3.object({ request: external_exports3.unknown(), response: external_exports3.unknown() }).nullable(),
146630
+ // The bare, schema-validated request body to send — `.request` unwrapped
146631
+ // from the transcript envelope and checked against the current bodySchema.
146632
+ // Null when there's no usable example or it's stale vs the schema; `example`
146633
+ // is retained for the response sample. Optional for back-compat with older
146634
+ // servers that don't emit it.
146635
+ exampleRequest: external_exports3.record(external_exports3.string(), external_exports3.unknown()).nullable().optional(),
146638
146636
  tags: external_exports3.array(external_exports3.string()).nullable(),
146639
146637
  exampleAgentPrompt: external_exports3.string().nullable().optional(),
146640
146638
  whatItDoes: external_exports3.string().nullable().optional(),
@@ -147018,6 +147016,48 @@ var Wallet = class {
147018
147016
  },
147019
147017
  userWalletDtoSchema
147020
147018
  );
147019
+ // Link an existing self-custody wallet to the session user by private key.
147020
+ // Session-only. 409s when the wallet is already linked (to this or another
147021
+ // profile — the error message says which).
147022
+ import = (opts) => request2(
147023
+ this.client,
147024
+ {
147025
+ method: "POST",
147026
+ path: "/v1/users/me/wallets/import",
147027
+ body: {
147028
+ privateKey: opts.privateKey,
147029
+ ...opts.makePrimary !== void 0 ? { makePrimary: opts.makePrimary } : {}
147030
+ },
147031
+ signal: opts.signal
147032
+ },
147033
+ userWalletDtoSchema
147034
+ );
147035
+ // Make one of the session user's linked wallets the primary payer.
147036
+ // Session-only. 404s when the address isn't linked to the user.
147037
+ setPrimary = (opts) => request2(
147038
+ this.client,
147039
+ {
147040
+ method: "PATCH",
147041
+ path: "/v1/users/me/wallets/primary",
147042
+ body: { walletAddress: opts.walletAddress },
147043
+ signal: opts.signal
147044
+ },
147045
+ userWalletDtoSchema
147046
+ );
147047
+ // Unlink a wallet from the session user. Session-only. 409s on the primary
147048
+ // wallet or a non-zero balance (the error message says which); 404s when
147049
+ // the address isn't linked. Responds 204 — resolves to void.
147050
+ remove = async (opts) => {
147051
+ await request2(
147052
+ this.client,
147053
+ {
147054
+ method: "DELETE",
147055
+ path: `/v1/users/me/wallets/${opts.walletAddress}`,
147056
+ signal: opts.signal
147057
+ },
147058
+ external_exports3.undefined()
147059
+ );
147060
+ };
147021
147061
  // Routes by identity: account mode signs EIP-191 against /v1/wallet/fund-url,
147022
147062
  // session mode hits /v1/users/me/fund-url (Bearer-authed, wallet resolved
147023
147063
  // server-side). Both honor `provider` (coinbase | stripe).
@@ -147742,7 +147782,7 @@ var placeholderFor = (fieldName, propSchema) => String(sampleValueFor(fieldName,
147742
147782
 
147743
147783
  // package.json
147744
147784
  var package_default2 = {
147745
- version: "1.16.0"};
147785
+ version: "1.18.0"};
147746
147786
 
147747
147787
  // src/app.ts
147748
147788
  init_esm_shims();
@@ -150006,13 +150046,20 @@ var buildResponseSection = (capability) => {
150006
150046
  return [];
150007
150047
  };
150008
150048
  var buildVerifiedExampleSection = (capability) => {
150009
- const req = capability.example?.request;
150010
- if (req === void 0 || req === null) return [];
150011
- const shown = unwrapTransportEnvelope(req);
150012
- if (shown === void 0 || shown === null) return [];
150013
- const json3 = typeof shown === "string" ? shown : JSON.stringify(shown);
150014
- const truncated = json3.length > 600 ? `${json3.slice(0, 600)}\u2026` : json3;
150015
- return ["", "Verified example (request):", ` ${truncated}`];
150049
+ const req = capability.exampleRequest;
150050
+ if (req) {
150051
+ const json3 = JSON.stringify(req);
150052
+ const truncated = json3.length > 600 ? `${json3.slice(0, 600)}\u2026` : json3;
150053
+ return ["", "Verified example (request):", ` ${truncated}`];
150054
+ }
150055
+ if (req === null && capability.example?.request !== void 0 && capability.example?.request !== null) {
150056
+ return [
150057
+ "",
150058
+ "Verified example: no usable request example for the current schema \u2014",
150059
+ " build the request from Parameters above."
150060
+ ];
150061
+ }
150062
+ return [];
150016
150063
  };
150017
150064
  var buildTryItExample = (capability) => {
150018
150065
  const method = capability.method.toUpperCase();
@@ -150102,6 +150149,21 @@ var formatCapability = (capability) => {
150102
150149
  lines.push(...buildTryItExample(capability));
150103
150150
  return lines.join("\n");
150104
150151
  };
150152
+ var URL_RESOLUTION_METHODS = [
150153
+ "POST",
150154
+ "GET",
150155
+ "PUT",
150156
+ "PATCH",
150157
+ "DELETE"
150158
+ ];
150159
+ var isHttpUrl = (value) => {
150160
+ try {
150161
+ const url4 = new URL(value);
150162
+ return url4.protocol === "http:" || url4.protocol === "https:";
150163
+ } catch {
150164
+ return false;
150165
+ }
150166
+ };
150105
150167
  var getCommand = (appContext) => new Command("get").description("Get details for a capability by token, slug, or uid").argument(
150106
150168
  "<identifier>",
150107
150169
  "Attribution token (z_xxx.N from search results), capability slug, or uid"
@@ -150111,7 +150173,30 @@ var getCommand = (appContext) => new Command("get").description("Get details for
150111
150173
  ).action(async (identifier, options) => {
150112
150174
  try {
150113
150175
  const { analyticsService, client } = appContext.services;
150114
- const capability = await client.capabilities.get(identifier);
150176
+ let capabilityRef = identifier;
150177
+ if (isHttpUrl(identifier)) {
150178
+ const matches2 = /* @__PURE__ */ new Map();
150179
+ for (const method of URL_RESOLUTION_METHODS) {
150180
+ const resolved = await client.capabilities.resolveByUrl(
150181
+ identifier,
150182
+ method
150183
+ );
150184
+ if (resolved) {
150185
+ matches2.set(resolved.capabilityId, resolved.capabilitySlug);
150186
+ }
150187
+ }
150188
+ if (matches2.size !== 1) {
150189
+ throw new Error(
150190
+ matches2.size === 0 ? "No indexed capability found for that URL." : "Multiple capabilities match that URL; use a capability slug or uid instead."
150191
+ );
150192
+ }
150193
+ const [resolvedCapabilityId] = matches2.keys();
150194
+ if (!resolvedCapabilityId) {
150195
+ throw new Error("No indexed capability found for that URL.");
150196
+ }
150197
+ capabilityRef = resolvedCapabilityId;
150198
+ }
150199
+ const capability = await client.capabilities.get(capabilityRef);
150115
150200
  if (options.formatted && !options.json) {
150116
150201
  console.log(formatCapability(capability));
150117
150202
  } else {
@@ -151795,17 +151880,20 @@ init_esm_shims();
151795
151880
 
151796
151881
  // src/util/migrate-config.ts
151797
151882
  init_esm_shims();
151798
- var backupAndStripPrivateKey = (zeroDir) => {
151883
+ var backupAndStripConfigKeys = (zeroDir, keys) => {
151799
151884
  const configPath = join$1(zeroDir, "config.json");
151800
151885
  const backupPath = join$1(zeroDir, "config.backup.json");
151801
151886
  const raw = readFileSync(configPath, "utf8");
151802
151887
  ensureSecureDir(zeroDir);
151803
151888
  writeSecureFile(backupPath, raw);
151804
151889
  const parsed = JSON.parse(raw);
151805
- delete parsed.privateKey;
151890
+ for (const key of keys) {
151891
+ delete parsed[key];
151892
+ }
151806
151893
  writeSecureFile(configPath, JSON.stringify(parsed, null, 2));
151807
151894
  return { backupPath, configPath };
151808
151895
  };
151896
+ var backupAndStripPrivateKey = (zeroDir) => backupAndStripConfigKeys(zeroDir, ["privateKey"]);
151809
151897
 
151810
151898
  // src/util/stdin.ts
151811
151899
  init_esm_shims();
@@ -152034,6 +152122,148 @@ var walletSetCommand = (appContext) => new Command("set").description("Set walle
152034
152122
  force: options.force ?? false
152035
152123
  });
152036
152124
  });
152125
+ var normalizeImportKey = (raw) => {
152126
+ const trimmed = raw.trim();
152127
+ const prefixed = trimmed.startsWith("0x") ? trimmed : `0x${trimmed}`;
152128
+ return PRIVATE_KEY_PATTERN.test(prefixed) ? prefixed : null;
152129
+ };
152130
+ var SIGN_IN_FIRST_MESSAGE = "This command requires a signed-in session. Run `zero auth login` first.";
152131
+ var walletImportCommand = (appContext) => new Command("import").description(
152132
+ "Link an existing self-custody wallet to your Zero profile by private key"
152133
+ ).argument("[privateKey]", "Hex-encoded private key (0x prefix optional)").option(
152134
+ "--key-stdin",
152135
+ "Read the private key from stdin instead of an argument"
152136
+ ).option("--primary", "Make the imported wallet your primary payer wallet").action(
152137
+ async (privateKeyArg, options) => {
152138
+ const { analyticsService, client } = appContext.services;
152139
+ if (privateKeyArg && options.keyStdin) {
152140
+ console.error(
152141
+ "Pass the key as an argument OR via --key-stdin, not both."
152142
+ );
152143
+ process.exitCode = 1;
152144
+ return;
152145
+ }
152146
+ if (!privateKeyArg && !options.keyStdin) {
152147
+ console.error(
152148
+ "Missing private key. Pass it as an argument or pipe it with --key-stdin."
152149
+ );
152150
+ process.exitCode = 1;
152151
+ return;
152152
+ }
152153
+ let rawKey;
152154
+ if (options.keyStdin) {
152155
+ if (process.stdin.isTTY) {
152156
+ console.error(
152157
+ "Expected a private key on stdin. Example:\n zero wallet generate --json | jq -r .privateKey | zero wallet import --key-stdin"
152158
+ );
152159
+ process.exitCode = 1;
152160
+ return;
152161
+ }
152162
+ rawKey = await readStdin();
152163
+ } else {
152164
+ rawKey = privateKeyArg;
152165
+ }
152166
+ const privateKey = normalizeImportKey(rawKey);
152167
+ if (!privateKey) {
152168
+ console.error(
152169
+ "Invalid private key (expected 64 hex chars, 0x prefix optional)."
152170
+ );
152171
+ process.exitCode = 1;
152172
+ return;
152173
+ }
152174
+ if (client.getCredentials().kind !== "session") {
152175
+ console.error(SIGN_IN_FIRST_MESSAGE);
152176
+ process.exitCode = 1;
152177
+ return;
152178
+ }
152179
+ let wallet;
152180
+ try {
152181
+ wallet = await client.wallet.import({
152182
+ privateKey,
152183
+ ...options.primary ? { makePrimary: true } : {}
152184
+ });
152185
+ } catch (err) {
152186
+ if (err instanceof ZeroApiError) {
152187
+ if (err.status === 401) {
152188
+ console.error(
152189
+ "Session expired. Run `zero auth login` and try again."
152190
+ );
152191
+ } else {
152192
+ console.error(`Could not import wallet: ${err.message}`);
152193
+ }
152194
+ } else {
152195
+ console.error("Could not import wallet: network error.");
152196
+ }
152197
+ process.exitCode = 1;
152198
+ return;
152199
+ }
152200
+ analyticsService.setWalletAddress(wallet.walletAddress);
152201
+ console.log(
152202
+ `Wallet imported: ${wallet.walletAddress}${wallet.isPrimary ? " (primary)" : ""}`
152203
+ );
152204
+ let localKeyStripped = false;
152205
+ const zeroDir = join$1(homedir(), ".zero");
152206
+ const configPath = join$1(zeroDir, "config.json");
152207
+ const config2 = existsSync(configPath) ? readConfig(configPath) : {};
152208
+ const localByoKey = config2.byoPrivateKey ? normalizeImportKey(config2.byoPrivateKey) : null;
152209
+ if (localByoKey && localByoKey.toLowerCase() === privateKey.toLowerCase()) {
152210
+ try {
152211
+ const { backupPath } = backupAndStripConfigKeys(zeroDir, [
152212
+ "byoPrivateKey"
152213
+ ]);
152214
+ localKeyStripped = true;
152215
+ console.log(
152216
+ `Local key backed up to ${backupPath} and removed from config \u2014 managed signing now applies.`
152217
+ );
152218
+ } catch {
152219
+ console.error(
152220
+ "Could not back up the local key; it was left in place in ~/.zero/config.json."
152221
+ );
152222
+ }
152223
+ }
152224
+ analyticsService.capture("wallet_imported", {
152225
+ primary: wallet.isPrimary,
152226
+ // biome-ignore lint/style/useNamingConvention: snake_case for analytics
152227
+ key_source: options.keyStdin ? "stdin" : "arg",
152228
+ // biome-ignore lint/style/useNamingConvention: snake_case for analytics
152229
+ local_key_stripped: localKeyStripped
152230
+ });
152231
+ }
152232
+ );
152233
+ var walletListCommand = (appContext) => new Command("list").description("List the wallets linked to your Zero profile").action(async () => {
152234
+ const { analyticsService, client } = appContext.services;
152235
+ if (client.getCredentials().kind !== "session") {
152236
+ console.error(SIGN_IN_FIRST_MESSAGE);
152237
+ process.exitCode = 1;
152238
+ return;
152239
+ }
152240
+ let wallets;
152241
+ try {
152242
+ wallets = await client.wallet.list();
152243
+ } catch (err) {
152244
+ const message2 = err instanceof ZeroApiError && err.status === 401 ? "Session expired. Run `zero auth login` and try again." : "Failed to list wallets.";
152245
+ console.error(message2);
152246
+ process.exitCode = 1;
152247
+ return;
152248
+ }
152249
+ if (wallets.length === 0) {
152250
+ console.log(
152251
+ "No wallets linked. One is provisioned automatically on your first paid call, or run `zero wallet import <key>`."
152252
+ );
152253
+ } else {
152254
+ for (const wallet of wallets) {
152255
+ const source = wallet.importedAt ? "imported" : wallet.source === "privy_embedded" ? "managed" : "byo";
152256
+ const columns = [
152257
+ wallet.walletAddress,
152258
+ source.padEnd(8),
152259
+ (wallet.isPrimary ? "PRIMARY" : "").padEnd(7),
152260
+ wallet.delegationGranted ? "delegated" : "not delegated"
152261
+ ];
152262
+ console.log(columns.join(" ").trimEnd());
152263
+ }
152264
+ }
152265
+ analyticsService.capture("wallet_listed", { count: wallets.length });
152266
+ });
152037
152267
  var walletGenerateCommand = (appContext) => new Command("generate").description(
152038
152268
  "Generate a fresh wallet (address + private key) without touching your configured wallet"
152039
152269
  ).option("--json", "Emit { address, privateKey } as JSON").option(
@@ -152121,6 +152351,8 @@ var walletCommand = (appContext) => {
152121
152351
  cmd.addCommand(walletAddressCommand(appContext));
152122
152352
  cmd.addCommand(walletSetCommand(appContext));
152123
152353
  cmd.addCommand(walletGenerateCommand(appContext));
152354
+ cmd.addCommand(walletImportCommand(appContext));
152355
+ cmd.addCommand(walletListCommand(appContext));
152124
152356
  return cmd;
152125
152357
  };
152126
152358
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zeroxyz/cli",
3
- "version": "1.16.0",
3
+ "version": "1.18.0",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "zero": "dist/index.js",