@opendatalabs/vana-sdk 3.23.0 → 4.0.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 (84) hide show
  1. package/README.md +57 -0
  2. package/dist/auth/errors.cjs +1 -1
  3. package/dist/auth/web3-signed.cjs +1 -1
  4. package/dist/crypto/envelope/job-stream.test.d.ts +1 -0
  5. package/dist/crypto/envelope/job.cjs +593 -38
  6. package/dist/crypto/envelope/job.cjs.map +1 -1
  7. package/dist/crypto/envelope/job.d.ts +44 -27
  8. package/dist/crypto/envelope/job.js +589 -37
  9. package/dist/crypto/envelope/job.js.map +1 -1
  10. package/dist/direct/access-request-client.cjs +1 -1
  11. package/dist/direct/connect-flow.cjs +43 -1
  12. package/dist/direct/connect-flow.cjs.map +1 -1
  13. package/dist/direct/connect-flow.d.ts +12 -0
  14. package/dist/direct/connect-flow.js +43 -1
  15. package/dist/direct/connect-flow.js.map +1 -1
  16. package/dist/direct/controller.cjs +1 -1
  17. package/dist/direct/errors.cjs +1 -1
  18. package/dist/direct/escrow-payment.cjs.map +1 -1
  19. package/dist/direct/escrow-payment.d.ts +2 -2
  20. package/dist/direct/escrow-payment.js.map +1 -1
  21. package/dist/direct/personal-server-read.cjs +2 -2
  22. package/dist/direct/use-direct-vana-connect.cjs +2 -1
  23. package/dist/direct/use-direct-vana-connect.cjs.map +1 -1
  24. package/dist/direct/use-direct-vana-connect.d.ts +3 -1
  25. package/dist/direct/use-direct-vana-connect.js +2 -1
  26. package/dist/direct/use-direct-vana-connect.js.map +1 -1
  27. package/dist/error-entry-points.test.d.ts +1 -0
  28. package/dist/errors.cjs +7 -0
  29. package/dist/errors.cjs.map +1 -1
  30. package/dist/errors.d.ts +10 -0
  31. package/dist/errors.js +6 -0
  32. package/dist/errors.js.map +1 -1
  33. package/dist/index.browser.d.ts +4 -4
  34. package/dist/index.browser.js +882 -518
  35. package/dist/index.browser.js.map +4 -4
  36. package/dist/index.node.cjs +1035 -705
  37. package/dist/index.node.cjs.map +4 -4
  38. package/dist/index.node.d.ts +4 -4
  39. package/dist/index.node.js +989 -567
  40. package/dist/index.node.js.map +4 -4
  41. package/dist/protocol/data-point-deletion.cjs +1 -1
  42. package/dist/protocol/derivative-questions.cjs +1 -1
  43. package/dist/protocol/derivative-status.cjs +1 -1
  44. package/dist/protocol/eip712.cjs +28 -2
  45. package/dist/protocol/eip712.cjs.map +1 -1
  46. package/dist/protocol/eip712.d.ts +70 -0
  47. package/dist/protocol/eip712.js +24 -1
  48. package/dist/protocol/eip712.js.map +1 -1
  49. package/dist/protocol/escrow.cjs +154 -2
  50. package/dist/protocol/escrow.cjs.map +1 -1
  51. package/dist/protocol/escrow.d.ts +145 -2
  52. package/dist/protocol/escrow.js +152 -1
  53. package/dist/protocol/escrow.js.map +1 -1
  54. package/dist/protocol/fixtures/moksha-identity.json +20 -0
  55. package/dist/protocol/gateway.cjs +1 -1
  56. package/dist/protocol/gateway.cjs.map +1 -1
  57. package/dist/protocol/gateway.d.ts +8 -38
  58. package/dist/protocol/gateway.js.map +1 -1
  59. package/dist/protocol/identity.cjs +7 -2
  60. package/dist/protocol/identity.cjs.map +1 -1
  61. package/dist/protocol/identity.js +7 -2
  62. package/dist/protocol/identity.js.map +1 -1
  63. package/dist/protocol/jobs-client.cjs +73 -21
  64. package/dist/protocol/jobs-client.cjs.map +1 -1
  65. package/dist/protocol/jobs-client.d.ts +7 -5
  66. package/dist/protocol/jobs-client.js +74 -21
  67. package/dist/protocol/jobs-client.js.map +1 -1
  68. package/dist/protocol/jobs.cjs +0 -3
  69. package/dist/protocol/jobs.cjs.map +1 -1
  70. package/dist/protocol/jobs.d.ts +21 -13
  71. package/dist/protocol/jobs.js +0 -2
  72. package/dist/protocol/jobs.js.map +1 -1
  73. package/dist/protocol/lineage.cjs +1 -1
  74. package/dist/protocol/personal-server-data.cjs +1 -1
  75. package/dist/protocol/personal-server-write.cjs +1 -1
  76. package/dist/protocol/write-request.cjs +1 -1
  77. package/dist/protocol/write-signer.cjs +1 -1
  78. package/dist/react.cjs.map +1 -1
  79. package/dist/react.d.ts +1 -1
  80. package/dist/react.js.map +1 -1
  81. package/dist/session-relay/client.cjs +1 -1
  82. package/dist/session-relay/errors.cjs +1 -1
  83. package/dist/session-relay/index.cjs +1 -1
  84. package/package.json +1 -1
@@ -1147,346 +1147,8 @@ var init_browser2 = __esm({
1147
1147
  }
1148
1148
  });
1149
1149
 
1150
- // src/errors.ts
1151
- var VanaError = class extends Error {
1152
- constructor(message, code) {
1153
- super(message);
1154
- this.code = code;
1155
- this.name = this.constructor.name;
1156
- if (Error.captureStackTrace) {
1157
- Error.captureStackTrace(this, this.constructor);
1158
- }
1159
- }
1160
- code;
1161
- };
1162
- var RelayerError = class extends VanaError {
1163
- constructor(message, statusCode, response) {
1164
- super(message, "RELAYER_ERROR");
1165
- this.statusCode = statusCode;
1166
- this.response = response;
1167
- }
1168
- statusCode;
1169
- response;
1170
- };
1171
- var UserRejectedRequestError = class extends VanaError {
1172
- constructor(message = "User rejected the signature request") {
1173
- super(message, "USER_REJECTED_REQUEST");
1174
- }
1175
- };
1176
- var InvalidConfigurationError = class extends VanaError {
1177
- constructor(message) {
1178
- super(message, "INVALID_CONFIGURATION");
1179
- }
1180
- };
1181
- var ContractNotFoundError = class extends VanaError {
1182
- constructor(contractName, chainId) {
1183
- super(
1184
- `Contract ${contractName} not found on chain ${chainId}`,
1185
- "CONTRACT_NOT_FOUND"
1186
- );
1187
- }
1188
- };
1189
- var BlockchainError = class extends VanaError {
1190
- constructor(message, originalError) {
1191
- super(message, "BLOCKCHAIN_ERROR");
1192
- this.originalError = originalError;
1193
- }
1194
- originalError;
1195
- };
1196
- var SerializationError = class extends VanaError {
1197
- constructor(message) {
1198
- super(message, "SERIALIZATION_ERROR");
1199
- }
1200
- };
1201
- var SignatureError = class extends VanaError {
1202
- constructor(message, originalError) {
1203
- super(message, "SIGNATURE_ERROR");
1204
- this.originalError = originalError;
1205
- }
1206
- originalError;
1207
- };
1208
- var NetworkError = class extends VanaError {
1209
- constructor(message, originalError) {
1210
- super(message, "NETWORK_ERROR");
1211
- this.originalError = originalError;
1212
- }
1213
- originalError;
1214
- };
1215
- var NonceError = class extends VanaError {
1216
- constructor(message) {
1217
- super(message, "NONCE_ERROR");
1218
- }
1219
- };
1220
- var PersonalServerError = class extends VanaError {
1221
- constructor(message, originalError) {
1222
- super(message, "PERSONAL_SERVER_ERROR");
1223
- this.originalError = originalError;
1224
- }
1225
- originalError;
1226
- };
1227
- var ServerUrlMismatchError = class extends VanaError {
1228
- constructor(existingUrl, providedUrl, serverId) {
1229
- super(
1230
- `Server ${serverId} is already registered with URL "${existingUrl}". Cannot change to "${providedUrl}".`,
1231
- "SERVER_URL_MISMATCH"
1232
- );
1233
- this.existingUrl = existingUrl;
1234
- this.providedUrl = providedUrl;
1235
- this.serverId = serverId;
1236
- }
1237
- existingUrl;
1238
- providedUrl;
1239
- serverId;
1240
- };
1241
- var PermissionError = class extends VanaError {
1242
- constructor(message, originalError) {
1243
- super(message, "PERMISSION_ERROR");
1244
- this.originalError = originalError;
1245
- }
1246
- originalError;
1247
- };
1248
- var ReadOnlyError = class extends VanaError {
1249
- constructor(operation, suggestion = "Initialize the SDK with a walletClient to perform this operation") {
1250
- super(
1251
- `Operation '${operation}' requires a wallet client. ${suggestion}`,
1252
- "READ_ONLY_ERROR"
1253
- );
1254
- this.operation = operation;
1255
- this.suggestion = suggestion;
1256
- }
1257
- /** The operation that was attempted */
1258
- operation;
1259
- /** Suggested solution for fixing the error */
1260
- suggestion;
1261
- };
1262
- var TransactionPendingError = class extends VanaError {
1263
- constructor(operationId, message, lastKnownStatus) {
1264
- super(
1265
- `Transaction operation pending: ${message} (operationId: ${operationId})`,
1266
- "TRANSACTION_PENDING"
1267
- );
1268
- this.operationId = operationId;
1269
- this.lastKnownStatus = lastKnownStatus;
1270
- }
1271
- operationId;
1272
- lastKnownStatus;
1273
- /**
1274
- * Converts the error to a JSON-serializable format.
1275
- *
1276
- * @remarks
1277
- * Useful for logging, storage, or transmission of error details.
1278
- *
1279
- * @returns JSON representation of the error
1280
- */
1281
- toJSON() {
1282
- return {
1283
- name: this.name,
1284
- code: this.code,
1285
- message: this.message,
1286
- operationId: this.operationId,
1287
- lastKnownStatus: this.lastKnownStatus
1288
- };
1289
- }
1290
- };
1291
- var PersonalServerWriteError = class extends VanaError {
1292
- constructor(message, code, status, errorCode = null, details) {
1293
- super(message, code);
1294
- this.status = status;
1295
- this.errorCode = errorCode;
1296
- this.details = details;
1297
- }
1298
- status;
1299
- errorCode;
1300
- details;
1301
- };
1302
- var WriteRequestError = class extends PersonalServerWriteError {
1303
- constructor(message, details) {
1304
- super(message, "WRITE_INVALID_REQUEST", void 0, null, details);
1305
- }
1306
- };
1307
- var WriteTransportError = class extends PersonalServerWriteError {
1308
- constructor(message, attempts, cause) {
1309
- super(message, "WRITE_TRANSPORT_ERROR", void 0, null, { attempts });
1310
- this.attempts = attempts;
1311
- this.cause = cause;
1312
- }
1313
- attempts;
1314
- };
1315
- var WriteSessionError = class extends PersonalServerWriteError {
1316
- constructor(message, status, errorCode = null, details) {
1317
- super(message, "WRITE_SESSION_REJECTED", status, errorCode, details);
1318
- }
1319
- };
1320
- var WriteSessionExpiredError = class extends PersonalServerWriteError {
1321
- constructor(message, details) {
1322
- super(message, "WRITE_SESSION_EXPIRED", void 0, null, details);
1323
- }
1324
- };
1325
- var WriteUnauthorizedError = class extends PersonalServerWriteError {
1326
- constructor(message, errorCode = null, details) {
1327
- super(message, "WRITE_UNAUTHORIZED", 401, errorCode, details);
1328
- }
1329
- };
1330
- var WriteForbiddenError = class extends PersonalServerWriteError {
1331
- constructor(message, errorCode = null, details) {
1332
- super(message, "WRITE_FORBIDDEN", 403, errorCode, details);
1333
- }
1334
- };
1335
- var WriteConflictError = class extends PersonalServerWriteError {
1336
- constructor(message, errorCode = null, details) {
1337
- super(message, "WRITE_CONFLICT", 409, errorCode, details);
1338
- }
1339
- };
1340
- var WriteLineageError = class extends PersonalServerWriteError {
1341
- constructor(message, status = 422, errorCode = null, details) {
1342
- super(message, "WRITE_LINEAGE_REJECTED", status, errorCode, details);
1343
- }
1344
- };
1345
- var WriteRejectedError = class extends PersonalServerWriteError {
1346
- constructor(message, status, errorCode = null, details) {
1347
- super(message, "WRITE_REJECTED", status, errorCode, details);
1348
- }
1349
- };
1350
- var JobsClientError = class extends VanaError {
1351
- constructor(message, code, status, errorCode = null, details) {
1352
- super(message, code);
1353
- this.status = status;
1354
- this.errorCode = errorCode;
1355
- this.details = details;
1356
- }
1357
- status;
1358
- errorCode;
1359
- details;
1360
- };
1361
- var BuilderUnknownError = class extends JobsClientError {
1362
- constructor(message, details) {
1363
- super(message, "JOB_BUILDER_UNKNOWN", 403, "BUILDER_UNKNOWN", details);
1364
- }
1365
- };
1366
- var GrantInvalidError = class extends JobsClientError {
1367
- constructor(message, details) {
1368
- super(message, "JOB_GRANT_INVALID", 403, "GRANT_INVALID", details);
1369
- }
1370
- };
1371
- var OwnerNotReadyError = class extends JobsClientError {
1372
- constructor(message, details) {
1373
- super(message, "JOB_OWNER_NOT_READY", 403, "OWNER_NOT_READY", details);
1374
- }
1375
- };
1376
- var JobIdTakenError = class extends JobsClientError {
1377
- constructor(message, details) {
1378
- super(message, "JOB_ID_TAKEN", 409, "JOB_ID_TAKEN", details);
1379
- }
1380
- };
1381
- var JobNotFoundError = class extends JobsClientError {
1382
- constructor(message, details) {
1383
- super(message, "JOB_NOT_FOUND", 404, "JOB_NOT_FOUND", details);
1384
- }
1385
- };
1386
- var JobRequestTooLargeError = class extends JobsClientError {
1387
- constructor(message, errorCode = "BODY_TOO_LARGE", details) {
1388
- super(message, "JOB_REQUEST_TOO_LARGE", 413, errorCode, details);
1389
- }
1390
- };
1391
- var JobTimeoutError = class extends JobsClientError {
1392
- constructor(message, details) {
1393
- super(message, "JOB_TIMEOUT", void 0, null, details);
1394
- }
1395
- };
1396
- var JobRejectedError = class extends JobsClientError {
1397
- constructor(message, status, errorCode = null, details) {
1398
- super(message, "JOB_REJECTED", status, errorCode, details);
1399
- }
1400
- };
1401
- var JobTransportError = class extends JobsClientError {
1402
- constructor(message, cause) {
1403
- super(message, "JOB_TRANSPORT_ERROR");
1404
- this.cause = cause;
1405
- }
1406
- };
1407
- var LineageReadError = class extends VanaError {
1408
- constructor(message, status, errorCode = null, details) {
1409
- super(message, "LINEAGE_READ_ERROR");
1410
- this.status = status;
1411
- this.errorCode = errorCode;
1412
- this.details = details;
1413
- }
1414
- status;
1415
- errorCode;
1416
- details;
1417
- };
1418
- var DerivativeQuestionRejectedError = class extends PersonalServerWriteError {
1419
- constructor(message, status, errorCode = null, details) {
1420
- super(message, "DERIVATIVE_QUESTION_REJECTED", status, errorCode, details);
1421
- }
1422
- };
1423
- var DerivativeQuestionInvalidError = class extends PersonalServerWriteError {
1424
- constructor(message, status = 400, errorCode = null, details) {
1425
- super(message, "DERIVATIVE_QUESTION_INVALID", status, errorCode, details);
1426
- }
1427
- };
1428
- var DerivativeQuestionNotFoundError = class extends PersonalServerWriteError {
1429
- constructor(message, errorCode = null, details) {
1430
- super(message, "DERIVATIVE_QUESTION_NOT_FOUND", 404, errorCode, details);
1431
- }
1432
- };
1433
- var DerivativeDerivedScopeRequiredError = class extends PersonalServerWriteError {
1434
- constructor(message, errorCode = null, details) {
1435
- super(
1436
- message,
1437
- "DERIVATIVE_DERIVED_SCOPE_REQUIRED",
1438
- 400,
1439
- errorCode,
1440
- details
1441
- );
1442
- }
1443
- };
1444
- var DerivativeSourceNotGrantedError = class extends PersonalServerWriteError {
1445
- constructor(message, errorCode = null, details) {
1446
- super(message, "DERIVATIVE_SOURCE_NOT_GRANTED", 403, errorCode, details);
1447
- }
1448
- };
1449
- var DerivativeCycleError = class extends PersonalServerWriteError {
1450
- constructor(message, errorCode = null, details) {
1451
- super(message, "DERIVATIVE_CYCLE", 409, errorCode, details);
1452
- }
1453
- };
1454
- var DerivativeComputeUnavailableError = class extends PersonalServerWriteError {
1455
- constructor(message, errorCode = null, details) {
1456
- super(message, "DERIVATIVE_COMPUTE_UNAVAILABLE", 503, errorCode, details);
1457
- }
1458
- };
1459
- var DerivativeQuestionTimeoutError = class extends PersonalServerWriteError {
1460
- constructor(message, details) {
1461
- super(message, "DERIVATIVE_QUESTION_TIMEOUT", void 0, null, details);
1462
- }
1463
- };
1464
- var DerivativeQuestionFailedError = class extends PersonalServerWriteError {
1465
- constructor(message, details) {
1466
- super(message, "DERIVATIVE_QUESTION_FAILED", void 0, null, details);
1467
- }
1468
- };
1469
- var DataPointDeletedError = class extends VanaError {
1470
- constructor(message, details = {}) {
1471
- super(message, "DATA_POINT_DELETED");
1472
- this.details = details;
1473
- }
1474
- details;
1475
- };
1476
- var DataPointNotFoundError = class extends VanaError {
1477
- constructor(message, details = {}) {
1478
- super(message, "DATA_POINT_NOT_FOUND");
1479
- this.details = details;
1480
- }
1481
- details;
1482
- };
1483
- var DataPointVersionConflictError = class extends VanaError {
1484
- constructor(message, details = {}) {
1485
- super(message, "DATA_POINT_VERSION_CONFLICT");
1486
- this.details = details;
1487
- }
1488
- details;
1489
- };
1150
+ // src/index.node.ts
1151
+ export * from "./errors.js";
1490
1152
 
1491
1153
  // src/contracts/contractController.ts
1492
1154
  import {
@@ -31860,31 +31522,11 @@ async function decryptWithPassword(encrypted, password) {
31860
31522
 
31861
31523
  // src/auth/web3-signed.ts
31862
31524
  import { recoverMessageAddress as recoverMessageAddress2 } from "viem";
31863
-
31864
- // src/auth/errors.ts
31865
- var MissingAuthError = class extends VanaError {
31866
- constructor(message = "Missing authentication", details) {
31867
- super(message, "MISSING_AUTH");
31868
- this.details = details;
31869
- }
31870
- details;
31871
- };
31872
- var InvalidSignatureError = class extends VanaError {
31873
- constructor(details, message = "Invalid signature") {
31874
- super(message, "INVALID_SIGNATURE");
31875
- this.details = details;
31876
- }
31877
- details;
31878
- };
31879
- var ExpiredTokenError = class extends VanaError {
31880
- constructor(details, message = "Token has expired") {
31881
- super(message, "EXPIRED_TOKEN");
31882
- this.details = details;
31883
- }
31884
- details;
31885
- };
31886
-
31887
- // src/auth/web3-signed.ts
31525
+ import {
31526
+ MissingAuthError,
31527
+ InvalidSignatureError,
31528
+ ExpiredTokenError
31529
+ } from "./auth/errors.js";
31888
31530
  var WEB3_SIGNED_PREFIX = "Web3Signed ";
31889
31531
  var CLOCK_SKEW_SECONDS = 60;
31890
31532
  function base64urlDecode(input) {
@@ -32002,6 +31644,13 @@ async function verifyWeb3Signed(params) {
32002
31644
  return { signer, payload };
32003
31645
  }
32004
31646
 
31647
+ // src/index.node.ts
31648
+ import {
31649
+ MissingAuthError as MissingAuthError2,
31650
+ InvalidSignatureError as InvalidSignatureError2,
31651
+ ExpiredTokenError as ExpiredTokenError2
31652
+ } from "./auth/errors.js";
31653
+
32005
31654
  // src/auth/pkce.ts
32006
31655
  var PKCE_VERIFIER_ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~";
32007
31656
  var PKCE_VERIFIER_MIN_LENGTH = 43;
@@ -32369,6 +32018,9 @@ function escrowPaymentDomain(config) {
32369
32018
  config.contracts.dataPortabilityEscrow
32370
32019
  );
32371
32020
  }
32021
+ function withdrawAuthorizationDomain(config) {
32022
+ return escrowPaymentDomain(config);
32023
+ }
32372
32024
  var GRANT_REGISTRATION_TYPES = {
32373
32025
  GrantRegistration: [
32374
32026
  { name: "grantorAddress", type: "address" },
@@ -32401,6 +32053,15 @@ var BUILDER_REGISTRATION_TYPES = {
32401
32053
  { name: "appUrl", type: "string" }
32402
32054
  ]
32403
32055
  };
32056
+ var WITHDRAW_AUTHORIZATION_TYPES = {
32057
+ WithdrawAuthorization: [
32058
+ { name: "account", type: "address" },
32059
+ { name: "asset", type: "address" },
32060
+ { name: "amount", type: "uint256" },
32061
+ { name: "withdrawNonce", type: "uint256" },
32062
+ { name: "deadline", type: "uint256" }
32063
+ ]
32064
+ };
32404
32065
  var ADD_DATA_TYPES = {
32405
32066
  AddData: [
32406
32067
  { name: "ownerAddress", type: "address" },
@@ -32419,6 +32080,14 @@ var RECORD_DATA_ACCESS_TYPES = {
32419
32080
  { name: "recordId", type: "bytes32" }
32420
32081
  ]
32421
32082
  };
32083
+ function buildWithdrawAuthorizationTypedData(config, message) {
32084
+ return {
32085
+ domain: withdrawAuthorizationDomain(config),
32086
+ types: WITHDRAW_AUTHORIZATION_TYPES,
32087
+ primaryType: "WithdrawAuthorization",
32088
+ message
32089
+ };
32090
+ }
32422
32091
 
32423
32092
  // src/protocol/identity.ts
32424
32093
  init_interface();
@@ -32457,8 +32126,13 @@ function emptyAnchor() {
32457
32126
  var ENCLAVE_TRUST_ANCHORS = Object.freeze({
32458
32127
  // filled at fleet provisioning; verify fails closed while empty
32459
32128
  [VANA_MAINNET_CHAIN_ID]: emptyAnchor(),
32460
- // filled at fleet provisioning; verify fails closed while empty
32461
- [MOKSHA_CHAIN_ID]: emptyAnchor()
32129
+ // Moksha workers share this dstack app and KMS root; the controller does not derive owner keys.
32130
+ [MOKSHA_CHAIN_ID]: Object.freeze({
32131
+ kmsRootPubkey: "0x0434c76e0c3f52ec64cbf9bbf5c910c272330166fd656c0a86bb330963e46910e1a0e6fa51bec74be2f9129342707636060d85856d102cee8290185409ecf7422f",
32132
+ appIds: Object.freeze([
32133
+ "0xec9a39de98c760e1ded9f1e97016dc5f0e357cf2"
32134
+ ])
32135
+ })
32462
32136
  });
32463
32137
  function userPsId(chainId, ownerAddress) {
32464
32138
  const packed = encodePacked(
@@ -32605,13 +32279,14 @@ var MAX_LEASE_SECONDS = 300;
32605
32279
  var MAX_ATTEMPTS = 3;
32606
32280
  var MAX_WAIT_SECONDS = 25;
32607
32281
  var CLAIM_POLL_FLOOR_MS = 1e3;
32608
- var MAX_INLINE_RESULT_BYTES = 1048576;
32609
32282
  var DEFAULT_JOB_DEADLINE_SECONDS = 600;
32610
32283
  var MAX_JOB_DEADLINE_SECONDS = 3600;
32611
32284
 
32612
32285
  // src/protocol/jobs-client.ts
32613
32286
  import { randomUUID } from "node:crypto";
32287
+ import { sha256 as sha2566 } from "@noble/hashes/sha2";
32614
32288
  import {
32289
+ bytesToHex as bytesToHex3,
32615
32290
  isAddress as isAddress2,
32616
32291
  isAddressEqual as isAddressEqual2,
32617
32292
  isHex as isHex2
@@ -32619,11 +32294,26 @@ import {
32619
32294
  import { privateKeyToAccount, publicKeyToAddress as publicKeyToAddress2 } from "viem/accounts";
32620
32295
 
32621
32296
  // src/crypto/envelope/job.ts
32297
+ init_constants();
32622
32298
  init_interface();
32623
32299
  import { sha256 as sha2565 } from "@noble/hashes/sha2";
32624
32300
  import { bytesToHex as bytesToHex2, fromHex as fromHex6, isAddress, isHex, toHex as toHex8 } from "viem";
32625
32301
  var textDecoder = new TextDecoder();
32626
32302
  var textEncoder = new TextEncoder();
32303
+ var MAX_JOB_RESULT_HEADER_BYTES = 4096;
32304
+ var WRAPPED_KEY_LENGTH_BYTES = 4;
32305
+ var FRAME_LENGTH_BYTES = 4;
32306
+ var FRAME_FLAGS_BYTES = 1;
32307
+ var AES_KEY_BYTES = 32;
32308
+ var AES_GCM_NONCE_BYTES = 12;
32309
+ var AES_GCM_TAG_BYTES = 16;
32310
+ var WRAPPED_METADATA_LENGTH_BYTES = 4;
32311
+ var WRAPPED_KEY_PLAINTEXT_PREFIX_BYTES = AES_KEY_BYTES + AES_GCM_NONCE_BYTES + WRAPPED_METADATA_LENGTH_BYTES;
32312
+ var MAX_WRAPPED_KEY_BYTES = 8192;
32313
+ var FINAL_FRAME_FLAG = 1;
32314
+ var MAX_CHUNK_INDEX = 4294967295;
32315
+ var JOB_RESULT_FORMAT_VERSION = 2;
32316
+ var JOB_RESULT_CHUNK_BYTES = 1024 * 1024;
32627
32317
  var JobEnvelopeError = class extends Error {
32628
32318
  constructor(message) {
32629
32319
  super(message);
@@ -32655,21 +32345,68 @@ function requestPlaintext(envelope) {
32655
32345
  validateRequestEnvelope(envelope);
32656
32346
  return canonicalJsonBytes(envelope);
32657
32347
  }
32658
- function resultPlaintext(result) {
32659
- return textEncoder.encode(
32660
- JSON.stringify({
32661
- v: result.v,
32662
- jobId: result.jobId,
32663
- scope: result.scope,
32664
- version: result.version,
32665
- contentType: result.contentType,
32666
- body: result.body
32667
- })
32668
- );
32348
+ function resultMetadata(result) {
32349
+ return {
32350
+ v: result.v,
32351
+ jobId: result.jobId,
32352
+ scope: result.scope,
32353
+ version: result.version,
32354
+ contentType: result.contentType
32355
+ };
32669
32356
  }
32670
32357
  function encryptedBytesToBase64(encrypted) {
32671
32358
  return toBase64(fromHex6(`0x${serializeECIES(encrypted)}`, "bytes"));
32672
32359
  }
32360
+ function encryptedToBytes(encrypted) {
32361
+ const bytes = new Uint8Array(
32362
+ encrypted.iv.length + encrypted.ephemPublicKey.length + encrypted.ciphertext.length + encrypted.mac.length
32363
+ );
32364
+ let offset = 0;
32365
+ bytes.set(encrypted.iv, offset);
32366
+ offset += encrypted.iv.length;
32367
+ bytes.set(encrypted.ephemPublicKey, offset);
32368
+ offset += encrypted.ephemPublicKey.length;
32369
+ bytes.set(encrypted.ciphertext, offset);
32370
+ offset += encrypted.ciphertext.length;
32371
+ bytes.set(encrypted.mac, offset);
32372
+ return bytes;
32373
+ }
32374
+ function bytesToEncrypted(bytes) {
32375
+ const absoluteMinLength = FORMAT.IV_LENGTH + 1 + MAC.LENGTH + 1;
32376
+ if (bytes.length < absoluteMinLength) {
32377
+ throw new ECIESError(
32378
+ `Invalid ECIES data: too short (${bytes.length} bytes, minimum ${absoluteMinLength} bytes required)`,
32379
+ "DECRYPTION_FAILED"
32380
+ );
32381
+ }
32382
+ const prefix = bytes[FORMAT.EPHEMERAL_KEY_OFFSET];
32383
+ if (prefix !== CURVE.PREFIX.UNCOMPRESSED) {
32384
+ throw new ECIESError(
32385
+ `Invalid ephemeral public key: must be uncompressed format (0x04 prefix), got 0x${prefix.toString(16).padStart(2, "0")}`,
32386
+ "DECRYPTION_FAILED"
32387
+ );
32388
+ }
32389
+ const ephemKeySize = CURVE.UNCOMPRESSED_PUBLIC_KEY_LENGTH;
32390
+ const minLength = FORMAT.IV_LENGTH + ephemKeySize + MAC.LENGTH + 1;
32391
+ if (bytes.length < minLength) {
32392
+ throw new ECIESError(
32393
+ `Invalid ECIES data: too short (${bytes.length} bytes, minimum ${minLength} bytes required)`,
32394
+ "DECRYPTION_FAILED"
32395
+ );
32396
+ }
32397
+ return {
32398
+ iv: bytes.subarray(FORMAT.IV_OFFSET, FORMAT.IV_OFFSET + FORMAT.IV_LENGTH),
32399
+ ephemPublicKey: bytes.subarray(
32400
+ FORMAT.EPHEMERAL_KEY_OFFSET,
32401
+ FORMAT.EPHEMERAL_KEY_OFFSET + ephemKeySize
32402
+ ),
32403
+ ciphertext: bytes.subarray(
32404
+ FORMAT.EPHEMERAL_KEY_OFFSET + ephemKeySize,
32405
+ bytes.length - MAC.LENGTH
32406
+ ),
32407
+ mac: bytes.subarray(bytes.length - MAC.LENGTH)
32408
+ };
32409
+ }
32673
32410
  function base64ToEncrypted(ciphertext) {
32674
32411
  return deserializeECIES(toHex8(fromBase64(ciphertext)));
32675
32412
  }
@@ -32770,11 +32507,11 @@ function validateRequestEnvelope(value) {
32770
32507
  requireString(value.auth, "auth", "job request envelope");
32771
32508
  return value;
32772
32509
  }
32773
- function validateResult(value) {
32774
- requirePlainObject(value, "result", "job result");
32510
+ function validateResultMetadata(value) {
32511
+ requirePlainObject(value, "metadata", "job result");
32775
32512
  requireExactKeys(
32776
32513
  value,
32777
- ["v", "jobId", "scope", "version", "contentType", "body"],
32514
+ ["v", "jobId", "scope", "version", "contentType"],
32778
32515
  "job result"
32779
32516
  );
32780
32517
  if (value.v !== JOB_PROTOCOL_VERSION) {
@@ -32785,14 +32522,222 @@ function validateResult(value) {
32785
32522
  for (const field of ["jobId", "scope", "contentType"]) {
32786
32523
  requireString(value[field], field, "job result");
32787
32524
  }
32788
- if (typeof value.body !== "string") {
32789
- throw new JobEnvelopeError("Invalid job result: missing body");
32790
- }
32791
32525
  if (value.version !== null && typeof value.version !== "string") {
32792
32526
  throw new JobEnvelopeError("Invalid job result: missing version");
32793
32527
  }
32794
32528
  return value;
32795
32529
  }
32530
+ function validateResult(value) {
32531
+ requirePlainObject(value, "result", "job result");
32532
+ requireExactKeys(
32533
+ value,
32534
+ ["v", "jobId", "scope", "version", "contentType", "body"],
32535
+ "job result"
32536
+ );
32537
+ validateResultMetadata(resultMetadata(value));
32538
+ if (!(value.body instanceof Uint8Array)) {
32539
+ throw new JobEnvelopeError("Invalid job result: missing body");
32540
+ }
32541
+ return value;
32542
+ }
32543
+ function webCrypto() {
32544
+ if (typeof globalThis.crypto === "undefined" || typeof globalThis.crypto.getRandomValues !== "function" || !globalThis.crypto.subtle) {
32545
+ throw new JobEnvelopeError(
32546
+ "Job result streaming requires the Web Crypto API"
32547
+ );
32548
+ }
32549
+ return globalThis.crypto;
32550
+ }
32551
+ function uint32(value) {
32552
+ const bytes = new Uint8Array(4);
32553
+ new DataView(bytes.buffer).setUint32(0, value);
32554
+ return bytes;
32555
+ }
32556
+ function readUint32(bytes, offset = 0) {
32557
+ return new DataView(bytes.buffer, bytes.byteOffset + offset, 4).getUint32(0);
32558
+ }
32559
+ function wrappedKeyPlaintext(contentKey, noncePrefix, metadataBytes) {
32560
+ const plaintext = new Uint8Array(
32561
+ WRAPPED_KEY_PLAINTEXT_PREFIX_BYTES + metadataBytes.length
32562
+ );
32563
+ plaintext.set(contentKey, 0);
32564
+ plaintext.set(noncePrefix, AES_KEY_BYTES);
32565
+ new DataView(plaintext.buffer).setUint32(
32566
+ AES_KEY_BYTES + AES_GCM_NONCE_BYTES,
32567
+ metadataBytes.length
32568
+ );
32569
+ plaintext.set(metadataBytes, WRAPPED_KEY_PLAINTEXT_PREFIX_BYTES);
32570
+ return plaintext;
32571
+ }
32572
+ function parseWrappedKeyPlaintext(plaintext) {
32573
+ if (plaintext.length < WRAPPED_KEY_PLAINTEXT_PREFIX_BYTES) {
32574
+ throw new JobEnvelopeError("Invalid job result: wrapped key is truncated");
32575
+ }
32576
+ const metadataLength = readUint32(
32577
+ plaintext,
32578
+ AES_KEY_BYTES + AES_GCM_NONCE_BYTES
32579
+ );
32580
+ if (metadataLength > MAX_JOB_RESULT_HEADER_BYTES) {
32581
+ throw new JobEnvelopeError(
32582
+ `Invalid job result: header exceeds ${MAX_JOB_RESULT_HEADER_BYTES} bytes`
32583
+ );
32584
+ }
32585
+ if (plaintext.length !== WRAPPED_KEY_PLAINTEXT_PREFIX_BYTES + metadataLength) {
32586
+ throw new JobEnvelopeError(
32587
+ "Invalid job result: header length exceeds payload"
32588
+ );
32589
+ }
32590
+ const metadataBytes = plaintext.slice(WRAPPED_KEY_PLAINTEXT_PREFIX_BYTES);
32591
+ const metadata = validateResultMetadata(
32592
+ parseObject(metadataBytes, "job result header")
32593
+ );
32594
+ return {
32595
+ contentKey: plaintext.slice(0, AES_KEY_BYTES),
32596
+ noncePrefix: plaintext.slice(
32597
+ AES_KEY_BYTES,
32598
+ AES_KEY_BYTES + AES_GCM_NONCE_BYTES
32599
+ ),
32600
+ metadataBytes,
32601
+ metadata
32602
+ };
32603
+ }
32604
+ async function importAesKey(contentKey, usage) {
32605
+ return webCrypto().subtle.importKey(
32606
+ "raw",
32607
+ contentKey,
32608
+ { name: "AES-GCM" },
32609
+ false,
32610
+ [usage]
32611
+ );
32612
+ }
32613
+ function chunkNonce(noncePrefix, chunkIndex) {
32614
+ if (chunkIndex > MAX_CHUNK_INDEX) {
32615
+ throw new JobEnvelopeError("Invalid job result: too many chunks");
32616
+ }
32617
+ const nonce = noncePrefix.slice();
32618
+ const view = new DataView(nonce.buffer, nonce.byteOffset, nonce.byteLength);
32619
+ view.setUint32(8, view.getUint32(8) ^ chunkIndex);
32620
+ return nonce;
32621
+ }
32622
+ function chunkAad(metadataBytes, chunkIndex, final, plaintextLength) {
32623
+ const aad = new Uint8Array(14 + metadataBytes.length);
32624
+ aad[0] = JOB_RESULT_FORMAT_VERSION;
32625
+ aad.set(uint32(metadataBytes.length), 1);
32626
+ aad.set(metadataBytes, 5);
32627
+ aad.set(uint32(chunkIndex), 5 + metadataBytes.length);
32628
+ aad[9 + metadataBytes.length] = final ? FINAL_FRAME_FLAG : 0;
32629
+ aad.set(uint32(plaintextLength), 10 + metadataBytes.length);
32630
+ return aad;
32631
+ }
32632
+ async function encryptResultChunk(key, noncePrefix, metadataBytes, plaintext, chunkIndex, final) {
32633
+ const encrypted = new Uint8Array(
32634
+ await webCrypto().subtle.encrypt(
32635
+ {
32636
+ name: "AES-GCM",
32637
+ iv: chunkNonce(noncePrefix, chunkIndex),
32638
+ additionalData: chunkAad(
32639
+ metadataBytes,
32640
+ chunkIndex,
32641
+ final,
32642
+ plaintext.length
32643
+ ),
32644
+ tagLength: AES_GCM_TAG_BYTES * 8
32645
+ },
32646
+ key,
32647
+ plaintext
32648
+ )
32649
+ );
32650
+ const frame = new Uint8Array(
32651
+ FRAME_LENGTH_BYTES + FRAME_FLAGS_BYTES + encrypted.length
32652
+ );
32653
+ new DataView(frame.buffer).setUint32(0, encrypted.length);
32654
+ frame[FRAME_LENGTH_BYTES] = final ? FINAL_FRAME_FLAG : 0;
32655
+ frame.set(encrypted, FRAME_LENGTH_BYTES + FRAME_FLAGS_BYTES);
32656
+ return frame;
32657
+ }
32658
+ function verifyResultBindings(metadata, expect) {
32659
+ if (metadata.jobId !== expect.jobId) {
32660
+ throw new JobEnvelopeError(
32661
+ `Job result ID ${metadata.jobId} does not match expected job ID ${expect.jobId}`
32662
+ );
32663
+ }
32664
+ if (expect.scope !== void 0 && metadata.scope !== expect.scope) {
32665
+ throw new JobEnvelopeError(
32666
+ `Job result scope ${metadata.scope} does not match expected scope ${expect.scope}`
32667
+ );
32668
+ }
32669
+ if (expect.version !== void 0 && metadata.version !== expect.version) {
32670
+ throw new JobEnvelopeError(
32671
+ `Job result version ${String(metadata.version)} does not match expected version ${String(expect.version)}`
32672
+ );
32673
+ }
32674
+ }
32675
+ var ByteStreamReader = class {
32676
+ reader;
32677
+ current;
32678
+ offset = 0;
32679
+ ended = false;
32680
+ constructor(stream) {
32681
+ this.reader = stream.getReader();
32682
+ }
32683
+ async ensureBytes() {
32684
+ while (!this.current || this.offset === this.current.length) {
32685
+ if (this.ended) return false;
32686
+ const next = await this.reader.read();
32687
+ if (next.done) {
32688
+ this.ended = true;
32689
+ this.current = void 0;
32690
+ return false;
32691
+ }
32692
+ if (!(next.value instanceof Uint8Array)) {
32693
+ throw new JobEnvelopeError(
32694
+ "Invalid job result: stream yielded non-byte data"
32695
+ );
32696
+ }
32697
+ this.current = next.value;
32698
+ this.offset = 0;
32699
+ }
32700
+ return true;
32701
+ }
32702
+ async readExactOrNull(length) {
32703
+ if (!await this.ensureBytes()) return null;
32704
+ const bytes = new Uint8Array(length);
32705
+ let written = 0;
32706
+ while (written < length) {
32707
+ if (!await this.ensureBytes()) {
32708
+ throw new JobEnvelopeError("Invalid job result: truncated payload");
32709
+ }
32710
+ const available = this.current.length - this.offset;
32711
+ const count = Math.min(available, length - written);
32712
+ bytes.set(
32713
+ this.current.subarray(this.offset, this.offset + count),
32714
+ written
32715
+ );
32716
+ this.offset += count;
32717
+ written += count;
32718
+ }
32719
+ return bytes;
32720
+ }
32721
+ async readExact(length) {
32722
+ const bytes = await this.readExactOrNull(length);
32723
+ if (!bytes) {
32724
+ throw new JobEnvelopeError("Invalid job result: truncated payload");
32725
+ }
32726
+ return bytes;
32727
+ }
32728
+ async hasRemaining() {
32729
+ return this.ensureBytes();
32730
+ }
32731
+ async cancel(reason) {
32732
+ await this.reader.cancel(reason);
32733
+ }
32734
+ };
32735
+ function normalizeChunkError(error) {
32736
+ if (error instanceof JobEnvelopeError) return error;
32737
+ return new JobEnvelopeError(
32738
+ `Invalid job result: chunk authentication failed${error instanceof Error ? `: ${error.message}` : ""}`
32739
+ );
32740
+ }
32796
32741
  async function sealJobRequest(envelope, enclavePublicKey, ecies) {
32797
32742
  const encrypted = await ecies.encrypt(
32798
32743
  fromHex6(enclavePublicKey, "bytes"),
@@ -32809,41 +32754,333 @@ async function openJobRequest(ciphertext, privateKey, ecies) {
32809
32754
  parseObject(plaintext, "job request envelope")
32810
32755
  );
32811
32756
  }
32812
- async function sealJobResult(result, builderPublicKey, ecies) {
32813
- validateResult(result);
32814
- const encrypted = await ecies.encrypt(
32757
+ async function sealJobResultStream(metadataValue, builderPublicKey, ecies) {
32758
+ const metadata = validateResultMetadata(metadataValue);
32759
+ const metadataBytes = canonicalJsonBytes(metadata);
32760
+ if (metadataBytes.length > MAX_JOB_RESULT_HEADER_BYTES) {
32761
+ throw new JobEnvelopeError(
32762
+ `Invalid job result: header exceeds ${MAX_JOB_RESULT_HEADER_BYTES} bytes`
32763
+ );
32764
+ }
32765
+ const crypto2 = webCrypto();
32766
+ const contentKey = crypto2.getRandomValues(new Uint8Array(AES_KEY_BYTES));
32767
+ const noncePrefix = crypto2.getRandomValues(
32768
+ new Uint8Array(AES_GCM_NONCE_BYTES)
32769
+ );
32770
+ const key = await importAesKey(contentKey, "encrypt");
32771
+ const keyPlaintext = wrappedKeyPlaintext(
32772
+ contentKey,
32773
+ noncePrefix,
32774
+ metadataBytes
32775
+ );
32776
+ const encryptedKey = await ecies.encrypt(
32815
32777
  fromHex6(builderPublicKey, "bytes"),
32816
- resultPlaintext(result)
32778
+ keyPlaintext
32779
+ );
32780
+ contentKey.fill(0);
32781
+ keyPlaintext.fill(0);
32782
+ const wrappedKey = encryptedToBytes(encryptedKey);
32783
+ if (wrappedKey.length > MAX_WRAPPED_KEY_BYTES) {
32784
+ throw new JobEnvelopeError("Invalid job result: wrapped key is too large");
32785
+ }
32786
+ const header = new Uint8Array(
32787
+ 1 + WRAPPED_KEY_LENGTH_BYTES + wrappedKey.length
32817
32788
  );
32818
- const ciphertext = encryptedBytesToBase64(encrypted);
32819
- const bytes = fromBase64(ciphertext);
32820
- return { ciphertext, hash: bytesToHex2(sha2565(bytes)), size: bytes.length };
32789
+ header[0] = JOB_RESULT_FORMAT_VERSION;
32790
+ new DataView(header.buffer).setUint32(1, wrappedKey.length);
32791
+ header.set(wrappedKey, 1 + WRAPPED_KEY_LENGTH_BYTES);
32792
+ let pending = new Uint8Array(JOB_RESULT_CHUNK_BYTES);
32793
+ let pendingLength = 0;
32794
+ let chunkIndex = 0;
32795
+ const transform = new TransformStream({
32796
+ async transform(chunk, controller) {
32797
+ if (!(chunk instanceof Uint8Array)) {
32798
+ throw new JobEnvelopeError(
32799
+ "Invalid job result: stream yielded non-byte data"
32800
+ );
32801
+ }
32802
+ let offset = 0;
32803
+ while (offset < chunk.length) {
32804
+ if (pendingLength === JOB_RESULT_CHUNK_BYTES) {
32805
+ controller.enqueue(
32806
+ await encryptResultChunk(
32807
+ key,
32808
+ noncePrefix,
32809
+ metadataBytes,
32810
+ pending,
32811
+ chunkIndex,
32812
+ false
32813
+ )
32814
+ );
32815
+ chunkIndex += 1;
32816
+ pending = new Uint8Array(JOB_RESULT_CHUNK_BYTES);
32817
+ pendingLength = 0;
32818
+ }
32819
+ const count = Math.min(
32820
+ chunk.length - offset,
32821
+ JOB_RESULT_CHUNK_BYTES - pendingLength
32822
+ );
32823
+ pending.set(chunk.subarray(offset, offset + count), pendingLength);
32824
+ pendingLength += count;
32825
+ offset += count;
32826
+ }
32827
+ },
32828
+ async flush(controller) {
32829
+ controller.enqueue(
32830
+ await encryptResultChunk(
32831
+ key,
32832
+ noncePrefix,
32833
+ metadataBytes,
32834
+ pending.subarray(0, pendingLength),
32835
+ chunkIndex,
32836
+ true
32837
+ )
32838
+ );
32839
+ }
32840
+ });
32841
+ return { header, transform };
32821
32842
  }
32822
- async function openJobResult(ciphertext, builderPrivateKey, ecies, expect) {
32823
- const plaintext = await ecies.decrypt(
32824
- fromHex6(builderPrivateKey, "bytes"),
32825
- base64ToEncrypted(ciphertext)
32843
+ async function sealJobResult(result, builderPublicKey, ecies) {
32844
+ validateResult(result);
32845
+ const sealed = await sealJobResultStream(
32846
+ resultMetadata(result),
32847
+ builderPublicKey,
32848
+ ecies
32826
32849
  );
32827
- const result = validateResult(parseObject(plaintext, "job result"));
32828
- if (result.jobId !== expect.jobId) {
32850
+ const frameCount = Math.max(
32851
+ 1,
32852
+ Math.ceil(result.body.length / JOB_RESULT_CHUNK_BYTES)
32853
+ );
32854
+ const size = sealed.header.length + result.body.length + frameCount * (FRAME_LENGTH_BYTES + FRAME_FLAGS_BYTES + AES_GCM_TAG_BYTES);
32855
+ const bytes = new Uint8Array(size);
32856
+ bytes.set(sealed.header, 0);
32857
+ let outputOffset = sealed.header.length;
32858
+ const reader = sealed.transform.readable.getReader();
32859
+ const drain = (async () => {
32860
+ for (; ; ) {
32861
+ const next = await reader.read();
32862
+ if (next.done) break;
32863
+ bytes.set(next.value, outputOffset);
32864
+ outputOffset += next.value.length;
32865
+ }
32866
+ })();
32867
+ const writer = sealed.transform.writable.getWriter();
32868
+ const fill = (async () => {
32869
+ for (let offset = 0; offset < result.body.length; offset += JOB_RESULT_CHUNK_BYTES) {
32870
+ await writer.write(
32871
+ result.body.subarray(offset, offset + JOB_RESULT_CHUNK_BYTES)
32872
+ );
32873
+ }
32874
+ await writer.close();
32875
+ })();
32876
+ await Promise.all([drain, fill]);
32877
+ if (outputOffset !== bytes.length) {
32878
+ throw new JobEnvelopeError("Invalid job result: sealed size mismatch");
32879
+ }
32880
+ return { bytes, hash: bytesToHex2(sha2565(bytes)), size };
32881
+ }
32882
+ async function openJobResultStream(bytesStream, builderPrivateKey, ecies, expect) {
32883
+ const reader = new ByteStreamReader(bytesStream);
32884
+ const headerPrefix = await reader.readExact(1 + WRAPPED_KEY_LENGTH_BYTES);
32885
+ const formatVersion = headerPrefix[0];
32886
+ if (formatVersion !== JOB_RESULT_FORMAT_VERSION) {
32829
32887
  throw new JobEnvelopeError(
32830
- `Job result ID ${result.jobId} does not match expected job ID ${expect.jobId}`
32888
+ `Unsupported job result format: ${String(formatVersion)}`
32831
32889
  );
32832
32890
  }
32833
- if (expect.scope !== void 0 && result.scope !== expect.scope) {
32891
+ const wrappedKeyLength = readUint32(headerPrefix, 1);
32892
+ if (wrappedKeyLength === 0 || wrappedKeyLength > MAX_WRAPPED_KEY_BYTES) {
32834
32893
  throw new JobEnvelopeError(
32835
- `Job result scope ${result.scope} does not match expected scope ${expect.scope}`
32894
+ "Invalid job result: invalid wrapped key length"
32836
32895
  );
32837
32896
  }
32838
- if (expect.version !== void 0 && result.version !== expect.version) {
32897
+ const wrappedKey = await reader.readExact(wrappedKeyLength);
32898
+ const keyPlaintext = await ecies.decrypt(
32899
+ fromHex6(builderPrivateKey, "bytes"),
32900
+ bytesToEncrypted(wrappedKey)
32901
+ );
32902
+ const parsed = parseWrappedKeyPlaintext(keyPlaintext);
32903
+ verifyResultBindings(parsed.metadata, expect);
32904
+ const key = await importAesKey(parsed.contentKey, "decrypt");
32905
+ parsed.contentKey.fill(0);
32906
+ keyPlaintext.fill(0);
32907
+ let chunkIndex = 0;
32908
+ let finished = false;
32909
+ const body = new ReadableStream({
32910
+ async pull(controller) {
32911
+ if (finished) {
32912
+ controller.close();
32913
+ return;
32914
+ }
32915
+ try {
32916
+ const frameHeader = await reader.readExactOrNull(
32917
+ FRAME_LENGTH_BYTES + FRAME_FLAGS_BYTES
32918
+ );
32919
+ if (!frameHeader) {
32920
+ throw new JobEnvelopeError("Invalid job result: missing final chunk");
32921
+ }
32922
+ const encryptedLength = readUint32(frameHeader);
32923
+ if (encryptedLength < AES_GCM_TAG_BYTES || encryptedLength > JOB_RESULT_CHUNK_BYTES + AES_GCM_TAG_BYTES) {
32924
+ throw new JobEnvelopeError(
32925
+ "Invalid job result: invalid chunk length"
32926
+ );
32927
+ }
32928
+ const flags = frameHeader[FRAME_LENGTH_BYTES];
32929
+ if (flags !== 0 && flags !== FINAL_FRAME_FLAG) {
32930
+ throw new JobEnvelopeError("Invalid job result: invalid chunk flags");
32931
+ }
32932
+ const final = flags === FINAL_FRAME_FLAG;
32933
+ const plaintextLength = encryptedLength - AES_GCM_TAG_BYTES;
32934
+ if (!final && plaintextLength !== JOB_RESULT_CHUNK_BYTES) {
32935
+ throw new JobEnvelopeError(
32936
+ "Invalid job result: short non-final chunk"
32937
+ );
32938
+ }
32939
+ const encrypted = await reader.readExact(encryptedLength);
32940
+ const plaintext = new Uint8Array(
32941
+ await webCrypto().subtle.decrypt(
32942
+ {
32943
+ name: "AES-GCM",
32944
+ iv: chunkNonce(parsed.noncePrefix, chunkIndex),
32945
+ additionalData: chunkAad(
32946
+ parsed.metadataBytes,
32947
+ chunkIndex,
32948
+ final,
32949
+ plaintextLength
32950
+ ),
32951
+ tagLength: AES_GCM_TAG_BYTES * 8
32952
+ },
32953
+ key,
32954
+ encrypted
32955
+ )
32956
+ );
32957
+ if (plaintext.length !== plaintextLength) {
32958
+ throw new JobEnvelopeError(
32959
+ "Invalid job result: decrypted chunk length mismatch"
32960
+ );
32961
+ }
32962
+ chunkIndex += 1;
32963
+ if (final) {
32964
+ if (await reader.hasRemaining()) {
32965
+ throw new JobEnvelopeError(
32966
+ "Invalid job result: bytes follow final chunk"
32967
+ );
32968
+ }
32969
+ finished = true;
32970
+ }
32971
+ controller.enqueue(plaintext);
32972
+ if (finished) controller.close();
32973
+ } catch (error) {
32974
+ controller.error(normalizeChunkError(error));
32975
+ void reader.cancel(error).catch(() => void 0);
32976
+ }
32977
+ },
32978
+ cancel(reason) {
32979
+ return reader.cancel(reason);
32980
+ }
32981
+ });
32982
+ return { metadata: parsed.metadata, body };
32983
+ }
32984
+ function bufferedResultBodySize(sealedBytes) {
32985
+ if (sealedBytes.length < 1 + WRAPPED_KEY_LENGTH_BYTES) {
32986
+ throw new JobEnvelopeError("Invalid job result: truncated payload");
32987
+ }
32988
+ if (sealedBytes[0] !== JOB_RESULT_FORMAT_VERSION) {
32839
32989
  throw new JobEnvelopeError(
32840
- `Job result version ${String(result.version)} does not match expected version ${String(expect.version)}`
32990
+ `Unsupported job result format: ${String(sealedBytes[0])}`
32841
32991
  );
32842
32992
  }
32843
- return result;
32993
+ const wrappedKeyLength = readUint32(sealedBytes, 1);
32994
+ if (wrappedKeyLength === 0 || wrappedKeyLength > MAX_WRAPPED_KEY_BYTES) {
32995
+ throw new JobEnvelopeError(
32996
+ "Invalid job result: invalid wrapped key length"
32997
+ );
32998
+ }
32999
+ let offset = 1 + WRAPPED_KEY_LENGTH_BYTES + wrappedKeyLength;
33000
+ if (offset > sealedBytes.length) {
33001
+ throw new JobEnvelopeError("Invalid job result: truncated payload");
33002
+ }
33003
+ let bodySize = 0;
33004
+ let sawFinal = false;
33005
+ while (offset < sealedBytes.length) {
33006
+ if (sealedBytes.length - offset < FRAME_LENGTH_BYTES + FRAME_FLAGS_BYTES) {
33007
+ throw new JobEnvelopeError("Invalid job result: truncated payload");
33008
+ }
33009
+ const encryptedLength = readUint32(sealedBytes, offset);
33010
+ const flags = sealedBytes[offset + FRAME_LENGTH_BYTES];
33011
+ if (encryptedLength < AES_GCM_TAG_BYTES || encryptedLength > JOB_RESULT_CHUNK_BYTES + AES_GCM_TAG_BYTES || flags !== 0 && flags !== FINAL_FRAME_FLAG) {
33012
+ throw new JobEnvelopeError("Invalid job result: invalid chunk framing");
33013
+ }
33014
+ const plaintextLength = encryptedLength - AES_GCM_TAG_BYTES;
33015
+ if (flags === 0 && plaintextLength !== JOB_RESULT_CHUNK_BYTES) {
33016
+ throw new JobEnvelopeError("Invalid job result: short non-final chunk");
33017
+ }
33018
+ offset += FRAME_LENGTH_BYTES + FRAME_FLAGS_BYTES;
33019
+ if (encryptedLength > sealedBytes.length - offset) {
33020
+ throw new JobEnvelopeError("Invalid job result: truncated payload");
33021
+ }
33022
+ offset += encryptedLength;
33023
+ bodySize += plaintextLength;
33024
+ if (flags === FINAL_FRAME_FLAG) {
33025
+ sawFinal = true;
33026
+ if (offset !== sealedBytes.length) {
33027
+ throw new JobEnvelopeError(
33028
+ "Invalid job result: bytes follow final chunk"
33029
+ );
33030
+ }
33031
+ }
33032
+ }
33033
+ if (!sawFinal) {
33034
+ throw new JobEnvelopeError("Invalid job result: missing final chunk");
33035
+ }
33036
+ return bodySize;
33037
+ }
33038
+ async function openJobResult(sealedBytes, builderPrivateKey, ecies, expect) {
33039
+ const bodySize = bufferedResultBodySize(sealedBytes);
33040
+ const stream = new ReadableStream({
33041
+ start(controller) {
33042
+ controller.enqueue(sealedBytes);
33043
+ controller.close();
33044
+ }
33045
+ });
33046
+ const opened = await openJobResultStream(
33047
+ stream,
33048
+ builderPrivateKey,
33049
+ ecies,
33050
+ expect
33051
+ );
33052
+ const body = new Uint8Array(bodySize);
33053
+ let offset = 0;
33054
+ await opened.body.pipeTo(
33055
+ new WritableStream({
33056
+ write(chunk) {
33057
+ body.set(chunk, offset);
33058
+ offset += chunk.length;
33059
+ }
33060
+ })
33061
+ );
33062
+ if (offset !== body.length) {
33063
+ throw new JobEnvelopeError("Invalid job result: opened size mismatch");
33064
+ }
33065
+ return { ...opened.metadata, body };
32844
33066
  }
32845
33067
 
33068
+ // src/protocol/jobs-client.ts
33069
+ import {
33070
+ BuilderUnknownError,
33071
+ GrantInvalidError,
33072
+ JobIdTakenError,
33073
+ JobNotFoundError,
33074
+ JobRejectedError,
33075
+ JobResultIntegrityError,
33076
+ JobRequestTooLargeError,
33077
+ JobTimeoutError,
33078
+ JobTransportError,
33079
+ OwnerNotReadyError
33080
+ } from "./errors.js";
33081
+
32846
33082
  // src/protocol/write-signer.ts
33083
+ import { WriteRequestError } from "./errors.js";
32847
33084
  function isRecord(value) {
32848
33085
  return value !== null && typeof value === "object";
32849
33086
  }
@@ -33046,7 +33283,7 @@ async function rejectedResponse(response, fallback) {
33046
33283
  return new JobRejectedError(message, response.status, parsed.code, details);
33047
33284
  }
33048
33285
  function requireStatus(value, status) {
33049
- if (!isRecord2(value) || !isNonEmptyString(value["jobId"]) || typeof value["state"] !== "string" || !JOB_STATES.includes(value["state"]) || !isNonEmptyString(value["owner"]) || !isNonEmptyString(value["grantId"]) || !isNonEmptyString(value["scope"]) || !isNonEmptyString(value["operation"]) || !JOB_OPERATIONS.includes(value["operation"])) {
33286
+ if (!isRecord2(value) || !isNonEmptyString(value["jobId"]) || typeof value["state"] !== "string" || !JOB_STATES.includes(value["state"]) || !isNonEmptyString(value["owner"]) || !isNonEmptyString(value["grantId"]) || !isNonEmptyString(value["scope"]) || !isNonEmptyString(value["operation"]) || !JOB_OPERATIONS.includes(value["operation"]) || value["state"] === "completed" && !isResultHandle(value["result"])) {
33050
33287
  throw new JobRejectedError(
33051
33288
  "Gateway response did not contain a job status",
33052
33289
  status
@@ -33057,6 +33294,17 @@ function requireStatus(value, status) {
33057
33294
  function isNonEmptyString(value) {
33058
33295
  return typeof value === "string" && value.length > 0;
33059
33296
  }
33297
+ function isResultHandle(value) {
33298
+ if (!isRecord2(value) || !isNonEmptyString(value["objectKey"]) || !isNonEmptyString(value["url"]) || typeof value["size"] !== "number" || !Number.isInteger(value["size"]) || value["size"] < 0 || typeof value["hash"] !== "string" || !/^0x[0-9a-fA-F]{64}$/.test(value["hash"]) || typeof value["expiresAt"] !== "string" || Number.isNaN(Date.parse(value["expiresAt"]))) {
33299
+ return false;
33300
+ }
33301
+ try {
33302
+ const url = new URL(value["url"]);
33303
+ return url.protocol === "https:" || url.protocol === "http:";
33304
+ } catch {
33305
+ return false;
33306
+ }
33307
+ }
33060
33308
  function hasMatchingIdentityKey(value) {
33061
33309
  const address = value["address"];
33062
33310
  const publicKey = value["publicKey"];
@@ -33302,31 +33550,51 @@ function createJobsClient(options) {
33302
33550
  await sleep2(Math.min(pollMs, remaining));
33303
33551
  }
33304
33552
  },
33305
- async openResult(job, openOptions) {
33306
- if (!job.resultCiphertext) {
33553
+ async openResult(handle, openOptions) {
33554
+ if (!privateKey) {
33307
33555
  throw new JobRejectedError(
33308
- "Job status does not include inline resultCiphertext",
33309
- void 0,
33310
- null,
33556
+ "openResult requires createJobsClient({ builderPrivateKey })"
33557
+ );
33558
+ }
33559
+ const response = await request(
33560
+ handle.url,
33561
+ { method: GET_METHOD },
33562
+ "Job result fetch"
33563
+ );
33564
+ if (!response.ok) {
33565
+ throw await rejectedResponse(response, "Job result fetch rejected");
33566
+ }
33567
+ let bytes;
33568
+ try {
33569
+ bytes = new Uint8Array(await response.arrayBuffer());
33570
+ } catch (error) {
33571
+ throw new JobTransportError(
33572
+ `Job result fetch failed: ${error instanceof Error ? error.message : String(error)}`,
33573
+ error
33574
+ );
33575
+ }
33576
+ const actualHash = bytesToHex3(sha2566(bytes));
33577
+ if (actualHash.toLowerCase() !== handle.hash.toLowerCase()) {
33578
+ throw new JobResultIntegrityError(
33579
+ "Fetched job result hash does not match its handle",
33311
33580
  {
33312
- jobId: job.jobId,
33313
- state: job.state,
33314
- resultHandle: job.resultHandle,
33315
- maxInlineResultBytes: MAX_INLINE_RESULT_BYTES
33581
+ objectKey: handle.objectKey,
33582
+ expectedHash: handle.hash,
33583
+ actualHash
33316
33584
  }
33317
33585
  );
33318
33586
  }
33319
- if (!privateKey) {
33320
- throw new JobRejectedError(
33321
- "openResult requires createJobsClient({ builderPrivateKey })"
33587
+ if (bytes.length !== handle.size) {
33588
+ throw new JobResultIntegrityError(
33589
+ "Fetched job result size does not match its handle",
33590
+ {
33591
+ objectKey: handle.objectKey,
33592
+ expectedSize: handle.size,
33593
+ actualSize: bytes.length
33594
+ }
33322
33595
  );
33323
33596
  }
33324
- return openJobResult(
33325
- job.resultCiphertext,
33326
- privateKey,
33327
- ecies,
33328
- openOptions.expect
33329
- );
33597
+ return openJobResult(bytes, privateKey, ecies, openOptions.expect);
33330
33598
  },
33331
33599
  async readRaw(params) {
33332
33600
  const submitted = await client.submitRawRead(params);
@@ -33334,7 +33602,27 @@ function createJobsClient(options) {
33334
33602
  timeoutMs: params.timeoutMs,
33335
33603
  pollMs: params.pollMs
33336
33604
  });
33337
- return client.openResult(job, {
33605
+ if (job.state !== "completed") {
33606
+ throw new JobRejectedError(
33607
+ `Job ${job.jobId} ended in state ${job.state}${job.failureReason ? `: ${job.failureReason}` : ""}`,
33608
+ void 0,
33609
+ null,
33610
+ {
33611
+ jobId: job.jobId,
33612
+ state: job.state,
33613
+ ...job.failureReason ? { failureReason: job.failureReason } : {}
33614
+ }
33615
+ );
33616
+ }
33617
+ if (!job.result) {
33618
+ throw new JobRejectedError(
33619
+ "Completed job status does not include a result handle",
33620
+ void 0,
33621
+ null,
33622
+ { jobId: job.jobId, state: job.state }
33623
+ );
33624
+ }
33625
+ return client.openResult(job.result, {
33338
33626
  expect: {
33339
33627
  jobId: submitted.jobId,
33340
33628
  scope: params.scope,
@@ -34049,6 +34337,7 @@ import {
34049
34337
  maxUint256,
34050
34338
  stringToBytes as stringToBytes3
34051
34339
  } from "viem";
34340
+ import { DataPointDeletedError, DataPointNotFoundError } from "./errors.js";
34052
34341
 
34053
34342
  // src/protocol/lineage.ts
34054
34343
  import {
@@ -34057,6 +34346,7 @@ import {
34057
34346
  keccak256 as keccak2562
34058
34347
  } from "viem";
34059
34348
  import { z } from "zod";
34349
+ import { LineageReadError, WriteRequestError as WriteRequestError2 } from "./errors.js";
34060
34350
 
34061
34351
  // src/protocol/personal-server-error-body.ts
34062
34352
  function isRecord4(value) {
@@ -34128,7 +34418,7 @@ function derivedScopeViolatesNaming(derivedScope, sourceScope) {
34128
34418
  function assertDerivedScopeNaming(derivedScope, sourceScopes) {
34129
34419
  for (const sourceScope of sourceScopes) {
34130
34420
  if (derivedScopeViolatesNaming(derivedScope, sourceScope)) {
34131
- throw new WriteRequestError(
34421
+ throw new WriteRequestError2(
34132
34422
  `Derived scope ${derivedScope} must not share its first segment with source scope ${sourceScope}; put derivatives in the app's own namespace`,
34133
34423
  { scope: derivedScope, sourceScope }
34134
34424
  );
@@ -34486,6 +34776,9 @@ async function deleteDataPoint(input) {
34486
34776
  }
34487
34777
  }
34488
34778
 
34779
+ // src/protocol/personal-server-data.ts
34780
+ import { DataPointDeletedError as DataPointDeletedError2 } from "./errors.js";
34781
+
34489
34782
  // src/protocol/data-file.ts
34490
34783
  import { z as z2 } from "zod";
34491
34784
  var DataFileEnvelopeSchema = z2.object({
@@ -34544,7 +34837,7 @@ async function readPersonalServerData(params) {
34544
34837
  const request = await buildPersonalServerDataReadRequest(params);
34545
34838
  const response = await fetchFn(request);
34546
34839
  if (response.status === 410) {
34547
- throw new DataPointDeletedError(
34840
+ throw new DataPointDeletedError2(
34548
34841
  `Personal Server scope '${params.scope}' has been deleted`,
34549
34842
  {
34550
34843
  scope: params.scope,
@@ -34559,7 +34852,7 @@ async function readPersonalServerData(params) {
34559
34852
  }
34560
34853
  const body = await response.json();
34561
34854
  if (isDataPointTombstone(body)) {
34562
- throw new DataPointDeletedError(
34855
+ throw new DataPointDeletedError2(
34563
34856
  `Personal Server scope '${params.scope}' has been deleted`,
34564
34857
  { scope: params.scope, deletedAt: tombstoneDeletedAt(body) }
34565
34858
  );
@@ -34759,20 +35052,31 @@ function tryGrantPermissions(scopes) {
34759
35052
  }
34760
35053
 
34761
35054
  // src/protocol/personal-server-write.ts
34762
- import { sha256 as sha2567 } from "@noble/hashes/sha2";
34763
- import { bytesToHex as bytesToHex4, isAddress as isAddress8 } from "viem";
35055
+ import { sha256 as sha2568 } from "@noble/hashes/sha2";
35056
+ import { bytesToHex as bytesToHex5, isAddress as isAddress8 } from "viem";
34764
35057
  import { z as z4 } from "zod";
35058
+ import {
35059
+ WriteConflictError,
35060
+ WriteForbiddenError,
35061
+ WriteLineageError,
35062
+ WriteRejectedError,
35063
+ WriteRequestError as WriteRequestError4,
35064
+ WriteSessionError,
35065
+ WriteSessionExpiredError,
35066
+ WriteUnauthorizedError
35067
+ } from "./errors.js";
34765
35068
 
34766
35069
  // src/protocol/write-request.ts
34767
- import { sha256 as sha2566 } from "@noble/hashes/sha2";
34768
- import { bytesToHex as bytesToHex3 } from "viem";
35070
+ import { sha256 as sha2567 } from "@noble/hashes/sha2";
35071
+ import { bytesToHex as bytesToHex4 } from "viem";
35072
+ import { WriteRequestError as WriteRequestError3, WriteTransportError } from "./errors.js";
34769
35073
  function normalizeBaseUrl2(url) {
34770
35074
  return url.replace(/\/+$/, "");
34771
35075
  }
34772
35076
  function resolveFetch3(fetchFn) {
34773
35077
  const resolved = fetchFn ?? globalThis.fetch;
34774
35078
  if (resolved === void 0) {
34775
- throw new WriteRequestError("No fetch implementation available");
35079
+ throw new WriteRequestError3("No fetch implementation available");
34776
35080
  }
34777
35081
  return resolved;
34778
35082
  }
@@ -34827,27 +35131,27 @@ function nextProofIat(proofKey) {
34827
35131
  return sleep3(waitSec * 1e3).then(() => iat);
34828
35132
  }
34829
35133
  function freshProofNonce() {
34830
- const webCrypto = globalThis.crypto;
34831
- if (typeof webCrypto?.randomUUID === "function") {
34832
- return webCrypto.randomUUID();
35134
+ const webCrypto2 = globalThis.crypto;
35135
+ if (typeof webCrypto2?.randomUUID === "function") {
35136
+ return webCrypto2.randomUUID();
34833
35137
  }
34834
- if (typeof webCrypto?.getRandomValues === "function") {
34835
- return bytesToHex3(webCrypto.getRandomValues(new Uint8Array(16)));
35138
+ if (typeof webCrypto2?.getRandomValues === "function") {
35139
+ return bytesToHex4(webCrypto2.getRandomValues(new Uint8Array(16)));
34836
35140
  }
34837
- throw new WriteRequestError(
35141
+ throw new WriteRequestError3(
34838
35142
  "No secure random source available to build a proof nonce; provide a crypto global"
34839
35143
  );
34840
35144
  }
34841
35145
  function proofKeyFor(parts) {
34842
- return bytesToHex3(
34843
- sha2566(
35146
+ return bytesToHex4(
35147
+ sha2567(
34844
35148
  new TextEncoder().encode(
34845
35149
  JSON.stringify([
34846
35150
  parts.aud,
34847
35151
  parts.method,
34848
35152
  parts.uri,
34849
35153
  parts.grantId,
34850
- parts.signedBytes ? bytesToHex3(sha2566(parts.signedBytes)) : ""
35154
+ parts.signedBytes ? bytesToHex4(sha2567(parts.signedBytes)) : ""
34851
35155
  ])
34852
35156
  )
34853
35157
  )
@@ -34990,7 +35294,7 @@ function isWriteSession(value) {
34990
35294
  }
34991
35295
  function sessionCoversScope(session, scope) {
34992
35296
  if (!isRecord4(session) || !Array.isArray(session.writeScopes) || !session.writeScopes.every((pattern) => typeof pattern === "string")) {
34993
- throw new WriteRequestError("session must come from openWriteSession");
35297
+ throw new WriteRequestError4("session must come from openWriteSession");
34994
35298
  }
34995
35299
  return session.writeScopes.some(
34996
35300
  (pattern) => scopeMatchesPattern(scope, pattern)
@@ -35015,12 +35319,12 @@ function encodeWriteMetadataHeader(metadata) {
35015
35319
  try {
35016
35320
  json = JSON.stringify(metadata);
35017
35321
  } catch (err) {
35018
- throw new WriteRequestError(
35322
+ throw new WriteRequestError4(
35019
35323
  `metadata is not JSON-serialisable: ${errorMessage(err)}`
35020
35324
  );
35021
35325
  }
35022
35326
  if (typeof json !== "string") {
35023
- throw new WriteRequestError("metadata must serialise to JSON");
35327
+ throw new WriteRequestError4("metadata must serialise to JSON");
35024
35328
  }
35025
35329
  return json.replace(
35026
35330
  /[\u007f-\uffff]/g,
@@ -35034,7 +35338,7 @@ function binaryWriteSignedBytes(input) {
35034
35338
  mimeType: normalizeBinaryMimeType(input.contentType),
35035
35339
  ...input.filename ? { filename: input.filename } : {},
35036
35340
  sizeBytes: input.bytes.length,
35037
- contentHash: bytesToHex4(sha2567(input.bytes)),
35341
+ contentHash: bytesToHex5(sha2568(input.bytes)),
35038
35342
  encoding: "base64",
35039
35343
  content: toBase64(input.bytes),
35040
35344
  ...metadata !== void 0 ? { metadata } : {}
@@ -35055,7 +35359,7 @@ function setFilenameHeader(headers, filename) {
35055
35359
  function assertNoReservedKeys(value, where) {
35056
35360
  for (const key of RESERVED_WRITE_KEYS) {
35057
35361
  if (Object.prototype.hasOwnProperty.call(value, key)) {
35058
- throw new WriteRequestError(
35362
+ throw new WriteRequestError4(
35059
35363
  `${where} must not contain the reserved ${key} key; the Personal Server stamps it`,
35060
35364
  { key }
35061
35365
  );
@@ -35067,10 +35371,10 @@ function isLineagePair(value) {
35067
35371
  }
35068
35372
  function normalizeLineage(lineage, derivedScope) {
35069
35373
  if (!Array.isArray(lineage)) {
35070
- throw new WriteRequestError("lineage must be an array of data point ids");
35374
+ throw new WriteRequestError4("lineage must be an array of data point ids");
35071
35375
  }
35072
35376
  if (lineage.length > MAX_LINEAGE_SOURCES) {
35073
- throw new WriteRequestError(
35377
+ throw new WriteRequestError4(
35074
35378
  `lineage lists ${lineage.length} sources; the maximum is ${MAX_LINEAGE_SOURCES}`,
35075
35379
  { max: MAX_LINEAGE_SOURCES, count: lineage.length }
35076
35380
  );
@@ -35083,13 +35387,13 @@ function normalizeLineage(lineage, derivedScope) {
35083
35387
  let id;
35084
35388
  if (isLineagePair(entry)) {
35085
35389
  if (!isAddress8(entry.ownerAddress, { strict: false })) {
35086
- throw new WriteRequestError(
35390
+ throw new WriteRequestError4(
35087
35391
  "lineage source ownerAddress must be an EVM address",
35088
35392
  { ownerAddress: entry.ownerAddress }
35089
35393
  );
35090
35394
  }
35091
35395
  if (entry.scope.length === 0) {
35092
- throw new WriteRequestError("lineage source scope is required");
35396
+ throw new WriteRequestError4("lineage source scope is required");
35093
35397
  }
35094
35398
  id = deriveDataPointId(entry.ownerAddress, entry.scope);
35095
35399
  sourceScopes.push(entry.scope);
@@ -35097,14 +35401,14 @@ function normalizeLineage(lineage, derivedScope) {
35097
35401
  } else if (isDataPointId(entry)) {
35098
35402
  id = entry;
35099
35403
  } else {
35100
- throw new WriteRequestError(
35404
+ throw new WriteRequestError4(
35101
35405
  "lineage entries must be 32-byte hex data point ids or { ownerAddress, scope } pairs",
35102
35406
  { entry }
35103
35407
  );
35104
35408
  }
35105
35409
  const normalized = id.toLowerCase();
35106
35410
  if (seen.has(normalized)) {
35107
- throw new WriteRequestError("lineage must not repeat a data point id", {
35411
+ throw new WriteRequestError4("lineage must not repeat a data point id", {
35108
35412
  dataPointId: normalized
35109
35413
  });
35110
35414
  }
@@ -35113,7 +35417,7 @@ function normalizeLineage(lineage, derivedScope) {
35113
35417
  }
35114
35418
  for (const own of ownIds) {
35115
35419
  if (seen.has(own)) {
35116
- throw new WriteRequestError(
35420
+ throw new WriteRequestError4(
35117
35421
  "lineage must not cite the record's own data point",
35118
35422
  { dataPointId: own, scope: derivedScope }
35119
35423
  );
@@ -35124,7 +35428,7 @@ function normalizeLineage(lineage, derivedScope) {
35124
35428
  }
35125
35429
  function assertNoLineageField(value, where) {
35126
35430
  if (Object.prototype.hasOwnProperty.call(value, LINEAGE_FIELD)) {
35127
- throw new WriteRequestError(
35431
+ throw new WriteRequestError4(
35128
35432
  `${where}.${LINEAGE_FIELD} is reserved; pass sources through the lineage option`
35129
35433
  );
35130
35434
  }
@@ -35132,7 +35436,7 @@ function assertNoLineageField(value, where) {
35132
35436
  function buildMetadataHeader(metadata, sources) {
35133
35437
  if (metadata !== void 0) {
35134
35438
  if (!isRecord4(metadata)) {
35135
- throw new WriteRequestError("metadata must be a plain object");
35439
+ throw new WriteRequestError4("metadata must be a plain object");
35136
35440
  }
35137
35441
  assertNoReservedKeys(metadata, "metadata");
35138
35442
  assertNoLineageField(metadata, "metadata");
@@ -35145,24 +35449,24 @@ function buildMetadataHeader(metadata, sources) {
35145
35449
  }
35146
35450
  function prepareWrite(params) {
35147
35451
  if (params.binary !== void 0 && params.data !== void 0) {
35148
- throw new WriteRequestError("Pass either data or binary, not both");
35452
+ throw new WriteRequestError4("Pass either data or binary, not both");
35149
35453
  }
35150
35454
  const rawLineage = params.lineage;
35151
35455
  const sources = rawLineage === void 0 || rawLineage === null ? void 0 : normalizeLineage(rawLineage, params.scope);
35152
35456
  if (params.binary !== void 0) {
35153
35457
  const { bytes, contentType, filename } = params.binary;
35154
35458
  if (!(bytes instanceof Uint8Array)) {
35155
- throw new WriteRequestError("binary.bytes must be a Uint8Array");
35459
+ throw new WriteRequestError4("binary.bytes must be a Uint8Array");
35156
35460
  }
35157
35461
  if (typeof contentType !== "string" || contentType.trim() === "") {
35158
- throw new WriteRequestError("binary.contentType is required");
35462
+ throw new WriteRequestError4("binary.contentType is required");
35159
35463
  }
35160
35464
  if (filename !== void 0) {
35161
35465
  if (typeof filename !== "string") {
35162
- throw new WriteRequestError("binary.filename must be a string");
35466
+ throw new WriteRequestError4("binary.filename must be a string");
35163
35467
  }
35164
35468
  if (filename !== filename.trim()) {
35165
- throw new WriteRequestError(
35469
+ throw new WriteRequestError4(
35166
35470
  "binary.filename must not have leading or trailing whitespace"
35167
35471
  );
35168
35472
  }
@@ -35182,13 +35486,13 @@ function prepareWrite(params) {
35182
35486
  };
35183
35487
  }
35184
35488
  if (params.data === void 0) {
35185
- throw new WriteRequestError("Pass data (a JSON object) or binary");
35489
+ throw new WriteRequestError4("Pass data (a JSON object) or binary");
35186
35490
  }
35187
35491
  if (!isRecord4(params.data)) {
35188
- throw new WriteRequestError("data must be a plain JSON object");
35492
+ throw new WriteRequestError4("data must be a plain JSON object");
35189
35493
  }
35190
35494
  if (params.metadata !== void 0) {
35191
- throw new WriteRequestError(
35495
+ throw new WriteRequestError4(
35192
35496
  "metadata applies to binary writes; put fields to store inside data"
35193
35497
  );
35194
35498
  }
@@ -35199,12 +35503,12 @@ function prepareWrite(params) {
35199
35503
  try {
35200
35504
  text = JSON.stringify(record);
35201
35505
  } catch (err) {
35202
- throw new WriteRequestError(
35506
+ throw new WriteRequestError4(
35203
35507
  `data is not JSON-serialisable: ${errorMessage(err)}`
35204
35508
  );
35205
35509
  }
35206
35510
  if (typeof text !== "string" || !text.startsWith("{")) {
35207
- throw new WriteRequestError("data must serialise to a JSON object");
35511
+ throw new WriteRequestError4("data must serialise to a JSON object");
35208
35512
  }
35209
35513
  const body = new TextEncoder().encode(text);
35210
35514
  return {
@@ -35233,11 +35537,11 @@ async function writeErrorFromResponse(response) {
35233
35537
  async function writeData(params) {
35234
35538
  const { session } = params;
35235
35539
  if (!isWriteSession(session)) {
35236
- throw new WriteRequestError("session must come from openWriteSession");
35540
+ throw new WriteRequestError4("session must come from openWriteSession");
35237
35541
  }
35238
35542
  const fetchFn = resolveFetch3(params.fetch);
35239
35543
  if (typeof params.scope !== "string" || params.scope.length === 0) {
35240
- throw new WriteRequestError("scope is required");
35544
+ throw new WriteRequestError4("scope is required");
35241
35545
  }
35242
35546
  const prepared = prepareWrite(params);
35243
35547
  if (Date.now() >= session.expiresAt) {
@@ -35333,6 +35637,21 @@ async function writePersonalServerData(params) {
35333
35637
 
35334
35638
  // src/protocol/derivative-questions.ts
35335
35639
  import { z as z5 } from "zod";
35640
+ import {
35641
+ DerivativeComputeUnavailableError,
35642
+ DerivativeCycleError,
35643
+ DerivativeDerivedScopeRequiredError,
35644
+ DerivativeQuestionFailedError,
35645
+ DerivativeQuestionInvalidError,
35646
+ DerivativeQuestionNotFoundError,
35647
+ DerivativeQuestionRejectedError,
35648
+ DerivativeQuestionTimeoutError,
35649
+ DerivativeSourceNotGrantedError,
35650
+ WriteConflictError as WriteConflictError2,
35651
+ WriteForbiddenError as WriteForbiddenError2,
35652
+ WriteRequestError as WriteRequestError5,
35653
+ WriteUnauthorizedError as WriteUnauthorizedError2
35654
+ } from "./errors.js";
35336
35655
  var DERIVATIVE_QUESTIONS_PATH = "/v1/derivatives/questions";
35337
35656
  var MAX_QUESTION_SOURCE_SCOPES = 16;
35338
35657
  var MAX_QUESTION_CHARS = 8e3;
@@ -35415,15 +35734,15 @@ function fetchIdOf(fetchFn) {
35415
35734
  }
35416
35735
  function resolveRequest(params) {
35417
35736
  if (typeof params.personalServerUrl !== "string" || params.personalServerUrl.length === 0) {
35418
- throw new WriteRequestError("personalServerUrl is required");
35737
+ throw new WriteRequestError5("personalServerUrl is required");
35419
35738
  }
35420
35739
  if (typeof params.grantId !== "string" || params.grantId.length === 0) {
35421
- throw new WriteRequestError(
35740
+ throw new WriteRequestError5(
35422
35741
  "grantId is required; a question call runs under the grant carrying write:<derivedScope>"
35423
35742
  );
35424
35743
  }
35425
35744
  if (params.signer === null || typeof params.signer !== "object") {
35426
- throw new WriteRequestError(
35745
+ throw new WriteRequestError5(
35427
35746
  "signer must be a viem LocalAccount, a viem WalletClient, or a { signMessage } object"
35428
35747
  );
35429
35748
  }
@@ -35499,13 +35818,13 @@ async function questionErrorFromResponse(response, body) {
35499
35818
  }
35500
35819
  switch (response.status) {
35501
35820
  case 401:
35502
- return new WriteUnauthorizedError(text, errorCode, details);
35821
+ return new WriteUnauthorizedError2(text, errorCode, details);
35503
35822
  case 403:
35504
- return new WriteForbiddenError(text, errorCode, details);
35823
+ return new WriteForbiddenError2(text, errorCode, details);
35505
35824
  case 404:
35506
35825
  return new DerivativeQuestionNotFoundError(text, errorCode, details);
35507
35826
  case 409:
35508
- return new WriteConflictError(text, errorCode, details);
35827
+ return new WriteConflictError2(text, errorCode, details);
35509
35828
  default:
35510
35829
  return new DerivativeQuestionRejectedError(
35511
35830
  text,
@@ -35607,22 +35926,22 @@ async function sendQuestionRequest(params, spec, schema) {
35607
35926
  }
35608
35927
  function assertQuestionId(questionId) {
35609
35928
  if (typeof questionId !== "string" || questionId.length === 0) {
35610
- throw new WriteRequestError("questionId is required");
35929
+ throw new WriteRequestError5("questionId is required");
35611
35930
  }
35612
35931
  return `${DERIVATIVE_QUESTIONS_PATH}/${encodeURIComponent(questionId)}`;
35613
35932
  }
35614
35933
  function registrationBody(params) {
35615
35934
  const { derivedScope, question } = params;
35616
35935
  if (typeof derivedScope !== "string" || derivedScope.length === 0) {
35617
- throw new WriteRequestError("derivedScope is required");
35936
+ throw new WriteRequestError5("derivedScope is required");
35618
35937
  }
35619
35938
  if (!Array.isArray(params.sourceScopes) || params.sourceScopes.length === 0) {
35620
- throw new WriteRequestError(
35939
+ throw new WriteRequestError5(
35621
35940
  "sourceScopes must be a non-empty array of scopes"
35622
35941
  );
35623
35942
  }
35624
35943
  if (params.sourceScopes.length > MAX_QUESTION_SOURCE_SCOPES) {
35625
- throw new WriteRequestError(
35944
+ throw new WriteRequestError5(
35626
35945
  `sourceScopes lists ${params.sourceScopes.length} scopes; the maximum is ${MAX_QUESTION_SOURCE_SCOPES}`,
35627
35946
  { max: MAX_QUESTION_SOURCE_SCOPES, count: params.sourceScopes.length }
35628
35947
  );
@@ -35630,15 +35949,15 @@ function registrationBody(params) {
35630
35949
  const sourceScopes = [];
35631
35950
  for (const scope of params.sourceScopes) {
35632
35951
  if (typeof scope !== "string" || scope.length === 0) {
35633
- throw new WriteRequestError("sourceScopes entries must be scope strings");
35952
+ throw new WriteRequestError5("sourceScopes entries must be scope strings");
35634
35953
  }
35635
35954
  if (sourceScopes.includes(scope)) {
35636
- throw new WriteRequestError("sourceScopes must not repeat a scope", {
35955
+ throw new WriteRequestError5("sourceScopes must not repeat a scope", {
35637
35956
  duplicate: scope
35638
35957
  });
35639
35958
  }
35640
35959
  if (scope === derivedScope) {
35641
- throw new WriteRequestError(
35960
+ throw new WriteRequestError5(
35642
35961
  "derivedScope cannot be one of its own sources",
35643
35962
  { scope }
35644
35963
  );
@@ -35646,17 +35965,17 @@ function registrationBody(params) {
35646
35965
  sourceScopes.push(scope);
35647
35966
  }
35648
35967
  if (typeof question !== "string" || question.trim() === "") {
35649
- throw new WriteRequestError("question must be a non-empty string");
35968
+ throw new WriteRequestError5("question must be a non-empty string");
35650
35969
  }
35651
35970
  if (question.length > MAX_QUESTION_CHARS) {
35652
- throw new WriteRequestError(
35971
+ throw new WriteRequestError5(
35653
35972
  `question is ${question.length} characters; the maximum is ${MAX_QUESTION_CHARS}`,
35654
35973
  { max: MAX_QUESTION_CHARS, length: question.length }
35655
35974
  );
35656
35975
  }
35657
35976
  if (params.model !== void 0) {
35658
35977
  if (typeof params.model !== "string" || params.model.length > MAX_QUESTION_MODEL_CHARS || !MODEL_ID_PATTERN.test(params.model)) {
35659
- throw new WriteRequestError("model must be a provider model id", {
35978
+ throw new WriteRequestError5("model must be a provider model id", {
35660
35979
  model: params.model
35661
35980
  });
35662
35981
  }
@@ -35692,7 +36011,7 @@ async function getQuestion(params) {
35692
36011
  }
35693
36012
  async function listQuestions(params) {
35694
36013
  if (typeof params.derivedScope !== "string" || params.derivedScope.length === 0) {
35695
- throw new WriteRequestError(
36014
+ throw new WriteRequestError5(
35696
36015
  "derivedScope is required; a builder may only list its own questions on a scope it may write"
35697
36016
  );
35698
36017
  }
@@ -35797,6 +36116,12 @@ async function askPersonalServer(params) {
35797
36116
 
35798
36117
  // src/protocol/derivative-status.ts
35799
36118
  import { z as z6 } from "zod";
36119
+ import {
36120
+ DerivativeQuestionRejectedError as DerivativeQuestionRejectedError2,
36121
+ DerivativeQuestionTimeoutError as DerivativeQuestionTimeoutError2,
36122
+ WriteRequestError as WriteRequestError6,
36123
+ WriteTransportError as WriteTransportError2
36124
+ } from "./errors.js";
35800
36125
  var DERIVATIVE_STATUS_PATH = "/v1/derivatives/status";
35801
36126
  var DEFAULT_DERIVATIVE_STATUS_TIMEOUT_MS = 12e4;
35802
36127
  var DEFAULT_DERIVATIVE_STATUS_POLL_INTERVAL_MS = 2e3;
@@ -35827,13 +36152,13 @@ function normalizeBaseUrl3(url) {
35827
36152
  function resolveFetch4(fetchFn) {
35828
36153
  const resolved = fetchFn ?? globalThis.fetch;
35829
36154
  if (resolved === void 0) {
35830
- throw new WriteRequestError("No fetch implementation available");
36155
+ throw new WriteRequestError6("No fetch implementation available");
35831
36156
  }
35832
36157
  return resolved;
35833
36158
  }
35834
36159
  function requireDerivedScope(derivedScope) {
35835
36160
  if (typeof derivedScope !== "string" || derivedScope.length === 0) {
35836
- throw new WriteRequestError("derivedScope is required");
36161
+ throw new WriteRequestError6("derivedScope is required");
35837
36162
  }
35838
36163
  return derivedScope;
35839
36164
  }
@@ -35852,7 +36177,7 @@ function sleep4(ms, signal) {
35852
36177
  });
35853
36178
  }
35854
36179
  function timeoutError(latest, timeoutMs) {
35855
- return new DerivativeQuestionTimeoutError(
36180
+ return new DerivativeQuestionTimeoutError2(
35856
36181
  `Derived scope ${latest.derivedScope} was still ${latest.status} after ${timeoutMs}ms`,
35857
36182
  {
35858
36183
  derivedScope: latest.derivedScope,
@@ -35865,7 +36190,7 @@ function timeoutError(latest, timeoutMs) {
35865
36190
  }
35866
36191
  function abortError2(signal) {
35867
36192
  const reason = signal?.reason;
35868
- return reason instanceof Error ? reason : new WriteRequestError("Derivative status wait was aborted");
36193
+ return reason instanceof Error ? reason : new WriteRequestError6("Derivative status wait was aborted");
35869
36194
  }
35870
36195
  function isDerivativeStatusSettled(status) {
35871
36196
  if (status.status === "ready") return true;
@@ -35898,7 +36223,7 @@ async function getDerivativeStatus(params) {
35898
36223
  }
35899
36224
  );
35900
36225
  } catch (err) {
35901
- throw new WriteTransportError(
36226
+ throw new WriteTransportError2(
35902
36227
  `Derivative status read failed: ${err instanceof Error ? err.message : String(err)}`,
35903
36228
  1,
35904
36229
  err
@@ -35913,7 +36238,7 @@ async function getDerivativeStatus(params) {
35913
36238
  try {
35914
36239
  body = await response.json();
35915
36240
  } catch (err) {
35916
- throw new DerivativeQuestionRejectedError(
36241
+ throw new DerivativeQuestionRejectedError2(
35917
36242
  "Derivative status response is not JSON",
35918
36243
  response.status,
35919
36244
  null,
@@ -35922,7 +36247,7 @@ async function getDerivativeStatus(params) {
35922
36247
  }
35923
36248
  const parsed = DerivativeStatusSchema.safeParse(body);
35924
36249
  if (!parsed.success) {
35925
- throw new DerivativeQuestionRejectedError(
36250
+ throw new DerivativeQuestionRejectedError2(
35926
36251
  "Derivative status response is not a status view",
35927
36252
  response.status,
35928
36253
  null,
@@ -35956,6 +36281,11 @@ async function waitForDerivativeStatus(params) {
35956
36281
  }
35957
36282
 
35958
36283
  // src/protocol/gateway.ts
36284
+ import {
36285
+ DataPointDeletedError as DataPointDeletedError3,
36286
+ DataPointNotFoundError as DataPointNotFoundError2,
36287
+ DataPointVersionConflictError
36288
+ } from "./errors.js";
35959
36289
  function withGrantPermissions(grant) {
35960
36290
  const stripped = { ...grant };
35961
36291
  delete stripped.permissions;
@@ -36001,7 +36331,7 @@ function createGatewayClient(baseUrl) {
36001
36331
  }
36002
36332
  async function deletedError(res, details) {
36003
36333
  const body = await readBody(res);
36004
- return new DataPointDeletedError(
36334
+ return new DataPointDeletedError3(
36005
36335
  `Data point ${details.dataPointId ?? details.scope ?? ""} has been deleted`,
36006
36336
  { ...details, deletedAt: tombstoneDeletedAt(body) }
36007
36337
  );
@@ -36074,7 +36404,7 @@ function createGatewayClient(baseUrl) {
36074
36404
  }
36075
36405
  const record = await unwrapEnvelope(res);
36076
36406
  if (!options?.includeDeleted && isDataPointTombstone(record)) {
36077
- throw new DataPointDeletedError(
36407
+ throw new DataPointDeletedError3(
36078
36408
  `Data point ${dataPointId} has been deleted`,
36079
36409
  {
36080
36410
  dataPointId,
@@ -36236,7 +36566,7 @@ function createGatewayClient(baseUrl) {
36236
36566
  })
36237
36567
  });
36238
36568
  if (res.status === 404) {
36239
- throw new DataPointNotFoundError(
36569
+ throw new DataPointNotFoundError2(
36240
36570
  `Data point ${dataPointId} (scope '${params.scope}') is not registered`,
36241
36571
  details
36242
36572
  );
@@ -36378,6 +36708,7 @@ function createGatewayClient(baseUrl) {
36378
36708
  }
36379
36709
 
36380
36710
  // src/protocol/escrow.ts
36711
+ import { isHex as isHex3 } from "viem";
36381
36712
  var GENERIC_PAYMENT_TYPES = {
36382
36713
  GenericPayment: [
36383
36714
  { name: "payerAddress", type: "address" },
@@ -36417,6 +36748,26 @@ var ESCROW_DEPOSIT_ABI2 = [
36417
36748
  }
36418
36749
  ];
36419
36750
  var NATIVE_ASSET_ADDRESS = "0x0000000000000000000000000000000000000000";
36751
+ var EscrowWithdrawalLifecycleError = class extends Error {
36752
+ constructor(httpStatus, result) {
36753
+ super(result.error);
36754
+ this.httpStatus = httpStatus;
36755
+ this.result = result;
36756
+ }
36757
+ httpStatus;
36758
+ result;
36759
+ name = "EscrowWithdrawalLifecycleError";
36760
+ };
36761
+ var EscrowWithdrawalRejectionError = class extends Error {
36762
+ constructor(httpStatus, result) {
36763
+ super(result.error);
36764
+ this.httpStatus = httpStatus;
36765
+ this.result = result;
36766
+ }
36767
+ httpStatus;
36768
+ result;
36769
+ name = "EscrowWithdrawalRejectionError";
36770
+ };
36420
36771
  function createEscrowGatewayClient(baseUrl) {
36421
36772
  const base = baseUrl.replace(/\/+$/, "");
36422
36773
  async function throwOnError(res, context) {
@@ -36432,6 +36783,27 @@ function createEscrowGatewayClient(baseUrl) {
36432
36783
  );
36433
36784
  }
36434
36785
  }
36786
+ async function throwOnWithdrawError(res) {
36787
+ if (res.ok) return;
36788
+ let body;
36789
+ try {
36790
+ body = await res.json();
36791
+ } catch {
36792
+ throw new Error(
36793
+ `Escrow gateway error (POST /v1/escrow/withdraw): ${res.status} ${res.statusText}`
36794
+ );
36795
+ }
36796
+ if (isEscrowWithdrawalFailureResult(body)) {
36797
+ throw new EscrowWithdrawalLifecycleError(res.status, body);
36798
+ }
36799
+ if (isEscrowWithdrawalRejectedResult(body)) {
36800
+ throw new EscrowWithdrawalRejectionError(res.status, body);
36801
+ }
36802
+ const error = getGatewayErrorMessage(body);
36803
+ throw new Error(
36804
+ `Escrow gateway error (POST /v1/escrow/withdraw): ${res.status} ${res.statusText}${error ? `: ${error}` : ""}`
36805
+ );
36806
+ }
36435
36807
  return {
36436
36808
  async submitDeposit({ txHash }) {
36437
36809
  const res = await fetch(`${base}/v1/escrow/deposit`, {
@@ -36487,9 +36859,108 @@ function createEscrowGatewayClient(baseUrl) {
36487
36859
  });
36488
36860
  await throwOnError(res, "POST /v1/escrow/pay");
36489
36861
  return res.json();
36862
+ },
36863
+ async withdraw({
36864
+ account,
36865
+ asset,
36866
+ amount,
36867
+ withdrawNonce,
36868
+ deadline,
36869
+ signature
36870
+ }) {
36871
+ const res = await fetch(`${base}/v1/escrow/withdraw`, {
36872
+ method: "POST",
36873
+ headers: {
36874
+ "Content-Type": "application/json",
36875
+ Authorization: `Web3Signed ${signature}`
36876
+ },
36877
+ body: JSON.stringify({
36878
+ account,
36879
+ asset,
36880
+ amount,
36881
+ withdrawNonce,
36882
+ deadline
36883
+ })
36884
+ });
36885
+ await throwOnWithdrawError(res);
36886
+ return res.json();
36887
+ },
36888
+ async getWithdrawNonce(account) {
36889
+ const res = await fetch(
36890
+ `${base}/v1/escrow/withdraw/nonce?account=${encodeURIComponent(account)}`,
36891
+ { cache: "no-store" }
36892
+ );
36893
+ await throwOnError(res, "GET /v1/escrow/withdraw/nonce");
36894
+ const body = await res.json();
36895
+ if (!isWithdrawNonceResponse(body, account)) {
36896
+ throw new Error(
36897
+ "GET /v1/escrow/withdraw/nonce: invalid response structure"
36898
+ );
36899
+ }
36900
+ return body;
36490
36901
  }
36491
36902
  };
36492
36903
  }
36904
+ function getGatewayErrorMessage(body) {
36905
+ if (typeof body === "object" && body !== null && "error" in body && typeof body.error === "string") {
36906
+ return body.error;
36907
+ }
36908
+ return void 0;
36909
+ }
36910
+ function isEscrowWithdrawalFailureResult(body) {
36911
+ if (typeof body !== "object" || body === null) return false;
36912
+ const value = body;
36913
+ return value.success === false && (value.status === "retryable" || value.status === "reorged" || value.status === "failed") && typeof value.error === "string" && isAddressHex(value.account) && isAddressHex(value.asset) && isUint256Decimal(value.amount) && isUint256Decimal(value.withdrawNonce) && isUint256Decimal(value.deadline) && (isHash(value.txHash) || value.txHash === null) && (!("blockNumber" in value) || isBlockNumber(value.blockNumber));
36914
+ }
36915
+ function isEscrowWithdrawalRejectedResult(body) {
36916
+ if (typeof body !== "object" || body === null) return false;
36917
+ const value = body;
36918
+ return value.success === false && value.status === "rejected" && isWithdrawalRejectionCode(value.code) && typeof value.error === "string" && isAddressHex(value.account) && isAddressHex(value.asset) && isUint256Decimal(value.amount) && isUint256Decimal(value.withdrawNonce) && isUint256Decimal(value.deadline) && optionalUint256Decimal(value.balance) && optionalUint256Decimal(value.authorizedAmount) && optionalUint256Decimal(value.withdrawingAmount) && optionalUint256Decimal(value.availableAmount) && optionalUint256Decimal(value.requestedAmount) && optionalUint256Decimal(value.minimumAmount);
36919
+ }
36920
+ function isWithdrawalRejectionCode(value) {
36921
+ return value === "below_minimum" || value === "deadline_too_far" || value === "expired" || value === "insufficient_available" || value === "stale_nonce";
36922
+ }
36923
+ function optionalUint256Decimal(value) {
36924
+ return value === void 0 || isUint256Decimal(value);
36925
+ }
36926
+ function isAddressHex(value) {
36927
+ return typeof value === "string" && isHex3(value, { strict: true }) && value.length === 42;
36928
+ }
36929
+ function isHash(value) {
36930
+ return typeof value === "string" && isHex3(value, { strict: true }) && value.length === 66;
36931
+ }
36932
+ function isUint256Decimal(value) {
36933
+ if (typeof value !== "string" || value.length === 0 || value.length > 78) {
36934
+ return false;
36935
+ }
36936
+ if (!/^(0|[1-9]\d*)$/.test(value)) return false;
36937
+ return BigInt(value) <= 2n ** 256n - 1n;
36938
+ }
36939
+ function isBlockNumber(value) {
36940
+ return value === null || isUint256Decimal(value);
36941
+ }
36942
+ function isWithdrawNonceResponse(body, requestedAccount) {
36943
+ if (typeof body !== "object" || body === null) return false;
36944
+ const value = body;
36945
+ if (value.success !== true) return false;
36946
+ if (!isAddressHex(value.account)) return false;
36947
+ if (value.account.toLowerCase() !== requestedAccount.toLowerCase())
36948
+ return false;
36949
+ if (typeof value.chainId !== "string") return false;
36950
+ if (!/^(0|[1-9]\d*)$/.test(value.chainId)) return false;
36951
+ const isLastNull = value.lastWithdrawNonce === null;
36952
+ const lastNonceValid = isLastNull || isUint256Decimal(value.lastWithdrawNonce);
36953
+ if (!lastNonceValid) return false;
36954
+ if (!isUint256Decimal(value.nextWithdrawNonce)) return false;
36955
+ if (isLastNull) {
36956
+ return value.nextWithdrawNonce === "1";
36957
+ }
36958
+ const lastNonce = BigInt(value.lastWithdrawNonce);
36959
+ const nextNonce = BigInt(value.nextWithdrawNonce);
36960
+ const expectedNextNonce = lastNonce + 1n;
36961
+ if (expectedNextNonce > 2n ** 256n - 1n) return false;
36962
+ return nextNonce === expectedNextNonce;
36963
+ }
36493
36964
 
36494
36965
  // src/direct/escrow-payment.ts
36495
36966
  var GRANT_OP_TYPE = "grant";
@@ -36526,12 +36997,12 @@ var UINT256_MAX = (1n << 256n) - 1n;
36526
36997
  var ADDRESS_RE = /^0x[0-9a-fA-F]{40}$/;
36527
36998
  var BYTES32_RE = /^0x[0-9a-fA-F]{64}$/;
36528
36999
  var SIGNATURE_RE = /^0x[0-9a-fA-F]{130}$/;
36529
- function isUint256Decimal(value, allowZero) {
37000
+ function isUint256Decimal2(value, allowZero) {
36530
37001
  const pattern = allowZero ? /^(0|[1-9]\d*)$/ : /^[1-9]\d*$/;
36531
37002
  return value.length <= UINT256_MAX.toString().length && pattern.test(value) && BigInt(value) <= UINT256_MAX;
36532
37003
  }
36533
37004
  function isValidAccessRecord(record) {
36534
- return BYTES32_RE.test(record.dataPointId) && isUint256Decimal(record.version, false) && ADDRESS_RE.test(record.accessor) && BYTES32_RE.test(record.recordId) && SIGNATURE_RE.test(record.signature);
37005
+ return BYTES32_RE.test(record.dataPointId) && isUint256Decimal2(record.version, false) && ADDRESS_RE.test(record.accessor) && BYTES32_RE.test(record.recordId) && SIGNATURE_RE.test(record.signature);
36535
37006
  }
36536
37007
  function validateSigningOperation(payerAddress, required) {
36537
37008
  if (!ADDRESS_RE.test(payerAddress)) {
@@ -36543,10 +37014,10 @@ function validateSigningOperation(payerAddress, required) {
36543
37014
  if (!ADDRESS_RE.test(required.asset || NATIVE_ASSET_ADDRESS)) {
36544
37015
  throw new Error("Payment asset must be a 20-byte EVM address");
36545
37016
  }
36546
- if (!isUint256Decimal(required.amount, true)) {
37017
+ if (!isUint256Decimal2(required.amount, true)) {
36547
37018
  throw new Error("Payment amount must be a canonical uint256 decimal");
36548
37019
  }
36549
- if (required.paymentNonce !== void 0 && !isUint256Decimal(required.paymentNonce, false)) {
37020
+ if (required.paymentNonce !== void 0 && !isUint256Decimal2(required.paymentNonce, false)) {
36550
37021
  throw new Error("Payment nonce must be a positive uint256 decimal");
36551
37022
  }
36552
37023
  const accessRecord = required.accessRecord;
@@ -36677,7 +37148,7 @@ function paymentResponseMetadataFromHeader(header) {
36677
37148
  const registrationFee = stringField(breakdown, "registrationFee");
36678
37149
  const dataAccessFee = stringField(breakdown, "dataAccessFee");
36679
37150
  const paidAt = stringField(result, "paidAt");
36680
- if (result?.success !== true || !opType || !opId || !BYTES32_RE.test(opId) || !payerAddress || !ADDRESS_RE.test(payerAddress) || !asset || !ADDRESS_RE.test(asset) || !amount || !isUint256Decimal(amount, true) || !paymentNonce || !isUint256Decimal(paymentNonce, false) || !registrationFee || !isUint256Decimal(registrationFee, true) || !dataAccessFee || !isUint256Decimal(dataAccessFee, true) || typeof breakdown?.registrationPaid !== "boolean" || !paidAt || !isCanonicalIsoTimestamp(paidAt)) {
37151
+ if (result?.success !== true || !opType || !opId || !BYTES32_RE.test(opId) || !payerAddress || !ADDRESS_RE.test(payerAddress) || !asset || !ADDRESS_RE.test(asset) || !amount || !isUint256Decimal2(amount, true) || !paymentNonce || !isUint256Decimal2(paymentNonce, false) || !registrationFee || !isUint256Decimal2(registrationFee, true) || !dataAccessFee || !isUint256Decimal2(dataAccessFee, true) || typeof breakdown?.registrationPaid !== "boolean" || !paidAt || !isCanonicalIsoTimestamp(paidAt)) {
36681
37152
  return void 0;
36682
37153
  }
36683
37154
  return {
@@ -36726,18 +37197,9 @@ async function authorizeEscrowPayment(params) {
36726
37197
  return toDirectPaymentReceipt(result);
36727
37198
  }
36728
37199
 
36729
- // src/direct/errors.ts
36730
- var PersonalServerReadError = class extends VanaError {
36731
- constructor(message, status, details) {
36732
- super(message, "DIRECT_PERSONAL_SERVER_READ_ERROR");
36733
- this.status = status;
36734
- this.details = details;
36735
- }
36736
- status;
36737
- details;
36738
- };
36739
-
36740
37200
  // src/direct/personal-server-read.ts
37201
+ import { PaymentRequiredError, PersonalServerReadError } from "./direct/errors.js";
37202
+ import { DataPointDeletedError as DataPointDeletedError4 } from "./errors.js";
36741
37203
  function asRecord2(value) {
36742
37204
  return value && typeof value === "object" && !Array.isArray(value) ? value : void 0;
36743
37205
  }
@@ -36767,15 +37229,15 @@ function isBytes32Hex(value) {
36767
37229
  return /^0x[0-9a-fA-F]{64}$/.test(value);
36768
37230
  }
36769
37231
  var UINT256_MAX2 = (1n << 256n) - 1n;
36770
- function isAddressHex(value) {
37232
+ function isAddressHex2(value) {
36771
37233
  return /^0x[0-9a-fA-F]{40}$/.test(value);
36772
37234
  }
36773
- function isUint256Decimal2(value, allowZero) {
37235
+ function isUint256Decimal3(value, allowZero) {
36774
37236
  const pattern = allowZero ? /^(0|[1-9]\d*)$/ : /^[1-9]\d*$/;
36775
37237
  return value.length <= UINT256_MAX2.toString().length && pattern.test(value) && BigInt(value) <= UINT256_MAX2;
36776
37238
  }
36777
37239
  function isValidDataAccessRecord(record) {
36778
- return isBytes32Hex(record.dataPointId) && isUint256Decimal2(record.version, false) && isAddressHex(record.accessor) && isBytes32Hex(record.recordId) && /^0x[0-9a-fA-F]{130}$/.test(record.signature);
37240
+ return isBytes32Hex(record.dataPointId) && isUint256Decimal3(record.version, false) && isAddressHex2(record.accessor) && isBytes32Hex(record.recordId) && /^0x[0-9a-fA-F]{130}$/.test(record.signature);
36779
37241
  }
36780
37242
  function parseLegacyGrantOperation(params) {
36781
37243
  const { challengeGrantId, challengeOpId, challengeOpType, grantId } = params;
@@ -36826,7 +37288,7 @@ function parseCanonicalDataAccessAccept(value) {
36826
37288
  const accessRecord = parseAccessRecord(accept?.accessRecord);
36827
37289
  const acceptAsset = stringField2(accept, "asset");
36828
37290
  const acceptAmount = stringField2(accept, "amount");
36829
- if (!network || !payerAddress || !isAddressHex(payerAddress) || !opId || !isBytes32Hex(opId) || !asset || !isAddressHex(asset) || !amount || !isUint256Decimal2(amount, true) || !paymentNonce || !isUint256Decimal2(paymentNonce, false) || !accessRecord || !isValidDataAccessRecord(accessRecord) || payerAddress.toLowerCase() !== accessRecord.accessor.toLowerCase() || opId.toLowerCase() !== accessRecord.recordId.toLowerCase() || !acceptAsset || acceptAsset.toLowerCase() !== asset.toLowerCase() || acceptAmount !== amount) {
37291
+ if (!network || !payerAddress || !isAddressHex2(payerAddress) || !opId || !isBytes32Hex(opId) || !asset || !isAddressHex2(asset) || !amount || !isUint256Decimal3(amount, true) || !paymentNonce || !isUint256Decimal3(paymentNonce, false) || !accessRecord || !isValidDataAccessRecord(accessRecord) || payerAddress.toLowerCase() !== accessRecord.accessor.toLowerCase() || opId.toLowerCase() !== accessRecord.recordId.toLowerCase() || !acceptAsset || acceptAsset.toLowerCase() !== asset.toLowerCase() || acceptAmount !== amount) {
36830
37292
  return null;
36831
37293
  }
36832
37294
  return {
@@ -36911,7 +37373,7 @@ async function parsePersonalServerPaymentRequired(res, grantId) {
36911
37373
  const acceptAmount = stringField2(accept, "amount");
36912
37374
  const accessRecord2 = parseAccessRecord(accept.accessRecord);
36913
37375
  const hasAccessRecord = accept.accessRecord !== void 0;
36914
- if (!network || !payerAddress || !isAddressHex(payerAddress) || !opId || !isBytes32Hex(opId) || !asset || !isAddressHex(asset) || !amount || !isUint256Decimal2(amount, true) || !paymentNonce || !isUint256Decimal2(paymentNonce, false) || !acceptAsset || acceptAsset.toLowerCase() !== asset.toLowerCase() || acceptAmount !== amount || hasAccessRecord && (!accessRecord2 || !isValidDataAccessRecord(accessRecord2) || accessRecord2.accessor.toLowerCase() !== payerAddress.toLowerCase()) || amount === "0" && !accessRecord2) {
37376
+ if (!network || !payerAddress || !isAddressHex2(payerAddress) || !opId || !isBytes32Hex(opId) || !asset || !isAddressHex2(asset) || !amount || !isUint256Decimal3(amount, true) || !paymentNonce || !isUint256Decimal3(paymentNonce, false) || !acceptAsset || acceptAsset.toLowerCase() !== asset.toLowerCase() || acceptAmount !== amount || hasAccessRecord && (!accessRecord2 || !isValidDataAccessRecord(accessRecord2) || accessRecord2.accessor.toLowerCase() !== payerAddress.toLowerCase()) || amount === "0" && !accessRecord2) {
36915
37377
  throw new PersonalServerReadError(
36916
37378
  "Personal Server grant payment challenge was untrusted or incomplete",
36917
37379
  402
@@ -37027,14 +37489,11 @@ export {
37027
37489
  AccountPersonalServerLiteOwnerBindingError,
37028
37490
  AccountPersonalServerRegistrationError,
37029
37491
  BUILDER_REGISTRATION_TYPES,
37030
- BlockchainError,
37031
37492
  BrowserPlatformAdapter,
37032
- BuilderUnknownError,
37033
37493
  CLAIM_POLL_FLOOR_MS,
37034
37494
  CONTRACTS,
37035
37495
  CallbackStorage,
37036
37496
  ContractFactory,
37037
- ContractNotFoundError,
37038
37497
  DATA_ACCESS_OP_TYPE,
37039
37498
  DATA_REGISTRY_STATUS_ABI,
37040
37499
  DEFAULT_DERIVATIVE_STATUS_POLL_INTERVAL_MS,
@@ -37047,21 +37506,9 @@ export {
37047
37506
  DERIVATIVE_QUESTIONS_PATH,
37048
37507
  DERIVATIVE_STATUS_PATH,
37049
37508
  DataFileEnvelopeSchema,
37050
- DataPointDeletedError,
37051
- DataPointNotFoundError,
37052
37509
  DataPointStatus,
37053
- DataPointVersionConflictError,
37054
- DerivativeComputeUnavailableError,
37055
- DerivativeCycleError,
37056
- DerivativeDerivedScopeRequiredError,
37057
37510
  DerivativeErrorCodeSchema,
37058
- DerivativeQuestionFailedError,
37059
- DerivativeQuestionInvalidError,
37060
- DerivativeQuestionNotFoundError,
37061
- DerivativeQuestionRejectedError,
37062
37511
  DerivativeQuestionSchema,
37063
- DerivativeQuestionTimeoutError,
37064
- DerivativeSourceNotGrantedError,
37065
37512
  DerivativeStatusSchema,
37066
37513
  DropboxStorage,
37067
37514
  ECIESError,
@@ -37069,42 +37516,35 @@ export {
37069
37516
  ENCLAVE_TRUST_ANCHORS,
37070
37517
  ENCLAVE_WALLET_PURPOSE,
37071
37518
  ESCROW_DEPOSIT_ABI2 as ESCROW_DEPOSIT_ABI,
37072
- ExpiredTokenError,
37519
+ EscrowWithdrawalLifecycleError,
37520
+ EscrowWithdrawalRejectionError,
37521
+ ExpiredTokenError2 as ExpiredTokenError,
37073
37522
  FEE_REGISTRY_ABI,
37074
37523
  GENERIC_PAYMENT_TYPES,
37075
37524
  GRANT_OP_TYPE,
37076
37525
  GRANT_REGISTRATION_TYPES,
37077
37526
  GRANT_REVOCATION_TYPES,
37078
37527
  GoogleDriveStorage,
37079
- GrantInvalidError,
37080
37528
  InMemoryTokenStore,
37081
37529
  IngestResponseSchema,
37082
- InvalidConfigurationError,
37083
37530
  InvalidScopeEntryError,
37084
- InvalidSignatureError,
37531
+ InvalidSignatureError2 as InvalidSignatureError,
37085
37532
  IpfsStorage,
37086
37533
  JOB_OPERATIONS,
37087
37534
  JOB_PROTOCOL_VERSION,
37535
+ JOB_RESULT_CHUNK_BYTES,
37536
+ JOB_RESULT_FORMAT_VERSION,
37088
37537
  JOB_STATES,
37089
37538
  JobEnvelopeError,
37090
- JobIdTakenError,
37091
- JobNotFoundError,
37092
- JobRejectedError,
37093
- JobRequestTooLargeError,
37094
- JobTimeoutError,
37095
- JobTransportError,
37096
- JobsClientError,
37097
37539
  LINEAGE_FIELD,
37098
37540
  LINEAGE_KEY,
37099
37541
  LineageEntrySchema,
37100
37542
  LineageGraphSchema,
37101
37543
  LineageNodeSchema,
37102
- LineageReadError,
37103
37544
  MASTER_KEY_MESSAGE,
37104
37545
  MASTER_SIGNATURE_DELIVERY_MAX_AGE_SECONDS,
37105
37546
  MASTER_SIGNATURE_DELIVERY_VERSION,
37106
37547
  MAX_ATTEMPTS,
37107
- MAX_INLINE_RESULT_BYTES,
37108
37548
  MAX_JOB_DEADLINE_SECONDS,
37109
37549
  MAX_LEASE_SECONDS,
37110
37550
  MAX_LINEAGE_SOURCES,
@@ -37112,15 +37552,12 @@ export {
37112
37552
  MAX_QUESTION_MODEL_CHARS,
37113
37553
  MAX_QUESTION_SOURCE_SCOPES,
37114
37554
  MAX_WAIT_SECONDS,
37115
- MissingAuthError,
37555
+ MissingAuthError2 as MissingAuthError,
37116
37556
  NATIVE_ASSET_ADDRESS,
37117
37557
  NATIVE_VANA_ASSET,
37118
- NetworkError,
37119
37558
  NodeECIESUint8Provider as NodeECIESProvider,
37120
37559
  NodePlatformAdapter,
37121
- NonceError,
37122
37560
  OAuthClient,
37123
- OwnerNotReadyError,
37124
37561
  PERSONAL_SERVER_LITE_OWNER_BINDING_PREFIX,
37125
37562
  PERSONAL_SERVER_LITE_OWNER_BINDING_PURPOSE,
37126
37563
  PERSONAL_SERVER_LITE_OWNER_BINDING_VERSION,
@@ -37129,9 +37566,6 @@ export {
37129
37566
  PKCE_CHALLENGE_PATTERN,
37130
37567
  PKCE_VERIFIER_PATTERN,
37131
37568
  PSError,
37132
- PermissionError,
37133
- PersonalServerError,
37134
- PersonalServerWriteError,
37135
37569
  PinataStorage,
37136
37570
  QUESTION_STATUSES,
37137
37571
  QuestionDeleteResultSchema,
@@ -37142,42 +37576,26 @@ export {
37142
37576
  RECORD_DATA_ACCESS_TYPES,
37143
37577
  REGISTRATION_KIND_FOR_OP,
37144
37578
  RESERVED_WRITE_KEYS,
37145
- ReadOnlyError,
37146
37579
  RedactedLineageNodeSchema,
37147
- RelayerError,
37148
37580
  SCOPE_ACTIONS,
37149
37581
  SEALED_ENVELOPE_VERSION,
37150
37582
  SERVER_REGISTRATION_TYPES,
37151
37583
  ScopeSchema,
37152
- SerializationError,
37153
- ServerUrlMismatchError,
37154
- SignatureError,
37155
37584
  StorageError,
37156
37585
  StorageManager,
37157
37586
  TOMBSTONE_DATA_HASH,
37158
37587
  TOMBSTONE_DATA_HASH_PREIMAGE,
37159
37588
  TOMBSTONE_METADATA_HASH,
37160
37589
  TOMBSTONE_METADATA_HASH_PREIMAGE,
37161
- TransactionPendingError,
37162
37590
  USER_PS_ID_DOMAIN,
37163
- UserRejectedRequestError,
37164
- VanaError,
37165
37591
  VanaStorage,
37592
+ WITHDRAW_AUTHORIZATION_TYPES,
37166
37593
  WRITER_ATTRIBUTION_KEY,
37167
37594
  WRITE_CONTENT_DISPOSITION_HEADER,
37168
37595
  WRITE_FILENAME_HEADER,
37169
37596
  WRITE_METADATA_HEADER,
37170
37597
  WRITE_SESSION_PATH,
37171
37598
  WRITE_SIGNATURE_HEADER,
37172
- WriteConflictError,
37173
- WriteForbiddenError,
37174
- WriteLineageError,
37175
- WriteRejectedError,
37176
- WriteRequestError,
37177
- WriteSessionError,
37178
- WriteSessionExpiredError,
37179
- WriteTransportError,
37180
- WriteUnauthorizedError,
37181
37599
  appRootPreimage,
37182
37600
  askPersonalServer,
37183
37601
  assertDerivedScopeNaming,
@@ -37200,6 +37618,7 @@ export {
37200
37618
  buildPersonalServerRegistrationTypedData,
37201
37619
  buildSetDataPointStatusRequest,
37202
37620
  buildWeb3SignedHeader,
37621
+ buildWithdrawAuthorizationTypedData,
37203
37622
  builderRegistrationDomain,
37204
37623
  canonicalJobRequestBytes,
37205
37624
  chains,
@@ -37282,6 +37701,7 @@ export {
37282
37701
  normalizeBinaryMimeType,
37283
37702
  openJobRequest,
37284
37703
  openJobResult,
37704
+ openJobResultStream,
37285
37705
  openWriteSession,
37286
37706
  parsePSError,
37287
37707
  parsePersonalServerPaymentRequired,
@@ -37307,6 +37727,7 @@ export {
37307
37727
  scopeToPathSegments,
37308
37728
  sealJobRequest,
37309
37729
  sealJobResult,
37730
+ sealJobResultStream,
37310
37731
  serializeECIES,
37311
37732
  serverRegistrationDomain,
37312
37733
  sessionCoversScope,
@@ -37325,6 +37746,7 @@ export {
37325
37746
  verifyWeb3Signed,
37326
37747
  waitForDerivativeStatus,
37327
37748
  waitForQuestion,
37749
+ withdrawAuthorizationDomain,
37328
37750
  writeData,
37329
37751
  writePersonalServerData
37330
37752
  };