@zeroxyz/sdk 0.11.0 → 0.13.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.
@@ -13,36 +13,40 @@ import { createHash } from 'crypto';
13
13
  import { z } from 'zod';
14
14
 
15
15
  // src/auth/managed-account.ts
16
- var createManagedAccount = (client, address) => toAccount({
17
- address,
18
- async signMessage({ message }) {
19
- return await client.auth.signMessage(
20
- { message },
21
- { expectedAddress: address }
22
- );
23
- },
24
- async signTypedData(typedData) {
25
- const td = typedData;
26
- return await client.auth.signTypedData(
27
- {
28
- domain: td.domain,
29
- types: td.types,
30
- primaryType: td.primaryType,
31
- message: td.message
32
- },
33
- { expectedAddress: address }
34
- );
35
- },
36
- async signTransaction(transaction, options) {
37
- const serialize = options?.serializer ?? serializeTransaction;
38
- const unsigned = await serialize(transaction);
39
- const signature = await client.auth.signTransaction(
40
- { unsignedTransaction: unsigned },
41
- { expectedAddress: address }
42
- );
43
- return await serialize(transaction, parseSignature(signature));
44
- }
45
- });
16
+ var createManagedAccount = (client, address, opts = {}) => {
17
+ const signOptions = {
18
+ // expectedAddress pins verification to this adapter's frozen address.
19
+ expectedAddress: address,
20
+ ...opts.explicitWallet ? { walletAddress: address } : {}
21
+ };
22
+ return toAccount({
23
+ address,
24
+ async signMessage({ message }) {
25
+ return await client.auth.signMessage({ message }, signOptions);
26
+ },
27
+ async signTypedData(typedData) {
28
+ const td = typedData;
29
+ return await client.auth.signTypedData(
30
+ {
31
+ domain: td.domain,
32
+ types: td.types,
33
+ primaryType: td.primaryType,
34
+ message: td.message
35
+ },
36
+ signOptions
37
+ );
38
+ },
39
+ async signTransaction(transaction, options) {
40
+ const serialize = options?.serializer ?? serializeTransaction;
41
+ const unsigned = await serialize(transaction);
42
+ const signature = await client.auth.signTransaction(
43
+ { unsignedTransaction: unsigned },
44
+ signOptions
45
+ );
46
+ return await serialize(transaction, parseSignature(signature));
47
+ }
48
+ });
49
+ };
46
50
  var USDC_BASE = "0x833589fcd6edb6e08f4c7c32d4f71b54bda02913";
47
51
  var USDC_TEMPO = "0x20c000000000000000000000b9537d11c60e8b50";
48
52
  var TEMPO_CHAIN_ID = 4217;
@@ -589,6 +593,7 @@ var pickSessionCloseAmount = (receipt, openTimeCumulative) => {
589
593
  if (receipt.metered === true) return fromReceipt;
590
594
  return fromReceipt > openTimeCumulative ? fromReceipt : openTimeCumulative;
591
595
  };
596
+ var isMeteredZeroReceipt = (receipt) => receipt?.metered === true && BigInt(receipt.acceptedCumulative) === 0n && BigInt(receipt.spent) === 0n;
592
597
  var raceWithSignal = (p, signal, client) => {
593
598
  if (!signal) return p;
594
599
  if (signal.aborted) {
@@ -638,12 +643,12 @@ var cancelBody = (response) => {
638
643
  } catch {
639
644
  }
640
645
  };
641
- var resolveAccount = async (client, overrideAccount, signal) => {
646
+ var resolveAccount = async (client, overrideAccount, signal, walletAddress) => {
642
647
  if (overrideAccount) return overrideAccount;
643
648
  const credentials = client.getCredentials();
644
649
  if (credentials.kind === "account") return credentials.account;
645
650
  if (credentials.kind === "session") {
646
- return await client.resolveManagedAccount(signal);
651
+ return await client.resolveManagedAccount(signal, walletAddress);
647
652
  }
648
653
  throw new ZeroAuthError(
649
654
  "auth_no_credentials",
@@ -689,7 +694,8 @@ var Payments = class {
689
694
  const account = await resolveAccount(
690
695
  this.client,
691
696
  input.account,
692
- input.signal
697
+ input.signal,
698
+ input.walletAddress
693
699
  );
694
700
  let capturedAmount = null;
695
701
  let capturedNetwork;
@@ -824,7 +830,8 @@ var Payments = class {
824
830
  const account = await resolveAccount(
825
831
  this.client,
826
832
  input.account,
827
- input.signal
833
+ input.signal,
834
+ input.walletAddress
828
835
  );
829
836
  const configuredFetch = buildConfiguredFetch(this.client, {
830
837
  timeoutMs: input.timeoutMs
@@ -1162,7 +1169,7 @@ var Payments = class {
1162
1169
  }
1163
1170
  const receipt = readSessionReceipt(response);
1164
1171
  let closeAmount = pickSessionCloseAmount(receipt, openTimeCumulative);
1165
- if (closeAmount === 0n && channelEntry.cumulativeAmount > 0n) {
1172
+ if (closeAmount === 0n && channelEntry.cumulativeAmount > 0n && !isMeteredZeroReceipt(receipt)) {
1166
1173
  closeAmount = channelEntry.cumulativeAmount;
1167
1174
  }
1168
1175
  const reconcileAmount = receipt && isUintString(receipt.acceptedCumulative) ? receipt.acceptedCumulative : closeAmount.toString();
@@ -1179,7 +1186,7 @@ var Payments = class {
1179
1186
  capturedAmount,
1180
1187
  cause
1181
1188
  });
1182
- if (closeAmount === 0n) {
1189
+ if (closeAmount === 0n && !isMeteredZeroReceipt(receipt)) {
1183
1190
  throw closeFailed(
1184
1191
  `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.`
1185
1192
  );
@@ -1604,7 +1611,8 @@ var recordErrorFetchRun = async (client, opts, result, capabilityIdOverride) =>
1604
1611
  ...fetchOriginForRecord && { fetchOrigin: fetchOriginForRecord },
1605
1612
  ...result.status !== null && { status: result.status },
1606
1613
  latencyMs: result.latencyMs,
1607
- ...opts.requestSchema && { requestSchema: opts.requestSchema }
1614
+ ...opts.requestSchema && { requestSchema: opts.requestSchema },
1615
+ ...opts.walletAddress && !opts.account && { walletAddress: opts.walletAddress }
1608
1616
  });
1609
1617
  result.runId = created.runId;
1610
1618
  delete result.runTrackingSkipped;
@@ -1713,6 +1721,7 @@ var clientFetch = async (client, url, opts = {}) => {
1713
1721
  body: requestBody,
1714
1722
  maxPay: opts.maxPay,
1715
1723
  account: opts.account,
1724
+ ...opts.walletAddress && { walletAddress: opts.walletAddress },
1716
1725
  signal: opts.signal,
1717
1726
  timeoutMs: opts.timeoutMs,
1718
1727
  ...opts.displayCostAmount && {
@@ -1885,6 +1894,10 @@ var clientFetch = async (client, url, opts = {}) => {
1885
1894
  ...opts.capabilityId === void 0 ? { fetchOrigin: "direct_url" } : opts.fetchOrigin && { fetchOrigin: opts.fetchOrigin },
1886
1895
  status: response.status,
1887
1896
  latencyMs,
1897
+ // Attribute to the selected wallet in session mode. Skipped when a
1898
+ // per-call `account` override records the run — that account's own
1899
+ // EIP-191 identity is the attribution.
1900
+ ...opts.walletAddress && !opts.account && { walletAddress: opts.walletAddress },
1888
1901
  ...opts.requestSchema && { requestSchema: opts.requestSchema },
1889
1902
  ...derived?.responseSchema && {
1890
1903
  responseSchema: derived.responseSchema
@@ -1950,7 +1963,7 @@ var clientFetch = async (client, url, opts = {}) => {
1950
1963
 
1951
1964
  // package.json
1952
1965
  var package_default = {
1953
- version: "0.11.0"};
1966
+ version: "0.13.0"};
1954
1967
 
1955
1968
  // src/version.ts
1956
1969
  var SDK_VERSION = package_default.version;
@@ -2440,6 +2453,9 @@ var userWalletDtoSchema = z.object({
2440
2453
  walletAddress: z.string(),
2441
2454
  source: z.enum(["self_custody", "privy_embedded"]),
2442
2455
  isPrimary: z.boolean(),
2456
+ // Owner-chosen display name; null/absent = unnamed (show the address).
2457
+ // Optional so the SDK tolerates servers that predate nicknames.
2458
+ nickname: z.string().nullable().optional(),
2443
2459
  linkedAt: z.union([z.string(), z.date()]).nullable().optional(),
2444
2460
  importedAt: z.union([z.string(), z.date()]).nullable().optional(),
2445
2461
  delegationGranted: z.boolean(),
@@ -2657,7 +2673,10 @@ var Auth = class {
2657
2673
  {
2658
2674
  method: "POST",
2659
2675
  path: "/v1/users/me/sign-message",
2660
- body: { message: normalizeMessage(input.message) }
2676
+ body: {
2677
+ message: normalizeMessage(input.message),
2678
+ ...opts.walletAddress ? { walletAddress: opts.walletAddress } : {}
2679
+ }
2661
2680
  },
2662
2681
  signResponseSchema
2663
2682
  );
@@ -2682,7 +2701,10 @@ var Auth = class {
2682
2701
  {
2683
2702
  method: "POST",
2684
2703
  path: "/v1/users/me/sign-transaction",
2685
- body: { unsignedTransaction: input.unsignedTransaction }
2704
+ body: {
2705
+ unsignedTransaction: input.unsignedTransaction,
2706
+ ...opts.walletAddress ? { walletAddress: opts.walletAddress } : {}
2707
+ }
2686
2708
  },
2687
2709
  signResponseSchema
2688
2710
  );
@@ -2721,7 +2743,10 @@ var Auth = class {
2721
2743
  {
2722
2744
  method: "POST",
2723
2745
  path: "/v1/users/me/sign-typed-data",
2724
- body: { typedData: input }
2746
+ body: {
2747
+ typedData: input,
2748
+ ...opts.walletAddress ? { walletAddress: opts.walletAddress } : {}
2749
+ }
2725
2750
  },
2726
2751
  signResponseSchema
2727
2752
  );
@@ -2840,6 +2865,12 @@ var capabilityResponseSchema = z.object({
2840
2865
  bodySchema: z.record(z.string(), z.unknown()).nullable(),
2841
2866
  responseSchema: z.record(z.string(), z.unknown()).nullable(),
2842
2867
  example: z.object({ request: z.unknown(), response: z.unknown() }).nullable(),
2868
+ // The bare, schema-validated request body to send — `.request` unwrapped
2869
+ // from the transcript envelope and checked against the current bodySchema.
2870
+ // Null when there's no usable example or it's stale vs the schema; `example`
2871
+ // is retained for the response sample. Optional for back-compat with older
2872
+ // servers that don't emit it.
2873
+ exampleRequest: z.record(z.string(), z.unknown()).nullable().optional(),
2843
2874
  tags: z.array(z.string()).nullable(),
2844
2875
  exampleAgentPrompt: z.string().nullable().optional(),
2845
2876
  whatItDoes: z.string().nullable().optional(),
@@ -3092,6 +3123,9 @@ var Runs = class {
3092
3123
  if (params.unreviewed !== void 0) query.unreviewed = params.unreviewed;
3093
3124
  if (params.limit !== void 0) query.limit = params.limit;
3094
3125
  if (params.cursor !== void 0) query.cursor = params.cursor;
3126
+ if (params.walletAddress !== void 0) {
3127
+ query.walletAddress = Array.isArray(params.walletAddress) ? params.walletAddress.join(",") : params.walletAddress;
3128
+ }
3095
3129
  return request(
3096
3130
  this.client,
3097
3131
  {
@@ -3227,6 +3261,50 @@ var Wallet = class {
3227
3261
  },
3228
3262
  userWalletDtoSchema
3229
3263
  );
3264
+ // Re-stamp Zero's signing delegation on a profile wallet (default: the
3265
+ // primary). Session-only. Naming a wallet re-authorizes THAT wallet and
3266
+ // never provisions; the server 404s an address not on the profile.
3267
+ reauthorizeDelegation = (opts = {}) => request(
3268
+ this.client,
3269
+ {
3270
+ method: "POST",
3271
+ path: "/v1/users/me/wallets/provision",
3272
+ ...opts.walletAddress ? { body: { walletAddress: opts.walletAddress } } : {},
3273
+ signal: opts.signal
3274
+ },
3275
+ userWalletDtoSchema
3276
+ );
3277
+ // Revoke Zero's signing delegation on a profile wallet (default: the
3278
+ // primary). Session-only. Managed signing on that wallet 403s until it is
3279
+ // re-authorized. Note: this stamps the server-side gate — removing Zero's
3280
+ // signer cryptographically is owner-authorized and happens in the user's
3281
+ // Privy session (the web profile page does both).
3282
+ revokeDelegation = (opts = {}) => request(
3283
+ this.client,
3284
+ {
3285
+ method: "DELETE",
3286
+ path: "/v1/users/me/wallets/delegation",
3287
+ ...opts.walletAddress ? { query: { walletAddress: opts.walletAddress } } : {},
3288
+ signal: opts.signal
3289
+ },
3290
+ userWalletDtoSchema
3291
+ );
3292
+ // Set, change, or clear (null / empty string) the owner-chosen nickname on
3293
+ // a profile wallet. Session-only. Nicknames are private to the
3294
+ // authenticated user — they never appear on reviews or public surfaces.
3295
+ setNickname = (opts) => request(
3296
+ this.client,
3297
+ {
3298
+ method: "PATCH",
3299
+ path: "/v1/users/me/wallets/nickname",
3300
+ body: {
3301
+ walletAddress: opts.walletAddress,
3302
+ nickname: opts.nickname
3303
+ },
3304
+ signal: opts.signal
3305
+ },
3306
+ userWalletDtoSchema
3307
+ );
3230
3308
  // Link an existing self-custody wallet to the session user by private key.
3231
3309
  // Session-only. 409s when the wallet is already linked (to this or another
3232
3310
  // profile — the error message says which).
@@ -3237,7 +3315,8 @@ var Wallet = class {
3237
3315
  path: "/v1/users/me/wallets/import",
3238
3316
  body: {
3239
3317
  privateKey: opts.privateKey,
3240
- ...opts.makePrimary !== void 0 ? { makePrimary: opts.makePrimary } : {}
3318
+ ...opts.makePrimary !== void 0 ? { makePrimary: opts.makePrimary } : {},
3319
+ ...opts.nickname !== void 0 ? { nickname: opts.nickname } : {}
3241
3320
  },
3242
3321
  signal: opts.signal
3243
3322
  },
@@ -3440,6 +3519,9 @@ var ZeroClient = class _ZeroClient {
3440
3519
  managedAccountInFlight = null;
3441
3520
  managedAccountAC = null;
3442
3521
  managedAccountGen = 0;
3522
+ // Explicitly-selected (non-default) managed wallets, keyed by lowercased
3523
+ // address. Same lifecycle as managedAccount: cleared on clearManagedAccount.
3524
+ managedAccountByAddress = /* @__PURE__ */ new Map();
3443
3525
  // Multi-tenant servers calling `client.fetch(url, { account: tenantAccount })`
3444
3526
  // on every request would otherwise construct a new ZeroClient (with
3445
3527
  // five namespace instances) per call. Keyed by lowercased account
@@ -3661,8 +3743,16 @@ var ZeroClient = class _ZeroClient {
3661
3743
  }
3662
3744
  this.withAccountCache.clear();
3663
3745
  };
3664
- /** @internal — used by payments.pay() in session mode. Cached, dedupes concurrent lookups. */
3665
- resolveManagedAccount = (signal) => {
3746
+ /**
3747
+ * @internal — used by payments.pay() in session mode. Cached, dedupes
3748
+ * concurrent lookups. Pass `walletAddress` to sign as a specific profile
3749
+ * wallet instead of the primary; explicit wallets are cached per address
3750
+ * and their sign requests carry the address so intent and signer agree.
3751
+ */
3752
+ resolveManagedAccount = (signal, walletAddress) => {
3753
+ if (walletAddress) {
3754
+ return this.resolveManagedAccountByAddress(walletAddress, signal);
3755
+ }
3666
3756
  if (this.managedAccount) return Promise.resolve(this.managedAccount);
3667
3757
  if (this.managedAccountInFlight) {
3668
3758
  return this.raceWithSignal(this.managedAccountInFlight, signal);
@@ -3704,6 +3794,42 @@ var ZeroClient = class _ZeroClient {
3704
3794
  });
3705
3795
  return this.raceWithSignal(this.managedAccountInFlight, signal);
3706
3796
  };
3797
+ // Explicit-wallet variant of resolveManagedAccount. No in-flight dedupe:
3798
+ // this is the rare path (per-wallet pay), the resolution is idempotent, and
3799
+ // the per-address cache absorbs repeat calls.
3800
+ resolveManagedAccountByAddress = async (walletAddress, signal) => {
3801
+ if (this.credentials.kind !== "session") {
3802
+ throw new ZeroAuthError(
3803
+ "auth_no_credentials",
3804
+ "resolveManagedAccount() requires session credentials."
3805
+ );
3806
+ }
3807
+ const canonical = getAddress(walletAddress);
3808
+ const cached = this.managedAccountByAddress.get(canonical.toLowerCase());
3809
+ if (cached) return cached;
3810
+ const startedAtGen = this.managedAccountGen;
3811
+ const wallets = await this.auth.wallets({ signal });
3812
+ const match = wallets.find(
3813
+ (w) => w.walletAddress.toLowerCase() === canonical.toLowerCase()
3814
+ );
3815
+ if (!match || match.source !== "privy_embedded") {
3816
+ throw new ZeroAuthError(
3817
+ "auth_error",
3818
+ `Wallet ${canonical} is not a Privy-embedded wallet on this profile. Managed signing can only use profile wallets (see client.wallet.list()).`
3819
+ );
3820
+ }
3821
+ if (this.managedAccountGen !== startedAtGen) {
3822
+ throw new ZeroAuthError(
3823
+ "auth_session_expired",
3824
+ "Session cleared during managed-account resolution. Retry to rebuild against the current session."
3825
+ );
3826
+ }
3827
+ const acc = createManagedAccount(this, canonical, {
3828
+ explicitWallet: true
3829
+ });
3830
+ this.managedAccountByAddress.set(canonical.toLowerCase(), acc);
3831
+ return acc;
3832
+ };
3707
3833
  // Per-caller signal gate: each caller can reject on their own abort
3708
3834
  // without cancelling the shared underlying promise.
3709
3835
  raceWithSignal = (p, signal) => {
@@ -3734,6 +3860,7 @@ var ZeroClient = class _ZeroClient {
3734
3860
  this.managedAccountAC?.abort();
3735
3861
  this.managedAccountInFlight = null;
3736
3862
  this.managedAccountAC = null;
3863
+ this.managedAccountByAddress.clear();
3737
3864
  this.managedAccountGen++;
3738
3865
  };
3739
3866
  /** @internal — Read cached managed account without triggering resolution. */
@@ -3787,5 +3914,5 @@ var ZeroClient = class _ZeroClient {
3787
3914
  };
3788
3915
 
3789
3916
  export { Auth, AuthAgent, AuthDevice, BUG_REPORT_CATEGORIES, BugReports, Capabilities, DEFAULT_BASE_URL, DEFAULT_MAX_RETRIES, DEFAULT_TIMEOUT_MS, FETCH_SKIP_REASONS, FETCH_WARNINGS, Payments, Runs, SDK_VERSION, TEMPO_CHAIN_ID2 as TEMPO_CHAIN_ID, TEMPO_TESTNET_CHAIN_ID, USDC_BASE, USDC_DECIMALS, USDC_TEMPO, Wallet, ZeroAgentAuthError, ZeroApiError, ZeroAuthError, ZeroClient, ZeroConfigurationError, ZeroError, ZeroPaymentError, ZeroSessionCloseFailedError, ZeroTimeoutError, ZeroValidationError, ZeroWalletError, asSchemaNode, coerceTempoChainId, createManagedAccount, extractInputEnvelope, isShortToken, normalizeTransportEnvelopeRequest, paymentHasAnchor, tempoChainLabelFromId, unwrapTransportEnvelope };
3790
- //# sourceMappingURL=chunk-T77VVLOM.js.map
3791
- //# sourceMappingURL=chunk-T77VVLOM.js.map
3917
+ //# sourceMappingURL=chunk-CYB4Y3ID.js.map
3918
+ //# sourceMappingURL=chunk-CYB4Y3ID.js.map