@opendatalabs/vana-sdk 3.4.0 → 3.4.1-canary.7afbfe0

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 (49) hide show
  1. package/dist/index.browser.d.ts +7 -3
  2. package/dist/index.browser.js +423 -128
  3. package/dist/index.browser.js.map +4 -4
  4. package/dist/index.node.cjs +448 -133
  5. package/dist/index.node.cjs.map +4 -4
  6. package/dist/index.node.d.ts +7 -3
  7. package/dist/index.node.js +423 -128
  8. package/dist/index.node.js.map +4 -4
  9. package/dist/protocol/data-point-status.cjs +80 -0
  10. package/dist/protocol/data-point-status.cjs.map +1 -0
  11. package/dist/protocol/data-point-status.d.ts +34 -0
  12. package/dist/protocol/data-point-status.js +51 -0
  13. package/dist/protocol/data-point-status.js.map +1 -0
  14. package/dist/protocol/data-point-status.test.d.ts +1 -0
  15. package/dist/protocol/eip712.cjs +53 -31
  16. package/dist/protocol/eip712.cjs.map +1 -1
  17. package/dist/protocol/eip712.d.ts +98 -43
  18. package/dist/protocol/eip712.js +47 -27
  19. package/dist/protocol/eip712.js.map +1 -1
  20. package/dist/protocol/escrow-deposit.cjs +89 -0
  21. package/dist/protocol/escrow-deposit.cjs.map +1 -0
  22. package/dist/protocol/escrow-deposit.d.ts +47 -0
  23. package/dist/protocol/escrow-deposit.js +60 -0
  24. package/dist/protocol/escrow-deposit.js.map +1 -0
  25. package/dist/protocol/escrow-deposit.test.d.ts +1 -0
  26. package/dist/protocol/escrow-flow.test.d.ts +21 -0
  27. package/dist/protocol/fee-registry.cjs +116 -0
  28. package/dist/protocol/fee-registry.cjs.map +1 -0
  29. package/dist/protocol/fee-registry.d.ts +151 -0
  30. package/dist/protocol/fee-registry.js +89 -0
  31. package/dist/protocol/fee-registry.js.map +1 -0
  32. package/dist/protocol/fee-registry.test.d.ts +1 -0
  33. package/dist/protocol/gateway.cjs +110 -38
  34. package/dist/protocol/gateway.cjs.map +1 -1
  35. package/dist/protocol/gateway.d.ts +238 -56
  36. package/dist/protocol/gateway.js +110 -38
  37. package/dist/protocol/gateway.js.map +1 -1
  38. package/dist/protocol/grants.cjs +27 -64
  39. package/dist/protocol/grants.cjs.map +1 -1
  40. package/dist/protocol/grants.d.ts +6 -13
  41. package/dist/protocol/grants.js +27 -63
  42. package/dist/protocol/grants.js.map +1 -1
  43. package/dist/protocol/personal-server-data.cjs +71 -0
  44. package/dist/protocol/personal-server-data.cjs.map +1 -0
  45. package/dist/protocol/personal-server-data.d.ts +16 -0
  46. package/dist/protocol/personal-server-data.js +47 -0
  47. package/dist/protocol/personal-server-data.js.map +1 -0
  48. package/dist/protocol/personal-server-data.test.d.ts +1 -0
  49. package/package.json +3 -2
@@ -1,6 +1,22 @@
1
1
  export interface GatewayEnvelope<T> {
2
2
  data: T;
3
3
  proof: GatewayProof;
4
+ /**
5
+ * Cursor-based pagination metadata, present on list endpoints (e.g.
6
+ * `GET /v1/data`). A sibling of `data`, not nested inside it — so callers
7
+ * that need it must read the full envelope rather than going through
8
+ * `unwrapEnvelope`, which intentionally returns only `data`.
9
+ */
10
+ pagination?: GatewayPagination;
11
+ }
12
+ export interface GatewayPagination {
13
+ limit: number;
14
+ hasMore: boolean;
15
+ /**
16
+ * Opaque cursor for the NEXT page; pass back as the `cursor` query param.
17
+ * Null when there are no further pages.
18
+ */
19
+ nextCursor: string | null;
4
20
  }
5
21
  export interface GatewayProof {
6
22
  signature: string;
@@ -35,75 +51,71 @@ export interface ServerInfo {
35
51
  publicKey: string;
36
52
  serverUrl: string;
37
53
  addedAt: string;
54
+ revokedAt: string | null;
38
55
  }
56
+ export interface GatewayGrantFee {
57
+ asset: string;
58
+ registrationFee: string;
59
+ dataAccessFee: string;
60
+ totalDue: string;
61
+ }
62
+ export type GatewayGrantStatus = "pending" | "submitting" | "confirmed" | "finalized" | "reorged";
39
63
  export interface GatewayGrantResponse {
40
64
  id: string;
41
65
  grantorAddress: string;
42
66
  granteeId: string;
43
- grant: string;
44
- fileIds: string[];
45
- status: "pending" | "confirmed";
67
+ scopes: string[];
68
+ status: GatewayGrantStatus;
46
69
  addedAt: string;
70
+ expiresAt: string | null;
71
+ expired: boolean;
47
72
  revokedAt: string | null;
48
73
  revocationSignature: string | null;
74
+ paymentStatus: "pending" | "paid";
75
+ paidAt: string | null;
76
+ paidBy: string | null;
77
+ grantVersion: string;
78
+ settleTxHash: string | null;
79
+ settleSubmittedAt: string | null;
80
+ revocationTxHash: string | null;
81
+ revocationSubmittedAt: string | null;
82
+ fee: GatewayGrantFee;
49
83
  }
50
- export interface GrantListItem {
84
+ export type GrantListItem = GatewayGrantResponse;
85
+ export interface DataPointRecord {
51
86
  id: string;
52
- grantorAddress: string;
53
- granteeId: string;
54
- grant: string;
55
- fileIds: string[];
56
- status: "pending" | "confirmed";
87
+ ownerAddress: string;
88
+ scope: string;
89
+ dataHash: string;
90
+ metadataHash: string;
91
+ expectedVersion: string;
57
92
  addedAt: string;
58
- revokedAt: string | null;
59
- revocationSignature: string | null;
60
- }
61
- export interface FileRecord {
62
- fileId: string;
63
- owner: string;
64
- url: string;
65
- schemaId: string;
66
- createdAt: string;
67
- /**
68
- * Soft-deletion timestamp (ISO 8601), or null if the file is active. Always present
69
- * (`normalizeFileRecord` populates it); non-null only when the gateway returns deletion state
70
- * (e.g. listed with `includeDeleted`). Drives the PS sync delete-reconciliation.
71
- */
72
- deletedAt: string | null;
73
93
  }
74
- export interface FileListResult {
75
- files: FileRecord[];
94
+ export interface DataPointListResult {
95
+ dataPoints: DataPointRecord[];
76
96
  cursor: string | null;
77
97
  }
78
- export interface ListFilesOptions {
98
+ export interface ListDataPointsOptions {
79
99
  /**
80
- * Include soft-deleted files in the result (each carries a non-null `deletedAt`). Default false.
81
- * Used by the PS sync download worker to reconcile deletions of files it already holds locally.
100
+ * Only return rows added at or after this ISO 8601 timestamp. Used by sync
101
+ * loops that want incremental tails pass the last seen `addedAt`.
82
102
  */
83
- includeDeleted?: boolean;
84
- }
85
- export interface RegisterFileParams {
86
- ownerAddress: string;
87
- url: string;
88
- schemaId: string;
89
- signature: string;
103
+ since?: string;
104
+ /** Page size. Capped at 1000 by the gateway. */
105
+ limit?: number;
90
106
  }
91
107
  export interface CreateGrantParams {
92
108
  grantorAddress: string;
93
109
  granteeId: string;
94
- grant: string;
95
- fileIds: string[];
110
+ scopes: string[];
111
+ grantVersion: string;
112
+ expiresAt: string;
96
113
  signature: string;
97
114
  }
98
115
  export interface RevokeGrantParams {
99
116
  grantId: string;
100
117
  grantorAddress: string;
101
- signature: string;
102
- }
103
- export interface DeleteFileParams {
104
- fileId: string;
105
- ownerAddress: string;
106
- /** EIP-712 FileDeletion signature, signed by the owner or the owner's registered server. */
118
+ grantVersion: string;
107
119
  signature: string;
108
120
  }
109
121
  export interface RegisterServerParams {
@@ -117,6 +129,171 @@ export interface RegisterServerResult {
117
129
  serverId?: string;
118
130
  alreadyRegistered: boolean;
119
131
  }
132
+ export interface RegisterBuilderParams {
133
+ ownerAddress: string;
134
+ granteeAddress: string;
135
+ publicKey: string;
136
+ appUrl: string;
137
+ signature: string;
138
+ }
139
+ export interface RegisterBuilderResult {
140
+ builderId?: string;
141
+ alreadyRegistered: boolean;
142
+ }
143
+ export interface RegisterDataPointParams {
144
+ ownerAddress: string;
145
+ scope: string;
146
+ dataHash: string;
147
+ metadataHash: string;
148
+ expectedVersion: string;
149
+ signature: string;
150
+ }
151
+ export interface RegisterDataPointResult {
152
+ dataPointId?: string;
153
+ expectedVersion?: string;
154
+ }
155
+ export interface AccessRecord {
156
+ dataPointId: string;
157
+ version: string;
158
+ accessor: string;
159
+ recordId: string;
160
+ signature: string;
161
+ }
162
+ export interface PayForOperationParams {
163
+ payerAddress: string;
164
+ opType: string;
165
+ opId: string;
166
+ asset: string;
167
+ amount: string;
168
+ paymentNonce: string;
169
+ signature: string;
170
+ accessRecord?: AccessRecord;
171
+ }
172
+ export interface PayForOperationResult {
173
+ opType: string;
174
+ opId: string;
175
+ payerAddress: string;
176
+ asset: string;
177
+ amount: string;
178
+ breakdown: {
179
+ registrationFee: string;
180
+ dataAccessFee: string;
181
+ registrationPaid: boolean;
182
+ };
183
+ paymentNonce: string;
184
+ paidAt: string;
185
+ }
186
+ export type SettleOpType = "grant" | "server" | "data" | "access";
187
+ export type SettleItem = {
188
+ opType: SettleOpType;
189
+ opId: string;
190
+ status: "submitting" | "confirmed";
191
+ settleTxHash: string | null;
192
+ settleSubmittedAt: string | null;
193
+ chainBlockHeight: string | null;
194
+ revocationTxHash: string | null;
195
+ revocationSubmittedAt: string | null;
196
+ placeholder: boolean;
197
+ } | {
198
+ opType: SettleOpType;
199
+ opId: string;
200
+ status: "skipped";
201
+ reason: string;
202
+ } | {
203
+ opType: SettleOpType;
204
+ opId: string;
205
+ status: "failed";
206
+ error: string;
207
+ };
208
+ export interface SettlePromoteResult {
209
+ opType: SettleOpType;
210
+ opId: string;
211
+ status: "confirmed" | "failed" | "pending" | "skipped";
212
+ txHash: string;
213
+ chainBlockHeight: string | null;
214
+ reason?: string;
215
+ }
216
+ export interface SettleReconcileItem {
217
+ opId: string;
218
+ status: "finalized" | "reorged" | "unchanged";
219
+ chainBlockHeight: string | null;
220
+ settleTxHash: string | null;
221
+ reason?: string;
222
+ }
223
+ export interface SettleParams {
224
+ limit?: number;
225
+ }
226
+ export interface SettleResult {
227
+ scanned: number;
228
+ submitted: number;
229
+ confirmed: number;
230
+ skipped: number;
231
+ failed: number;
232
+ items: SettleItem[];
233
+ promoted: {
234
+ count: number;
235
+ items: SettlePromoteResult[];
236
+ };
237
+ reconciled: {
238
+ scanned: number;
239
+ finalized: number;
240
+ reorged: number;
241
+ unchanged: number;
242
+ items: SettleReconcileItem[];
243
+ };
244
+ paced?: {
245
+ iterations: number;
246
+ };
247
+ }
248
+ export interface EscrowBalanceEntry {
249
+ asset: string;
250
+ balance: string;
251
+ pendingAmount: string;
252
+ authorizedAmount: string;
253
+ availableAmount: string;
254
+ updatedAt: string | null;
255
+ }
256
+ export interface EscrowDepositSubmitted {
257
+ txHash: string;
258
+ submittedAt: string;
259
+ claimedAsset: string;
260
+ claimedAmount: string;
261
+ }
262
+ export interface EscrowDepositFinalized {
263
+ txHash: string;
264
+ finalizedAt: string | null;
265
+ blockNumber: string | null;
266
+ claimedAsset: string;
267
+ claimedAmount: string;
268
+ }
269
+ export interface EscrowDepositFailed {
270
+ txHash: string;
271
+ submittedAt: string;
272
+ claimedAsset: string;
273
+ claimedAmount: string;
274
+ lastError: string | null;
275
+ }
276
+ export interface EscrowBalance {
277
+ account: string;
278
+ balances: EscrowBalanceEntry[];
279
+ deposits: {
280
+ submitted: EscrowDepositSubmitted[];
281
+ finalized: EscrowDepositFinalized[];
282
+ failed: EscrowDepositFailed[];
283
+ };
284
+ }
285
+ export interface SubmitDepositParams {
286
+ txHash: string;
287
+ }
288
+ export interface DepositState {
289
+ txHash: string;
290
+ account: string;
291
+ status: string;
292
+ blockNumber: string | null;
293
+ submittedAt: string;
294
+ finalizedAt: string | null;
295
+ lastError: string | null;
296
+ }
120
297
  export interface GatewayClient {
121
298
  isRegisteredBuilder(address: string): Promise<boolean>;
122
299
  getBuilder(address: string): Promise<Builder | null>;
@@ -124,23 +301,28 @@ export interface GatewayClient {
124
301
  listGrantsByUser(userAddress: string): Promise<GrantListItem[]>;
125
302
  getSchemaForScope(scope: string): Promise<Schema | null>;
126
303
  getServer(address: string): Promise<ServerInfo | null>;
127
- getFile(fileId: string): Promise<FileRecord | null>;
128
- listFilesSince(owner: string, cursor: string | null, options?: ListFilesOptions): Promise<FileListResult>;
304
+ /**
305
+ * Fetch a single data point by its deterministic id (keccak256 of (owner, scope)).
306
+ * Returns null on 404. The gateway omits `status` from the response body — read it
307
+ * from the on-chain DataRegistryV2 contract when you need the canonical lifecycle state.
308
+ */
309
+ getDataPoint(dataPointId: string): Promise<DataPointRecord | null>;
310
+ /**
311
+ * Page through an owner's data points. Cursor is opaque; pass `null` for the first
312
+ * page and feed back `result.cursor` until it returns null.
313
+ */
314
+ listDataPointsByOwner(owner: string, cursor: string | null, options?: ListDataPointsOptions): Promise<DataPointListResult>;
129
315
  getSchema(schemaId: string): Promise<Schema | null>;
130
316
  registerServer(params: RegisterServerParams): Promise<RegisterServerResult>;
131
- registerFile(params: RegisterFileParams): Promise<{
132
- fileId?: string;
133
- }>;
317
+ registerBuilder(params: RegisterBuilderParams): Promise<RegisterBuilderResult>;
318
+ registerDataPoint(params: RegisterDataPointParams): Promise<RegisterDataPointResult>;
134
319
  createGrant(params: CreateGrantParams): Promise<{
135
320
  grantId?: string;
136
321
  }>;
137
322
  revokeGrant(params: RevokeGrantParams): Promise<void>;
138
- /**
139
- * Soft-deletes (de-registers) a file at the gateway. Resolves on 200 and on 409
140
- * (already deleted) — 409 is treated as idempotent success. Other non-2xx, including
141
- * 404 (file not registered), throw; the PS delete cascade decides whether a 404 is
142
- * benign (blob already gone) or a hard failure.
143
- */
144
- deleteFile(params: DeleteFileParams): Promise<void>;
323
+ getEscrowBalance(account: string): Promise<EscrowBalance>;
324
+ submitEscrowDeposit(params: SubmitDepositParams): Promise<DepositState>;
325
+ payForOperation(params: PayForOperationParams): Promise<PayForOperationResult>;
326
+ settle(params?: SettleParams): Promise<SettleResult>;
145
327
  }
146
328
  export declare function createGatewayClient(baseUrl: string): GatewayClient;
@@ -4,16 +4,6 @@ function createGatewayClient(baseUrl) {
4
4
  const envelope = await res.json();
5
5
  return envelope.data;
6
6
  }
7
- function normalizeFileRecord(record) {
8
- return {
9
- fileId: record.fileId ?? record.id ?? "",
10
- owner: record.owner ?? record.ownerAddress ?? "",
11
- url: record.url,
12
- schemaId: record.schemaId,
13
- createdAt: record.createdAt ?? record.addedAt ?? "",
14
- deletedAt: record.deletedAt ?? null
15
- };
16
- }
17
7
  function getMutationId(body, key) {
18
8
  const value = body[key] ?? body["id"];
19
9
  return typeof value === "string" ? value : void 0;
@@ -63,30 +53,34 @@ function createGatewayClient(baseUrl) {
63
53
  }
64
54
  return unwrapEnvelope(res);
65
55
  },
66
- async getFile(fileId) {
67
- const res = await fetch(`${base}/v1/files/${fileId}`);
56
+ async getDataPoint(dataPointId) {
57
+ const res = await fetch(`${base}/v1/data/${dataPointId}`);
68
58
  if (res.status === 404) return null;
69
59
  if (!res.ok) {
70
60
  throw new Error(`Gateway error: ${res.status} ${res.statusText}`);
71
61
  }
72
- return normalizeFileRecord(await unwrapEnvelope(res));
62
+ return unwrapEnvelope(res);
73
63
  },
74
- async listFilesSince(owner, cursor, options) {
64
+ async listDataPointsByOwner(owner, cursor, options) {
75
65
  const params = new URLSearchParams({ user: owner });
76
66
  if (cursor !== null) {
77
- params.set("since", cursor);
67
+ params.set("cursor", cursor);
68
+ }
69
+ if (options?.since) {
70
+ params.set("since", options.since);
78
71
  }
79
- if (options?.includeDeleted) {
80
- params.set("includeDeleted", "true");
72
+ if (options?.limit !== void 0) {
73
+ params.set("limit", String(options.limit));
81
74
  }
82
- const res = await fetch(`${base}/v1/files?${params.toString()}`);
75
+ const res = await fetch(`${base}/v1/data?${params.toString()}`);
83
76
  if (!res.ok) {
84
77
  throw new Error(`Gateway error: ${res.status} ${res.statusText}`);
85
78
  }
86
- const data = await unwrapEnvelope(res);
79
+ const envelope = await res.json();
80
+ const nextCursor = envelope.pagination?.hasMore === false ? null : envelope.pagination?.nextCursor ?? null;
87
81
  return {
88
- files: data.files.map(normalizeFileRecord),
89
- cursor: data.cursor
82
+ dataPoints: envelope.data.dataPoints,
83
+ cursor: nextCursor
90
84
  };
91
85
  },
92
86
  async getSchema(schemaId) {
@@ -127,8 +121,8 @@ function createGatewayClient(baseUrl) {
127
121
  alreadyRegistered: false
128
122
  };
129
123
  },
130
- async registerFile(params) {
131
- const res = await fetch(`${base}/v1/files`, {
124
+ async registerBuilder(params) {
125
+ const res = await fetch(`${base}/v1/builders`, {
132
126
  method: "POST",
133
127
  headers: {
134
128
  "Content-Type": "application/json",
@@ -136,22 +130,57 @@ function createGatewayClient(baseUrl) {
136
130
  },
137
131
  body: JSON.stringify({
138
132
  ownerAddress: params.ownerAddress,
139
- url: params.url,
140
- schemaId: params.schemaId
133
+ granteeAddress: params.granteeAddress,
134
+ publicKey: params.publicKey,
135
+ appUrl: params.appUrl
141
136
  })
142
137
  });
143
138
  if (res.status === 409) {
144
139
  const body2 = await res.json().catch(() => ({}));
145
140
  return {
146
- fileId: getMutationId(body2, "fileId")
141
+ builderId: getMutationId(
142
+ body2,
143
+ "builderId"
144
+ ),
145
+ alreadyRegistered: true
147
146
  };
148
147
  }
149
148
  if (!res.ok) {
150
149
  throw new Error(`Gateway error: ${res.status} ${res.statusText}`);
151
150
  }
152
- const body = await res.json();
151
+ const body = await res.json().catch(() => ({}));
152
+ return {
153
+ builderId: getMutationId(body, "builderId"),
154
+ alreadyRegistered: false
155
+ };
156
+ },
157
+ async registerDataPoint(params) {
158
+ const res = await fetch(`${base}/v1/data`, {
159
+ method: "POST",
160
+ headers: {
161
+ "Content-Type": "application/json",
162
+ Authorization: `Web3Signed ${params.signature}`
163
+ },
164
+ body: JSON.stringify({
165
+ ownerAddress: params.ownerAddress,
166
+ scope: params.scope,
167
+ dataHash: params.dataHash,
168
+ metadataHash: params.metadataHash,
169
+ expectedVersion: params.expectedVersion
170
+ })
171
+ });
172
+ if (!res.ok) {
173
+ const body2 = await res.json().catch(() => ({}));
174
+ const detail = body2.error ?? res.statusText;
175
+ throw new Error(`Gateway error: ${res.status} ${detail}`);
176
+ }
177
+ const body = await res.json().catch(() => ({}));
153
178
  return {
154
- fileId: getMutationId(body, "fileId")
179
+ dataPointId: getMutationId(
180
+ body,
181
+ "dataPointId"
182
+ ),
183
+ expectedVersion: body.expectedVersion
155
184
  };
156
185
  },
157
186
  async createGrant(params) {
@@ -164,8 +193,9 @@ function createGatewayClient(baseUrl) {
164
193
  body: JSON.stringify({
165
194
  grantorAddress: params.grantorAddress,
166
195
  granteeId: params.granteeId,
167
- grant: params.grant,
168
- fileIds: params.fileIds
196
+ scopes: params.scopes,
197
+ grantVersion: params.grantVersion,
198
+ expiresAt: params.expiresAt
169
199
  })
170
200
  });
171
201
  if (res.status === 409) {
@@ -190,7 +220,8 @@ function createGatewayClient(baseUrl) {
190
220
  Authorization: `Web3Signed ${params.signature}`
191
221
  },
192
222
  body: JSON.stringify({
193
- grantorAddress: params.grantorAddress
223
+ grantorAddress: params.grantorAddress,
224
+ grantVersion: params.grantVersion
194
225
  })
195
226
  });
196
227
  if (res.status === 409) return;
@@ -198,21 +229,62 @@ function createGatewayClient(baseUrl) {
198
229
  throw new Error(`Gateway error: ${res.status} ${res.statusText}`);
199
230
  }
200
231
  },
201
- async deleteFile(params) {
202
- const res = await fetch(`${base}/v1/files/${params.fileId}`, {
203
- method: "DELETE",
232
+ async getEscrowBalance(account) {
233
+ const res = await fetch(`${base}/v1/escrow/balance?account=${account}`);
234
+ if (!res.ok) {
235
+ throw new Error(`Gateway error: ${res.status} ${res.statusText}`);
236
+ }
237
+ return await res.json();
238
+ },
239
+ async submitEscrowDeposit(params) {
240
+ const res = await fetch(`${base}/v1/escrow/deposit`, {
241
+ method: "POST",
242
+ headers: { "Content-Type": "application/json" },
243
+ body: JSON.stringify({ txHash: params.txHash })
244
+ });
245
+ if (res.status !== 200 && res.status !== 202) {
246
+ throw new Error(`Gateway error: ${res.status} ${res.statusText}`);
247
+ }
248
+ return await res.json();
249
+ },
250
+ async payForOperation(params) {
251
+ const body = {
252
+ payerAddress: params.payerAddress,
253
+ opType: params.opType,
254
+ opId: params.opId,
255
+ asset: params.asset,
256
+ amount: params.amount,
257
+ paymentNonce: params.paymentNonce
258
+ };
259
+ if (params.accessRecord) {
260
+ body["accessRecord"] = params.accessRecord;
261
+ }
262
+ const res = await fetch(`${base}/v1/escrow/pay`, {
263
+ method: "POST",
204
264
  headers: {
205
265
  "Content-Type": "application/json",
206
266
  Authorization: `Web3Signed ${params.signature}`
207
267
  },
208
- body: JSON.stringify({
209
- ownerAddress: params.ownerAddress
210
- })
268
+ body: JSON.stringify(body)
269
+ });
270
+ if (!res.ok) {
271
+ throw new Error(`Gateway error: ${res.status} ${res.statusText}`);
272
+ }
273
+ return await res.json();
274
+ },
275
+ async settle(params) {
276
+ const res = await fetch(`${base}/v1/settle`, {
277
+ method: "POST",
278
+ headers: { "Content-Type": "application/json" },
279
+ // The gateway accepts an empty body; only `limit` is recognised.
280
+ // Always send a JSON body so the gateway's req.body shape parse
281
+ // doesn't have to deal with an undefined.
282
+ body: JSON.stringify(params ?? {})
211
283
  });
212
- if (res.status === 409) return;
213
284
  if (!res.ok) {
214
285
  throw new Error(`Gateway error: ${res.status} ${res.statusText}`);
215
286
  }
287
+ return await res.json();
216
288
  }
217
289
  };
218
290
  }