@opendatalabs/vana-sdk 3.8.3 → 3.9.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 (39) hide show
  1. package/README.md +31 -10
  2. package/dist/session-relay/client.cjs +215 -0
  3. package/dist/session-relay/client.cjs.map +1 -0
  4. package/dist/session-relay/client.d.ts +16 -0
  5. package/dist/session-relay/client.js +190 -0
  6. package/dist/session-relay/client.js.map +1 -0
  7. package/dist/session-relay/client.test.d.ts +1 -0
  8. package/dist/session-relay/endpoints.cjs +37 -0
  9. package/dist/session-relay/endpoints.cjs.map +1 -0
  10. package/dist/session-relay/endpoints.d.ts +7 -0
  11. package/dist/session-relay/endpoints.js +11 -0
  12. package/dist/session-relay/endpoints.js.map +1 -0
  13. package/dist/session-relay/errors.cjs +36 -0
  14. package/dist/session-relay/errors.cjs.map +1 -0
  15. package/dist/session-relay/errors.d.ts +13 -0
  16. package/dist/session-relay/errors.js +12 -0
  17. package/dist/session-relay/errors.js.map +1 -0
  18. package/dist/session-relay/index.cjs +46 -0
  19. package/dist/session-relay/index.cjs.map +1 -0
  20. package/dist/session-relay/index.d.ts +5 -0
  21. package/dist/session-relay/index.js +25 -0
  22. package/dist/session-relay/index.js.map +1 -0
  23. package/dist/session-relay/signing.cjs +62 -0
  24. package/dist/session-relay/signing.cjs.map +1 -0
  25. package/dist/session-relay/signing.d.ts +21 -0
  26. package/dist/session-relay/signing.js +39 -0
  27. package/dist/session-relay/signing.js.map +1 -0
  28. package/dist/session-relay/signing.test.d.ts +1 -0
  29. package/dist/session-relay/types.cjs +17 -0
  30. package/dist/session-relay/types.cjs.map +1 -0
  31. package/dist/session-relay/types.d.ts +119 -0
  32. package/dist/session-relay/types.js +1 -0
  33. package/dist/session-relay/types.js.map +1 -0
  34. package/dist/session-relay.cjs +46 -0
  35. package/dist/session-relay.cjs.map +1 -0
  36. package/dist/session-relay.d.ts +27 -0
  37. package/dist/session-relay.js +27 -0
  38. package/dist/session-relay.js.map +1 -0
  39. package/package.json +10 -1
package/README.md CHANGED
@@ -29,6 +29,10 @@ encryption, storage providers, and a shared isomorphic platform layer.
29
29
  - **Storage providers** — `VanaStorage` (default, talks to `storage.vana.org`),
30
30
  `R2Storage`, `StorageManager`, `IpfsStorage`, `PinataStorage`,
31
31
  `GoogleDriveStorage`, `DropboxStorage`, `CallbackStorage`.
32
+ - **Vana service integrations** — `@opendatalabs/vana-sdk/server`,
33
+ `@opendatalabs/vana-sdk/react`, and `@opendatalabs/vana-sdk/session-relay`
34
+ for Vana-operated app handoff flows. These are integration helpers, not
35
+ protocol-core modules.
32
36
  - **Platform adapters** — `NodePlatformAdapter` and `BrowserPlatformAdapter`
33
37
  with a shared `VanaPlatformAdapter` interface, plus detection helpers
34
38
  (`detectPlatform`, `isPlatformSupported`, `createPlatformAdapter`,
@@ -104,12 +108,12 @@ const result = await storage.upload(myBlob, "report.json");
104
108
  console.log(result.url);
105
109
  ```
106
110
 
107
- ## Build a direct Vana app
111
+ ## Build a Vana app
108
112
 
109
113
  Request user-approved data, read it from the user's Personal Server, and pay
110
114
  for the read — without the browser ever seeing your app private key or choosing
111
- scopes. Your **backend** owns the controller (`@opendatalabs/vana-sdk/server`);
112
- your **frontend** drives a two-tab approval flow with a React hook
115
+ scopes. Your **backend** owns the Data Portability controller
116
+ (`@opendatalabs/vana-sdk/server`); your **frontend** drives a two-tab approval flow with a React hook
113
117
  (`@opendatalabs/vana-sdk/react`).
114
118
 
115
119
  > **How it fits together.** Access requests are created through the Vana Account
@@ -136,12 +140,12 @@ export const vana = createDirectDataController({
136
140
  network: process.env.VANA_NETWORK === "moksha" ? "moksha" : "mainnet",
137
141
  appPrivateKey: process.env.VANA_APP_PRIVATE_KEY!,
138
142
  app: {
139
- id: "notes-lens",
140
- name: "Notes Lens",
143
+ id: "spotify-taste",
144
+ name: "Spotify Taste",
141
145
  homepageUrl: process.env.VANA_APP_URL!,
142
146
  },
143
- source: "icloud_notes",
144
- scopes: ["icloud_notes.notes"],
147
+ source: "spotify",
148
+ scopes: ["spotify.savedTracks"],
145
149
  // Settle paid reads through the DPv2 escrow gateway. The controller signs the
146
150
  // GenericPayment with your app key; you supply the gateway client + contract.
147
151
  escrow: {
@@ -172,7 +176,7 @@ const status = await vana.getAccessRequestStatus(requestId);
172
176
  // GET /api/vana/data?requestId=...
173
177
  const result = await vana.readApprovedData({ requestId });
174
178
  // -> {
175
- // scope: "icloud_notes.notes",
179
+ // scope: "spotify.savedTracks",
176
180
  // data: ...,
177
181
  // payment?: { // present only when this read settled a payment
178
182
  // amount, asset, paymentNonce, paidAt,
@@ -194,7 +198,7 @@ amount and asset owed.
194
198
  "use client";
195
199
  import { useDirectVanaConnect } from "@opendatalabs/vana-sdk/react";
196
200
 
197
- export function ConnectNotesButton() {
201
+ export function ConnectSpotifyButton() {
198
202
  const connect = useDirectVanaConnect({
199
203
  createRequest: () =>
200
204
  fetch("/api/vana/request", { method: "POST" }).then((r) => r.json()),
@@ -214,7 +218,7 @@ export function ConnectNotesButton() {
214
218
  onClick={connect.start}
215
219
  type="button"
216
220
  >
217
- {connect.state.type === "idle" ? "Connect Apple Notes" : "Connecting..."}
221
+ {connect.state.type === "idle" ? "Connect Spotify" : "Connecting..."}
218
222
  </button>
219
223
  );
220
224
  }
@@ -225,6 +229,23 @@ until the request is approved, then calls `readResult`. `react` is an optional
225
229
  peer dependency. The underlying `createDirectConnectFlow` store is also exported
226
230
  for non-React frontends.
227
231
 
232
+ ### Test with large sample data
233
+
234
+ When testing with realistic exports, use the public fixture catalog in
235
+ [`vana-com/data-connectors`](https://github.com/vana-com/data-connectors). Keep
236
+ the payload in a file or raw URL and point your app or agent at that location.
237
+ Do not paste large JSON into the terminal.
238
+
239
+ The controller can run against local test data by injecting an
240
+ `accessRequestClient` that returns an approved request and a
241
+ `personalServerFetch` that loads the sample payload, while the rest of your app
242
+ still calls `readApprovedData`.
243
+
244
+ See [`examples/vana-app`](../../examples/vana-app) for a runnable Next.js Vana
245
+ app. It includes the route handlers, return page, and React connect button from
246
+ this flow, defaults to sample-data mode using `vana-com/data-connectors`, and
247
+ can be switched to live protocol mode with environment variables.
248
+
228
249
  ## Networks
229
250
 
230
251
  | Network | Chain ID | RPC URL |
@@ -0,0 +1,215 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+ var client_exports = {};
20
+ __export(client_exports, {
21
+ createSessionRelayBuilderClient: () => createSessionRelayBuilderClient,
22
+ createSessionRelayClient: () => createSessionRelayClient
23
+ });
24
+ module.exports = __toCommonJS(client_exports);
25
+ var import_endpoints = require("./endpoints");
26
+ var import_errors = require("./errors");
27
+ var import_signing = require("./signing");
28
+ const DEFAULT_POLL_INTERVAL_MS = 2e3;
29
+ const DEFAULT_POLL_TIMEOUT_MS = 15 * 6e4;
30
+ function stripTrailingSlash(url) {
31
+ return url.replace(/\/+$/, "");
32
+ }
33
+ function resolveFetch(fetchFn) {
34
+ const resolved = fetchFn ?? globalThis.fetch;
35
+ if (!resolved) {
36
+ throw new import_errors.SessionRelayError(
37
+ "No fetch implementation available. Pass `fetchFn` to the Session Relay client.",
38
+ { relayErrorCode: "SESSION_RELAY_CONFIG_ERROR" }
39
+ );
40
+ }
41
+ return resolved;
42
+ }
43
+ function endpoint(options) {
44
+ return stripTrailingSlash(options.baseUrl ?? (0, import_endpoints.getSessionRelayUrl)(options.env));
45
+ }
46
+ async function parseJson(res) {
47
+ if (res.status === 204) return void 0;
48
+ if (res.text) {
49
+ const text = await res.text();
50
+ if (text.length === 0) return void 0;
51
+ try {
52
+ return JSON.parse(text);
53
+ } catch {
54
+ throw new import_errors.SessionRelayError(
55
+ `Session Relay returned a non-JSON response (HTTP ${res.status})`,
56
+ { status: res.status }
57
+ );
58
+ }
59
+ }
60
+ try {
61
+ return await res.json();
62
+ } catch {
63
+ throw new import_errors.SessionRelayError(
64
+ `Session Relay returned a non-JSON response (HTTP ${res.status})`,
65
+ { status: res.status }
66
+ );
67
+ }
68
+ }
69
+ function relayErrorFromBody(body) {
70
+ if (body === null || typeof body !== "object" || !("error" in body)) {
71
+ return void 0;
72
+ }
73
+ const error = body.error;
74
+ if (error === null || typeof error !== "object") return void 0;
75
+ return error;
76
+ }
77
+ async function relayFetch(fetchFn, url, init) {
78
+ let res;
79
+ try {
80
+ res = await fetchFn(url, init);
81
+ } catch (err) {
82
+ throw new import_errors.SessionRelayError(
83
+ "Network error communicating with Session Relay",
84
+ {
85
+ body: err
86
+ }
87
+ );
88
+ }
89
+ const body = await parseJson(res);
90
+ if (!res.ok) {
91
+ const relayError = relayErrorFromBody(body);
92
+ throw new import_errors.SessionRelayError(
93
+ relayError?.message ?? `Session Relay request failed (HTTP ${res.status})`,
94
+ {
95
+ status: res.status,
96
+ relayCode: relayError?.code,
97
+ relayErrorCode: relayError?.errorCode,
98
+ body
99
+ }
100
+ );
101
+ }
102
+ return body;
103
+ }
104
+ async function pollSession(fetchFn, baseUrl, sessionId) {
105
+ return relayFetch(
106
+ fetchFn,
107
+ `${baseUrl}/v1/session/${encodeURIComponent(sessionId)}/poll`,
108
+ { method: "GET" }
109
+ );
110
+ }
111
+ async function pollUntilComplete(fetchFn, baseUrl, sessionId, opts) {
112
+ const intervalMs = opts?.intervalMs ?? DEFAULT_POLL_INTERVAL_MS;
113
+ const timeoutMs = opts?.timeoutMs ?? DEFAULT_POLL_TIMEOUT_MS;
114
+ const deadline = Date.now() + timeoutMs;
115
+ while (Date.now() < deadline) {
116
+ const result = await pollSession(fetchFn, baseUrl, sessionId);
117
+ if (result.status === "approved" || result.status === "denied" || result.status === "expired") {
118
+ return result;
119
+ }
120
+ await new Promise((resolve) => setTimeout(resolve, intervalMs));
121
+ }
122
+ throw new import_errors.SessionRelayError("Polling timed out", {
123
+ relayErrorCode: "SESSION_RELAY_POLL_TIMEOUT"
124
+ });
125
+ }
126
+ function createSessionRelayClient(options = {}) {
127
+ const fetchFn = resolveFetch(options.fetchFn);
128
+ const baseUrl = endpoint(options);
129
+ return {
130
+ claimSession(request) {
131
+ return relayFetch(
132
+ fetchFn,
133
+ `${baseUrl}/v1/session/claim`,
134
+ {
135
+ method: "POST",
136
+ headers: { "Content-Type": "application/json" },
137
+ body: JSON.stringify(request)
138
+ }
139
+ );
140
+ },
141
+ async approveSession(sessionId, request) {
142
+ await relayFetch(
143
+ fetchFn,
144
+ `${baseUrl}/v1/session/${encodeURIComponent(sessionId)}/approve`,
145
+ {
146
+ method: "POST",
147
+ headers: { "Content-Type": "application/json" },
148
+ body: JSON.stringify(request)
149
+ }
150
+ );
151
+ },
152
+ async denySession(sessionId, request) {
153
+ await relayFetch(
154
+ fetchFn,
155
+ `${baseUrl}/v1/session/${encodeURIComponent(sessionId)}/deny`,
156
+ {
157
+ method: "POST",
158
+ headers: { "Content-Type": "application/json" },
159
+ body: JSON.stringify(request)
160
+ }
161
+ );
162
+ },
163
+ pollSession(sessionId) {
164
+ return pollSession(fetchFn, baseUrl, sessionId);
165
+ },
166
+ pollUntilComplete(sessionId, opts) {
167
+ return pollUntilComplete(fetchFn, baseUrl, sessionId, opts);
168
+ }
169
+ };
170
+ }
171
+ function createSessionRelayBuilderClient(options) {
172
+ const fetchFn = resolveFetch(options.fetchFn);
173
+ const baseUrl = endpoint(options);
174
+ return {
175
+ async initSession(params) {
176
+ const path = "/v1/session/init";
177
+ const body = JSON.stringify({
178
+ granteeAddress: options.granteeAddress,
179
+ scopes: params.scopes,
180
+ ...params.webhookUrl && { webhookUrl: params.webhookUrl },
181
+ ...params.appUserId && { appUserId: params.appUserId }
182
+ });
183
+ const iat = options.now?.() ?? Math.floor(Date.now() / 1e3);
184
+ const authHeader = await (0, import_signing.buildSessionRelayWeb3SignedHeader)({
185
+ signMessage: options.signMessage,
186
+ aud: baseUrl,
187
+ method: "POST",
188
+ uri: path,
189
+ body,
190
+ iat,
191
+ exp: iat + 300
192
+ });
193
+ return relayFetch(fetchFn, `${baseUrl}${path}`, {
194
+ method: "POST",
195
+ headers: {
196
+ "Content-Type": "application/json",
197
+ Authorization: authHeader
198
+ },
199
+ body
200
+ });
201
+ },
202
+ pollSession(sessionId) {
203
+ return pollSession(fetchFn, baseUrl, sessionId);
204
+ },
205
+ pollUntilComplete(sessionId, opts) {
206
+ return pollUntilComplete(fetchFn, baseUrl, sessionId, opts);
207
+ }
208
+ };
209
+ }
210
+ // Annotate the CommonJS export names for ESM import in node:
211
+ 0 && (module.exports = {
212
+ createSessionRelayBuilderClient,
213
+ createSessionRelayClient
214
+ });
215
+ //# sourceMappingURL=client.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/session-relay/client.ts"],"sourcesContent":["import { getSessionRelayUrl } from \"./endpoints\";\nimport { SessionRelayError } from \"./errors\";\nimport { buildSessionRelayWeb3SignedHeader } from \"./signing\";\nimport type {\n SessionRelayApproveRequest,\n SessionRelayBuilderClient,\n SessionRelayBuilderClientOptions,\n SessionRelayClaimRequest,\n SessionRelayClaimResponse,\n SessionRelayClient,\n SessionRelayClientOptions,\n SessionRelayDenyRequest,\n SessionRelayFetch,\n SessionRelayInitParams,\n SessionRelayInitResult,\n SessionRelayPollResult,\n} from \"./types\";\n\nconst DEFAULT_POLL_INTERVAL_MS = 2_000;\nconst DEFAULT_POLL_TIMEOUT_MS = 15 * 60_000;\n\nfunction stripTrailingSlash(url: string): string {\n return url.replace(/\\/+$/, \"\");\n}\n\nfunction resolveFetch(fetchFn?: SessionRelayFetch): SessionRelayFetch {\n const resolved = fetchFn ?? (globalThis.fetch as SessionRelayFetch);\n if (!resolved) {\n throw new SessionRelayError(\n \"No fetch implementation available. Pass `fetchFn` to the Session Relay client.\",\n { relayErrorCode: \"SESSION_RELAY_CONFIG_ERROR\" },\n );\n }\n return resolved;\n}\n\nfunction endpoint(options: SessionRelayClientOptions): string {\n return stripTrailingSlash(options.baseUrl ?? getSessionRelayUrl(options.env));\n}\n\nasync function parseJson(res: Awaited<ReturnType<SessionRelayFetch>>) {\n if (res.status === 204) return undefined;\n\n if (res.text) {\n const text = await res.text();\n if (text.length === 0) return undefined;\n try {\n return JSON.parse(text) as unknown;\n } catch {\n throw new SessionRelayError(\n `Session Relay returned a non-JSON response (HTTP ${res.status})`,\n { status: res.status },\n );\n }\n }\n\n try {\n return await res.json();\n } catch {\n throw new SessionRelayError(\n `Session Relay returned a non-JSON response (HTTP ${res.status})`,\n { status: res.status },\n );\n }\n}\n\nfunction relayErrorFromBody(\n body: unknown,\n):\n | { message?: string; code?: number; errorCode?: string; details?: unknown }\n | undefined {\n if (body === null || typeof body !== \"object\" || !(\"error\" in body)) {\n return undefined;\n }\n const error = (body as { error?: unknown }).error;\n if (error === null || typeof error !== \"object\") return undefined;\n return error as {\n message?: string;\n code?: number;\n errorCode?: string;\n details?: unknown;\n };\n}\n\nasync function relayFetch<T>(\n fetchFn: SessionRelayFetch,\n url: string,\n init: { method: string; headers?: Record<string, string>; body?: string },\n): Promise<T> {\n let res: Awaited<ReturnType<SessionRelayFetch>>;\n try {\n res = await fetchFn(url, init);\n } catch (err) {\n throw new SessionRelayError(\n \"Network error communicating with Session Relay\",\n {\n body: err,\n },\n );\n }\n\n const body = await parseJson(res);\n if (!res.ok) {\n const relayError = relayErrorFromBody(body);\n throw new SessionRelayError(\n relayError?.message ??\n `Session Relay request failed (HTTP ${res.status})`,\n {\n status: res.status,\n relayCode: relayError?.code,\n relayErrorCode: relayError?.errorCode,\n body,\n },\n );\n }\n\n return body as T;\n}\n\nasync function pollSession(\n fetchFn: SessionRelayFetch,\n baseUrl: string,\n sessionId: string,\n): Promise<SessionRelayPollResult> {\n return relayFetch<SessionRelayPollResult>(\n fetchFn,\n `${baseUrl}/v1/session/${encodeURIComponent(sessionId)}/poll`,\n { method: \"GET\" },\n );\n}\n\nasync function pollUntilComplete(\n fetchFn: SessionRelayFetch,\n baseUrl: string,\n sessionId: string,\n opts?: { intervalMs?: number; timeoutMs?: number },\n): Promise<SessionRelayPollResult> {\n const intervalMs = opts?.intervalMs ?? DEFAULT_POLL_INTERVAL_MS;\n const timeoutMs = opts?.timeoutMs ?? DEFAULT_POLL_TIMEOUT_MS;\n const deadline = Date.now() + timeoutMs;\n\n while (Date.now() < deadline) {\n const result = await pollSession(fetchFn, baseUrl, sessionId);\n if (\n result.status === \"approved\" ||\n result.status === \"denied\" ||\n result.status === \"expired\"\n ) {\n return result;\n }\n await new Promise((resolve) => setTimeout(resolve, intervalMs));\n }\n\n throw new SessionRelayError(\"Polling timed out\", {\n relayErrorCode: \"SESSION_RELAY_POLL_TIMEOUT\",\n });\n}\n\n/**\n * Create a Session Relay client for app-side claim/approve/deny calls and\n * unsigned polling.\n *\n * @remarks\n * This is a Vana service integration client, not a protocol-core primitive.\n * It intentionally models the current Session Relay HTTP API while leaving\n * user-facing grant orchestration to the app using it.\n */\nexport function createSessionRelayClient(\n options: SessionRelayClientOptions = {},\n): SessionRelayClient {\n const fetchFn = resolveFetch(options.fetchFn);\n const baseUrl = endpoint(options);\n\n return {\n claimSession(\n request: SessionRelayClaimRequest,\n ): Promise<SessionRelayClaimResponse> {\n return relayFetch<SessionRelayClaimResponse>(\n fetchFn,\n `${baseUrl}/v1/session/claim`,\n {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(request),\n },\n );\n },\n\n async approveSession(\n sessionId: string,\n request: SessionRelayApproveRequest,\n ): Promise<void> {\n await relayFetch<unknown>(\n fetchFn,\n `${baseUrl}/v1/session/${encodeURIComponent(sessionId)}/approve`,\n {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(request),\n },\n );\n },\n\n async denySession(\n sessionId: string,\n request: SessionRelayDenyRequest,\n ): Promise<void> {\n await relayFetch<unknown>(\n fetchFn,\n `${baseUrl}/v1/session/${encodeURIComponent(sessionId)}/deny`,\n {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(request),\n },\n );\n },\n\n pollSession(sessionId: string): Promise<SessionRelayPollResult> {\n return pollSession(fetchFn, baseUrl, sessionId);\n },\n\n pollUntilComplete(\n sessionId: string,\n opts?: { intervalMs?: number; timeoutMs?: number },\n ): Promise<SessionRelayPollResult> {\n return pollUntilComplete(fetchFn, baseUrl, sessionId, opts);\n },\n };\n}\n\n/**\n * Create a builder-side Session Relay client for signed session init and\n * unsigned polling.\n */\nexport function createSessionRelayBuilderClient(\n options: SessionRelayBuilderClientOptions,\n): SessionRelayBuilderClient {\n const fetchFn = resolveFetch(options.fetchFn);\n const baseUrl = endpoint(options);\n\n return {\n async initSession(\n params: SessionRelayInitParams,\n ): Promise<SessionRelayInitResult> {\n const path = \"/v1/session/init\";\n const body = JSON.stringify({\n granteeAddress: options.granteeAddress,\n scopes: params.scopes,\n ...(params.webhookUrl && { webhookUrl: params.webhookUrl }),\n ...(params.appUserId && { appUserId: params.appUserId }),\n });\n const iat = options.now?.() ?? Math.floor(Date.now() / 1000);\n const authHeader = await buildSessionRelayWeb3SignedHeader({\n signMessage: options.signMessage,\n aud: baseUrl,\n method: \"POST\",\n uri: path,\n body,\n iat,\n exp: iat + 300,\n });\n\n return relayFetch<SessionRelayInitResult>(fetchFn, `${baseUrl}${path}`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: authHeader,\n },\n body,\n });\n },\n\n pollSession(sessionId: string): Promise<SessionRelayPollResult> {\n return pollSession(fetchFn, baseUrl, sessionId);\n },\n\n pollUntilComplete(\n sessionId: string,\n opts?: { intervalMs?: number; timeoutMs?: number },\n ): Promise<SessionRelayPollResult> {\n return pollUntilComplete(fetchFn, baseUrl, sessionId, opts);\n },\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,uBAAmC;AACnC,oBAAkC;AAClC,qBAAkD;AAgBlD,MAAM,2BAA2B;AACjC,MAAM,0BAA0B,KAAK;AAErC,SAAS,mBAAmB,KAAqB;AAC/C,SAAO,IAAI,QAAQ,QAAQ,EAAE;AAC/B;AAEA,SAAS,aAAa,SAAgD;AACpE,QAAM,WAAW,WAAY,WAAW;AACxC,MAAI,CAAC,UAAU;AACb,UAAM,IAAI;AAAA,MACR;AAAA,MACA,EAAE,gBAAgB,6BAA6B;AAAA,IACjD;AAAA,EACF;AACA,SAAO;AACT;AAEA,SAAS,SAAS,SAA4C;AAC5D,SAAO,mBAAmB,QAAQ,eAAW,qCAAmB,QAAQ,GAAG,CAAC;AAC9E;AAEA,eAAe,UAAU,KAA6C;AACpE,MAAI,IAAI,WAAW,IAAK,QAAO;AAE/B,MAAI,IAAI,MAAM;AACZ,UAAM,OAAO,MAAM,IAAI,KAAK;AAC5B,QAAI,KAAK,WAAW,EAAG,QAAO;AAC9B,QAAI;AACF,aAAO,KAAK,MAAM,IAAI;AAAA,IACxB,QAAQ;AACN,YAAM,IAAI;AAAA,QACR,oDAAoD,IAAI,MAAM;AAAA,QAC9D,EAAE,QAAQ,IAAI,OAAO;AAAA,MACvB;AAAA,IACF;AAAA,EACF;AAEA,MAAI;AACF,WAAO,MAAM,IAAI,KAAK;AAAA,EACxB,QAAQ;AACN,UAAM,IAAI;AAAA,MACR,oDAAoD,IAAI,MAAM;AAAA,MAC9D,EAAE,QAAQ,IAAI,OAAO;AAAA,IACvB;AAAA,EACF;AACF;AAEA,SAAS,mBACP,MAGY;AACZ,MAAI,SAAS,QAAQ,OAAO,SAAS,YAAY,EAAE,WAAW,OAAO;AACnE,WAAO;AAAA,EACT;AACA,QAAM,QAAS,KAA6B;AAC5C,MAAI,UAAU,QAAQ,OAAO,UAAU,SAAU,QAAO;AACxD,SAAO;AAMT;AAEA,eAAe,WACb,SACA,KACA,MACY;AACZ,MAAI;AACJ,MAAI;AACF,UAAM,MAAM,QAAQ,KAAK,IAAI;AAAA,EAC/B,SAAS,KAAK;AACZ,UAAM,IAAI;AAAA,MACR;AAAA,MACA;AAAA,QACE,MAAM;AAAA,MACR;AAAA,IACF;AAAA,EACF;AAEA,QAAM,OAAO,MAAM,UAAU,GAAG;AAChC,MAAI,CAAC,IAAI,IAAI;AACX,UAAM,aAAa,mBAAmB,IAAI;AAC1C,UAAM,IAAI;AAAA,MACR,YAAY,WACV,sCAAsC,IAAI,MAAM;AAAA,MAClD;AAAA,QACE,QAAQ,IAAI;AAAA,QACZ,WAAW,YAAY;AAAA,QACvB,gBAAgB,YAAY;AAAA,QAC5B;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;AAEA,eAAe,YACb,SACA,SACA,WACiC;AACjC,SAAO;AAAA,IACL;AAAA,IACA,GAAG,OAAO,eAAe,mBAAmB,SAAS,CAAC;AAAA,IACtD,EAAE,QAAQ,MAAM;AAAA,EAClB;AACF;AAEA,eAAe,kBACb,SACA,SACA,WACA,MACiC;AACjC,QAAM,aAAa,MAAM,cAAc;AACvC,QAAM,YAAY,MAAM,aAAa;AACrC,QAAM,WAAW,KAAK,IAAI,IAAI;AAE9B,SAAO,KAAK,IAAI,IAAI,UAAU;AAC5B,UAAM,SAAS,MAAM,YAAY,SAAS,SAAS,SAAS;AAC5D,QACE,OAAO,WAAW,cAClB,OAAO,WAAW,YAClB,OAAO,WAAW,WAClB;AACA,aAAO;AAAA,IACT;AACA,UAAM,IAAI,QAAQ,CAAC,YAAY,WAAW,SAAS,UAAU,CAAC;AAAA,EAChE;AAEA,QAAM,IAAI,gCAAkB,qBAAqB;AAAA,IAC/C,gBAAgB;AAAA,EAClB,CAAC;AACH;AAWO,SAAS,yBACd,UAAqC,CAAC,GAClB;AACpB,QAAM,UAAU,aAAa,QAAQ,OAAO;AAC5C,QAAM,UAAU,SAAS,OAAO;AAEhC,SAAO;AAAA,IACL,aACE,SACoC;AACpC,aAAO;AAAA,QACL;AAAA,QACA,GAAG,OAAO;AAAA,QACV;AAAA,UACE,QAAQ;AAAA,UACR,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,UAC9C,MAAM,KAAK,UAAU,OAAO;AAAA,QAC9B;AAAA,MACF;AAAA,IACF;AAAA,IAEA,MAAM,eACJ,WACA,SACe;AACf,YAAM;AAAA,QACJ;AAAA,QACA,GAAG,OAAO,eAAe,mBAAmB,SAAS,CAAC;AAAA,QACtD;AAAA,UACE,QAAQ;AAAA,UACR,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,UAC9C,MAAM,KAAK,UAAU,OAAO;AAAA,QAC9B;AAAA,MACF;AAAA,IACF;AAAA,IAEA,MAAM,YACJ,WACA,SACe;AACf,YAAM;AAAA,QACJ;AAAA,QACA,GAAG,OAAO,eAAe,mBAAmB,SAAS,CAAC;AAAA,QACtD;AAAA,UACE,QAAQ;AAAA,UACR,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,UAC9C,MAAM,KAAK,UAAU,OAAO;AAAA,QAC9B;AAAA,MACF;AAAA,IACF;AAAA,IAEA,YAAY,WAAoD;AAC9D,aAAO,YAAY,SAAS,SAAS,SAAS;AAAA,IAChD;AAAA,IAEA,kBACE,WACA,MACiC;AACjC,aAAO,kBAAkB,SAAS,SAAS,WAAW,IAAI;AAAA,IAC5D;AAAA,EACF;AACF;AAMO,SAAS,gCACd,SAC2B;AAC3B,QAAM,UAAU,aAAa,QAAQ,OAAO;AAC5C,QAAM,UAAU,SAAS,OAAO;AAEhC,SAAO;AAAA,IACL,MAAM,YACJ,QACiC;AACjC,YAAM,OAAO;AACb,YAAM,OAAO,KAAK,UAAU;AAAA,QAC1B,gBAAgB,QAAQ;AAAA,QACxB,QAAQ,OAAO;AAAA,QACf,GAAI,OAAO,cAAc,EAAE,YAAY,OAAO,WAAW;AAAA,QACzD,GAAI,OAAO,aAAa,EAAE,WAAW,OAAO,UAAU;AAAA,MACxD,CAAC;AACD,YAAM,MAAM,QAAQ,MAAM,KAAK,KAAK,MAAM,KAAK,IAAI,IAAI,GAAI;AAC3D,YAAM,aAAa,UAAM,kDAAkC;AAAA,QACzD,aAAa,QAAQ;AAAA,QACrB,KAAK;AAAA,QACL,QAAQ;AAAA,QACR,KAAK;AAAA,QACL;AAAA,QACA;AAAA,QACA,KAAK,MAAM;AAAA,MACb,CAAC;AAED,aAAO,WAAmC,SAAS,GAAG,OAAO,GAAG,IAAI,IAAI;AAAA,QACtE,QAAQ;AAAA,QACR,SAAS;AAAA,UACP,gBAAgB;AAAA,UAChB,eAAe;AAAA,QACjB;AAAA,QACA;AAAA,MACF,CAAC;AAAA,IACH;AAAA,IAEA,YAAY,WAAoD;AAC9D,aAAO,YAAY,SAAS,SAAS,SAAS;AAAA,IAChD;AAAA,IAEA,kBACE,WACA,MACiC;AACjC,aAAO,kBAAkB,SAAS,SAAS,WAAW,IAAI;AAAA,IAC5D;AAAA,EACF;AACF;","names":[]}
@@ -0,0 +1,16 @@
1
+ import type { SessionRelayBuilderClient, SessionRelayBuilderClientOptions, SessionRelayClient, SessionRelayClientOptions } from "./types";
2
+ /**
3
+ * Create a Session Relay client for app-side claim/approve/deny calls and
4
+ * unsigned polling.
5
+ *
6
+ * @remarks
7
+ * This is a Vana service integration client, not a protocol-core primitive.
8
+ * It intentionally models the current Session Relay HTTP API while leaving
9
+ * user-facing grant orchestration to the app using it.
10
+ */
11
+ export declare function createSessionRelayClient(options?: SessionRelayClientOptions): SessionRelayClient;
12
+ /**
13
+ * Create a builder-side Session Relay client for signed session init and
14
+ * unsigned polling.
15
+ */
16
+ export declare function createSessionRelayBuilderClient(options: SessionRelayBuilderClientOptions): SessionRelayBuilderClient;
@@ -0,0 +1,190 @@
1
+ import { getSessionRelayUrl } from "./endpoints.js";
2
+ import { SessionRelayError } from "./errors.js";
3
+ import { buildSessionRelayWeb3SignedHeader } from "./signing.js";
4
+ const DEFAULT_POLL_INTERVAL_MS = 2e3;
5
+ const DEFAULT_POLL_TIMEOUT_MS = 15 * 6e4;
6
+ function stripTrailingSlash(url) {
7
+ return url.replace(/\/+$/, "");
8
+ }
9
+ function resolveFetch(fetchFn) {
10
+ const resolved = fetchFn ?? globalThis.fetch;
11
+ if (!resolved) {
12
+ throw new SessionRelayError(
13
+ "No fetch implementation available. Pass `fetchFn` to the Session Relay client.",
14
+ { relayErrorCode: "SESSION_RELAY_CONFIG_ERROR" }
15
+ );
16
+ }
17
+ return resolved;
18
+ }
19
+ function endpoint(options) {
20
+ return stripTrailingSlash(options.baseUrl ?? getSessionRelayUrl(options.env));
21
+ }
22
+ async function parseJson(res) {
23
+ if (res.status === 204) return void 0;
24
+ if (res.text) {
25
+ const text = await res.text();
26
+ if (text.length === 0) return void 0;
27
+ try {
28
+ return JSON.parse(text);
29
+ } catch {
30
+ throw new SessionRelayError(
31
+ `Session Relay returned a non-JSON response (HTTP ${res.status})`,
32
+ { status: res.status }
33
+ );
34
+ }
35
+ }
36
+ try {
37
+ return await res.json();
38
+ } catch {
39
+ throw new SessionRelayError(
40
+ `Session Relay returned a non-JSON response (HTTP ${res.status})`,
41
+ { status: res.status }
42
+ );
43
+ }
44
+ }
45
+ function relayErrorFromBody(body) {
46
+ if (body === null || typeof body !== "object" || !("error" in body)) {
47
+ return void 0;
48
+ }
49
+ const error = body.error;
50
+ if (error === null || typeof error !== "object") return void 0;
51
+ return error;
52
+ }
53
+ async function relayFetch(fetchFn, url, init) {
54
+ let res;
55
+ try {
56
+ res = await fetchFn(url, init);
57
+ } catch (err) {
58
+ throw new SessionRelayError(
59
+ "Network error communicating with Session Relay",
60
+ {
61
+ body: err
62
+ }
63
+ );
64
+ }
65
+ const body = await parseJson(res);
66
+ if (!res.ok) {
67
+ const relayError = relayErrorFromBody(body);
68
+ throw new SessionRelayError(
69
+ relayError?.message ?? `Session Relay request failed (HTTP ${res.status})`,
70
+ {
71
+ status: res.status,
72
+ relayCode: relayError?.code,
73
+ relayErrorCode: relayError?.errorCode,
74
+ body
75
+ }
76
+ );
77
+ }
78
+ return body;
79
+ }
80
+ async function pollSession(fetchFn, baseUrl, sessionId) {
81
+ return relayFetch(
82
+ fetchFn,
83
+ `${baseUrl}/v1/session/${encodeURIComponent(sessionId)}/poll`,
84
+ { method: "GET" }
85
+ );
86
+ }
87
+ async function pollUntilComplete(fetchFn, baseUrl, sessionId, opts) {
88
+ const intervalMs = opts?.intervalMs ?? DEFAULT_POLL_INTERVAL_MS;
89
+ const timeoutMs = opts?.timeoutMs ?? DEFAULT_POLL_TIMEOUT_MS;
90
+ const deadline = Date.now() + timeoutMs;
91
+ while (Date.now() < deadline) {
92
+ const result = await pollSession(fetchFn, baseUrl, sessionId);
93
+ if (result.status === "approved" || result.status === "denied" || result.status === "expired") {
94
+ return result;
95
+ }
96
+ await new Promise((resolve) => setTimeout(resolve, intervalMs));
97
+ }
98
+ throw new SessionRelayError("Polling timed out", {
99
+ relayErrorCode: "SESSION_RELAY_POLL_TIMEOUT"
100
+ });
101
+ }
102
+ function createSessionRelayClient(options = {}) {
103
+ const fetchFn = resolveFetch(options.fetchFn);
104
+ const baseUrl = endpoint(options);
105
+ return {
106
+ claimSession(request) {
107
+ return relayFetch(
108
+ fetchFn,
109
+ `${baseUrl}/v1/session/claim`,
110
+ {
111
+ method: "POST",
112
+ headers: { "Content-Type": "application/json" },
113
+ body: JSON.stringify(request)
114
+ }
115
+ );
116
+ },
117
+ async approveSession(sessionId, request) {
118
+ await relayFetch(
119
+ fetchFn,
120
+ `${baseUrl}/v1/session/${encodeURIComponent(sessionId)}/approve`,
121
+ {
122
+ method: "POST",
123
+ headers: { "Content-Type": "application/json" },
124
+ body: JSON.stringify(request)
125
+ }
126
+ );
127
+ },
128
+ async denySession(sessionId, request) {
129
+ await relayFetch(
130
+ fetchFn,
131
+ `${baseUrl}/v1/session/${encodeURIComponent(sessionId)}/deny`,
132
+ {
133
+ method: "POST",
134
+ headers: { "Content-Type": "application/json" },
135
+ body: JSON.stringify(request)
136
+ }
137
+ );
138
+ },
139
+ pollSession(sessionId) {
140
+ return pollSession(fetchFn, baseUrl, sessionId);
141
+ },
142
+ pollUntilComplete(sessionId, opts) {
143
+ return pollUntilComplete(fetchFn, baseUrl, sessionId, opts);
144
+ }
145
+ };
146
+ }
147
+ function createSessionRelayBuilderClient(options) {
148
+ const fetchFn = resolveFetch(options.fetchFn);
149
+ const baseUrl = endpoint(options);
150
+ return {
151
+ async initSession(params) {
152
+ const path = "/v1/session/init";
153
+ const body = JSON.stringify({
154
+ granteeAddress: options.granteeAddress,
155
+ scopes: params.scopes,
156
+ ...params.webhookUrl && { webhookUrl: params.webhookUrl },
157
+ ...params.appUserId && { appUserId: params.appUserId }
158
+ });
159
+ const iat = options.now?.() ?? Math.floor(Date.now() / 1e3);
160
+ const authHeader = await buildSessionRelayWeb3SignedHeader({
161
+ signMessage: options.signMessage,
162
+ aud: baseUrl,
163
+ method: "POST",
164
+ uri: path,
165
+ body,
166
+ iat,
167
+ exp: iat + 300
168
+ });
169
+ return relayFetch(fetchFn, `${baseUrl}${path}`, {
170
+ method: "POST",
171
+ headers: {
172
+ "Content-Type": "application/json",
173
+ Authorization: authHeader
174
+ },
175
+ body
176
+ });
177
+ },
178
+ pollSession(sessionId) {
179
+ return pollSession(fetchFn, baseUrl, sessionId);
180
+ },
181
+ pollUntilComplete(sessionId, opts) {
182
+ return pollUntilComplete(fetchFn, baseUrl, sessionId, opts);
183
+ }
184
+ };
185
+ }
186
+ export {
187
+ createSessionRelayBuilderClient,
188
+ createSessionRelayClient
189
+ };
190
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/session-relay/client.ts"],"sourcesContent":["import { getSessionRelayUrl } from \"./endpoints\";\nimport { SessionRelayError } from \"./errors\";\nimport { buildSessionRelayWeb3SignedHeader } from \"./signing\";\nimport type {\n SessionRelayApproveRequest,\n SessionRelayBuilderClient,\n SessionRelayBuilderClientOptions,\n SessionRelayClaimRequest,\n SessionRelayClaimResponse,\n SessionRelayClient,\n SessionRelayClientOptions,\n SessionRelayDenyRequest,\n SessionRelayFetch,\n SessionRelayInitParams,\n SessionRelayInitResult,\n SessionRelayPollResult,\n} from \"./types\";\n\nconst DEFAULT_POLL_INTERVAL_MS = 2_000;\nconst DEFAULT_POLL_TIMEOUT_MS = 15 * 60_000;\n\nfunction stripTrailingSlash(url: string): string {\n return url.replace(/\\/+$/, \"\");\n}\n\nfunction resolveFetch(fetchFn?: SessionRelayFetch): SessionRelayFetch {\n const resolved = fetchFn ?? (globalThis.fetch as SessionRelayFetch);\n if (!resolved) {\n throw new SessionRelayError(\n \"No fetch implementation available. Pass `fetchFn` to the Session Relay client.\",\n { relayErrorCode: \"SESSION_RELAY_CONFIG_ERROR\" },\n );\n }\n return resolved;\n}\n\nfunction endpoint(options: SessionRelayClientOptions): string {\n return stripTrailingSlash(options.baseUrl ?? getSessionRelayUrl(options.env));\n}\n\nasync function parseJson(res: Awaited<ReturnType<SessionRelayFetch>>) {\n if (res.status === 204) return undefined;\n\n if (res.text) {\n const text = await res.text();\n if (text.length === 0) return undefined;\n try {\n return JSON.parse(text) as unknown;\n } catch {\n throw new SessionRelayError(\n `Session Relay returned a non-JSON response (HTTP ${res.status})`,\n { status: res.status },\n );\n }\n }\n\n try {\n return await res.json();\n } catch {\n throw new SessionRelayError(\n `Session Relay returned a non-JSON response (HTTP ${res.status})`,\n { status: res.status },\n );\n }\n}\n\nfunction relayErrorFromBody(\n body: unknown,\n):\n | { message?: string; code?: number; errorCode?: string; details?: unknown }\n | undefined {\n if (body === null || typeof body !== \"object\" || !(\"error\" in body)) {\n return undefined;\n }\n const error = (body as { error?: unknown }).error;\n if (error === null || typeof error !== \"object\") return undefined;\n return error as {\n message?: string;\n code?: number;\n errorCode?: string;\n details?: unknown;\n };\n}\n\nasync function relayFetch<T>(\n fetchFn: SessionRelayFetch,\n url: string,\n init: { method: string; headers?: Record<string, string>; body?: string },\n): Promise<T> {\n let res: Awaited<ReturnType<SessionRelayFetch>>;\n try {\n res = await fetchFn(url, init);\n } catch (err) {\n throw new SessionRelayError(\n \"Network error communicating with Session Relay\",\n {\n body: err,\n },\n );\n }\n\n const body = await parseJson(res);\n if (!res.ok) {\n const relayError = relayErrorFromBody(body);\n throw new SessionRelayError(\n relayError?.message ??\n `Session Relay request failed (HTTP ${res.status})`,\n {\n status: res.status,\n relayCode: relayError?.code,\n relayErrorCode: relayError?.errorCode,\n body,\n },\n );\n }\n\n return body as T;\n}\n\nasync function pollSession(\n fetchFn: SessionRelayFetch,\n baseUrl: string,\n sessionId: string,\n): Promise<SessionRelayPollResult> {\n return relayFetch<SessionRelayPollResult>(\n fetchFn,\n `${baseUrl}/v1/session/${encodeURIComponent(sessionId)}/poll`,\n { method: \"GET\" },\n );\n}\n\nasync function pollUntilComplete(\n fetchFn: SessionRelayFetch,\n baseUrl: string,\n sessionId: string,\n opts?: { intervalMs?: number; timeoutMs?: number },\n): Promise<SessionRelayPollResult> {\n const intervalMs = opts?.intervalMs ?? DEFAULT_POLL_INTERVAL_MS;\n const timeoutMs = opts?.timeoutMs ?? DEFAULT_POLL_TIMEOUT_MS;\n const deadline = Date.now() + timeoutMs;\n\n while (Date.now() < deadline) {\n const result = await pollSession(fetchFn, baseUrl, sessionId);\n if (\n result.status === \"approved\" ||\n result.status === \"denied\" ||\n result.status === \"expired\"\n ) {\n return result;\n }\n await new Promise((resolve) => setTimeout(resolve, intervalMs));\n }\n\n throw new SessionRelayError(\"Polling timed out\", {\n relayErrorCode: \"SESSION_RELAY_POLL_TIMEOUT\",\n });\n}\n\n/**\n * Create a Session Relay client for app-side claim/approve/deny calls and\n * unsigned polling.\n *\n * @remarks\n * This is a Vana service integration client, not a protocol-core primitive.\n * It intentionally models the current Session Relay HTTP API while leaving\n * user-facing grant orchestration to the app using it.\n */\nexport function createSessionRelayClient(\n options: SessionRelayClientOptions = {},\n): SessionRelayClient {\n const fetchFn = resolveFetch(options.fetchFn);\n const baseUrl = endpoint(options);\n\n return {\n claimSession(\n request: SessionRelayClaimRequest,\n ): Promise<SessionRelayClaimResponse> {\n return relayFetch<SessionRelayClaimResponse>(\n fetchFn,\n `${baseUrl}/v1/session/claim`,\n {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(request),\n },\n );\n },\n\n async approveSession(\n sessionId: string,\n request: SessionRelayApproveRequest,\n ): Promise<void> {\n await relayFetch<unknown>(\n fetchFn,\n `${baseUrl}/v1/session/${encodeURIComponent(sessionId)}/approve`,\n {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(request),\n },\n );\n },\n\n async denySession(\n sessionId: string,\n request: SessionRelayDenyRequest,\n ): Promise<void> {\n await relayFetch<unknown>(\n fetchFn,\n `${baseUrl}/v1/session/${encodeURIComponent(sessionId)}/deny`,\n {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(request),\n },\n );\n },\n\n pollSession(sessionId: string): Promise<SessionRelayPollResult> {\n return pollSession(fetchFn, baseUrl, sessionId);\n },\n\n pollUntilComplete(\n sessionId: string,\n opts?: { intervalMs?: number; timeoutMs?: number },\n ): Promise<SessionRelayPollResult> {\n return pollUntilComplete(fetchFn, baseUrl, sessionId, opts);\n },\n };\n}\n\n/**\n * Create a builder-side Session Relay client for signed session init and\n * unsigned polling.\n */\nexport function createSessionRelayBuilderClient(\n options: SessionRelayBuilderClientOptions,\n): SessionRelayBuilderClient {\n const fetchFn = resolveFetch(options.fetchFn);\n const baseUrl = endpoint(options);\n\n return {\n async initSession(\n params: SessionRelayInitParams,\n ): Promise<SessionRelayInitResult> {\n const path = \"/v1/session/init\";\n const body = JSON.stringify({\n granteeAddress: options.granteeAddress,\n scopes: params.scopes,\n ...(params.webhookUrl && { webhookUrl: params.webhookUrl }),\n ...(params.appUserId && { appUserId: params.appUserId }),\n });\n const iat = options.now?.() ?? Math.floor(Date.now() / 1000);\n const authHeader = await buildSessionRelayWeb3SignedHeader({\n signMessage: options.signMessage,\n aud: baseUrl,\n method: \"POST\",\n uri: path,\n body,\n iat,\n exp: iat + 300,\n });\n\n return relayFetch<SessionRelayInitResult>(fetchFn, `${baseUrl}${path}`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: authHeader,\n },\n body,\n });\n },\n\n pollSession(sessionId: string): Promise<SessionRelayPollResult> {\n return pollSession(fetchFn, baseUrl, sessionId);\n },\n\n pollUntilComplete(\n sessionId: string,\n opts?: { intervalMs?: number; timeoutMs?: number },\n ): Promise<SessionRelayPollResult> {\n return pollUntilComplete(fetchFn, baseUrl, sessionId, opts);\n },\n };\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,37 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+ var endpoints_exports = {};
20
+ __export(endpoints_exports, {
21
+ SESSION_RELAY_DEV_URL: () => SESSION_RELAY_DEV_URL,
22
+ SESSION_RELAY_PRODUCTION_URL: () => SESSION_RELAY_PRODUCTION_URL,
23
+ getSessionRelayUrl: () => getSessionRelayUrl
24
+ });
25
+ module.exports = __toCommonJS(endpoints_exports);
26
+ const SESSION_RELAY_PRODUCTION_URL = "https://session-relay.vana.org";
27
+ const SESSION_RELAY_DEV_URL = "https://dev.session-relay.vana.org";
28
+ function getSessionRelayUrl(env = "production") {
29
+ return env === "dev" ? SESSION_RELAY_DEV_URL : SESSION_RELAY_PRODUCTION_URL;
30
+ }
31
+ // Annotate the CommonJS export names for ESM import in node:
32
+ 0 && (module.exports = {
33
+ SESSION_RELAY_DEV_URL,
34
+ SESSION_RELAY_PRODUCTION_URL,
35
+ getSessionRelayUrl
36
+ });
37
+ //# sourceMappingURL=endpoints.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/session-relay/endpoints.ts"],"sourcesContent":["import type { SessionRelayEnvironment } from \"./types\";\n\n/** Production Session Relay URL. */\nexport const SESSION_RELAY_PRODUCTION_URL = \"https://session-relay.vana.org\";\n\n/** Internal dev Session Relay URL. */\nexport const SESSION_RELAY_DEV_URL = \"https://dev.session-relay.vana.org\";\n\n/** Resolve the default Session Relay URL for a deployment environment. */\nexport function getSessionRelayUrl(\n env: SessionRelayEnvironment = \"production\",\n): string {\n return env === \"dev\" ? SESSION_RELAY_DEV_URL : SESSION_RELAY_PRODUCTION_URL;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAGO,MAAM,+BAA+B;AAGrC,MAAM,wBAAwB;AAG9B,SAAS,mBACd,MAA+B,cACvB;AACR,SAAO,QAAQ,QAAQ,wBAAwB;AACjD;","names":[]}
@@ -0,0 +1,7 @@
1
+ import type { SessionRelayEnvironment } from "./types";
2
+ /** Production Session Relay URL. */
3
+ export declare const SESSION_RELAY_PRODUCTION_URL = "https://session-relay.vana.org";
4
+ /** Internal dev Session Relay URL. */
5
+ export declare const SESSION_RELAY_DEV_URL = "https://dev.session-relay.vana.org";
6
+ /** Resolve the default Session Relay URL for a deployment environment. */
7
+ export declare function getSessionRelayUrl(env?: SessionRelayEnvironment): string;
@@ -0,0 +1,11 @@
1
+ const SESSION_RELAY_PRODUCTION_URL = "https://session-relay.vana.org";
2
+ const SESSION_RELAY_DEV_URL = "https://dev.session-relay.vana.org";
3
+ function getSessionRelayUrl(env = "production") {
4
+ return env === "dev" ? SESSION_RELAY_DEV_URL : SESSION_RELAY_PRODUCTION_URL;
5
+ }
6
+ export {
7
+ SESSION_RELAY_DEV_URL,
8
+ SESSION_RELAY_PRODUCTION_URL,
9
+ getSessionRelayUrl
10
+ };
11
+ //# sourceMappingURL=endpoints.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/session-relay/endpoints.ts"],"sourcesContent":["import type { SessionRelayEnvironment } from \"./types\";\n\n/** Production Session Relay URL. */\nexport const SESSION_RELAY_PRODUCTION_URL = \"https://session-relay.vana.org\";\n\n/** Internal dev Session Relay URL. */\nexport const SESSION_RELAY_DEV_URL = \"https://dev.session-relay.vana.org\";\n\n/** Resolve the default Session Relay URL for a deployment environment. */\nexport function getSessionRelayUrl(\n env: SessionRelayEnvironment = \"production\",\n): string {\n return env === \"dev\" ? SESSION_RELAY_DEV_URL : SESSION_RELAY_PRODUCTION_URL;\n}\n"],"mappings":"AAGO,MAAM,+BAA+B;AAGrC,MAAM,wBAAwB;AAG9B,SAAS,mBACd,MAA+B,cACvB;AACR,SAAO,QAAQ,QAAQ,wBAAwB;AACjD;","names":[]}
@@ -0,0 +1,36 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+ var errors_exports = {};
20
+ __export(errors_exports, {
21
+ SessionRelayError: () => SessionRelayError
22
+ });
23
+ module.exports = __toCommonJS(errors_exports);
24
+ var import_errors = require("../errors");
25
+ class SessionRelayError extends import_errors.VanaError {
26
+ constructor(message, details = {}) {
27
+ super(message, details.relayErrorCode ?? "SESSION_RELAY_ERROR");
28
+ this.details = details;
29
+ }
30
+ details;
31
+ }
32
+ // Annotate the CommonJS export names for ESM import in node:
33
+ 0 && (module.exports = {
34
+ SessionRelayError
35
+ });
36
+ //# sourceMappingURL=errors.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/session-relay/errors.ts"],"sourcesContent":["import { VanaError } from \"../errors\";\n\n/** Error details returned by Session Relay. */\nexport interface SessionRelayErrorDetails {\n status?: number;\n relayCode?: number;\n relayErrorCode?: string;\n body?: unknown;\n}\n\n/** Error thrown by Session Relay client operations. */\nexport class SessionRelayError extends VanaError {\n constructor(\n message: string,\n public readonly details: SessionRelayErrorDetails = {},\n ) {\n super(message, details.relayErrorCode ?? \"SESSION_RELAY_ERROR\");\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,oBAA0B;AAWnB,MAAM,0BAA0B,wBAAU;AAAA,EAC/C,YACE,SACgB,UAAoC,CAAC,GACrD;AACA,UAAM,SAAS,QAAQ,kBAAkB,qBAAqB;AAF9C;AAAA,EAGlB;AAAA,EAHkB;AAIpB;","names":[]}
@@ -0,0 +1,13 @@
1
+ import { VanaError } from "../errors";
2
+ /** Error details returned by Session Relay. */
3
+ export interface SessionRelayErrorDetails {
4
+ status?: number;
5
+ relayCode?: number;
6
+ relayErrorCode?: string;
7
+ body?: unknown;
8
+ }
9
+ /** Error thrown by Session Relay client operations. */
10
+ export declare class SessionRelayError extends VanaError {
11
+ readonly details: SessionRelayErrorDetails;
12
+ constructor(message: string, details?: SessionRelayErrorDetails);
13
+ }
@@ -0,0 +1,12 @@
1
+ import { VanaError } from "../errors.js";
2
+ class SessionRelayError extends VanaError {
3
+ constructor(message, details = {}) {
4
+ super(message, details.relayErrorCode ?? "SESSION_RELAY_ERROR");
5
+ this.details = details;
6
+ }
7
+ details;
8
+ }
9
+ export {
10
+ SessionRelayError
11
+ };
12
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/session-relay/errors.ts"],"sourcesContent":["import { VanaError } from \"../errors\";\n\n/** Error details returned by Session Relay. */\nexport interface SessionRelayErrorDetails {\n status?: number;\n relayCode?: number;\n relayErrorCode?: string;\n body?: unknown;\n}\n\n/** Error thrown by Session Relay client operations. */\nexport class SessionRelayError extends VanaError {\n constructor(\n message: string,\n public readonly details: SessionRelayErrorDetails = {},\n ) {\n super(message, details.relayErrorCode ?? \"SESSION_RELAY_ERROR\");\n }\n}\n"],"mappings":"AAAA,SAAS,iBAAiB;AAWnB,MAAM,0BAA0B,UAAU;AAAA,EAC/C,YACE,SACgB,UAAoC,CAAC,GACrD;AACA,UAAM,SAAS,QAAQ,kBAAkB,qBAAqB;AAF9C;AAAA,EAGlB;AAAA,EAHkB;AAIpB;","names":[]}
@@ -0,0 +1,46 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+ var session_relay_exports = {};
20
+ __export(session_relay_exports, {
21
+ SESSION_RELAY_DEV_URL: () => import_endpoints.SESSION_RELAY_DEV_URL,
22
+ SESSION_RELAY_PRODUCTION_URL: () => import_endpoints.SESSION_RELAY_PRODUCTION_URL,
23
+ SessionRelayError: () => import_errors.SessionRelayError,
24
+ buildSessionRelayWeb3SignedHeader: () => import_signing.buildSessionRelayWeb3SignedHeader,
25
+ computeSessionRelayBodyHash: () => import_signing.computeSessionRelayBodyHash,
26
+ createSessionRelayBuilderClient: () => import_client.createSessionRelayBuilderClient,
27
+ createSessionRelayClient: () => import_client.createSessionRelayClient,
28
+ getSessionRelayUrl: () => import_endpoints.getSessionRelayUrl
29
+ });
30
+ module.exports = __toCommonJS(session_relay_exports);
31
+ var import_endpoints = require("./endpoints");
32
+ var import_errors = require("./errors");
33
+ var import_signing = require("./signing");
34
+ var import_client = require("./client");
35
+ // Annotate the CommonJS export names for ESM import in node:
36
+ 0 && (module.exports = {
37
+ SESSION_RELAY_DEV_URL,
38
+ SESSION_RELAY_PRODUCTION_URL,
39
+ SessionRelayError,
40
+ buildSessionRelayWeb3SignedHeader,
41
+ computeSessionRelayBodyHash,
42
+ createSessionRelayBuilderClient,
43
+ createSessionRelayClient,
44
+ getSessionRelayUrl
45
+ });
46
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/session-relay/index.ts"],"sourcesContent":["export {\n SESSION_RELAY_DEV_URL,\n SESSION_RELAY_PRODUCTION_URL,\n getSessionRelayUrl,\n} from \"./endpoints\";\nexport { SessionRelayError, type SessionRelayErrorDetails } from \"./errors\";\nexport {\n computeSessionRelayBodyHash,\n buildSessionRelayWeb3SignedHeader,\n} from \"./signing\";\nexport {\n createSessionRelayClient,\n createSessionRelayBuilderClient,\n} from \"./client\";\nexport type {\n SessionRelayEnvironment,\n SessionRelayFetch,\n SessionRelayClientOptions,\n SessionRelayBuilderClientOptions,\n SessionRelayInitParams,\n SessionRelayInitResult,\n SessionRelayGrantPayload,\n SessionRelayPollResult,\n SessionRelayClaimRequest,\n SessionRelayClaimResponse,\n SessionRelayApproveRequest,\n SessionRelayDenyRequest,\n SessionRelayClient,\n SessionRelayBuilderClient,\n} from \"./types\";\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,uBAIO;AACP,oBAAiE;AACjE,qBAGO;AACP,oBAGO;","names":[]}
@@ -0,0 +1,5 @@
1
+ export { SESSION_RELAY_DEV_URL, SESSION_RELAY_PRODUCTION_URL, getSessionRelayUrl, } from "./endpoints";
2
+ export { SessionRelayError, type SessionRelayErrorDetails } from "./errors";
3
+ export { computeSessionRelayBodyHash, buildSessionRelayWeb3SignedHeader, } from "./signing";
4
+ export { createSessionRelayClient, createSessionRelayBuilderClient, } from "./client";
5
+ export type { SessionRelayEnvironment, SessionRelayFetch, SessionRelayClientOptions, SessionRelayBuilderClientOptions, SessionRelayInitParams, SessionRelayInitResult, SessionRelayGrantPayload, SessionRelayPollResult, SessionRelayClaimRequest, SessionRelayClaimResponse, SessionRelayApproveRequest, SessionRelayDenyRequest, SessionRelayClient, SessionRelayBuilderClient, } from "./types";
@@ -0,0 +1,25 @@
1
+ import {
2
+ SESSION_RELAY_DEV_URL,
3
+ SESSION_RELAY_PRODUCTION_URL,
4
+ getSessionRelayUrl
5
+ } from "./endpoints.js";
6
+ import { SessionRelayError } from "./errors.js";
7
+ import {
8
+ computeSessionRelayBodyHash,
9
+ buildSessionRelayWeb3SignedHeader
10
+ } from "./signing.js";
11
+ import {
12
+ createSessionRelayClient,
13
+ createSessionRelayBuilderClient
14
+ } from "./client.js";
15
+ export {
16
+ SESSION_RELAY_DEV_URL,
17
+ SESSION_RELAY_PRODUCTION_URL,
18
+ SessionRelayError,
19
+ buildSessionRelayWeb3SignedHeader,
20
+ computeSessionRelayBodyHash,
21
+ createSessionRelayBuilderClient,
22
+ createSessionRelayClient,
23
+ getSessionRelayUrl
24
+ };
25
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/session-relay/index.ts"],"sourcesContent":["export {\n SESSION_RELAY_DEV_URL,\n SESSION_RELAY_PRODUCTION_URL,\n getSessionRelayUrl,\n} from \"./endpoints\";\nexport { SessionRelayError, type SessionRelayErrorDetails } from \"./errors\";\nexport {\n computeSessionRelayBodyHash,\n buildSessionRelayWeb3SignedHeader,\n} from \"./signing\";\nexport {\n createSessionRelayClient,\n createSessionRelayBuilderClient,\n} from \"./client\";\nexport type {\n SessionRelayEnvironment,\n SessionRelayFetch,\n SessionRelayClientOptions,\n SessionRelayBuilderClientOptions,\n SessionRelayInitParams,\n SessionRelayInitResult,\n SessionRelayGrantPayload,\n SessionRelayPollResult,\n SessionRelayClaimRequest,\n SessionRelayClaimResponse,\n SessionRelayApproveRequest,\n SessionRelayDenyRequest,\n SessionRelayClient,\n SessionRelayBuilderClient,\n} from \"./types\";\n"],"mappings":"AAAA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,yBAAwD;AACjE;AAAA,EACE;AAAA,EACA;AAAA,OACK;AACP;AAAA,EACE;AAAA,EACA;AAAA,OACK;","names":[]}
@@ -0,0 +1,62 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+ var signing_exports = {};
20
+ __export(signing_exports, {
21
+ buildSessionRelayWeb3SignedHeader: () => buildSessionRelayWeb3SignedHeader,
22
+ computeSessionRelayBodyHash: () => computeSessionRelayBodyHash
23
+ });
24
+ module.exports = __toCommonJS(signing_exports);
25
+ var import_sha2 = require("@noble/hashes/sha2");
26
+ var import_viem = require("viem");
27
+ var import_web3_signed_builder = require("../auth/web3-signed-builder");
28
+ const textEncoder = new TextEncoder();
29
+ function canonicalizeJson(value) {
30
+ if (value === null || typeof value !== "object") return value;
31
+ if (Array.isArray(value)) return value.map(canonicalizeJson);
32
+ const sorted = {};
33
+ for (const key of Object.keys(value).sort()) {
34
+ if (key === "signature") continue;
35
+ sorted[key] = canonicalizeJson(value[key]);
36
+ }
37
+ return sorted;
38
+ }
39
+ function computeSessionRelayBodyHash(body) {
40
+ if (!body || body.length === 0) return "";
41
+ const parsed = JSON.parse(body);
42
+ const canonical = canonicalizeJson(parsed);
43
+ const digest = (0, import_sha2.sha256)(textEncoder.encode(JSON.stringify(canonical)));
44
+ return (0, import_viem.bytesToHex)(digest).slice(2);
45
+ }
46
+ function buildSessionRelayWeb3SignedHeader(params) {
47
+ return (0, import_web3_signed_builder.buildWeb3SignedHeader)({
48
+ signMessage: params.signMessage,
49
+ aud: params.aud,
50
+ method: params.method,
51
+ uri: params.uri,
52
+ bodyHash: computeSessionRelayBodyHash(params.body),
53
+ iat: params.iat,
54
+ exp: params.exp
55
+ });
56
+ }
57
+ // Annotate the CommonJS export names for ESM import in node:
58
+ 0 && (module.exports = {
59
+ buildSessionRelayWeb3SignedHeader,
60
+ computeSessionRelayBodyHash
61
+ });
62
+ //# sourceMappingURL=signing.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/session-relay/signing.ts"],"sourcesContent":["import { sha256 } from \"@noble/hashes/sha2\";\nimport { bytesToHex } from \"viem\";\nimport {\n buildWeb3SignedHeader,\n type Web3SignedSignFn,\n} from \"../auth/web3-signed-builder\";\n\nconst textEncoder = new TextEncoder();\n\nfunction canonicalizeJson(value: unknown): unknown {\n if (value === null || typeof value !== \"object\") return value;\n if (Array.isArray(value)) return value.map(canonicalizeJson);\n\n const sorted: Record<string, unknown> = {};\n for (const key of Object.keys(value as Record<string, unknown>).sort()) {\n if (key === \"signature\") continue;\n sorted[key] = canonicalizeJson((value as Record<string, unknown>)[key]);\n }\n return sorted;\n}\n\n/**\n * Compute the legacy bodyHash shape currently accepted by Session Relay.\n *\n * @remarks\n * Personal Server Web3Signed requests use `sha256:<hex>`, including a canonical\n * empty-body hash. Session Relay's current signed init endpoint verifies a\n * legacy body hash: bare SHA-256 hex for non-empty JSON bodies and `\"\"` for\n * empty bodies. Keep this compatibility local to the Relay integration.\n */\nexport function computeSessionRelayBodyHash(body: string | undefined): string {\n if (!body || body.length === 0) return \"\";\n\n const parsed = JSON.parse(body);\n const canonical = canonicalizeJson(parsed);\n const digest = sha256(textEncoder.encode(JSON.stringify(canonical)));\n return bytesToHex(digest).slice(2);\n}\n\n/** Build a Web3Signed header compatible with Session Relay's signed endpoints. */\nexport function buildSessionRelayWeb3SignedHeader(params: {\n signMessage: Web3SignedSignFn;\n aud: string;\n method: string;\n uri: string;\n body?: string;\n iat?: number;\n exp?: number;\n}): Promise<string> {\n return buildWeb3SignedHeader({\n signMessage: params.signMessage,\n aud: params.aud,\n method: params.method,\n uri: params.uri,\n bodyHash: computeSessionRelayBodyHash(params.body),\n iat: params.iat,\n exp: params.exp,\n });\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,kBAAuB;AACvB,kBAA2B;AAC3B,iCAGO;AAEP,MAAM,cAAc,IAAI,YAAY;AAEpC,SAAS,iBAAiB,OAAyB;AACjD,MAAI,UAAU,QAAQ,OAAO,UAAU,SAAU,QAAO;AACxD,MAAI,MAAM,QAAQ,KAAK,EAAG,QAAO,MAAM,IAAI,gBAAgB;AAE3D,QAAM,SAAkC,CAAC;AACzC,aAAW,OAAO,OAAO,KAAK,KAAgC,EAAE,KAAK,GAAG;AACtE,QAAI,QAAQ,YAAa;AACzB,WAAO,GAAG,IAAI,iBAAkB,MAAkC,GAAG,CAAC;AAAA,EACxE;AACA,SAAO;AACT;AAWO,SAAS,4BAA4B,MAAkC;AAC5E,MAAI,CAAC,QAAQ,KAAK,WAAW,EAAG,QAAO;AAEvC,QAAM,SAAS,KAAK,MAAM,IAAI;AAC9B,QAAM,YAAY,iBAAiB,MAAM;AACzC,QAAM,aAAS,oBAAO,YAAY,OAAO,KAAK,UAAU,SAAS,CAAC,CAAC;AACnE,aAAO,wBAAW,MAAM,EAAE,MAAM,CAAC;AACnC;AAGO,SAAS,kCAAkC,QAQ9B;AAClB,aAAO,kDAAsB;AAAA,IAC3B,aAAa,OAAO;AAAA,IACpB,KAAK,OAAO;AAAA,IACZ,QAAQ,OAAO;AAAA,IACf,KAAK,OAAO;AAAA,IACZ,UAAU,4BAA4B,OAAO,IAAI;AAAA,IACjD,KAAK,OAAO;AAAA,IACZ,KAAK,OAAO;AAAA,EACd,CAAC;AACH;","names":[]}
@@ -0,0 +1,21 @@
1
+ import { type Web3SignedSignFn } from "../auth/web3-signed-builder";
2
+ /**
3
+ * Compute the legacy bodyHash shape currently accepted by Session Relay.
4
+ *
5
+ * @remarks
6
+ * Personal Server Web3Signed requests use `sha256:<hex>`, including a canonical
7
+ * empty-body hash. Session Relay's current signed init endpoint verifies a
8
+ * legacy body hash: bare SHA-256 hex for non-empty JSON bodies and `""` for
9
+ * empty bodies. Keep this compatibility local to the Relay integration.
10
+ */
11
+ export declare function computeSessionRelayBodyHash(body: string | undefined): string;
12
+ /** Build a Web3Signed header compatible with Session Relay's signed endpoints. */
13
+ export declare function buildSessionRelayWeb3SignedHeader(params: {
14
+ signMessage: Web3SignedSignFn;
15
+ aud: string;
16
+ method: string;
17
+ uri: string;
18
+ body?: string;
19
+ iat?: number;
20
+ exp?: number;
21
+ }): Promise<string>;
@@ -0,0 +1,39 @@
1
+ import { sha256 } from "@noble/hashes/sha2";
2
+ import { bytesToHex } from "viem";
3
+ import {
4
+ buildWeb3SignedHeader
5
+ } from "../auth/web3-signed-builder.js";
6
+ const textEncoder = new TextEncoder();
7
+ function canonicalizeJson(value) {
8
+ if (value === null || typeof value !== "object") return value;
9
+ if (Array.isArray(value)) return value.map(canonicalizeJson);
10
+ const sorted = {};
11
+ for (const key of Object.keys(value).sort()) {
12
+ if (key === "signature") continue;
13
+ sorted[key] = canonicalizeJson(value[key]);
14
+ }
15
+ return sorted;
16
+ }
17
+ function computeSessionRelayBodyHash(body) {
18
+ if (!body || body.length === 0) return "";
19
+ const parsed = JSON.parse(body);
20
+ const canonical = canonicalizeJson(parsed);
21
+ const digest = sha256(textEncoder.encode(JSON.stringify(canonical)));
22
+ return bytesToHex(digest).slice(2);
23
+ }
24
+ function buildSessionRelayWeb3SignedHeader(params) {
25
+ return buildWeb3SignedHeader({
26
+ signMessage: params.signMessage,
27
+ aud: params.aud,
28
+ method: params.method,
29
+ uri: params.uri,
30
+ bodyHash: computeSessionRelayBodyHash(params.body),
31
+ iat: params.iat,
32
+ exp: params.exp
33
+ });
34
+ }
35
+ export {
36
+ buildSessionRelayWeb3SignedHeader,
37
+ computeSessionRelayBodyHash
38
+ };
39
+ //# sourceMappingURL=signing.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/session-relay/signing.ts"],"sourcesContent":["import { sha256 } from \"@noble/hashes/sha2\";\nimport { bytesToHex } from \"viem\";\nimport {\n buildWeb3SignedHeader,\n type Web3SignedSignFn,\n} from \"../auth/web3-signed-builder\";\n\nconst textEncoder = new TextEncoder();\n\nfunction canonicalizeJson(value: unknown): unknown {\n if (value === null || typeof value !== \"object\") return value;\n if (Array.isArray(value)) return value.map(canonicalizeJson);\n\n const sorted: Record<string, unknown> = {};\n for (const key of Object.keys(value as Record<string, unknown>).sort()) {\n if (key === \"signature\") continue;\n sorted[key] = canonicalizeJson((value as Record<string, unknown>)[key]);\n }\n return sorted;\n}\n\n/**\n * Compute the legacy bodyHash shape currently accepted by Session Relay.\n *\n * @remarks\n * Personal Server Web3Signed requests use `sha256:<hex>`, including a canonical\n * empty-body hash. Session Relay's current signed init endpoint verifies a\n * legacy body hash: bare SHA-256 hex for non-empty JSON bodies and `\"\"` for\n * empty bodies. Keep this compatibility local to the Relay integration.\n */\nexport function computeSessionRelayBodyHash(body: string | undefined): string {\n if (!body || body.length === 0) return \"\";\n\n const parsed = JSON.parse(body);\n const canonical = canonicalizeJson(parsed);\n const digest = sha256(textEncoder.encode(JSON.stringify(canonical)));\n return bytesToHex(digest).slice(2);\n}\n\n/** Build a Web3Signed header compatible with Session Relay's signed endpoints. */\nexport function buildSessionRelayWeb3SignedHeader(params: {\n signMessage: Web3SignedSignFn;\n aud: string;\n method: string;\n uri: string;\n body?: string;\n iat?: number;\n exp?: number;\n}): Promise<string> {\n return buildWeb3SignedHeader({\n signMessage: params.signMessage,\n aud: params.aud,\n method: params.method,\n uri: params.uri,\n bodyHash: computeSessionRelayBodyHash(params.body),\n iat: params.iat,\n exp: params.exp,\n });\n}\n"],"mappings":"AAAA,SAAS,cAAc;AACvB,SAAS,kBAAkB;AAC3B;AAAA,EACE;AAAA,OAEK;AAEP,MAAM,cAAc,IAAI,YAAY;AAEpC,SAAS,iBAAiB,OAAyB;AACjD,MAAI,UAAU,QAAQ,OAAO,UAAU,SAAU,QAAO;AACxD,MAAI,MAAM,QAAQ,KAAK,EAAG,QAAO,MAAM,IAAI,gBAAgB;AAE3D,QAAM,SAAkC,CAAC;AACzC,aAAW,OAAO,OAAO,KAAK,KAAgC,EAAE,KAAK,GAAG;AACtE,QAAI,QAAQ,YAAa;AACzB,WAAO,GAAG,IAAI,iBAAkB,MAAkC,GAAG,CAAC;AAAA,EACxE;AACA,SAAO;AACT;AAWO,SAAS,4BAA4B,MAAkC;AAC5E,MAAI,CAAC,QAAQ,KAAK,WAAW,EAAG,QAAO;AAEvC,QAAM,SAAS,KAAK,MAAM,IAAI;AAC9B,QAAM,YAAY,iBAAiB,MAAM;AACzC,QAAM,SAAS,OAAO,YAAY,OAAO,KAAK,UAAU,SAAS,CAAC,CAAC;AACnE,SAAO,WAAW,MAAM,EAAE,MAAM,CAAC;AACnC;AAGO,SAAS,kCAAkC,QAQ9B;AAClB,SAAO,sBAAsB;AAAA,IAC3B,aAAa,OAAO;AAAA,IACpB,KAAK,OAAO;AAAA,IACZ,QAAQ,OAAO;AAAA,IACf,KAAK,OAAO;AAAA,IACZ,UAAU,4BAA4B,OAAO,IAAI;AAAA,IACjD,KAAK,OAAO;AAAA,IACZ,KAAK,OAAO;AAAA,EACd,CAAC;AACH;","names":[]}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __copyProps = (to, from, except, desc) => {
7
+ if (from && typeof from === "object" || typeof from === "function") {
8
+ for (let key of __getOwnPropNames(from))
9
+ if (!__hasOwnProp.call(to, key) && key !== except)
10
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
11
+ }
12
+ return to;
13
+ };
14
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
15
+ var types_exports = {};
16
+ module.exports = __toCommonJS(types_exports);
17
+ //# sourceMappingURL=types.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/session-relay/types.ts"],"sourcesContent":["import type { Web3SignedSignFn } from \"../auth/web3-signed-builder\";\n\n/** Deployment environment for Vana's Session Relay service. */\nexport type SessionRelayEnvironment = \"production\" | \"dev\";\n\n/** Minimal fetch signature accepted by the Session Relay clients. */\nexport type SessionRelayFetch = (\n input: string,\n init?: {\n method?: string;\n headers?: Record<string, string>;\n body?: string;\n },\n) => Promise<{\n ok: boolean;\n status: number;\n statusText?: string;\n json(): Promise<unknown>;\n text?(): Promise<string>;\n}>;\n\n/** Shared Session Relay client options. */\nexport interface SessionRelayClientOptions {\n /** Session Relay base URL. Defaults from `env` when omitted. */\n baseUrl?: string;\n /** Vana deployment environment. Defaults to `\"production\"`. */\n env?: SessionRelayEnvironment;\n /** Fetch implementation. Defaults to `globalThis.fetch`. */\n fetchFn?: SessionRelayFetch;\n}\n\n/** Builder-side Session Relay options. */\nexport interface SessionRelayBuilderClientOptions extends SessionRelayClientOptions {\n /** Builder/app address registered with the Vana builder registry. */\n granteeAddress: `0x${string}`;\n /** EIP-191 signer for Web3Signed Relay requests. */\n signMessage: Web3SignedSignFn;\n /** Clock source used for signed request freshness claims. */\n now?: () => number;\n}\n\n/** Parameters for creating a Session Relay session. */\nexport interface SessionRelayInitParams {\n /** Data scopes requested from the user. */\n scopes: string[];\n /** Public HTTPS callback URL for grant notifications. */\n webhookUrl?: string;\n /** App-owned user id for correlating the approved grant. */\n appUserId?: string;\n}\n\n/** Raw Session Relay init result. */\nexport interface SessionRelayInitResult {\n sessionId: string;\n deepLinkUrl: string;\n expiresAt: string;\n}\n\n/** Grant payload returned after a Relay session is approved. */\nexport interface SessionRelayGrantPayload {\n grantId: string;\n userAddress: string;\n builderAddress: string;\n scopes: string[];\n serverAddress?: string;\n appUserId?: string;\n}\n\n/** Session Relay poll result. */\nexport interface SessionRelayPollResult {\n /**\n * Current session status.\n *\n * @remarks\n * Current Session Relay deployments may report expired sessions as a\n * structured `SESSION_EXPIRED` error instead of a JSON body with\n * `status: \"expired\"`. The `\"expired\"` status is accepted for deployments\n * that return expiry as a terminal poll body.\n */\n status: \"pending\" | \"claimed\" | \"approved\" | \"denied\" | \"expired\";\n grant?: SessionRelayGrantPayload;\n reason?: string;\n}\n\n/** Desktop/app-side claim request. */\nexport interface SessionRelayClaimRequest {\n sessionId: string;\n secret: string;\n}\n\n/** Claimed session data returned to the app that completes user consent. */\nexport interface SessionRelayClaimResponse {\n sessionId: string;\n granteeAddress: string;\n scopes: string[];\n expiresAt: string;\n webhookUrl?: string;\n appUserId?: string;\n}\n\n/** Desktop/app-side approval request. */\nexport interface SessionRelayApproveRequest {\n secret: string;\n grantId: string;\n userAddress: string;\n serverAddress?: string;\n scopes: string[];\n}\n\n/** Desktop/app-side denial request. */\nexport interface SessionRelayDenyRequest {\n secret: string;\n reason?: string;\n}\n\n/** Session Relay methods that do not require builder signing. */\nexport interface SessionRelayClient {\n claimSession(\n request: SessionRelayClaimRequest,\n ): Promise<SessionRelayClaimResponse>;\n approveSession(\n sessionId: string,\n request: SessionRelayApproveRequest,\n ): Promise<void>;\n denySession(\n sessionId: string,\n request: SessionRelayDenyRequest,\n ): Promise<void>;\n pollSession(sessionId: string): Promise<SessionRelayPollResult>;\n pollUntilComplete(\n sessionId: string,\n opts?: { intervalMs?: number; timeoutMs?: number },\n ): Promise<SessionRelayPollResult>;\n}\n\n/** Builder-side Session Relay methods. */\nexport interface SessionRelayBuilderClient {\n initSession(params: SessionRelayInitParams): Promise<SessionRelayInitResult>;\n pollSession(sessionId: string): Promise<SessionRelayPollResult>;\n pollUntilComplete(\n sessionId: string,\n opts?: { intervalMs?: number; timeoutMs?: number },\n ): Promise<SessionRelayPollResult>;\n}\n"],"mappings":";;;;;;;;;;;;;;AAAA;AAAA;","names":[]}
@@ -0,0 +1,119 @@
1
+ import type { Web3SignedSignFn } from "../auth/web3-signed-builder";
2
+ /** Deployment environment for Vana's Session Relay service. */
3
+ export type SessionRelayEnvironment = "production" | "dev";
4
+ /** Minimal fetch signature accepted by the Session Relay clients. */
5
+ export type SessionRelayFetch = (input: string, init?: {
6
+ method?: string;
7
+ headers?: Record<string, string>;
8
+ body?: string;
9
+ }) => Promise<{
10
+ ok: boolean;
11
+ status: number;
12
+ statusText?: string;
13
+ json(): Promise<unknown>;
14
+ text?(): Promise<string>;
15
+ }>;
16
+ /** Shared Session Relay client options. */
17
+ export interface SessionRelayClientOptions {
18
+ /** Session Relay base URL. Defaults from `env` when omitted. */
19
+ baseUrl?: string;
20
+ /** Vana deployment environment. Defaults to `"production"`. */
21
+ env?: SessionRelayEnvironment;
22
+ /** Fetch implementation. Defaults to `globalThis.fetch`. */
23
+ fetchFn?: SessionRelayFetch;
24
+ }
25
+ /** Builder-side Session Relay options. */
26
+ export interface SessionRelayBuilderClientOptions extends SessionRelayClientOptions {
27
+ /** Builder/app address registered with the Vana builder registry. */
28
+ granteeAddress: `0x${string}`;
29
+ /** EIP-191 signer for Web3Signed Relay requests. */
30
+ signMessage: Web3SignedSignFn;
31
+ /** Clock source used for signed request freshness claims. */
32
+ now?: () => number;
33
+ }
34
+ /** Parameters for creating a Session Relay session. */
35
+ export interface SessionRelayInitParams {
36
+ /** Data scopes requested from the user. */
37
+ scopes: string[];
38
+ /** Public HTTPS callback URL for grant notifications. */
39
+ webhookUrl?: string;
40
+ /** App-owned user id for correlating the approved grant. */
41
+ appUserId?: string;
42
+ }
43
+ /** Raw Session Relay init result. */
44
+ export interface SessionRelayInitResult {
45
+ sessionId: string;
46
+ deepLinkUrl: string;
47
+ expiresAt: string;
48
+ }
49
+ /** Grant payload returned after a Relay session is approved. */
50
+ export interface SessionRelayGrantPayload {
51
+ grantId: string;
52
+ userAddress: string;
53
+ builderAddress: string;
54
+ scopes: string[];
55
+ serverAddress?: string;
56
+ appUserId?: string;
57
+ }
58
+ /** Session Relay poll result. */
59
+ export interface SessionRelayPollResult {
60
+ /**
61
+ * Current session status.
62
+ *
63
+ * @remarks
64
+ * Current Session Relay deployments may report expired sessions as a
65
+ * structured `SESSION_EXPIRED` error instead of a JSON body with
66
+ * `status: "expired"`. The `"expired"` status is accepted for deployments
67
+ * that return expiry as a terminal poll body.
68
+ */
69
+ status: "pending" | "claimed" | "approved" | "denied" | "expired";
70
+ grant?: SessionRelayGrantPayload;
71
+ reason?: string;
72
+ }
73
+ /** Desktop/app-side claim request. */
74
+ export interface SessionRelayClaimRequest {
75
+ sessionId: string;
76
+ secret: string;
77
+ }
78
+ /** Claimed session data returned to the app that completes user consent. */
79
+ export interface SessionRelayClaimResponse {
80
+ sessionId: string;
81
+ granteeAddress: string;
82
+ scopes: string[];
83
+ expiresAt: string;
84
+ webhookUrl?: string;
85
+ appUserId?: string;
86
+ }
87
+ /** Desktop/app-side approval request. */
88
+ export interface SessionRelayApproveRequest {
89
+ secret: string;
90
+ grantId: string;
91
+ userAddress: string;
92
+ serverAddress?: string;
93
+ scopes: string[];
94
+ }
95
+ /** Desktop/app-side denial request. */
96
+ export interface SessionRelayDenyRequest {
97
+ secret: string;
98
+ reason?: string;
99
+ }
100
+ /** Session Relay methods that do not require builder signing. */
101
+ export interface SessionRelayClient {
102
+ claimSession(request: SessionRelayClaimRequest): Promise<SessionRelayClaimResponse>;
103
+ approveSession(sessionId: string, request: SessionRelayApproveRequest): Promise<void>;
104
+ denySession(sessionId: string, request: SessionRelayDenyRequest): Promise<void>;
105
+ pollSession(sessionId: string): Promise<SessionRelayPollResult>;
106
+ pollUntilComplete(sessionId: string, opts?: {
107
+ intervalMs?: number;
108
+ timeoutMs?: number;
109
+ }): Promise<SessionRelayPollResult>;
110
+ }
111
+ /** Builder-side Session Relay methods. */
112
+ export interface SessionRelayBuilderClient {
113
+ initSession(params: SessionRelayInitParams): Promise<SessionRelayInitResult>;
114
+ pollSession(sessionId: string): Promise<SessionRelayPollResult>;
115
+ pollUntilComplete(sessionId: string, opts?: {
116
+ intervalMs?: number;
117
+ timeoutMs?: number;
118
+ }): Promise<SessionRelayPollResult>;
119
+ }
@@ -0,0 +1 @@
1
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -0,0 +1,46 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+ var session_relay_exports = {};
20
+ __export(session_relay_exports, {
21
+ SESSION_RELAY_DEV_URL: () => import_endpoints.SESSION_RELAY_DEV_URL,
22
+ SESSION_RELAY_PRODUCTION_URL: () => import_endpoints.SESSION_RELAY_PRODUCTION_URL,
23
+ SessionRelayError: () => import_errors.SessionRelayError,
24
+ buildSessionRelayWeb3SignedHeader: () => import_signing.buildSessionRelayWeb3SignedHeader,
25
+ computeSessionRelayBodyHash: () => import_signing.computeSessionRelayBodyHash,
26
+ createSessionRelayBuilderClient: () => import_client.createSessionRelayBuilderClient,
27
+ createSessionRelayClient: () => import_client.createSessionRelayClient,
28
+ getSessionRelayUrl: () => import_endpoints.getSessionRelayUrl
29
+ });
30
+ module.exports = __toCommonJS(session_relay_exports);
31
+ var import_endpoints = require("./session-relay/endpoints");
32
+ var import_errors = require("./session-relay/errors");
33
+ var import_signing = require("./session-relay/signing");
34
+ var import_client = require("./session-relay/client");
35
+ // Annotate the CommonJS export names for ESM import in node:
36
+ 0 && (module.exports = {
37
+ SESSION_RELAY_DEV_URL,
38
+ SESSION_RELAY_PRODUCTION_URL,
39
+ SessionRelayError,
40
+ buildSessionRelayWeb3SignedHeader,
41
+ computeSessionRelayBodyHash,
42
+ createSessionRelayBuilderClient,
43
+ createSessionRelayClient,
44
+ getSessionRelayUrl
45
+ });
46
+ //# sourceMappingURL=session-relay.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/session-relay.ts"],"sourcesContent":["/**\n * Session Relay service integration for Vana app flows.\n *\n * @remarks\n * Session Relay coordinates the handoff between a builder app and the Vana app\n * that completes user consent. This entry point is intentionally separate from\n * `protocol/*`: it is a Vana-operated service integration, like Account or\n * Storage integrations, not a canonical on-chain protocol primitive.\n *\n * @example\n * ```typescript\n * import { createSessionRelayBuilderClient } from \"@opendatalabs/vana-sdk/session-relay\";\n *\n * const relay = createSessionRelayBuilderClient({\n * granteeAddress: appAddress,\n * signMessage,\n * });\n * ```\n *\n * @category Integrations\n * @module session-relay\n */\n\nexport {\n SESSION_RELAY_DEV_URL,\n SESSION_RELAY_PRODUCTION_URL,\n getSessionRelayUrl,\n} from \"./session-relay/endpoints\";\nexport {\n SessionRelayError,\n type SessionRelayErrorDetails,\n} from \"./session-relay/errors\";\nexport {\n computeSessionRelayBodyHash,\n buildSessionRelayWeb3SignedHeader,\n} from \"./session-relay/signing\";\nexport {\n createSessionRelayClient,\n createSessionRelayBuilderClient,\n} from \"./session-relay/client\";\nexport type {\n SessionRelayEnvironment,\n SessionRelayFetch,\n SessionRelayClientOptions,\n SessionRelayBuilderClientOptions,\n SessionRelayInitParams,\n SessionRelayInitResult,\n SessionRelayGrantPayload,\n SessionRelayPollResult,\n SessionRelayClaimRequest,\n SessionRelayClaimResponse,\n SessionRelayApproveRequest,\n SessionRelayDenyRequest,\n SessionRelayClient,\n SessionRelayBuilderClient,\n} from \"./session-relay/types\";\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAuBA,uBAIO;AACP,oBAGO;AACP,qBAGO;AACP,oBAGO;","names":[]}
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Session Relay service integration for Vana app flows.
3
+ *
4
+ * @remarks
5
+ * Session Relay coordinates the handoff between a builder app and the Vana app
6
+ * that completes user consent. This entry point is intentionally separate from
7
+ * `protocol/*`: it is a Vana-operated service integration, like Account or
8
+ * Storage integrations, not a canonical on-chain protocol primitive.
9
+ *
10
+ * @example
11
+ * ```typescript
12
+ * import { createSessionRelayBuilderClient } from "@opendatalabs/vana-sdk/session-relay";
13
+ *
14
+ * const relay = createSessionRelayBuilderClient({
15
+ * granteeAddress: appAddress,
16
+ * signMessage,
17
+ * });
18
+ * ```
19
+ *
20
+ * @category Integrations
21
+ * @module session-relay
22
+ */
23
+ export { SESSION_RELAY_DEV_URL, SESSION_RELAY_PRODUCTION_URL, getSessionRelayUrl, } from "./session-relay/endpoints";
24
+ export { SessionRelayError, type SessionRelayErrorDetails, } from "./session-relay/errors";
25
+ export { computeSessionRelayBodyHash, buildSessionRelayWeb3SignedHeader, } from "./session-relay/signing";
26
+ export { createSessionRelayClient, createSessionRelayBuilderClient, } from "./session-relay/client";
27
+ export type { SessionRelayEnvironment, SessionRelayFetch, SessionRelayClientOptions, SessionRelayBuilderClientOptions, SessionRelayInitParams, SessionRelayInitResult, SessionRelayGrantPayload, SessionRelayPollResult, SessionRelayClaimRequest, SessionRelayClaimResponse, SessionRelayApproveRequest, SessionRelayDenyRequest, SessionRelayClient, SessionRelayBuilderClient, } from "./session-relay/types";
@@ -0,0 +1,27 @@
1
+ import {
2
+ SESSION_RELAY_DEV_URL,
3
+ SESSION_RELAY_PRODUCTION_URL,
4
+ getSessionRelayUrl
5
+ } from "./session-relay/endpoints.js";
6
+ import {
7
+ SessionRelayError
8
+ } from "./session-relay/errors.js";
9
+ import {
10
+ computeSessionRelayBodyHash,
11
+ buildSessionRelayWeb3SignedHeader
12
+ } from "./session-relay/signing.js";
13
+ import {
14
+ createSessionRelayClient,
15
+ createSessionRelayBuilderClient
16
+ } from "./session-relay/client.js";
17
+ export {
18
+ SESSION_RELAY_DEV_URL,
19
+ SESSION_RELAY_PRODUCTION_URL,
20
+ SessionRelayError,
21
+ buildSessionRelayWeb3SignedHeader,
22
+ computeSessionRelayBodyHash,
23
+ createSessionRelayBuilderClient,
24
+ createSessionRelayClient,
25
+ getSessionRelayUrl
26
+ };
27
+ //# sourceMappingURL=session-relay.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/session-relay.ts"],"sourcesContent":["/**\n * Session Relay service integration for Vana app flows.\n *\n * @remarks\n * Session Relay coordinates the handoff between a builder app and the Vana app\n * that completes user consent. This entry point is intentionally separate from\n * `protocol/*`: it is a Vana-operated service integration, like Account or\n * Storage integrations, not a canonical on-chain protocol primitive.\n *\n * @example\n * ```typescript\n * import { createSessionRelayBuilderClient } from \"@opendatalabs/vana-sdk/session-relay\";\n *\n * const relay = createSessionRelayBuilderClient({\n * granteeAddress: appAddress,\n * signMessage,\n * });\n * ```\n *\n * @category Integrations\n * @module session-relay\n */\n\nexport {\n SESSION_RELAY_DEV_URL,\n SESSION_RELAY_PRODUCTION_URL,\n getSessionRelayUrl,\n} from \"./session-relay/endpoints\";\nexport {\n SessionRelayError,\n type SessionRelayErrorDetails,\n} from \"./session-relay/errors\";\nexport {\n computeSessionRelayBodyHash,\n buildSessionRelayWeb3SignedHeader,\n} from \"./session-relay/signing\";\nexport {\n createSessionRelayClient,\n createSessionRelayBuilderClient,\n} from \"./session-relay/client\";\nexport type {\n SessionRelayEnvironment,\n SessionRelayFetch,\n SessionRelayClientOptions,\n SessionRelayBuilderClientOptions,\n SessionRelayInitParams,\n SessionRelayInitResult,\n SessionRelayGrantPayload,\n SessionRelayPollResult,\n SessionRelayClaimRequest,\n SessionRelayClaimResponse,\n SessionRelayApproveRequest,\n SessionRelayDenyRequest,\n SessionRelayClient,\n SessionRelayBuilderClient,\n} from \"./session-relay/types\";\n"],"mappings":"AAuBA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP;AAAA,EACE;AAAA,OAEK;AACP;AAAA,EACE;AAAA,EACA;AAAA,OACK;AACP;AAAA,EACE;AAAA,EACA;AAAA,OACK;","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@opendatalabs/vana-sdk",
3
- "version": "3.8.3",
3
+ "version": "3.9.0",
4
4
  "description": "A TypeScript library for interacting with Vana Network smart contracts.",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -37,6 +37,15 @@
37
37
  "types": "./dist/react.d.ts",
38
38
  "import": "./dist/react.js"
39
39
  },
40
+ "./session-relay": {
41
+ "browser": {
42
+ "types": "./dist/session-relay.d.ts",
43
+ "import": "./dist/session-relay.js"
44
+ },
45
+ "types": "./dist/session-relay.d.ts",
46
+ "import": "./dist/session-relay.js",
47
+ "require": "./dist/session-relay.cjs"
48
+ },
40
49
  "./chains": {
41
50
  "browser": {
42
51
  "types": "./dist/chains.browser.d.ts",