@voidly/session 1.0.0 → 1.1.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/README.md +196 -19
- package/dist/index.d.ts +190 -3
- package/dist/index.mjs +1 -1
- package/dist/proofs.d.ts +67 -0
- package/dist/proofs.mjs +379 -0
- package/dist/proofsCli.mjs +417 -0
- package/package.json +28 -4
package/README.md
CHANGED
|
@@ -1,10 +1,16 @@
|
|
|
1
1
|
# @voidly/session
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
**Hire another agent and pay it for the work.** A hirer commissions sealed work
|
|
4
|
+
from a provider it has verified, pays on-chain with a pre-signed EIP-3009 USDC
|
|
5
|
+
authorization bound to that one hire, and reads back the sealed result.
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
**This SDK does not custody funds.** Payment use requires caller-supplied signing
|
|
8
|
+
functions. The default flow has the payee submit the authorization; explicit
|
|
9
|
+
opt-in submission helpers can instead broadcast a caller-authorized transaction
|
|
10
|
+
or ask a facilitator to submit it. The Proofs commands below do none of these:
|
|
11
|
+
they do not invoke payment, wallet or key-generation functions.
|
|
12
|
+
|
|
13
|
+
Both halves ship. The hirer builds and signs its own envelopes — the brief is
|
|
8
14
|
sealed to the provider's key before it leaves the machine, so nothing else is
|
|
9
15
|
possible — and the provider half is the validators and builders a daemon needs.
|
|
10
16
|
Which hires a provider accepts, and on what terms, is a daemon's own business and
|
|
@@ -14,25 +20,191 @@ is not in this package.
|
|
|
14
20
|
|
|
15
21
|
## Install
|
|
16
22
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
23
|
+
```bash
|
|
24
|
+
npm install --ignore-scripts --save-exact @voidly/session@1.1.0
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
The package name is public. Check the exact version's registry metadata and its
|
|
28
|
+
linked public source before installation; a source checkout does not prove that
|
|
29
|
+
version has been published. If 1.1.0 is not released yet, use a locally reviewed
|
|
30
|
+
tarball for development rather than substituting another version.
|
|
31
|
+
|
|
32
|
+
ESM only. Node ≥ 18 or any runtime with WebCrypto, `fetch` and `TextEncoder`.
|
|
33
|
+
Two exact runtime dependencies: `tweetnacl@1.0.3` and `tweetnacl-util@0.15.1`.
|
|
34
|
+
The Proofs CLI requires Node ≥ 20.3. No install or postinstall hooks run. The
|
|
35
|
+
`--ignore-scripts` option suppresses dependency lifecycle hooks, not code you
|
|
36
|
+
explicitly execute after installation.
|
|
37
|
+
|
|
38
|
+
> **Building from a checkout instead?** Pack it yourself:
|
|
24
39
|
>
|
|
25
40
|
> ```bash
|
|
26
|
-
> npm run build && npm pack # → voidly-session-1.
|
|
27
|
-
> npm install /path/to/voidly-session-1.
|
|
41
|
+
> npm run build && npm pack # → voidly-session-1.1.0.tgz
|
|
42
|
+
> npm install --ignore-scripts --save-exact /path/to/voidly-session-1.1.0.tgz
|
|
28
43
|
> ```
|
|
29
44
|
>
|
|
30
|
-
>
|
|
31
|
-
>
|
|
32
|
-
>
|
|
45
|
+
> `npm run gate` inspects the actual packed bytes. A local build is not registry
|
|
46
|
+
> release evidence: verify the published artifact's integrity and source/build
|
|
47
|
+
> provenance separately. Provenance establishes origin, not harmlessness.
|
|
33
48
|
|
|
34
|
-
|
|
35
|
-
|
|
49
|
+
---
|
|
50
|
+
|
|
51
|
+
## Start without a wallet: exercise the installed SDK
|
|
52
|
+
|
|
53
|
+
The website flow is released separately from this package. Follow the current
|
|
54
|
+
page's availability state; installing the SDK alone does not enable saving.
|
|
55
|
+
|
|
56
|
+
Review the installed source and respect your execution environment's permissions.
|
|
57
|
+
You do not need a Proofs token or any other credential for these commands. Do not
|
|
58
|
+
disable an agent's safeguards if it refuses to install or run software.
|
|
59
|
+
|
|
60
|
+
First, verify a signed public fixture with the installed SDK:
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
node node_modules/@voidly/session/dist/proofsCli.mjs self-test
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
This offline check verifies a signature, rejects the wrong identity pin, rejects
|
|
67
|
+
a modified manifest, and checks canonical hashing. It makes no network requests.
|
|
68
|
+
`ok: true` means the fixture checks passed, not that a live provider is healthy or
|
|
69
|
+
a proof has been saved. It is useful before integrating a provider into an agent.
|
|
70
|
+
|
|
71
|
+
For a fresh public check, open [Voidpay Proofs](https://voidly.ai/pay/proofs),
|
|
72
|
+
finish setup, then start the public exercise in the browser. The short deadline
|
|
73
|
+
begins at that point, not during installation. Supply the browser's public JSON
|
|
74
|
+
to the installed command's standard input:
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
node node_modules/@voidly/session/dist/proofsCli.mjs public-check < public-exercise.json
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
The command makes two public HTTPS GET requests, only to the fixed provider index
|
|
81
|
+
and manifest endpoints. It does not accept alternate URLs, follow redirects,
|
|
82
|
+
read environment variables, read or write files, post results, or access a
|
|
83
|
+
wallet. Network responses and input have byte and time limits. The shell opens
|
|
84
|
+
the explicit input file in the example; the command itself reads standard input.
|
|
85
|
+
|
|
86
|
+
Return the resulting JSON to the originating Proofs page, preview it, and choose
|
|
87
|
+
**Save proof**. Saving requires the browser owner's authorization and independent
|
|
88
|
+
server checks. Nothing is saved or published merely by running the command.
|
|
89
|
+
The server does not treat public result data as proof that someone installed this
|
|
90
|
+
package, is an AI agent, or is a unique person.
|
|
91
|
+
|
|
92
|
+
After a successful save, use its event identifier to render the same artwork
|
|
93
|
+
locally for display or an explicit save in your chat environment:
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
node node_modules/@voidly/session/dist/proofsCli.mjs artwork YOUR_SAVED_EVENT_ID
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
The command accepts exactly 32 lowercase hexadecimal characters and prints SVG
|
|
100
|
+
to standard output. It does not contact a server or verify that the identifier
|
|
101
|
+
belongs to a saved proof. Artwork is decorative; the signed receipt is separate.
|
|
102
|
+
The event identifier is not embedded in the SVG. Public sharing remains a choice
|
|
103
|
+
on the website. A hosted workspace's installation may be temporary; retain the
|
|
104
|
+
starter project only if you choose to do so.
|
|
105
|
+
|
|
106
|
+
Applications can use the same functions from `@voidly/session/proofs`:
|
|
107
|
+
|
|
108
|
+
```ts
|
|
109
|
+
import { runSessionsSelfTest, runPublicExercise } from "@voidly/session/proofs";
|
|
110
|
+
|
|
111
|
+
export async function checkPublicData(publicExerciseJson: string) {
|
|
112
|
+
const selfTest = await runSessionsSelfTest();
|
|
113
|
+
if (!selfTest.ok) throw new Error("SDK self-test failed");
|
|
114
|
+
// Bounded, non-secret JSON from the originating page.
|
|
115
|
+
return runPublicExercise(publicExerciseJson);
|
|
116
|
+
}
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
---
|
|
120
|
+
|
|
121
|
+
## Quickstart — hire, pay, read back
|
|
122
|
+
|
|
123
|
+
Five calls. This is the whole default path; everything after this section is
|
|
124
|
+
the *why*, and the failure modes you are agreeing to when you skip it.
|
|
125
|
+
|
|
126
|
+
```ts
|
|
127
|
+
import {
|
|
128
|
+
fetchVerifiedProvider,
|
|
129
|
+
buildHire,
|
|
130
|
+
buildReceivePaymentAuthorization,
|
|
131
|
+
submitHire,
|
|
132
|
+
recoverResult,
|
|
133
|
+
x402SessionAccountCaip10,
|
|
134
|
+
} from "@voidly/session";
|
|
135
|
+
|
|
136
|
+
// 1. VERIFY. `expectedProviderDid` is a pin and it is required — there is no
|
|
137
|
+
// unpinned arm. The brief gets sealed to whatever key this returns.
|
|
138
|
+
const found = await fetchVerifiedProvider({
|
|
139
|
+
manifestUrl, expectedProviderDid, fetchImpl: fetch,
|
|
140
|
+
});
|
|
141
|
+
if (!found.ok) throw new Error(found.reason);
|
|
142
|
+
|
|
143
|
+
// 2. HIRE. Every money field is COPIED off the signed manifest. A price you
|
|
144
|
+
// type yourself is refused by name — see "the price is not yours to type".
|
|
145
|
+
const SERVICE_REF = "voidly.observatory.query/v1";
|
|
146
|
+
const offering = found.provider.manifest.services.find((s) => s.ref === SERVICE_REF);
|
|
147
|
+
if (!offering) throw new Error(`provider does not offer ${SERVICE_REF}`);
|
|
148
|
+
|
|
149
|
+
const hire = await buildHire({
|
|
150
|
+
hirer: { did, signingPublicKeyBase64, sign }, // `sign` is Ed25519, detached
|
|
151
|
+
provider: found.provider,
|
|
152
|
+
service: { ref: SERVICE_REF },
|
|
153
|
+
task: { brief: "…" },
|
|
154
|
+
price: {
|
|
155
|
+
chain: offering.price.chain,
|
|
156
|
+
asset: offering.price.asset,
|
|
157
|
+
// the ONE field that is yours: the account the money leaves
|
|
158
|
+
payerAccount: x402SessionAccountCaip10(offering.price.chain, payer)!,
|
|
159
|
+
payeeAccount: offering.price.payee_account,
|
|
160
|
+
minAmount: offering.price.min_amount,
|
|
161
|
+
maxAmount: offering.price.max_amount,
|
|
162
|
+
},
|
|
163
|
+
ttl: { offerMs: 30 * 60_000, grantMs: 10 * 60_000 },
|
|
164
|
+
nowMs: Date.now(),
|
|
165
|
+
});
|
|
166
|
+
if (!hire.ok) throw new Error(hire.reason);
|
|
167
|
+
|
|
168
|
+
// 3. SIGN THE PAYMENT. The RECEIVE variant: only the payee named in it can
|
|
169
|
+
// spend it. Every money-steering field is derived from the grant.
|
|
170
|
+
const paid = await buildReceivePaymentAuthorization({
|
|
171
|
+
grant: hire.wire.grant,
|
|
172
|
+
grantHash: hire.keep.grant_hash,
|
|
173
|
+
nowMs: Date.now(),
|
|
174
|
+
sign: signReceive, // your wallet's EIP-712 signer
|
|
175
|
+
});
|
|
176
|
+
if (!paid.ok) throw new Error(paid.reason);
|
|
177
|
+
|
|
178
|
+
// 4. SUBMIT. Returns "accepted" only after the countersignature verifies.
|
|
179
|
+
const out = await submitHire({
|
|
180
|
+
url: found.provider.manifest.accept_url,
|
|
181
|
+
wire: hire.wire,
|
|
182
|
+
grantHash: hire.keep.grant_hash,
|
|
183
|
+
authorization: paid.authorization,
|
|
184
|
+
sign, nowMs: Date.now(), fetchImpl: fetch,
|
|
185
|
+
});
|
|
186
|
+
if (out.kind !== "accepted") throw new Error(out.kind);
|
|
187
|
+
|
|
188
|
+
// 5. NOTHING. The provider spends the authorization and writes its own
|
|
189
|
+
// settlement pointer. You do not pay gas, and you do not send a hint.
|
|
190
|
+
|
|
191
|
+
// 6. READ IT BACK. Poll while `no_result` — that is the normal answer until
|
|
192
|
+
// the provider has delivered.
|
|
193
|
+
const read = await recoverResult({
|
|
194
|
+
endpoint: { baseUrl: found.provider.manifest.worker_base_url },
|
|
195
|
+
wire: hire.wire,
|
|
196
|
+
grantHash: hire.keep.grant_hash,
|
|
197
|
+
sessionKey: hire.keep.sessionKey,
|
|
198
|
+
sign, nowMs: Date.now(),
|
|
199
|
+
});
|
|
200
|
+
if (read.kind === "opened") console.log(read.result);
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
**Before you ship that:** the price fields are compared with `===` and no
|
|
204
|
+
normalisation ([why](#the-price-is-not-yours-to-type)), the two payment
|
|
205
|
+
variants share one nonce and are alternatives rather than steps
|
|
206
|
+
([the fork](#the-fork-who-settles-the-payment)), and `ok: true` is a narrower
|
|
207
|
+
claim than it looks ([what it does not mean](#what-oktrue-does-not-mean)).
|
|
36
208
|
|
|
37
209
|
---
|
|
38
210
|
|
|
@@ -97,7 +269,12 @@ the opt-out path only; here, retrying with a fresh clock never succeeds.
|
|
|
97
269
|
|
|
98
270
|
---
|
|
99
271
|
|
|
100
|
-
##
|
|
272
|
+
## The same hire, annotated
|
|
273
|
+
|
|
274
|
+
The Quickstart above with every refusal reason spelled out at the line that
|
|
275
|
+
raises it. Same calls, same order — read this one before you go to production,
|
|
276
|
+
and read it in full if a call came back `ok: false` and you want the name of
|
|
277
|
+
what you tripped.
|
|
101
278
|
|
|
102
279
|
```ts
|
|
103
280
|
import {
|
package/dist/index.d.ts
CHANGED
|
@@ -19,6 +19,7 @@ export declare function acceptHire(input: {
|
|
|
19
19
|
reason: string;
|
|
20
20
|
}>;
|
|
21
21
|
type AccountSpellingRefuseDetail = "grant_payer_account_not_canonical" | "grant_payee_account_not_canonical";
|
|
22
|
+
export declare const AGENT_IDENTITY_PATH_PREFIX = "/v1/agent/identity/";
|
|
22
23
|
export type AssembleAuthorizationRefusal = HireRefuseDetail | SignRefusal | "grant_hash_mismatch" | "authorization_asset_not_frozen_usdc" | "valid_after_not_safe_integer" | "authorization_entry_point_mismatch";
|
|
23
24
|
export declare function assembleSignedReceiveAuthorization(input: AssembleSignedTransferAuthorizationInput): Promise<AssembleSignedReceiveAuthorizationResult>;
|
|
24
25
|
export type AssembleSignedReceiveAuthorizationResult = {
|
|
@@ -230,7 +231,36 @@ export declare function canonicalBytes(value: unknown): Uint8Array;
|
|
|
230
231
|
export declare function canonicalize(value: unknown): string;
|
|
231
232
|
declare const CAPSULE_ALG = "x25519-xsalsa20-poly1305+xsalsa20-poly1305";
|
|
232
233
|
export declare const CAPSULE_NONCE_LENGTH = 24;
|
|
234
|
+
export declare function checkPartiesRegistered(input: CheckPartiesRegisteredInput): Promise<CheckPartiesRegisteredResult>;
|
|
235
|
+
export interface CheckPartiesRegisteredInput {
|
|
236
|
+
readonly registryBaseUrl: string;
|
|
237
|
+
readonly hirerDid: string;
|
|
238
|
+
readonly providerDid: string;
|
|
239
|
+
readonly hirerSigningPublicKeyBase64?: string;
|
|
240
|
+
readonly fetchImpl: FetchLike;
|
|
241
|
+
readonly signal?: AbortSignal;
|
|
242
|
+
}
|
|
243
|
+
export type CheckPartiesRegisteredResult = {
|
|
244
|
+
readonly ok: true;
|
|
245
|
+
} | {
|
|
246
|
+
readonly ok: false;
|
|
247
|
+
readonly reason: PartiesRegisteredRefusal;
|
|
248
|
+
readonly detail: string;
|
|
249
|
+
};
|
|
233
250
|
export declare function checkSingleAuthorizationRelay(request: TransactionRequest, context?: SingleAuthorizationRelayContext): SingleAuthorizationCheck;
|
|
251
|
+
export declare function classifySessionStatus(word: string): SessionProgress;
|
|
252
|
+
export declare function closeOutSessionKeep(input: {
|
|
253
|
+
readonly fs: SessionKeepFs;
|
|
254
|
+
readonly dir: string;
|
|
255
|
+
readonly grantHash: string;
|
|
256
|
+
readonly sessionKey: SessionKey;
|
|
257
|
+
}): {
|
|
258
|
+
readonly ok: true;
|
|
259
|
+
readonly erased: boolean;
|
|
260
|
+
} | {
|
|
261
|
+
readonly ok: false;
|
|
262
|
+
readonly reason: SessionKeepRefusal;
|
|
263
|
+
};
|
|
234
264
|
export declare function compareDecimalStrings(a: string, b: string): number | null;
|
|
235
265
|
type CostRefusal = "estimate_unavailable" | "gas_price_unavailable" | "balance_unavailable" | "relayer_cannot_pay_gas";
|
|
236
266
|
export declare function createFacilitatorSubmitter(input: FacilitatorSubmitterInput): PaymentSubmitter;
|
|
@@ -244,11 +274,47 @@ export declare function decideFromSupported(args: {
|
|
|
244
274
|
readonly httpStatus: number | null;
|
|
245
275
|
}): FacilitatorPreflightResult;
|
|
246
276
|
export declare function decodeRevertReason(data: unknown): string | null;
|
|
277
|
+
export declare function defaultSessionKeepDir(homeDir: string): string;
|
|
247
278
|
export declare function deriveDidFromSigningKey(signingPublicKey: Uint8Array): string;
|
|
248
279
|
export declare function destroySessionKey(key: SessionKey): void;
|
|
249
280
|
export type DiscoveryTransportReason = "manifest_unreachable" | "manifest_not_json";
|
|
281
|
+
export declare function driveSettlementHint(input: DriveSettlementHintInput): Promise<DriveSettlementHintResult>;
|
|
282
|
+
export interface DriveSettlementHintInput {
|
|
283
|
+
readonly hintUrl: string;
|
|
284
|
+
readonly statusBaseUrl: string;
|
|
285
|
+
readonly grant: TaskGrantEnvelope;
|
|
286
|
+
readonly grantHash: string;
|
|
287
|
+
readonly evidence: unknown;
|
|
288
|
+
readonly sign: Signer;
|
|
289
|
+
readonly now: () => number;
|
|
290
|
+
readonly sleep: SleepLike;
|
|
291
|
+
readonly fetchImpl: FetchLike;
|
|
292
|
+
readonly maxAttempts?: number;
|
|
293
|
+
readonly pollIntervalMs?: number;
|
|
294
|
+
readonly deadlineMs?: number;
|
|
295
|
+
readonly signal?: AbortSignal;
|
|
296
|
+
}
|
|
297
|
+
export interface DriveSettlementHintResult {
|
|
298
|
+
readonly ok: boolean;
|
|
299
|
+
readonly outcome: DriveSettlementOutcome;
|
|
300
|
+
readonly attempts: readonly SettlementHintAttempt[];
|
|
301
|
+
readonly lastStatus: string | null;
|
|
302
|
+
readonly detail: string;
|
|
303
|
+
}
|
|
304
|
+
export type DriveSettlementOutcome = "settled" | "provider_relaying" | "session_terminal" | "hint_refused" | "unbuildable" | "status_unrecognized" | "budget_exhausted";
|
|
250
305
|
export declare function encodeSessionProviderProof(envelope: SessionProviderProofEnvelope, signatureBase64: string): string;
|
|
251
306
|
export declare function envelopeHash(env: object): Promise<string>;
|
|
307
|
+
export declare function eraseSessionKeep(input: {
|
|
308
|
+
readonly fs: SessionKeepFs;
|
|
309
|
+
readonly dir: string;
|
|
310
|
+
readonly grantHash: string;
|
|
311
|
+
}): {
|
|
312
|
+
readonly ok: true;
|
|
313
|
+
readonly erased: boolean;
|
|
314
|
+
} | {
|
|
315
|
+
readonly ok: false;
|
|
316
|
+
readonly reason: SessionKeepRefusal;
|
|
317
|
+
};
|
|
252
318
|
export declare function estimateRelayCost(input: {
|
|
253
319
|
readonly rpc: ReadOnlyEvmRpc;
|
|
254
320
|
readonly request: TransactionRequest;
|
|
@@ -350,6 +416,23 @@ export declare const KNOWN_ASSET_TRANSFER_METHODS: readonly [
|
|
|
350
416
|
"permit2",
|
|
351
417
|
"erc7710"
|
|
352
418
|
];
|
|
419
|
+
export declare function listSessionKeeps(input: {
|
|
420
|
+
readonly fs: SessionKeepFs;
|
|
421
|
+
readonly dir: string;
|
|
422
|
+
}): string[];
|
|
423
|
+
export declare function loadSessionKeep(input: {
|
|
424
|
+
readonly fs: SessionKeepFs;
|
|
425
|
+
readonly dir: string;
|
|
426
|
+
readonly grantHash: string;
|
|
427
|
+
}): Promise<LoadSessionKeepOutcome>;
|
|
428
|
+
export type LoadSessionKeepOutcome = {
|
|
429
|
+
readonly ok: true;
|
|
430
|
+
readonly keep: SessionKeepRecord;
|
|
431
|
+
readonly path: string;
|
|
432
|
+
} | {
|
|
433
|
+
readonly ok: false;
|
|
434
|
+
readonly reason: SessionKeepRefusal;
|
|
435
|
+
};
|
|
353
436
|
export type ManifestRejectReason = "manifest_not_object" | "manifest_schema_mismatch" | "manifest_unexpected_field" | "manifest_field_malformed" | "manifest_signature_missing" | "manifest_signature_malformed" | "manifest_signature_invalid" | "manifest_did_not_derived" | "manifest_did_not_pinned";
|
|
354
437
|
export interface MatchedKind {
|
|
355
438
|
readonly x402Version: number;
|
|
@@ -397,6 +480,7 @@ export type OpenDeliveredResultOutcome = {
|
|
|
397
480
|
reason: OpenDeliveredResultRefusal;
|
|
398
481
|
};
|
|
399
482
|
export type OpenDeliveredResultRefusal = "grant_hash_mismatch" | SessionResultRejectReason | "delivery_grant_mismatch";
|
|
483
|
+
export type PartiesRegisteredRefusal = "hirer_unregistered" | "hirer_key_not_registered" | "provider_unregistered" | "registry_unreadable";
|
|
400
484
|
export interface PayeeRelayBroadcasterInput {
|
|
401
485
|
readonly rpc: ReadOnlyEvmRpc;
|
|
402
486
|
readonly relayerAddress: string;
|
|
@@ -449,6 +533,22 @@ export interface PaymentSubmitter {
|
|
|
449
533
|
readonly kind: "facilitator" | "self";
|
|
450
534
|
submit(signed: SignedTransferAuthorization): Promise<SubmitResult>;
|
|
451
535
|
}
|
|
536
|
+
export declare function persistSessionKeep(input: {
|
|
537
|
+
readonly fs: SessionKeepFs;
|
|
538
|
+
readonly dir: string;
|
|
539
|
+
readonly grantHash: string;
|
|
540
|
+
readonly endpointBaseUrl: string;
|
|
541
|
+
readonly wire: HireWire;
|
|
542
|
+
readonly sessionKey: SessionKey;
|
|
543
|
+
readonly nowMs: number;
|
|
544
|
+
}): Promise<PersistSessionKeepOutcome>;
|
|
545
|
+
export type PersistSessionKeepOutcome = {
|
|
546
|
+
readonly ok: true;
|
|
547
|
+
readonly path: string;
|
|
548
|
+
} | {
|
|
549
|
+
readonly ok: false;
|
|
550
|
+
readonly reason: SessionKeepRefusal;
|
|
551
|
+
};
|
|
452
552
|
export declare function postDeliver(ep: SessionEndpoint, input: {
|
|
453
553
|
wire: HireWire;
|
|
454
554
|
receipt: TaskDeliveryReceipt;
|
|
@@ -546,6 +646,8 @@ export declare const PROVIDER_MANIFEST_KEYS: readonly [
|
|
|
546
646
|
"accept_url",
|
|
547
647
|
"hire_message_schema",
|
|
548
648
|
"worker_base_url",
|
|
649
|
+
"hint_url",
|
|
650
|
+
"relays",
|
|
549
651
|
"grant_ttl_ms",
|
|
550
652
|
"acceptance_ttl_ms",
|
|
551
653
|
"services",
|
|
@@ -564,6 +666,11 @@ export interface ProviderManifest {
|
|
|
564
666
|
readonly accept_url: string;
|
|
565
667
|
readonly hire_message_schema: typeof SESSION_HIRE_SCHEMA;
|
|
566
668
|
readonly worker_base_url: string;
|
|
669
|
+
readonly hint_url?: string;
|
|
670
|
+
readonly relays?: {
|
|
671
|
+
readonly provider_submits: boolean;
|
|
672
|
+
readonly accepted_entry_points: readonly AuthorizationEntryPoint[];
|
|
673
|
+
};
|
|
567
674
|
readonly grant_ttl_ms: {
|
|
568
675
|
readonly min: number;
|
|
569
676
|
readonly max: number;
|
|
@@ -596,6 +703,15 @@ export type ProviderOpenResult = {
|
|
|
596
703
|
kind: "unopenable";
|
|
597
704
|
};
|
|
598
705
|
export type ProviderTermsRejectReason = "provider_not_verified" | "provider_service_not_offered" | "provider_price_chain_not_offered" | "provider_price_asset_not_offered" | "provider_payee_not_manifested" | "provider_price_below_manifest_floor" | "provider_price_above_manifest_ceiling" | "provider_grant_ttl_below_manifest_floor" | "provider_grant_ttl_above_manifest_ceiling";
|
|
706
|
+
export declare function pruneSessionKeeps(input: {
|
|
707
|
+
readonly fs: SessionKeepFs;
|
|
708
|
+
readonly dir: string;
|
|
709
|
+
readonly nowMs: number;
|
|
710
|
+
readonly recoveryTtlMs: number;
|
|
711
|
+
}): {
|
|
712
|
+
readonly erased: string[];
|
|
713
|
+
readonly kept: string[];
|
|
714
|
+
};
|
|
599
715
|
export declare const READ_ONLY_RPC_METHODS: readonly string[];
|
|
600
716
|
export interface ReadOnlyEvmRpc {
|
|
601
717
|
readonly url: string;
|
|
@@ -606,6 +722,22 @@ export interface ReadOnlyEvmRpcInput {
|
|
|
606
722
|
readonly fetchImpl: FetchLike;
|
|
607
723
|
readonly signal?: AbortSignal;
|
|
608
724
|
}
|
|
725
|
+
export declare function readSessionStatus(input: ReadSessionStatusInput): Promise<ReadSessionStatusResult>;
|
|
726
|
+
export interface ReadSessionStatusInput {
|
|
727
|
+
readonly statusBaseUrl: string;
|
|
728
|
+
readonly grantHash: string;
|
|
729
|
+
readonly fetchImpl: FetchLike;
|
|
730
|
+
readonly signal?: AbortSignal;
|
|
731
|
+
}
|
|
732
|
+
export type ReadSessionStatusRefusal = "status_unknown" | "status_unreadable" | "status_grant_hash_malformed";
|
|
733
|
+
export type ReadSessionStatusResult = {
|
|
734
|
+
readonly ok: true;
|
|
735
|
+
readonly status: string;
|
|
736
|
+
} | {
|
|
737
|
+
readonly ok: false;
|
|
738
|
+
readonly reason: ReadSessionStatusRefusal;
|
|
739
|
+
readonly detail: string;
|
|
740
|
+
};
|
|
609
741
|
export declare const RECEIVE_WITH_AUTHORIZATION_SELECTOR = "0xef55bec6";
|
|
610
742
|
export declare const RECEIVE_WITH_AUTHORIZATION_TYPEHASH = "0xd099cc98ef71107a616c4f0f941f04c322d8e254fe26b3c6668db87aae413de8";
|
|
611
743
|
export interface ReceiveAuthorizationTypedData {
|
|
@@ -850,6 +982,9 @@ export type SendRelayTransaction = (transaction: {
|
|
|
850
982
|
declare const SESSION_HIRE_ACCEPTED_SCHEMA = "voidly-session-hire-accepted/v1";
|
|
851
983
|
declare const SESSION_HIRE_REFUSED_SCHEMA = "voidly-session-hire-refused/v1";
|
|
852
984
|
declare const SESSION_HIRE_SCHEMA = "voidly-session-hire/v1";
|
|
985
|
+
export declare const SESSION_KEEP_DIR_MODE = 448;
|
|
986
|
+
export declare const SESSION_KEEP_FILE_MODE = 384;
|
|
987
|
+
export declare const SESSION_KEEP_VERSION: 1;
|
|
853
988
|
declare const SESSION_OFFER_SCHEMA = "voidly-session-offer/v1";
|
|
854
989
|
export declare const SESSION_PATHS: Readonly<{
|
|
855
990
|
readonly redeem: "/v1/pay/session/redeem";
|
|
@@ -863,6 +998,7 @@ export declare const SESSION_PROVIDER_PROOF_SCHEMA = "voidly-session-provider-re
|
|
|
863
998
|
export declare const SESSION_RAIL_BLOCK_TIME_MS = 2000;
|
|
864
999
|
export declare const SESSION_RAIL_MIN_CONFIRMATIONS = 12;
|
|
865
1000
|
declare const SESSION_REATTEST_PROOF_SCHEMA = "voidly-session-provider-reattestation/v1";
|
|
1001
|
+
export declare const SESSION_STATUS_PATH_PREFIX = "/session/status/";
|
|
866
1002
|
export declare class SessionCryptoUnavailableError extends Error {
|
|
867
1003
|
readonly code = "session_crypto_unavailable";
|
|
868
1004
|
constructor(message: string);
|
|
@@ -897,6 +1033,30 @@ export type SessionHireRefused = {
|
|
|
897
1033
|
reason: HireRefuseReason;
|
|
898
1034
|
detail: ReceivedHireRefuseDetail;
|
|
899
1035
|
};
|
|
1036
|
+
export interface SessionKeepFs {
|
|
1037
|
+
mkdirSync(path: string, options: {
|
|
1038
|
+
recursive: true;
|
|
1039
|
+
mode: number;
|
|
1040
|
+
}): unknown;
|
|
1041
|
+
chmodSync(path: string, mode: number): void;
|
|
1042
|
+
openSync(path: string, flags: string, mode?: number): number;
|
|
1043
|
+
writeSync(fd: number, data: string): unknown;
|
|
1044
|
+
fsyncSync(fd: number): void;
|
|
1045
|
+
closeSync(fd: number): void;
|
|
1046
|
+
renameSync(from: string, to: string): void;
|
|
1047
|
+
existsSync(path: string): boolean;
|
|
1048
|
+
readFileSync(path: string, encoding: "utf-8"): string;
|
|
1049
|
+
readdirSync(path: string): string[];
|
|
1050
|
+
unlinkSync(path: string): void;
|
|
1051
|
+
}
|
|
1052
|
+
export interface SessionKeepRecord {
|
|
1053
|
+
readonly grantHash: string;
|
|
1054
|
+
readonly endpointBaseUrl: string;
|
|
1055
|
+
readonly wire: HireWire;
|
|
1056
|
+
readonly sessionKey: SessionKey;
|
|
1057
|
+
readonly createdAtMs: number;
|
|
1058
|
+
}
|
|
1059
|
+
export type SessionKeepRefusal = "session_key_unavailable" | "session_key_wrong_length" | "grant_hash_unusable" | "grant_hash_mismatch" | "endpoint_unusable" | "wire_unusable" | "serialization_would_not_restore" | "not_found" | "unreadable" | "version_unsupported" | "malformed" | "io_failed";
|
|
900
1060
|
export type SessionKey = SessionKeyHandle;
|
|
901
1061
|
declare class SessionKeyHandle {
|
|
902
1062
|
#private;
|
|
@@ -925,6 +1085,7 @@ interface SessionParty {
|
|
|
925
1085
|
readonly did: string;
|
|
926
1086
|
readonly signingPublicKey: Uint8Array;
|
|
927
1087
|
}
|
|
1088
|
+
export type SessionProgress = "unpaid" | "awaiting_settlement" | "opened" | "provider_relaying" | "terminal" | "unrecognized";
|
|
928
1089
|
export declare function sessionProviderProofEnvelope(input: SessionProviderProofFields): SessionProviderProofEnvelope;
|
|
929
1090
|
export interface SessionProviderProofEnvelope {
|
|
930
1091
|
schema: SessionProviderProofSchema;
|
|
@@ -958,8 +1119,17 @@ export declare class SessionUsageError extends Error {
|
|
|
958
1119
|
constructor(message: string);
|
|
959
1120
|
}
|
|
960
1121
|
export declare const SETTLEMENT_BINDING_DOMAIN = "voidly-session-settlement-binding/v1|";
|
|
1122
|
+
export declare const SETTLEMENT_EXPIRY_MARGIN_MS: number;
|
|
961
1123
|
declare const SETTLEMENT_HINT_SCHEMA: "voidly.session.settlement-hint/v1";
|
|
1124
|
+
export declare const SETTLEMENT_MAX_HINT_ATTEMPTS = 8;
|
|
1125
|
+
export declare const SETTLEMENT_POLL_INTERVAL_MS: number;
|
|
962
1126
|
export declare function settlementBindingReference(grantHash: string): Promise<string>;
|
|
1127
|
+
export interface SettlementHintAttempt {
|
|
1128
|
+
readonly attempt: number;
|
|
1129
|
+
readonly atMs: number;
|
|
1130
|
+
readonly result: SubmitSettlementHintResult;
|
|
1131
|
+
readonly statusWord: string | null;
|
|
1132
|
+
}
|
|
963
1133
|
export interface SettlementHintEnvelope {
|
|
964
1134
|
readonly schema: typeof SETTLEMENT_HINT_SCHEMA;
|
|
965
1135
|
readonly grant_hash: string;
|
|
@@ -967,6 +1137,13 @@ export interface SettlementHintEnvelope {
|
|
|
967
1137
|
readonly evidence_hash: string;
|
|
968
1138
|
readonly issued_at: string;
|
|
969
1139
|
}
|
|
1140
|
+
type SettlementHintTarget = {
|
|
1141
|
+
readonly provider: VerifiedProvider;
|
|
1142
|
+
readonly url?: string;
|
|
1143
|
+
} | {
|
|
1144
|
+
readonly provider?: undefined;
|
|
1145
|
+
readonly url: string;
|
|
1146
|
+
};
|
|
970
1147
|
export type SettlementLookupResult = {
|
|
971
1148
|
readonly kind: "found";
|
|
972
1149
|
readonly transactionHash: string;
|
|
@@ -1091,6 +1268,15 @@ export type SingleAuthorizationCheck = {
|
|
|
1091
1268
|
export interface SingleAuthorizationRelayContext {
|
|
1092
1269
|
readonly relayerAddress?: string;
|
|
1093
1270
|
}
|
|
1271
|
+
export type SleepLike = (ms: number) => Promise<void>;
|
|
1272
|
+
export interface StoredSessionKeep {
|
|
1273
|
+
readonly v: typeof SESSION_KEEP_VERSION;
|
|
1274
|
+
readonly grant_hash: string;
|
|
1275
|
+
readonly endpoint_base_url: string;
|
|
1276
|
+
readonly wire: HireWire;
|
|
1277
|
+
readonly session_key_base64: string;
|
|
1278
|
+
readonly created_at_ms: number;
|
|
1279
|
+
}
|
|
1094
1280
|
export declare function submitHire(input: {
|
|
1095
1281
|
readonly url: string;
|
|
1096
1282
|
readonly wire: HireWire;
|
|
@@ -1129,7 +1315,8 @@ export type SubmitResult = {
|
|
|
1129
1315
|
detail: string;
|
|
1130
1316
|
};
|
|
1131
1317
|
export declare function submitSettlementHint(input: {
|
|
1132
|
-
readonly
|
|
1318
|
+
readonly provider?: VerifiedProvider;
|
|
1319
|
+
readonly url?: string;
|
|
1133
1320
|
readonly grant: TaskGrantEnvelope;
|
|
1134
1321
|
readonly grantHash: string;
|
|
1135
1322
|
readonly evidence: unknown;
|
|
@@ -1137,8 +1324,8 @@ export declare function submitSettlementHint(input: {
|
|
|
1137
1324
|
readonly nowMs: number;
|
|
1138
1325
|
readonly fetchImpl: FetchLike;
|
|
1139
1326
|
readonly signal?: AbortSignal;
|
|
1140
|
-
}): Promise<SubmitSettlementHintResult>;
|
|
1141
|
-
export type SubmitSettlementHintRefusal = "grant_hash_mismatch" | "provider_did_unusable" | "evidence_unusable" | "signature_failed";
|
|
1327
|
+
} & SettlementHintTarget): Promise<SubmitSettlementHintResult>;
|
|
1328
|
+
export type SubmitSettlementHintRefusal = "grant_hash_mismatch" | "hint_url_unpublished" | "hint_url_conflict" | "provider_did_unusable" | "evidence_unusable" | "signature_failed";
|
|
1142
1329
|
export type SubmitSettlementHintResult = {
|
|
1143
1330
|
kind: "acknowledged";
|
|
1144
1331
|
status: number;
|