@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.
- package/CHANGELOG.md +19 -0
- package/README.md +17 -4
- package/dist/{chunk-HKF4TRC6.cjs → chunk-2A2ZZ5XR.cjs} +173 -46
- package/dist/chunk-2A2ZZ5XR.cjs.map +1 -0
- package/dist/{chunk-T77VVLOM.js → chunk-CYB4Y3ID.js} +173 -46
- package/dist/chunk-CYB4Y3ID.js.map +1 -0
- package/dist/{client-DKbrAo9Z.d.cts → client-C23Vw9bv.d.cts} +31 -3
- package/dist/{client-DKbrAo9Z.d.ts → client-C23Vw9bv.d.ts} +31 -3
- package/dist/index.cjs +44 -44
- package/dist/index.d.cts +5 -3
- package/dist/index.d.ts +5 -3
- package/dist/index.js +2 -2
- package/dist/testing.cjs +2 -2
- package/dist/testing.d.cts +1 -1
- package/dist/testing.d.ts +1 -1
- package/dist/testing.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-HKF4TRC6.cjs.map +0 -1
- package/dist/chunk-T77VVLOM.js.map +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,25 @@ All notable changes to `@zeroxyz/sdk` will be documented in this file.
|
|
|
4
4
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html) — with the pre-1.0 caveat that minor versions may include breaking changes.
|
|
6
6
|
|
|
7
|
+
## 0.13.0
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
|
|
11
|
+
- **Pay and sign from a non-primary wallet** — `client.fetch()`, `payments.pay()` / `payMpp()`, and `client.auth.signMessage/signTransaction/signTypedData` accept an optional `walletAddress` (session mode). The SDK resolves the named profile wallet for the payment intent's `from`, the managed signature, and the recorded run's attribution (`runs.create` gained the same optional `walletAddress`), so per-wallet run filters reflect which wallet acted. The wallet must be on the caller's profile. Default behavior (primary wallet) is unchanged. (ZERO-488)
|
|
12
|
+
- **`client.runs.list({ walletAddress })`** — narrow session run reads to specific profile wallets (string or string[]). Default remains all profile wallets; an address not on the profile is a server-side 400, never a silent intersection. (ZERO-488)
|
|
13
|
+
- **Wallet nicknames** — `client.wallet.setNickname({ walletAddress, nickname })` (null clears), optional `nickname` on `client.wallet.import()`, and `UserWalletDto.nickname`. Nicknames are private to the authenticated user. New export `SetNicknameOptions`. (ZERO-488)
|
|
14
|
+
- **`client.wallet.revokeDelegation()` / `client.wallet.reauthorizeDelegation()`** — per-wallet delegation lifecycle (default: the primary wallet). New export `DelegationOptions`. (ZERO-488)
|
|
15
|
+
|
|
16
|
+
## 0.12.0
|
|
17
|
+
|
|
18
|
+
### Added
|
|
19
|
+
|
|
20
|
+
- **`exampleRequest` on capability responses** (`capabilities.get()`) — the bare, ready-to-send request body an agent should copy: `.request` unwrapped from the stored `{request,response}` transcript **and** the HTTP-transport envelope, validated against the current `bodySchema`. `null` when there's no usable example or the stored one is stale (missing a now-required field); the raw `example` is retained for the response sample. Prefer `exampleRequest` over `example` when building a fetch body. (ZERO-393, #757)
|
|
21
|
+
|
|
22
|
+
### Fixed
|
|
23
|
+
|
|
24
|
+
- **MPP session close honors a metered zero receipt** — a no-result metered call now closes the channel at `$0` instead of throwing an orphan `close-failed`. An ambiguous zero close (no explicit metered receipt) still refuses, as before. (#761)
|
|
25
|
+
|
|
7
26
|
## 0.11.0
|
|
8
27
|
|
|
9
28
|
### Added
|
package/README.md
CHANGED
|
@@ -102,7 +102,7 @@ The SDK refreshes the access token automatically after a `401`, and every refres
|
|
|
102
102
|
|
|
103
103
|
Endpoints that don't charge pass straight through: a `200` on the first request returns with `payment: null` and `outcome: "success"`. No payment is attempted.
|
|
104
104
|
|
|
105
|
-
**Building the request — search → get → fetch.** A `search()` result carries the `url` and `method`, so a no-body `GET` capability can go straight to `fetch()`. For anything that takes a request body, call `capabilities.get()` first: its `bodySchema`, `method`, and `headers` are what tell you how to construct the call. Don't guess the body from the search summary.
|
|
105
|
+
**Building the request — search → get → fetch.** A `search()` result carries the `url` and `method`, so a no-body `GET` capability can go straight to `fetch()`. For anything that takes a request body, call `capabilities.get()` first: its `bodySchema`, `method`, and `headers` are what tell you how to construct the call. Don't guess the body from the search summary. When present, **`exampleRequest`** is the single best artifact to copy — the bare, ready-to-send request body from a real successful call, already unwrapped from the stored transcript and validated against the current schema (it's `null` when there's no example or the stored one is stale, so fall back to `bodySchema`). The raw `example` (`{ request, response }`) is retained for the response sample.
|
|
106
106
|
|
|
107
107
|
Each search result also carries a `token` field (format: `z_xxx.N`) — a short server-issued attribution token that encodes the search context and the result's position. Pass it as `capabilityId` to `fetch()` (or as the `id` to `capabilities.get()`) instead of the raw uid/slug; the server uses it to attribute the run back to the originating search for ranking and analytics. Tokens expire when the session rolls, so use them within the same search session.
|
|
108
108
|
|
|
@@ -133,6 +133,7 @@ const result = await client.fetch(url, {
|
|
|
133
133
|
body: JSON.stringify({ city: "tokyo" }),
|
|
134
134
|
maxPay: "0.01", // USDC ceiling; an over-cap challenge aborts before signing
|
|
135
135
|
capabilityId: "cap_abc", // attribute the run to a known capability
|
|
136
|
+
walletAddress: "0x…", // session mode: pay from this profile wallet (default: primary)
|
|
136
137
|
signal: controller.signal,
|
|
137
138
|
});
|
|
138
139
|
|
|
@@ -230,20 +231,32 @@ await client.wallet.list(); // every wallet linked to the session user
|
|
|
230
231
|
await client.wallet.provision(); // create the user's managed wallet (idempotent)
|
|
231
232
|
|
|
232
233
|
// Link an existing self-custody wallet by private key (0x prefix optional).
|
|
233
|
-
// Pass makePrimary to have it pay for the user's calls from now on
|
|
234
|
+
// Pass makePrimary to have it pay for the user's calls from now on, and an
|
|
235
|
+
// optional nickname (owner-private display name, max 64 chars).
|
|
234
236
|
const imported = await client.wallet.import({
|
|
235
237
|
privateKey: "0x…",
|
|
236
238
|
makePrimary: true,
|
|
239
|
+
nickname: "Trading bot",
|
|
237
240
|
});
|
|
238
241
|
|
|
239
242
|
// Switch which linked wallet is primary, or unlink one. remove() rejects the
|
|
240
243
|
// primary wallet and any wallet holding a balance — reassign / drain first.
|
|
241
244
|
await client.wallet.setPrimary({ walletAddress: imported.walletAddress });
|
|
242
245
|
await client.wallet.remove({ walletAddress: "0x…" });
|
|
246
|
+
|
|
247
|
+
// Nickname a wallet (or clear with null). Nicknames are private to the
|
|
248
|
+
// authenticated user — they never appear on reviews or public surfaces.
|
|
249
|
+
await client.wallet.setNickname({ walletAddress: "0x…", nickname: "Cold storage" });
|
|
250
|
+
|
|
251
|
+
// Revoke / re-grant Zero's signing delegation per wallet (default: primary).
|
|
252
|
+
await client.wallet.revokeDelegation({ walletAddress: "0x…" });
|
|
253
|
+
await client.wallet.reauthorizeDelegation({ walletAddress: "0x…" });
|
|
243
254
|
```
|
|
244
255
|
|
|
245
256
|
`wallet.address()` covers the common case (resolve — or provision — the primary managed wallet); reach for the methods above when you need the full wallet objects, explicit provisioning, or multi-wallet management. Imported wallets carry an `importedAt` timestamp on the returned wallet objects.
|
|
246
257
|
|
|
258
|
+
To **pay from a non-primary wallet**, pass `walletAddress` on the call itself — `client.fetch(url, { walletAddress })` (or `payments.pay` / `payMpp`) resolves the named profile wallet for the payment intent's `from`, the managed signature, and the recorded run's attribution, and `client.auth.sign*` accept `{ walletAddress }` too. The wallet must be a delegated Privy-embedded wallet on the session user's profile. Runs can likewise be filtered per wallet: `client.runs.list({ walletAddress: ["0x…"] })` (default remains all profile wallets; an address not on the profile is a 400).
|
|
259
|
+
|
|
247
260
|
## Namespaces
|
|
248
261
|
|
|
249
262
|
Beyond `search()` and `fetch()`, the client groups the rest of the API into resource namespaces:
|
|
@@ -262,8 +275,8 @@ const cap = await client.capabilities.get("cap_abc"); // by uid
|
|
|
262
275
|
const cap2 = await client.capabilities.get("z_Ab12cd.1"); // by search token
|
|
263
276
|
|
|
264
277
|
// Wallet — balance, one-time funding URL, and (session mode) multi-wallet
|
|
265
|
-
// management: list / provision / import / setPrimary / remove
|
|
266
|
-
// "Wallet & funding" above.
|
|
278
|
+
// management: list / provision / import / setPrimary / remove / setNickname /
|
|
279
|
+
// revokeDelegation / reauthorizeDelegation. See "Wallet & funding" above.
|
|
267
280
|
const { amount } = await client.wallet.balance();
|
|
268
281
|
const fundUrl = await client.wallet.fundingUrl({ amount: "10" });
|
|
269
282
|
|
|
@@ -15,36 +15,40 @@ var crypto$1 = require('crypto');
|
|
|
15
15
|
var zod = require('zod');
|
|
16
16
|
|
|
17
17
|
// src/auth/managed-account.ts
|
|
18
|
-
var createManagedAccount = (client, address) =>
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
18
|
+
var createManagedAccount = (client, address, opts = {}) => {
|
|
19
|
+
const signOptions = {
|
|
20
|
+
// expectedAddress pins verification to this adapter's frozen address.
|
|
21
|
+
expectedAddress: address,
|
|
22
|
+
...opts.explicitWallet ? { walletAddress: address } : {}
|
|
23
|
+
};
|
|
24
|
+
return accounts.toAccount({
|
|
25
|
+
address,
|
|
26
|
+
async signMessage({ message }) {
|
|
27
|
+
return await client.auth.signMessage({ message }, signOptions);
|
|
28
|
+
},
|
|
29
|
+
async signTypedData(typedData) {
|
|
30
|
+
const td = typedData;
|
|
31
|
+
return await client.auth.signTypedData(
|
|
32
|
+
{
|
|
33
|
+
domain: td.domain,
|
|
34
|
+
types: td.types,
|
|
35
|
+
primaryType: td.primaryType,
|
|
36
|
+
message: td.message
|
|
37
|
+
},
|
|
38
|
+
signOptions
|
|
39
|
+
);
|
|
40
|
+
},
|
|
41
|
+
async signTransaction(transaction, options) {
|
|
42
|
+
const serialize = options?.serializer ?? viem.serializeTransaction;
|
|
43
|
+
const unsigned = await serialize(transaction);
|
|
44
|
+
const signature = await client.auth.signTransaction(
|
|
45
|
+
{ unsignedTransaction: unsigned },
|
|
46
|
+
signOptions
|
|
47
|
+
);
|
|
48
|
+
return await serialize(transaction, viem.parseSignature(signature));
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
};
|
|
48
52
|
var USDC_BASE = "0x833589fcd6edb6e08f4c7c32d4f71b54bda02913";
|
|
49
53
|
var USDC_TEMPO = "0x20c000000000000000000000b9537d11c60e8b50";
|
|
50
54
|
var TEMPO_CHAIN_ID = 4217;
|
|
@@ -591,6 +595,7 @@ var pickSessionCloseAmount = (receipt, openTimeCumulative) => {
|
|
|
591
595
|
if (receipt.metered === true) return fromReceipt;
|
|
592
596
|
return fromReceipt > openTimeCumulative ? fromReceipt : openTimeCumulative;
|
|
593
597
|
};
|
|
598
|
+
var isMeteredZeroReceipt = (receipt) => receipt?.metered === true && BigInt(receipt.acceptedCumulative) === 0n && BigInt(receipt.spent) === 0n;
|
|
594
599
|
var raceWithSignal = (p, signal, client) => {
|
|
595
600
|
if (!signal) return p;
|
|
596
601
|
if (signal.aborted) {
|
|
@@ -640,12 +645,12 @@ var cancelBody = (response) => {
|
|
|
640
645
|
} catch {
|
|
641
646
|
}
|
|
642
647
|
};
|
|
643
|
-
var resolveAccount = async (client, overrideAccount, signal) => {
|
|
648
|
+
var resolveAccount = async (client, overrideAccount, signal, walletAddress) => {
|
|
644
649
|
if (overrideAccount) return overrideAccount;
|
|
645
650
|
const credentials = client.getCredentials();
|
|
646
651
|
if (credentials.kind === "account") return credentials.account;
|
|
647
652
|
if (credentials.kind === "session") {
|
|
648
|
-
return await client.resolveManagedAccount(signal);
|
|
653
|
+
return await client.resolveManagedAccount(signal, walletAddress);
|
|
649
654
|
}
|
|
650
655
|
throw new ZeroAuthError(
|
|
651
656
|
"auth_no_credentials",
|
|
@@ -691,7 +696,8 @@ var Payments = class {
|
|
|
691
696
|
const account = await resolveAccount(
|
|
692
697
|
this.client,
|
|
693
698
|
input.account,
|
|
694
|
-
input.signal
|
|
699
|
+
input.signal,
|
|
700
|
+
input.walletAddress
|
|
695
701
|
);
|
|
696
702
|
let capturedAmount = null;
|
|
697
703
|
let capturedNetwork;
|
|
@@ -826,7 +832,8 @@ var Payments = class {
|
|
|
826
832
|
const account = await resolveAccount(
|
|
827
833
|
this.client,
|
|
828
834
|
input.account,
|
|
829
|
-
input.signal
|
|
835
|
+
input.signal,
|
|
836
|
+
input.walletAddress
|
|
830
837
|
);
|
|
831
838
|
const configuredFetch = buildConfiguredFetch(this.client, {
|
|
832
839
|
timeoutMs: input.timeoutMs
|
|
@@ -1164,7 +1171,7 @@ var Payments = class {
|
|
|
1164
1171
|
}
|
|
1165
1172
|
const receipt = readSessionReceipt(response);
|
|
1166
1173
|
let closeAmount = pickSessionCloseAmount(receipt, openTimeCumulative);
|
|
1167
|
-
if (closeAmount === 0n && channelEntry.cumulativeAmount > 0n) {
|
|
1174
|
+
if (closeAmount === 0n && channelEntry.cumulativeAmount > 0n && !isMeteredZeroReceipt(receipt)) {
|
|
1168
1175
|
closeAmount = channelEntry.cumulativeAmount;
|
|
1169
1176
|
}
|
|
1170
1177
|
const reconcileAmount = receipt && isUintString(receipt.acceptedCumulative) ? receipt.acceptedCumulative : closeAmount.toString();
|
|
@@ -1181,7 +1188,7 @@ var Payments = class {
|
|
|
1181
1188
|
capturedAmount,
|
|
1182
1189
|
cause
|
|
1183
1190
|
});
|
|
1184
|
-
if (closeAmount === 0n) {
|
|
1191
|
+
if (closeAmount === 0n && !isMeteredZeroReceipt(receipt)) {
|
|
1185
1192
|
throw closeFailed(
|
|
1186
1193
|
`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.`
|
|
1187
1194
|
);
|
|
@@ -1606,7 +1613,8 @@ var recordErrorFetchRun = async (client, opts, result, capabilityIdOverride) =>
|
|
|
1606
1613
|
...fetchOriginForRecord && { fetchOrigin: fetchOriginForRecord },
|
|
1607
1614
|
...result.status !== null && { status: result.status },
|
|
1608
1615
|
latencyMs: result.latencyMs,
|
|
1609
|
-
...opts.requestSchema && { requestSchema: opts.requestSchema }
|
|
1616
|
+
...opts.requestSchema && { requestSchema: opts.requestSchema },
|
|
1617
|
+
...opts.walletAddress && !opts.account && { walletAddress: opts.walletAddress }
|
|
1610
1618
|
});
|
|
1611
1619
|
result.runId = created.runId;
|
|
1612
1620
|
delete result.runTrackingSkipped;
|
|
@@ -1715,6 +1723,7 @@ var clientFetch = async (client, url, opts = {}) => {
|
|
|
1715
1723
|
body: requestBody,
|
|
1716
1724
|
maxPay: opts.maxPay,
|
|
1717
1725
|
account: opts.account,
|
|
1726
|
+
...opts.walletAddress && { walletAddress: opts.walletAddress },
|
|
1718
1727
|
signal: opts.signal,
|
|
1719
1728
|
timeoutMs: opts.timeoutMs,
|
|
1720
1729
|
...opts.displayCostAmount && {
|
|
@@ -1887,6 +1896,10 @@ var clientFetch = async (client, url, opts = {}) => {
|
|
|
1887
1896
|
...opts.capabilityId === void 0 ? { fetchOrigin: "direct_url" } : opts.fetchOrigin && { fetchOrigin: opts.fetchOrigin },
|
|
1888
1897
|
status: response.status,
|
|
1889
1898
|
latencyMs,
|
|
1899
|
+
// Attribute to the selected wallet in session mode. Skipped when a
|
|
1900
|
+
// per-call `account` override records the run — that account's own
|
|
1901
|
+
// EIP-191 identity is the attribution.
|
|
1902
|
+
...opts.walletAddress && !opts.account && { walletAddress: opts.walletAddress },
|
|
1890
1903
|
...opts.requestSchema && { requestSchema: opts.requestSchema },
|
|
1891
1904
|
...derived?.responseSchema && {
|
|
1892
1905
|
responseSchema: derived.responseSchema
|
|
@@ -1952,7 +1965,7 @@ var clientFetch = async (client, url, opts = {}) => {
|
|
|
1952
1965
|
|
|
1953
1966
|
// package.json
|
|
1954
1967
|
var package_default = {
|
|
1955
|
-
version: "0.
|
|
1968
|
+
version: "0.13.0"};
|
|
1956
1969
|
|
|
1957
1970
|
// src/version.ts
|
|
1958
1971
|
var SDK_VERSION = package_default.version;
|
|
@@ -2442,6 +2455,9 @@ var userWalletDtoSchema = zod.z.object({
|
|
|
2442
2455
|
walletAddress: zod.z.string(),
|
|
2443
2456
|
source: zod.z.enum(["self_custody", "privy_embedded"]),
|
|
2444
2457
|
isPrimary: zod.z.boolean(),
|
|
2458
|
+
// Owner-chosen display name; null/absent = unnamed (show the address).
|
|
2459
|
+
// Optional so the SDK tolerates servers that predate nicknames.
|
|
2460
|
+
nickname: zod.z.string().nullable().optional(),
|
|
2445
2461
|
linkedAt: zod.z.union([zod.z.string(), zod.z.date()]).nullable().optional(),
|
|
2446
2462
|
importedAt: zod.z.union([zod.z.string(), zod.z.date()]).nullable().optional(),
|
|
2447
2463
|
delegationGranted: zod.z.boolean(),
|
|
@@ -2659,7 +2675,10 @@ var Auth = class {
|
|
|
2659
2675
|
{
|
|
2660
2676
|
method: "POST",
|
|
2661
2677
|
path: "/v1/users/me/sign-message",
|
|
2662
|
-
body: {
|
|
2678
|
+
body: {
|
|
2679
|
+
message: normalizeMessage(input.message),
|
|
2680
|
+
...opts.walletAddress ? { walletAddress: opts.walletAddress } : {}
|
|
2681
|
+
}
|
|
2663
2682
|
},
|
|
2664
2683
|
signResponseSchema
|
|
2665
2684
|
);
|
|
@@ -2684,7 +2703,10 @@ var Auth = class {
|
|
|
2684
2703
|
{
|
|
2685
2704
|
method: "POST",
|
|
2686
2705
|
path: "/v1/users/me/sign-transaction",
|
|
2687
|
-
body: {
|
|
2706
|
+
body: {
|
|
2707
|
+
unsignedTransaction: input.unsignedTransaction,
|
|
2708
|
+
...opts.walletAddress ? { walletAddress: opts.walletAddress } : {}
|
|
2709
|
+
}
|
|
2688
2710
|
},
|
|
2689
2711
|
signResponseSchema
|
|
2690
2712
|
);
|
|
@@ -2723,7 +2745,10 @@ var Auth = class {
|
|
|
2723
2745
|
{
|
|
2724
2746
|
method: "POST",
|
|
2725
2747
|
path: "/v1/users/me/sign-typed-data",
|
|
2726
|
-
body: {
|
|
2748
|
+
body: {
|
|
2749
|
+
typedData: input,
|
|
2750
|
+
...opts.walletAddress ? { walletAddress: opts.walletAddress } : {}
|
|
2751
|
+
}
|
|
2727
2752
|
},
|
|
2728
2753
|
signResponseSchema
|
|
2729
2754
|
);
|
|
@@ -2842,6 +2867,12 @@ var capabilityResponseSchema = zod.z.object({
|
|
|
2842
2867
|
bodySchema: zod.z.record(zod.z.string(), zod.z.unknown()).nullable(),
|
|
2843
2868
|
responseSchema: zod.z.record(zod.z.string(), zod.z.unknown()).nullable(),
|
|
2844
2869
|
example: zod.z.object({ request: zod.z.unknown(), response: zod.z.unknown() }).nullable(),
|
|
2870
|
+
// The bare, schema-validated request body to send — `.request` unwrapped
|
|
2871
|
+
// from the transcript envelope and checked against the current bodySchema.
|
|
2872
|
+
// Null when there's no usable example or it's stale vs the schema; `example`
|
|
2873
|
+
// is retained for the response sample. Optional for back-compat with older
|
|
2874
|
+
// servers that don't emit it.
|
|
2875
|
+
exampleRequest: zod.z.record(zod.z.string(), zod.z.unknown()).nullable().optional(),
|
|
2845
2876
|
tags: zod.z.array(zod.z.string()).nullable(),
|
|
2846
2877
|
exampleAgentPrompt: zod.z.string().nullable().optional(),
|
|
2847
2878
|
whatItDoes: zod.z.string().nullable().optional(),
|
|
@@ -3094,6 +3125,9 @@ var Runs = class {
|
|
|
3094
3125
|
if (params.unreviewed !== void 0) query.unreviewed = params.unreviewed;
|
|
3095
3126
|
if (params.limit !== void 0) query.limit = params.limit;
|
|
3096
3127
|
if (params.cursor !== void 0) query.cursor = params.cursor;
|
|
3128
|
+
if (params.walletAddress !== void 0) {
|
|
3129
|
+
query.walletAddress = Array.isArray(params.walletAddress) ? params.walletAddress.join(",") : params.walletAddress;
|
|
3130
|
+
}
|
|
3097
3131
|
return request(
|
|
3098
3132
|
this.client,
|
|
3099
3133
|
{
|
|
@@ -3229,6 +3263,50 @@ var Wallet = class {
|
|
|
3229
3263
|
},
|
|
3230
3264
|
userWalletDtoSchema
|
|
3231
3265
|
);
|
|
3266
|
+
// Re-stamp Zero's signing delegation on a profile wallet (default: the
|
|
3267
|
+
// primary). Session-only. Naming a wallet re-authorizes THAT wallet and
|
|
3268
|
+
// never provisions; the server 404s an address not on the profile.
|
|
3269
|
+
reauthorizeDelegation = (opts = {}) => request(
|
|
3270
|
+
this.client,
|
|
3271
|
+
{
|
|
3272
|
+
method: "POST",
|
|
3273
|
+
path: "/v1/users/me/wallets/provision",
|
|
3274
|
+
...opts.walletAddress ? { body: { walletAddress: opts.walletAddress } } : {},
|
|
3275
|
+
signal: opts.signal
|
|
3276
|
+
},
|
|
3277
|
+
userWalletDtoSchema
|
|
3278
|
+
);
|
|
3279
|
+
// Revoke Zero's signing delegation on a profile wallet (default: the
|
|
3280
|
+
// primary). Session-only. Managed signing on that wallet 403s until it is
|
|
3281
|
+
// re-authorized. Note: this stamps the server-side gate — removing Zero's
|
|
3282
|
+
// signer cryptographically is owner-authorized and happens in the user's
|
|
3283
|
+
// Privy session (the web profile page does both).
|
|
3284
|
+
revokeDelegation = (opts = {}) => request(
|
|
3285
|
+
this.client,
|
|
3286
|
+
{
|
|
3287
|
+
method: "DELETE",
|
|
3288
|
+
path: "/v1/users/me/wallets/delegation",
|
|
3289
|
+
...opts.walletAddress ? { query: { walletAddress: opts.walletAddress } } : {},
|
|
3290
|
+
signal: opts.signal
|
|
3291
|
+
},
|
|
3292
|
+
userWalletDtoSchema
|
|
3293
|
+
);
|
|
3294
|
+
// Set, change, or clear (null / empty string) the owner-chosen nickname on
|
|
3295
|
+
// a profile wallet. Session-only. Nicknames are private to the
|
|
3296
|
+
// authenticated user — they never appear on reviews or public surfaces.
|
|
3297
|
+
setNickname = (opts) => request(
|
|
3298
|
+
this.client,
|
|
3299
|
+
{
|
|
3300
|
+
method: "PATCH",
|
|
3301
|
+
path: "/v1/users/me/wallets/nickname",
|
|
3302
|
+
body: {
|
|
3303
|
+
walletAddress: opts.walletAddress,
|
|
3304
|
+
nickname: opts.nickname
|
|
3305
|
+
},
|
|
3306
|
+
signal: opts.signal
|
|
3307
|
+
},
|
|
3308
|
+
userWalletDtoSchema
|
|
3309
|
+
);
|
|
3232
3310
|
// Link an existing self-custody wallet to the session user by private key.
|
|
3233
3311
|
// Session-only. 409s when the wallet is already linked (to this or another
|
|
3234
3312
|
// profile — the error message says which).
|
|
@@ -3239,7 +3317,8 @@ var Wallet = class {
|
|
|
3239
3317
|
path: "/v1/users/me/wallets/import",
|
|
3240
3318
|
body: {
|
|
3241
3319
|
privateKey: opts.privateKey,
|
|
3242
|
-
...opts.makePrimary !== void 0 ? { makePrimary: opts.makePrimary } : {}
|
|
3320
|
+
...opts.makePrimary !== void 0 ? { makePrimary: opts.makePrimary } : {},
|
|
3321
|
+
...opts.nickname !== void 0 ? { nickname: opts.nickname } : {}
|
|
3243
3322
|
},
|
|
3244
3323
|
signal: opts.signal
|
|
3245
3324
|
},
|
|
@@ -3442,6 +3521,9 @@ var ZeroClient = class _ZeroClient {
|
|
|
3442
3521
|
managedAccountInFlight = null;
|
|
3443
3522
|
managedAccountAC = null;
|
|
3444
3523
|
managedAccountGen = 0;
|
|
3524
|
+
// Explicitly-selected (non-default) managed wallets, keyed by lowercased
|
|
3525
|
+
// address. Same lifecycle as managedAccount: cleared on clearManagedAccount.
|
|
3526
|
+
managedAccountByAddress = /* @__PURE__ */ new Map();
|
|
3445
3527
|
// Multi-tenant servers calling `client.fetch(url, { account: tenantAccount })`
|
|
3446
3528
|
// on every request would otherwise construct a new ZeroClient (with
|
|
3447
3529
|
// five namespace instances) per call. Keyed by lowercased account
|
|
@@ -3663,8 +3745,16 @@ var ZeroClient = class _ZeroClient {
|
|
|
3663
3745
|
}
|
|
3664
3746
|
this.withAccountCache.clear();
|
|
3665
3747
|
};
|
|
3666
|
-
/**
|
|
3667
|
-
|
|
3748
|
+
/**
|
|
3749
|
+
* @internal — used by payments.pay() in session mode. Cached, dedupes
|
|
3750
|
+
* concurrent lookups. Pass `walletAddress` to sign as a specific profile
|
|
3751
|
+
* wallet instead of the primary; explicit wallets are cached per address
|
|
3752
|
+
* and their sign requests carry the address so intent and signer agree.
|
|
3753
|
+
*/
|
|
3754
|
+
resolveManagedAccount = (signal, walletAddress) => {
|
|
3755
|
+
if (walletAddress) {
|
|
3756
|
+
return this.resolveManagedAccountByAddress(walletAddress, signal);
|
|
3757
|
+
}
|
|
3668
3758
|
if (this.managedAccount) return Promise.resolve(this.managedAccount);
|
|
3669
3759
|
if (this.managedAccountInFlight) {
|
|
3670
3760
|
return this.raceWithSignal(this.managedAccountInFlight, signal);
|
|
@@ -3706,6 +3796,42 @@ var ZeroClient = class _ZeroClient {
|
|
|
3706
3796
|
});
|
|
3707
3797
|
return this.raceWithSignal(this.managedAccountInFlight, signal);
|
|
3708
3798
|
};
|
|
3799
|
+
// Explicit-wallet variant of resolveManagedAccount. No in-flight dedupe:
|
|
3800
|
+
// this is the rare path (per-wallet pay), the resolution is idempotent, and
|
|
3801
|
+
// the per-address cache absorbs repeat calls.
|
|
3802
|
+
resolveManagedAccountByAddress = async (walletAddress, signal) => {
|
|
3803
|
+
if (this.credentials.kind !== "session") {
|
|
3804
|
+
throw new ZeroAuthError(
|
|
3805
|
+
"auth_no_credentials",
|
|
3806
|
+
"resolveManagedAccount() requires session credentials."
|
|
3807
|
+
);
|
|
3808
|
+
}
|
|
3809
|
+
const canonical = viem.getAddress(walletAddress);
|
|
3810
|
+
const cached = this.managedAccountByAddress.get(canonical.toLowerCase());
|
|
3811
|
+
if (cached) return cached;
|
|
3812
|
+
const startedAtGen = this.managedAccountGen;
|
|
3813
|
+
const wallets = await this.auth.wallets({ signal });
|
|
3814
|
+
const match = wallets.find(
|
|
3815
|
+
(w) => w.walletAddress.toLowerCase() === canonical.toLowerCase()
|
|
3816
|
+
);
|
|
3817
|
+
if (!match || match.source !== "privy_embedded") {
|
|
3818
|
+
throw new ZeroAuthError(
|
|
3819
|
+
"auth_error",
|
|
3820
|
+
`Wallet ${canonical} is not a Privy-embedded wallet on this profile. Managed signing can only use profile wallets (see client.wallet.list()).`
|
|
3821
|
+
);
|
|
3822
|
+
}
|
|
3823
|
+
if (this.managedAccountGen !== startedAtGen) {
|
|
3824
|
+
throw new ZeroAuthError(
|
|
3825
|
+
"auth_session_expired",
|
|
3826
|
+
"Session cleared during managed-account resolution. Retry to rebuild against the current session."
|
|
3827
|
+
);
|
|
3828
|
+
}
|
|
3829
|
+
const acc = createManagedAccount(this, canonical, {
|
|
3830
|
+
explicitWallet: true
|
|
3831
|
+
});
|
|
3832
|
+
this.managedAccountByAddress.set(canonical.toLowerCase(), acc);
|
|
3833
|
+
return acc;
|
|
3834
|
+
};
|
|
3709
3835
|
// Per-caller signal gate: each caller can reject on their own abort
|
|
3710
3836
|
// without cancelling the shared underlying promise.
|
|
3711
3837
|
raceWithSignal = (p, signal) => {
|
|
@@ -3736,6 +3862,7 @@ var ZeroClient = class _ZeroClient {
|
|
|
3736
3862
|
this.managedAccountAC?.abort();
|
|
3737
3863
|
this.managedAccountInFlight = null;
|
|
3738
3864
|
this.managedAccountAC = null;
|
|
3865
|
+
this.managedAccountByAddress.clear();
|
|
3739
3866
|
this.managedAccountGen++;
|
|
3740
3867
|
};
|
|
3741
3868
|
/** @internal — Read cached managed account without triggering resolution. */
|
|
@@ -3828,5 +3955,5 @@ exports.normalizeTransportEnvelopeRequest = normalizeTransportEnvelopeRequest;
|
|
|
3828
3955
|
exports.paymentHasAnchor = paymentHasAnchor;
|
|
3829
3956
|
exports.tempoChainLabelFromId = tempoChainLabelFromId;
|
|
3830
3957
|
exports.unwrapTransportEnvelope = unwrapTransportEnvelope;
|
|
3831
|
-
//# sourceMappingURL=chunk-
|
|
3832
|
-
//# sourceMappingURL=chunk-
|
|
3958
|
+
//# sourceMappingURL=chunk-2A2ZZ5XR.cjs.map
|
|
3959
|
+
//# sourceMappingURL=chunk-2A2ZZ5XR.cjs.map
|