@opendatalabs/vana-sdk 3.23.0 → 4.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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 +889 -526
  35. package/dist/index.browser.js.map +4 -4
  36. package/dist/index.node.cjs +1042 -713
  37. package/dist/index.node.cjs.map +4 -4
  38. package/dist/index.node.d.ts +4 -4
  39. package/dist/index.node.js +996 -575
  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 +14 -10
  60. package/dist/protocol/identity.cjs.map +1 -1
  61. package/dist/protocol/identity.js +14 -10
  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();
@@ -32448,17 +32117,21 @@ var PREIMAGE_SEPARATOR = ":";
32448
32117
  var UNCOMPRESSED_PUBLIC_KEY_BYTES = 65;
32449
32118
  var UNCOMPRESSED_PUBLIC_KEY_PREFIX = "04";
32450
32119
  var EMPTY_HEX = "0x";
32451
- function emptyAnchor() {
32452
- return Object.freeze({
32453
- kmsRootPubkey: EMPTY_HEX,
32454
- appIds: Object.freeze([])
32455
- });
32456
- }
32120
+ var MAINNET_ANCHOR = Object.freeze({
32121
+ kmsRootPubkey: "0x0434c76e0c3f52ec64cbf9bbf5c910c272330166fd656c0a86bb330963e46910e1a0e6fa51bec74be2f9129342707636060d85856d102cee8290185409ecf7422f",
32122
+ appIds: Object.freeze([
32123
+ "0x01bb1b6dcaf1ea170f1480c5e53b093f384d939a"
32124
+ ])
32125
+ });
32457
32126
  var ENCLAVE_TRUST_ANCHORS = Object.freeze({
32458
- // filled at fleet provisioning; verify fails closed while empty
32459
- [VANA_MAINNET_CHAIN_ID]: emptyAnchor(),
32460
- // filled at fleet provisioning; verify fails closed while empty
32461
- [MOKSHA_CHAIN_ID]: emptyAnchor()
32127
+ [VANA_MAINNET_CHAIN_ID]: MAINNET_ANCHOR,
32128
+ // Moksha workers share this dstack app and KMS root; the controller does not derive owner keys.
32129
+ [MOKSHA_CHAIN_ID]: Object.freeze({
32130
+ kmsRootPubkey: "0x0434c76e0c3f52ec64cbf9bbf5c910c272330166fd656c0a86bb330963e46910e1a0e6fa51bec74be2f9129342707636060d85856d102cee8290185409ecf7422f",
32131
+ appIds: Object.freeze([
32132
+ "0xec9a39de98c760e1ded9f1e97016dc5f0e357cf2"
32133
+ ])
32134
+ })
32462
32135
  });
32463
32136
  function userPsId(chainId, ownerAddress) {
32464
32137
  const packed = encodePacked(
@@ -32605,13 +32278,14 @@ var MAX_LEASE_SECONDS = 300;
32605
32278
  var MAX_ATTEMPTS = 3;
32606
32279
  var MAX_WAIT_SECONDS = 25;
32607
32280
  var CLAIM_POLL_FLOOR_MS = 1e3;
32608
- var MAX_INLINE_RESULT_BYTES = 1048576;
32609
32281
  var DEFAULT_JOB_DEADLINE_SECONDS = 600;
32610
32282
  var MAX_JOB_DEADLINE_SECONDS = 3600;
32611
32283
 
32612
32284
  // src/protocol/jobs-client.ts
32613
32285
  import { randomUUID } from "node:crypto";
32286
+ import { sha256 as sha2566 } from "@noble/hashes/sha2";
32614
32287
  import {
32288
+ bytesToHex as bytesToHex3,
32615
32289
  isAddress as isAddress2,
32616
32290
  isAddressEqual as isAddressEqual2,
32617
32291
  isHex as isHex2
@@ -32619,11 +32293,26 @@ import {
32619
32293
  import { privateKeyToAccount, publicKeyToAddress as publicKeyToAddress2 } from "viem/accounts";
32620
32294
 
32621
32295
  // src/crypto/envelope/job.ts
32296
+ init_constants();
32622
32297
  init_interface();
32623
32298
  import { sha256 as sha2565 } from "@noble/hashes/sha2";
32624
32299
  import { bytesToHex as bytesToHex2, fromHex as fromHex6, isAddress, isHex, toHex as toHex8 } from "viem";
32625
32300
  var textDecoder = new TextDecoder();
32626
32301
  var textEncoder = new TextEncoder();
32302
+ var MAX_JOB_RESULT_HEADER_BYTES = 4096;
32303
+ var WRAPPED_KEY_LENGTH_BYTES = 4;
32304
+ var FRAME_LENGTH_BYTES = 4;
32305
+ var FRAME_FLAGS_BYTES = 1;
32306
+ var AES_KEY_BYTES = 32;
32307
+ var AES_GCM_NONCE_BYTES = 12;
32308
+ var AES_GCM_TAG_BYTES = 16;
32309
+ var WRAPPED_METADATA_LENGTH_BYTES = 4;
32310
+ var WRAPPED_KEY_PLAINTEXT_PREFIX_BYTES = AES_KEY_BYTES + AES_GCM_NONCE_BYTES + WRAPPED_METADATA_LENGTH_BYTES;
32311
+ var MAX_WRAPPED_KEY_BYTES = 8192;
32312
+ var FINAL_FRAME_FLAG = 1;
32313
+ var MAX_CHUNK_INDEX = 4294967295;
32314
+ var JOB_RESULT_FORMAT_VERSION = 2;
32315
+ var JOB_RESULT_CHUNK_BYTES = 1024 * 1024;
32627
32316
  var JobEnvelopeError = class extends Error {
32628
32317
  constructor(message) {
32629
32318
  super(message);
@@ -32655,21 +32344,68 @@ function requestPlaintext(envelope) {
32655
32344
  validateRequestEnvelope(envelope);
32656
32345
  return canonicalJsonBytes(envelope);
32657
32346
  }
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
- );
32347
+ function resultMetadata(result) {
32348
+ return {
32349
+ v: result.v,
32350
+ jobId: result.jobId,
32351
+ scope: result.scope,
32352
+ version: result.version,
32353
+ contentType: result.contentType
32354
+ };
32669
32355
  }
32670
32356
  function encryptedBytesToBase64(encrypted) {
32671
32357
  return toBase64(fromHex6(`0x${serializeECIES(encrypted)}`, "bytes"));
32672
32358
  }
32359
+ function encryptedToBytes(encrypted) {
32360
+ const bytes = new Uint8Array(
32361
+ encrypted.iv.length + encrypted.ephemPublicKey.length + encrypted.ciphertext.length + encrypted.mac.length
32362
+ );
32363
+ let offset = 0;
32364
+ bytes.set(encrypted.iv, offset);
32365
+ offset += encrypted.iv.length;
32366
+ bytes.set(encrypted.ephemPublicKey, offset);
32367
+ offset += encrypted.ephemPublicKey.length;
32368
+ bytes.set(encrypted.ciphertext, offset);
32369
+ offset += encrypted.ciphertext.length;
32370
+ bytes.set(encrypted.mac, offset);
32371
+ return bytes;
32372
+ }
32373
+ function bytesToEncrypted(bytes) {
32374
+ const absoluteMinLength = FORMAT.IV_LENGTH + 1 + MAC.LENGTH + 1;
32375
+ if (bytes.length < absoluteMinLength) {
32376
+ throw new ECIESError(
32377
+ `Invalid ECIES data: too short (${bytes.length} bytes, minimum ${absoluteMinLength} bytes required)`,
32378
+ "DECRYPTION_FAILED"
32379
+ );
32380
+ }
32381
+ const prefix = bytes[FORMAT.EPHEMERAL_KEY_OFFSET];
32382
+ if (prefix !== CURVE.PREFIX.UNCOMPRESSED) {
32383
+ throw new ECIESError(
32384
+ `Invalid ephemeral public key: must be uncompressed format (0x04 prefix), got 0x${prefix.toString(16).padStart(2, "0")}`,
32385
+ "DECRYPTION_FAILED"
32386
+ );
32387
+ }
32388
+ const ephemKeySize = CURVE.UNCOMPRESSED_PUBLIC_KEY_LENGTH;
32389
+ const minLength = FORMAT.IV_LENGTH + ephemKeySize + MAC.LENGTH + 1;
32390
+ if (bytes.length < minLength) {
32391
+ throw new ECIESError(
32392
+ `Invalid ECIES data: too short (${bytes.length} bytes, minimum ${minLength} bytes required)`,
32393
+ "DECRYPTION_FAILED"
32394
+ );
32395
+ }
32396
+ return {
32397
+ iv: bytes.subarray(FORMAT.IV_OFFSET, FORMAT.IV_OFFSET + FORMAT.IV_LENGTH),
32398
+ ephemPublicKey: bytes.subarray(
32399
+ FORMAT.EPHEMERAL_KEY_OFFSET,
32400
+ FORMAT.EPHEMERAL_KEY_OFFSET + ephemKeySize
32401
+ ),
32402
+ ciphertext: bytes.subarray(
32403
+ FORMAT.EPHEMERAL_KEY_OFFSET + ephemKeySize,
32404
+ bytes.length - MAC.LENGTH
32405
+ ),
32406
+ mac: bytes.subarray(bytes.length - MAC.LENGTH)
32407
+ };
32408
+ }
32673
32409
  function base64ToEncrypted(ciphertext) {
32674
32410
  return deserializeECIES(toHex8(fromBase64(ciphertext)));
32675
32411
  }
@@ -32770,11 +32506,11 @@ function validateRequestEnvelope(value) {
32770
32506
  requireString(value.auth, "auth", "job request envelope");
32771
32507
  return value;
32772
32508
  }
32773
- function validateResult(value) {
32774
- requirePlainObject(value, "result", "job result");
32509
+ function validateResultMetadata(value) {
32510
+ requirePlainObject(value, "metadata", "job result");
32775
32511
  requireExactKeys(
32776
32512
  value,
32777
- ["v", "jobId", "scope", "version", "contentType", "body"],
32513
+ ["v", "jobId", "scope", "version", "contentType"],
32778
32514
  "job result"
32779
32515
  );
32780
32516
  if (value.v !== JOB_PROTOCOL_VERSION) {
@@ -32785,14 +32521,222 @@ function validateResult(value) {
32785
32521
  for (const field of ["jobId", "scope", "contentType"]) {
32786
32522
  requireString(value[field], field, "job result");
32787
32523
  }
32788
- if (typeof value.body !== "string") {
32789
- throw new JobEnvelopeError("Invalid job result: missing body");
32790
- }
32791
32524
  if (value.version !== null && typeof value.version !== "string") {
32792
32525
  throw new JobEnvelopeError("Invalid job result: missing version");
32793
32526
  }
32794
32527
  return value;
32795
32528
  }
32529
+ function validateResult(value) {
32530
+ requirePlainObject(value, "result", "job result");
32531
+ requireExactKeys(
32532
+ value,
32533
+ ["v", "jobId", "scope", "version", "contentType", "body"],
32534
+ "job result"
32535
+ );
32536
+ validateResultMetadata(resultMetadata(value));
32537
+ if (!(value.body instanceof Uint8Array)) {
32538
+ throw new JobEnvelopeError("Invalid job result: missing body");
32539
+ }
32540
+ return value;
32541
+ }
32542
+ function webCrypto() {
32543
+ if (typeof globalThis.crypto === "undefined" || typeof globalThis.crypto.getRandomValues !== "function" || !globalThis.crypto.subtle) {
32544
+ throw new JobEnvelopeError(
32545
+ "Job result streaming requires the Web Crypto API"
32546
+ );
32547
+ }
32548
+ return globalThis.crypto;
32549
+ }
32550
+ function uint32(value) {
32551
+ const bytes = new Uint8Array(4);
32552
+ new DataView(bytes.buffer).setUint32(0, value);
32553
+ return bytes;
32554
+ }
32555
+ function readUint32(bytes, offset = 0) {
32556
+ return new DataView(bytes.buffer, bytes.byteOffset + offset, 4).getUint32(0);
32557
+ }
32558
+ function wrappedKeyPlaintext(contentKey, noncePrefix, metadataBytes) {
32559
+ const plaintext = new Uint8Array(
32560
+ WRAPPED_KEY_PLAINTEXT_PREFIX_BYTES + metadataBytes.length
32561
+ );
32562
+ plaintext.set(contentKey, 0);
32563
+ plaintext.set(noncePrefix, AES_KEY_BYTES);
32564
+ new DataView(plaintext.buffer).setUint32(
32565
+ AES_KEY_BYTES + AES_GCM_NONCE_BYTES,
32566
+ metadataBytes.length
32567
+ );
32568
+ plaintext.set(metadataBytes, WRAPPED_KEY_PLAINTEXT_PREFIX_BYTES);
32569
+ return plaintext;
32570
+ }
32571
+ function parseWrappedKeyPlaintext(plaintext) {
32572
+ if (plaintext.length < WRAPPED_KEY_PLAINTEXT_PREFIX_BYTES) {
32573
+ throw new JobEnvelopeError("Invalid job result: wrapped key is truncated");
32574
+ }
32575
+ const metadataLength = readUint32(
32576
+ plaintext,
32577
+ AES_KEY_BYTES + AES_GCM_NONCE_BYTES
32578
+ );
32579
+ if (metadataLength > MAX_JOB_RESULT_HEADER_BYTES) {
32580
+ throw new JobEnvelopeError(
32581
+ `Invalid job result: header exceeds ${MAX_JOB_RESULT_HEADER_BYTES} bytes`
32582
+ );
32583
+ }
32584
+ if (plaintext.length !== WRAPPED_KEY_PLAINTEXT_PREFIX_BYTES + metadataLength) {
32585
+ throw new JobEnvelopeError(
32586
+ "Invalid job result: header length exceeds payload"
32587
+ );
32588
+ }
32589
+ const metadataBytes = plaintext.slice(WRAPPED_KEY_PLAINTEXT_PREFIX_BYTES);
32590
+ const metadata = validateResultMetadata(
32591
+ parseObject(metadataBytes, "job result header")
32592
+ );
32593
+ return {
32594
+ contentKey: plaintext.slice(0, AES_KEY_BYTES),
32595
+ noncePrefix: plaintext.slice(
32596
+ AES_KEY_BYTES,
32597
+ AES_KEY_BYTES + AES_GCM_NONCE_BYTES
32598
+ ),
32599
+ metadataBytes,
32600
+ metadata
32601
+ };
32602
+ }
32603
+ async function importAesKey(contentKey, usage) {
32604
+ return webCrypto().subtle.importKey(
32605
+ "raw",
32606
+ contentKey,
32607
+ { name: "AES-GCM" },
32608
+ false,
32609
+ [usage]
32610
+ );
32611
+ }
32612
+ function chunkNonce(noncePrefix, chunkIndex) {
32613
+ if (chunkIndex > MAX_CHUNK_INDEX) {
32614
+ throw new JobEnvelopeError("Invalid job result: too many chunks");
32615
+ }
32616
+ const nonce = noncePrefix.slice();
32617
+ const view = new DataView(nonce.buffer, nonce.byteOffset, nonce.byteLength);
32618
+ view.setUint32(8, view.getUint32(8) ^ chunkIndex);
32619
+ return nonce;
32620
+ }
32621
+ function chunkAad(metadataBytes, chunkIndex, final, plaintextLength) {
32622
+ const aad = new Uint8Array(14 + metadataBytes.length);
32623
+ aad[0] = JOB_RESULT_FORMAT_VERSION;
32624
+ aad.set(uint32(metadataBytes.length), 1);
32625
+ aad.set(metadataBytes, 5);
32626
+ aad.set(uint32(chunkIndex), 5 + metadataBytes.length);
32627
+ aad[9 + metadataBytes.length] = final ? FINAL_FRAME_FLAG : 0;
32628
+ aad.set(uint32(plaintextLength), 10 + metadataBytes.length);
32629
+ return aad;
32630
+ }
32631
+ async function encryptResultChunk(key, noncePrefix, metadataBytes, plaintext, chunkIndex, final) {
32632
+ const encrypted = new Uint8Array(
32633
+ await webCrypto().subtle.encrypt(
32634
+ {
32635
+ name: "AES-GCM",
32636
+ iv: chunkNonce(noncePrefix, chunkIndex),
32637
+ additionalData: chunkAad(
32638
+ metadataBytes,
32639
+ chunkIndex,
32640
+ final,
32641
+ plaintext.length
32642
+ ),
32643
+ tagLength: AES_GCM_TAG_BYTES * 8
32644
+ },
32645
+ key,
32646
+ plaintext
32647
+ )
32648
+ );
32649
+ const frame = new Uint8Array(
32650
+ FRAME_LENGTH_BYTES + FRAME_FLAGS_BYTES + encrypted.length
32651
+ );
32652
+ new DataView(frame.buffer).setUint32(0, encrypted.length);
32653
+ frame[FRAME_LENGTH_BYTES] = final ? FINAL_FRAME_FLAG : 0;
32654
+ frame.set(encrypted, FRAME_LENGTH_BYTES + FRAME_FLAGS_BYTES);
32655
+ return frame;
32656
+ }
32657
+ function verifyResultBindings(metadata, expect) {
32658
+ if (metadata.jobId !== expect.jobId) {
32659
+ throw new JobEnvelopeError(
32660
+ `Job result ID ${metadata.jobId} does not match expected job ID ${expect.jobId}`
32661
+ );
32662
+ }
32663
+ if (expect.scope !== void 0 && metadata.scope !== expect.scope) {
32664
+ throw new JobEnvelopeError(
32665
+ `Job result scope ${metadata.scope} does not match expected scope ${expect.scope}`
32666
+ );
32667
+ }
32668
+ if (expect.version !== void 0 && metadata.version !== expect.version) {
32669
+ throw new JobEnvelopeError(
32670
+ `Job result version ${String(metadata.version)} does not match expected version ${String(expect.version)}`
32671
+ );
32672
+ }
32673
+ }
32674
+ var ByteStreamReader = class {
32675
+ reader;
32676
+ current;
32677
+ offset = 0;
32678
+ ended = false;
32679
+ constructor(stream) {
32680
+ this.reader = stream.getReader();
32681
+ }
32682
+ async ensureBytes() {
32683
+ while (!this.current || this.offset === this.current.length) {
32684
+ if (this.ended) return false;
32685
+ const next = await this.reader.read();
32686
+ if (next.done) {
32687
+ this.ended = true;
32688
+ this.current = void 0;
32689
+ return false;
32690
+ }
32691
+ if (!(next.value instanceof Uint8Array)) {
32692
+ throw new JobEnvelopeError(
32693
+ "Invalid job result: stream yielded non-byte data"
32694
+ );
32695
+ }
32696
+ this.current = next.value;
32697
+ this.offset = 0;
32698
+ }
32699
+ return true;
32700
+ }
32701
+ async readExactOrNull(length) {
32702
+ if (!await this.ensureBytes()) return null;
32703
+ const bytes = new Uint8Array(length);
32704
+ let written = 0;
32705
+ while (written < length) {
32706
+ if (!await this.ensureBytes()) {
32707
+ throw new JobEnvelopeError("Invalid job result: truncated payload");
32708
+ }
32709
+ const available = this.current.length - this.offset;
32710
+ const count = Math.min(available, length - written);
32711
+ bytes.set(
32712
+ this.current.subarray(this.offset, this.offset + count),
32713
+ written
32714
+ );
32715
+ this.offset += count;
32716
+ written += count;
32717
+ }
32718
+ return bytes;
32719
+ }
32720
+ async readExact(length) {
32721
+ const bytes = await this.readExactOrNull(length);
32722
+ if (!bytes) {
32723
+ throw new JobEnvelopeError("Invalid job result: truncated payload");
32724
+ }
32725
+ return bytes;
32726
+ }
32727
+ async hasRemaining() {
32728
+ return this.ensureBytes();
32729
+ }
32730
+ async cancel(reason) {
32731
+ await this.reader.cancel(reason);
32732
+ }
32733
+ };
32734
+ function normalizeChunkError(error) {
32735
+ if (error instanceof JobEnvelopeError) return error;
32736
+ return new JobEnvelopeError(
32737
+ `Invalid job result: chunk authentication failed${error instanceof Error ? `: ${error.message}` : ""}`
32738
+ );
32739
+ }
32796
32740
  async function sealJobRequest(envelope, enclavePublicKey, ecies) {
32797
32741
  const encrypted = await ecies.encrypt(
32798
32742
  fromHex6(enclavePublicKey, "bytes"),
@@ -32809,41 +32753,333 @@ async function openJobRequest(ciphertext, privateKey, ecies) {
32809
32753
  parseObject(plaintext, "job request envelope")
32810
32754
  );
32811
32755
  }
32812
- async function sealJobResult(result, builderPublicKey, ecies) {
32813
- validateResult(result);
32814
- const encrypted = await ecies.encrypt(
32756
+ async function sealJobResultStream(metadataValue, builderPublicKey, ecies) {
32757
+ const metadata = validateResultMetadata(metadataValue);
32758
+ const metadataBytes = canonicalJsonBytes(metadata);
32759
+ if (metadataBytes.length > MAX_JOB_RESULT_HEADER_BYTES) {
32760
+ throw new JobEnvelopeError(
32761
+ `Invalid job result: header exceeds ${MAX_JOB_RESULT_HEADER_BYTES} bytes`
32762
+ );
32763
+ }
32764
+ const crypto2 = webCrypto();
32765
+ const contentKey = crypto2.getRandomValues(new Uint8Array(AES_KEY_BYTES));
32766
+ const noncePrefix = crypto2.getRandomValues(
32767
+ new Uint8Array(AES_GCM_NONCE_BYTES)
32768
+ );
32769
+ const key = await importAesKey(contentKey, "encrypt");
32770
+ const keyPlaintext = wrappedKeyPlaintext(
32771
+ contentKey,
32772
+ noncePrefix,
32773
+ metadataBytes
32774
+ );
32775
+ const encryptedKey = await ecies.encrypt(
32815
32776
  fromHex6(builderPublicKey, "bytes"),
32816
- resultPlaintext(result)
32777
+ keyPlaintext
32817
32778
  );
32818
- const ciphertext = encryptedBytesToBase64(encrypted);
32819
- const bytes = fromBase64(ciphertext);
32820
- return { ciphertext, hash: bytesToHex2(sha2565(bytes)), size: bytes.length };
32779
+ contentKey.fill(0);
32780
+ keyPlaintext.fill(0);
32781
+ const wrappedKey = encryptedToBytes(encryptedKey);
32782
+ if (wrappedKey.length > MAX_WRAPPED_KEY_BYTES) {
32783
+ throw new JobEnvelopeError("Invalid job result: wrapped key is too large");
32784
+ }
32785
+ const header = new Uint8Array(
32786
+ 1 + WRAPPED_KEY_LENGTH_BYTES + wrappedKey.length
32787
+ );
32788
+ header[0] = JOB_RESULT_FORMAT_VERSION;
32789
+ new DataView(header.buffer).setUint32(1, wrappedKey.length);
32790
+ header.set(wrappedKey, 1 + WRAPPED_KEY_LENGTH_BYTES);
32791
+ let pending = new Uint8Array(JOB_RESULT_CHUNK_BYTES);
32792
+ let pendingLength = 0;
32793
+ let chunkIndex = 0;
32794
+ const transform = new TransformStream({
32795
+ async transform(chunk, controller) {
32796
+ if (!(chunk instanceof Uint8Array)) {
32797
+ throw new JobEnvelopeError(
32798
+ "Invalid job result: stream yielded non-byte data"
32799
+ );
32800
+ }
32801
+ let offset = 0;
32802
+ while (offset < chunk.length) {
32803
+ if (pendingLength === JOB_RESULT_CHUNK_BYTES) {
32804
+ controller.enqueue(
32805
+ await encryptResultChunk(
32806
+ key,
32807
+ noncePrefix,
32808
+ metadataBytes,
32809
+ pending,
32810
+ chunkIndex,
32811
+ false
32812
+ )
32813
+ );
32814
+ chunkIndex += 1;
32815
+ pending = new Uint8Array(JOB_RESULT_CHUNK_BYTES);
32816
+ pendingLength = 0;
32817
+ }
32818
+ const count = Math.min(
32819
+ chunk.length - offset,
32820
+ JOB_RESULT_CHUNK_BYTES - pendingLength
32821
+ );
32822
+ pending.set(chunk.subarray(offset, offset + count), pendingLength);
32823
+ pendingLength += count;
32824
+ offset += count;
32825
+ }
32826
+ },
32827
+ async flush(controller) {
32828
+ controller.enqueue(
32829
+ await encryptResultChunk(
32830
+ key,
32831
+ noncePrefix,
32832
+ metadataBytes,
32833
+ pending.subarray(0, pendingLength),
32834
+ chunkIndex,
32835
+ true
32836
+ )
32837
+ );
32838
+ }
32839
+ });
32840
+ return { header, transform };
32821
32841
  }
32822
- async function openJobResult(ciphertext, builderPrivateKey, ecies, expect) {
32823
- const plaintext = await ecies.decrypt(
32824
- fromHex6(builderPrivateKey, "bytes"),
32825
- base64ToEncrypted(ciphertext)
32842
+ async function sealJobResult(result, builderPublicKey, ecies) {
32843
+ validateResult(result);
32844
+ const sealed = await sealJobResultStream(
32845
+ resultMetadata(result),
32846
+ builderPublicKey,
32847
+ ecies
32848
+ );
32849
+ const frameCount = Math.max(
32850
+ 1,
32851
+ Math.ceil(result.body.length / JOB_RESULT_CHUNK_BYTES)
32826
32852
  );
32827
- const result = validateResult(parseObject(plaintext, "job result"));
32828
- if (result.jobId !== expect.jobId) {
32853
+ const size = sealed.header.length + result.body.length + frameCount * (FRAME_LENGTH_BYTES + FRAME_FLAGS_BYTES + AES_GCM_TAG_BYTES);
32854
+ const bytes = new Uint8Array(size);
32855
+ bytes.set(sealed.header, 0);
32856
+ let outputOffset = sealed.header.length;
32857
+ const reader = sealed.transform.readable.getReader();
32858
+ const drain = (async () => {
32859
+ for (; ; ) {
32860
+ const next = await reader.read();
32861
+ if (next.done) break;
32862
+ bytes.set(next.value, outputOffset);
32863
+ outputOffset += next.value.length;
32864
+ }
32865
+ })();
32866
+ const writer = sealed.transform.writable.getWriter();
32867
+ const fill = (async () => {
32868
+ for (let offset = 0; offset < result.body.length; offset += JOB_RESULT_CHUNK_BYTES) {
32869
+ await writer.write(
32870
+ result.body.subarray(offset, offset + JOB_RESULT_CHUNK_BYTES)
32871
+ );
32872
+ }
32873
+ await writer.close();
32874
+ })();
32875
+ await Promise.all([drain, fill]);
32876
+ if (outputOffset !== bytes.length) {
32877
+ throw new JobEnvelopeError("Invalid job result: sealed size mismatch");
32878
+ }
32879
+ return { bytes, hash: bytesToHex2(sha2565(bytes)), size };
32880
+ }
32881
+ async function openJobResultStream(bytesStream, builderPrivateKey, ecies, expect) {
32882
+ const reader = new ByteStreamReader(bytesStream);
32883
+ const headerPrefix = await reader.readExact(1 + WRAPPED_KEY_LENGTH_BYTES);
32884
+ const formatVersion = headerPrefix[0];
32885
+ if (formatVersion !== JOB_RESULT_FORMAT_VERSION) {
32829
32886
  throw new JobEnvelopeError(
32830
- `Job result ID ${result.jobId} does not match expected job ID ${expect.jobId}`
32887
+ `Unsupported job result format: ${String(formatVersion)}`
32831
32888
  );
32832
32889
  }
32833
- if (expect.scope !== void 0 && result.scope !== expect.scope) {
32890
+ const wrappedKeyLength = readUint32(headerPrefix, 1);
32891
+ if (wrappedKeyLength === 0 || wrappedKeyLength > MAX_WRAPPED_KEY_BYTES) {
32834
32892
  throw new JobEnvelopeError(
32835
- `Job result scope ${result.scope} does not match expected scope ${expect.scope}`
32893
+ "Invalid job result: invalid wrapped key length"
32836
32894
  );
32837
32895
  }
32838
- if (expect.version !== void 0 && result.version !== expect.version) {
32896
+ const wrappedKey = await reader.readExact(wrappedKeyLength);
32897
+ const keyPlaintext = await ecies.decrypt(
32898
+ fromHex6(builderPrivateKey, "bytes"),
32899
+ bytesToEncrypted(wrappedKey)
32900
+ );
32901
+ const parsed = parseWrappedKeyPlaintext(keyPlaintext);
32902
+ verifyResultBindings(parsed.metadata, expect);
32903
+ const key = await importAesKey(parsed.contentKey, "decrypt");
32904
+ parsed.contentKey.fill(0);
32905
+ keyPlaintext.fill(0);
32906
+ let chunkIndex = 0;
32907
+ let finished = false;
32908
+ const body = new ReadableStream({
32909
+ async pull(controller) {
32910
+ if (finished) {
32911
+ controller.close();
32912
+ return;
32913
+ }
32914
+ try {
32915
+ const frameHeader = await reader.readExactOrNull(
32916
+ FRAME_LENGTH_BYTES + FRAME_FLAGS_BYTES
32917
+ );
32918
+ if (!frameHeader) {
32919
+ throw new JobEnvelopeError("Invalid job result: missing final chunk");
32920
+ }
32921
+ const encryptedLength = readUint32(frameHeader);
32922
+ if (encryptedLength < AES_GCM_TAG_BYTES || encryptedLength > JOB_RESULT_CHUNK_BYTES + AES_GCM_TAG_BYTES) {
32923
+ throw new JobEnvelopeError(
32924
+ "Invalid job result: invalid chunk length"
32925
+ );
32926
+ }
32927
+ const flags = frameHeader[FRAME_LENGTH_BYTES];
32928
+ if (flags !== 0 && flags !== FINAL_FRAME_FLAG) {
32929
+ throw new JobEnvelopeError("Invalid job result: invalid chunk flags");
32930
+ }
32931
+ const final = flags === FINAL_FRAME_FLAG;
32932
+ const plaintextLength = encryptedLength - AES_GCM_TAG_BYTES;
32933
+ if (!final && plaintextLength !== JOB_RESULT_CHUNK_BYTES) {
32934
+ throw new JobEnvelopeError(
32935
+ "Invalid job result: short non-final chunk"
32936
+ );
32937
+ }
32938
+ const encrypted = await reader.readExact(encryptedLength);
32939
+ const plaintext = new Uint8Array(
32940
+ await webCrypto().subtle.decrypt(
32941
+ {
32942
+ name: "AES-GCM",
32943
+ iv: chunkNonce(parsed.noncePrefix, chunkIndex),
32944
+ additionalData: chunkAad(
32945
+ parsed.metadataBytes,
32946
+ chunkIndex,
32947
+ final,
32948
+ plaintextLength
32949
+ ),
32950
+ tagLength: AES_GCM_TAG_BYTES * 8
32951
+ },
32952
+ key,
32953
+ encrypted
32954
+ )
32955
+ );
32956
+ if (plaintext.length !== plaintextLength) {
32957
+ throw new JobEnvelopeError(
32958
+ "Invalid job result: decrypted chunk length mismatch"
32959
+ );
32960
+ }
32961
+ chunkIndex += 1;
32962
+ if (final) {
32963
+ if (await reader.hasRemaining()) {
32964
+ throw new JobEnvelopeError(
32965
+ "Invalid job result: bytes follow final chunk"
32966
+ );
32967
+ }
32968
+ finished = true;
32969
+ }
32970
+ controller.enqueue(plaintext);
32971
+ if (finished) controller.close();
32972
+ } catch (error) {
32973
+ controller.error(normalizeChunkError(error));
32974
+ void reader.cancel(error).catch(() => void 0);
32975
+ }
32976
+ },
32977
+ cancel(reason) {
32978
+ return reader.cancel(reason);
32979
+ }
32980
+ });
32981
+ return { metadata: parsed.metadata, body };
32982
+ }
32983
+ function bufferedResultBodySize(sealedBytes) {
32984
+ if (sealedBytes.length < 1 + WRAPPED_KEY_LENGTH_BYTES) {
32985
+ throw new JobEnvelopeError("Invalid job result: truncated payload");
32986
+ }
32987
+ if (sealedBytes[0] !== JOB_RESULT_FORMAT_VERSION) {
32839
32988
  throw new JobEnvelopeError(
32840
- `Job result version ${String(result.version)} does not match expected version ${String(expect.version)}`
32989
+ `Unsupported job result format: ${String(sealedBytes[0])}`
32841
32990
  );
32842
32991
  }
32843
- return result;
32992
+ const wrappedKeyLength = readUint32(sealedBytes, 1);
32993
+ if (wrappedKeyLength === 0 || wrappedKeyLength > MAX_WRAPPED_KEY_BYTES) {
32994
+ throw new JobEnvelopeError(
32995
+ "Invalid job result: invalid wrapped key length"
32996
+ );
32997
+ }
32998
+ let offset = 1 + WRAPPED_KEY_LENGTH_BYTES + wrappedKeyLength;
32999
+ if (offset > sealedBytes.length) {
33000
+ throw new JobEnvelopeError("Invalid job result: truncated payload");
33001
+ }
33002
+ let bodySize = 0;
33003
+ let sawFinal = false;
33004
+ while (offset < sealedBytes.length) {
33005
+ if (sealedBytes.length - offset < FRAME_LENGTH_BYTES + FRAME_FLAGS_BYTES) {
33006
+ throw new JobEnvelopeError("Invalid job result: truncated payload");
33007
+ }
33008
+ const encryptedLength = readUint32(sealedBytes, offset);
33009
+ const flags = sealedBytes[offset + FRAME_LENGTH_BYTES];
33010
+ if (encryptedLength < AES_GCM_TAG_BYTES || encryptedLength > JOB_RESULT_CHUNK_BYTES + AES_GCM_TAG_BYTES || flags !== 0 && flags !== FINAL_FRAME_FLAG) {
33011
+ throw new JobEnvelopeError("Invalid job result: invalid chunk framing");
33012
+ }
33013
+ const plaintextLength = encryptedLength - AES_GCM_TAG_BYTES;
33014
+ if (flags === 0 && plaintextLength !== JOB_RESULT_CHUNK_BYTES) {
33015
+ throw new JobEnvelopeError("Invalid job result: short non-final chunk");
33016
+ }
33017
+ offset += FRAME_LENGTH_BYTES + FRAME_FLAGS_BYTES;
33018
+ if (encryptedLength > sealedBytes.length - offset) {
33019
+ throw new JobEnvelopeError("Invalid job result: truncated payload");
33020
+ }
33021
+ offset += encryptedLength;
33022
+ bodySize += plaintextLength;
33023
+ if (flags === FINAL_FRAME_FLAG) {
33024
+ sawFinal = true;
33025
+ if (offset !== sealedBytes.length) {
33026
+ throw new JobEnvelopeError(
33027
+ "Invalid job result: bytes follow final chunk"
33028
+ );
33029
+ }
33030
+ }
33031
+ }
33032
+ if (!sawFinal) {
33033
+ throw new JobEnvelopeError("Invalid job result: missing final chunk");
33034
+ }
33035
+ return bodySize;
33036
+ }
33037
+ async function openJobResult(sealedBytes, builderPrivateKey, ecies, expect) {
33038
+ const bodySize = bufferedResultBodySize(sealedBytes);
33039
+ const stream = new ReadableStream({
33040
+ start(controller) {
33041
+ controller.enqueue(sealedBytes);
33042
+ controller.close();
33043
+ }
33044
+ });
33045
+ const opened = await openJobResultStream(
33046
+ stream,
33047
+ builderPrivateKey,
33048
+ ecies,
33049
+ expect
33050
+ );
33051
+ const body = new Uint8Array(bodySize);
33052
+ let offset = 0;
33053
+ await opened.body.pipeTo(
33054
+ new WritableStream({
33055
+ write(chunk) {
33056
+ body.set(chunk, offset);
33057
+ offset += chunk.length;
33058
+ }
33059
+ })
33060
+ );
33061
+ if (offset !== body.length) {
33062
+ throw new JobEnvelopeError("Invalid job result: opened size mismatch");
33063
+ }
33064
+ return { ...opened.metadata, body };
32844
33065
  }
32845
33066
 
33067
+ // src/protocol/jobs-client.ts
33068
+ import {
33069
+ BuilderUnknownError,
33070
+ GrantInvalidError,
33071
+ JobIdTakenError,
33072
+ JobNotFoundError,
33073
+ JobRejectedError,
33074
+ JobResultIntegrityError,
33075
+ JobRequestTooLargeError,
33076
+ JobTimeoutError,
33077
+ JobTransportError,
33078
+ OwnerNotReadyError
33079
+ } from "./errors.js";
33080
+
32846
33081
  // src/protocol/write-signer.ts
33082
+ import { WriteRequestError } from "./errors.js";
32847
33083
  function isRecord(value) {
32848
33084
  return value !== null && typeof value === "object";
32849
33085
  }
@@ -33046,7 +33282,7 @@ async function rejectedResponse(response, fallback) {
33046
33282
  return new JobRejectedError(message, response.status, parsed.code, details);
33047
33283
  }
33048
33284
  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"])) {
33285
+ 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
33286
  throw new JobRejectedError(
33051
33287
  "Gateway response did not contain a job status",
33052
33288
  status
@@ -33057,6 +33293,17 @@ function requireStatus(value, status) {
33057
33293
  function isNonEmptyString(value) {
33058
33294
  return typeof value === "string" && value.length > 0;
33059
33295
  }
33296
+ function isResultHandle(value) {
33297
+ 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"]))) {
33298
+ return false;
33299
+ }
33300
+ try {
33301
+ const url = new URL(value["url"]);
33302
+ return url.protocol === "https:" || url.protocol === "http:";
33303
+ } catch {
33304
+ return false;
33305
+ }
33306
+ }
33060
33307
  function hasMatchingIdentityKey(value) {
33061
33308
  const address = value["address"];
33062
33309
  const publicKey = value["publicKey"];
@@ -33302,31 +33549,51 @@ function createJobsClient(options) {
33302
33549
  await sleep2(Math.min(pollMs, remaining));
33303
33550
  }
33304
33551
  },
33305
- async openResult(job, openOptions) {
33306
- if (!job.resultCiphertext) {
33552
+ async openResult(handle, openOptions) {
33553
+ if (!privateKey) {
33307
33554
  throw new JobRejectedError(
33308
- "Job status does not include inline resultCiphertext",
33309
- void 0,
33310
- null,
33555
+ "openResult requires createJobsClient({ builderPrivateKey })"
33556
+ );
33557
+ }
33558
+ const response = await request(
33559
+ handle.url,
33560
+ { method: GET_METHOD },
33561
+ "Job result fetch"
33562
+ );
33563
+ if (!response.ok) {
33564
+ throw await rejectedResponse(response, "Job result fetch rejected");
33565
+ }
33566
+ let bytes;
33567
+ try {
33568
+ bytes = new Uint8Array(await response.arrayBuffer());
33569
+ } catch (error) {
33570
+ throw new JobTransportError(
33571
+ `Job result fetch failed: ${error instanceof Error ? error.message : String(error)}`,
33572
+ error
33573
+ );
33574
+ }
33575
+ const actualHash = bytesToHex3(sha2566(bytes));
33576
+ if (actualHash.toLowerCase() !== handle.hash.toLowerCase()) {
33577
+ throw new JobResultIntegrityError(
33578
+ "Fetched job result hash does not match its handle",
33311
33579
  {
33312
- jobId: job.jobId,
33313
- state: job.state,
33314
- resultHandle: job.resultHandle,
33315
- maxInlineResultBytes: MAX_INLINE_RESULT_BYTES
33580
+ objectKey: handle.objectKey,
33581
+ expectedHash: handle.hash,
33582
+ actualHash
33316
33583
  }
33317
33584
  );
33318
33585
  }
33319
- if (!privateKey) {
33320
- throw new JobRejectedError(
33321
- "openResult requires createJobsClient({ builderPrivateKey })"
33586
+ if (bytes.length !== handle.size) {
33587
+ throw new JobResultIntegrityError(
33588
+ "Fetched job result size does not match its handle",
33589
+ {
33590
+ objectKey: handle.objectKey,
33591
+ expectedSize: handle.size,
33592
+ actualSize: bytes.length
33593
+ }
33322
33594
  );
33323
33595
  }
33324
- return openJobResult(
33325
- job.resultCiphertext,
33326
- privateKey,
33327
- ecies,
33328
- openOptions.expect
33329
- );
33596
+ return openJobResult(bytes, privateKey, ecies, openOptions.expect);
33330
33597
  },
33331
33598
  async readRaw(params) {
33332
33599
  const submitted = await client.submitRawRead(params);
@@ -33334,7 +33601,27 @@ function createJobsClient(options) {
33334
33601
  timeoutMs: params.timeoutMs,
33335
33602
  pollMs: params.pollMs
33336
33603
  });
33337
- return client.openResult(job, {
33604
+ if (job.state !== "completed") {
33605
+ throw new JobRejectedError(
33606
+ `Job ${job.jobId} ended in state ${job.state}${job.failureReason ? `: ${job.failureReason}` : ""}`,
33607
+ void 0,
33608
+ null,
33609
+ {
33610
+ jobId: job.jobId,
33611
+ state: job.state,
33612
+ ...job.failureReason ? { failureReason: job.failureReason } : {}
33613
+ }
33614
+ );
33615
+ }
33616
+ if (!job.result) {
33617
+ throw new JobRejectedError(
33618
+ "Completed job status does not include a result handle",
33619
+ void 0,
33620
+ null,
33621
+ { jobId: job.jobId, state: job.state }
33622
+ );
33623
+ }
33624
+ return client.openResult(job.result, {
33338
33625
  expect: {
33339
33626
  jobId: submitted.jobId,
33340
33627
  scope: params.scope,
@@ -34049,6 +34336,7 @@ import {
34049
34336
  maxUint256,
34050
34337
  stringToBytes as stringToBytes3
34051
34338
  } from "viem";
34339
+ import { DataPointDeletedError, DataPointNotFoundError } from "./errors.js";
34052
34340
 
34053
34341
  // src/protocol/lineage.ts
34054
34342
  import {
@@ -34057,6 +34345,7 @@ import {
34057
34345
  keccak256 as keccak2562
34058
34346
  } from "viem";
34059
34347
  import { z } from "zod";
34348
+ import { LineageReadError, WriteRequestError as WriteRequestError2 } from "./errors.js";
34060
34349
 
34061
34350
  // src/protocol/personal-server-error-body.ts
34062
34351
  function isRecord4(value) {
@@ -34128,7 +34417,7 @@ function derivedScopeViolatesNaming(derivedScope, sourceScope) {
34128
34417
  function assertDerivedScopeNaming(derivedScope, sourceScopes) {
34129
34418
  for (const sourceScope of sourceScopes) {
34130
34419
  if (derivedScopeViolatesNaming(derivedScope, sourceScope)) {
34131
- throw new WriteRequestError(
34420
+ throw new WriteRequestError2(
34132
34421
  `Derived scope ${derivedScope} must not share its first segment with source scope ${sourceScope}; put derivatives in the app's own namespace`,
34133
34422
  { scope: derivedScope, sourceScope }
34134
34423
  );
@@ -34486,6 +34775,9 @@ async function deleteDataPoint(input) {
34486
34775
  }
34487
34776
  }
34488
34777
 
34778
+ // src/protocol/personal-server-data.ts
34779
+ import { DataPointDeletedError as DataPointDeletedError2 } from "./errors.js";
34780
+
34489
34781
  // src/protocol/data-file.ts
34490
34782
  import { z as z2 } from "zod";
34491
34783
  var DataFileEnvelopeSchema = z2.object({
@@ -34544,7 +34836,7 @@ async function readPersonalServerData(params) {
34544
34836
  const request = await buildPersonalServerDataReadRequest(params);
34545
34837
  const response = await fetchFn(request);
34546
34838
  if (response.status === 410) {
34547
- throw new DataPointDeletedError(
34839
+ throw new DataPointDeletedError2(
34548
34840
  `Personal Server scope '${params.scope}' has been deleted`,
34549
34841
  {
34550
34842
  scope: params.scope,
@@ -34559,7 +34851,7 @@ async function readPersonalServerData(params) {
34559
34851
  }
34560
34852
  const body = await response.json();
34561
34853
  if (isDataPointTombstone(body)) {
34562
- throw new DataPointDeletedError(
34854
+ throw new DataPointDeletedError2(
34563
34855
  `Personal Server scope '${params.scope}' has been deleted`,
34564
34856
  { scope: params.scope, deletedAt: tombstoneDeletedAt(body) }
34565
34857
  );
@@ -34759,20 +35051,31 @@ function tryGrantPermissions(scopes) {
34759
35051
  }
34760
35052
 
34761
35053
  // 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";
35054
+ import { sha256 as sha2568 } from "@noble/hashes/sha2";
35055
+ import { bytesToHex as bytesToHex5, isAddress as isAddress8 } from "viem";
34764
35056
  import { z as z4 } from "zod";
35057
+ import {
35058
+ WriteConflictError,
35059
+ WriteForbiddenError,
35060
+ WriteLineageError,
35061
+ WriteRejectedError,
35062
+ WriteRequestError as WriteRequestError4,
35063
+ WriteSessionError,
35064
+ WriteSessionExpiredError,
35065
+ WriteUnauthorizedError
35066
+ } from "./errors.js";
34765
35067
 
34766
35068
  // src/protocol/write-request.ts
34767
- import { sha256 as sha2566 } from "@noble/hashes/sha2";
34768
- import { bytesToHex as bytesToHex3 } from "viem";
35069
+ import { sha256 as sha2567 } from "@noble/hashes/sha2";
35070
+ import { bytesToHex as bytesToHex4 } from "viem";
35071
+ import { WriteRequestError as WriteRequestError3, WriteTransportError } from "./errors.js";
34769
35072
  function normalizeBaseUrl2(url) {
34770
35073
  return url.replace(/\/+$/, "");
34771
35074
  }
34772
35075
  function resolveFetch3(fetchFn) {
34773
35076
  const resolved = fetchFn ?? globalThis.fetch;
34774
35077
  if (resolved === void 0) {
34775
- throw new WriteRequestError("No fetch implementation available");
35078
+ throw new WriteRequestError3("No fetch implementation available");
34776
35079
  }
34777
35080
  return resolved;
34778
35081
  }
@@ -34827,27 +35130,27 @@ function nextProofIat(proofKey) {
34827
35130
  return sleep3(waitSec * 1e3).then(() => iat);
34828
35131
  }
34829
35132
  function freshProofNonce() {
34830
- const webCrypto = globalThis.crypto;
34831
- if (typeof webCrypto?.randomUUID === "function") {
34832
- return webCrypto.randomUUID();
35133
+ const webCrypto2 = globalThis.crypto;
35134
+ if (typeof webCrypto2?.randomUUID === "function") {
35135
+ return webCrypto2.randomUUID();
34833
35136
  }
34834
- if (typeof webCrypto?.getRandomValues === "function") {
34835
- return bytesToHex3(webCrypto.getRandomValues(new Uint8Array(16)));
35137
+ if (typeof webCrypto2?.getRandomValues === "function") {
35138
+ return bytesToHex4(webCrypto2.getRandomValues(new Uint8Array(16)));
34836
35139
  }
34837
- throw new WriteRequestError(
35140
+ throw new WriteRequestError3(
34838
35141
  "No secure random source available to build a proof nonce; provide a crypto global"
34839
35142
  );
34840
35143
  }
34841
35144
  function proofKeyFor(parts) {
34842
- return bytesToHex3(
34843
- sha2566(
35145
+ return bytesToHex4(
35146
+ sha2567(
34844
35147
  new TextEncoder().encode(
34845
35148
  JSON.stringify([
34846
35149
  parts.aud,
34847
35150
  parts.method,
34848
35151
  parts.uri,
34849
35152
  parts.grantId,
34850
- parts.signedBytes ? bytesToHex3(sha2566(parts.signedBytes)) : ""
35153
+ parts.signedBytes ? bytesToHex4(sha2567(parts.signedBytes)) : ""
34851
35154
  ])
34852
35155
  )
34853
35156
  )
@@ -34990,7 +35293,7 @@ function isWriteSession(value) {
34990
35293
  }
34991
35294
  function sessionCoversScope(session, scope) {
34992
35295
  if (!isRecord4(session) || !Array.isArray(session.writeScopes) || !session.writeScopes.every((pattern) => typeof pattern === "string")) {
34993
- throw new WriteRequestError("session must come from openWriteSession");
35296
+ throw new WriteRequestError4("session must come from openWriteSession");
34994
35297
  }
34995
35298
  return session.writeScopes.some(
34996
35299
  (pattern) => scopeMatchesPattern(scope, pattern)
@@ -35015,12 +35318,12 @@ function encodeWriteMetadataHeader(metadata) {
35015
35318
  try {
35016
35319
  json = JSON.stringify(metadata);
35017
35320
  } catch (err) {
35018
- throw new WriteRequestError(
35321
+ throw new WriteRequestError4(
35019
35322
  `metadata is not JSON-serialisable: ${errorMessage(err)}`
35020
35323
  );
35021
35324
  }
35022
35325
  if (typeof json !== "string") {
35023
- throw new WriteRequestError("metadata must serialise to JSON");
35326
+ throw new WriteRequestError4("metadata must serialise to JSON");
35024
35327
  }
35025
35328
  return json.replace(
35026
35329
  /[\u007f-\uffff]/g,
@@ -35034,7 +35337,7 @@ function binaryWriteSignedBytes(input) {
35034
35337
  mimeType: normalizeBinaryMimeType(input.contentType),
35035
35338
  ...input.filename ? { filename: input.filename } : {},
35036
35339
  sizeBytes: input.bytes.length,
35037
- contentHash: bytesToHex4(sha2567(input.bytes)),
35340
+ contentHash: bytesToHex5(sha2568(input.bytes)),
35038
35341
  encoding: "base64",
35039
35342
  content: toBase64(input.bytes),
35040
35343
  ...metadata !== void 0 ? { metadata } : {}
@@ -35055,7 +35358,7 @@ function setFilenameHeader(headers, filename) {
35055
35358
  function assertNoReservedKeys(value, where) {
35056
35359
  for (const key of RESERVED_WRITE_KEYS) {
35057
35360
  if (Object.prototype.hasOwnProperty.call(value, key)) {
35058
- throw new WriteRequestError(
35361
+ throw new WriteRequestError4(
35059
35362
  `${where} must not contain the reserved ${key} key; the Personal Server stamps it`,
35060
35363
  { key }
35061
35364
  );
@@ -35067,10 +35370,10 @@ function isLineagePair(value) {
35067
35370
  }
35068
35371
  function normalizeLineage(lineage, derivedScope) {
35069
35372
  if (!Array.isArray(lineage)) {
35070
- throw new WriteRequestError("lineage must be an array of data point ids");
35373
+ throw new WriteRequestError4("lineage must be an array of data point ids");
35071
35374
  }
35072
35375
  if (lineage.length > MAX_LINEAGE_SOURCES) {
35073
- throw new WriteRequestError(
35376
+ throw new WriteRequestError4(
35074
35377
  `lineage lists ${lineage.length} sources; the maximum is ${MAX_LINEAGE_SOURCES}`,
35075
35378
  { max: MAX_LINEAGE_SOURCES, count: lineage.length }
35076
35379
  );
@@ -35083,13 +35386,13 @@ function normalizeLineage(lineage, derivedScope) {
35083
35386
  let id;
35084
35387
  if (isLineagePair(entry)) {
35085
35388
  if (!isAddress8(entry.ownerAddress, { strict: false })) {
35086
- throw new WriteRequestError(
35389
+ throw new WriteRequestError4(
35087
35390
  "lineage source ownerAddress must be an EVM address",
35088
35391
  { ownerAddress: entry.ownerAddress }
35089
35392
  );
35090
35393
  }
35091
35394
  if (entry.scope.length === 0) {
35092
- throw new WriteRequestError("lineage source scope is required");
35395
+ throw new WriteRequestError4("lineage source scope is required");
35093
35396
  }
35094
35397
  id = deriveDataPointId(entry.ownerAddress, entry.scope);
35095
35398
  sourceScopes.push(entry.scope);
@@ -35097,14 +35400,14 @@ function normalizeLineage(lineage, derivedScope) {
35097
35400
  } else if (isDataPointId(entry)) {
35098
35401
  id = entry;
35099
35402
  } else {
35100
- throw new WriteRequestError(
35403
+ throw new WriteRequestError4(
35101
35404
  "lineage entries must be 32-byte hex data point ids or { ownerAddress, scope } pairs",
35102
35405
  { entry }
35103
35406
  );
35104
35407
  }
35105
35408
  const normalized = id.toLowerCase();
35106
35409
  if (seen.has(normalized)) {
35107
- throw new WriteRequestError("lineage must not repeat a data point id", {
35410
+ throw new WriteRequestError4("lineage must not repeat a data point id", {
35108
35411
  dataPointId: normalized
35109
35412
  });
35110
35413
  }
@@ -35113,7 +35416,7 @@ function normalizeLineage(lineage, derivedScope) {
35113
35416
  }
35114
35417
  for (const own of ownIds) {
35115
35418
  if (seen.has(own)) {
35116
- throw new WriteRequestError(
35419
+ throw new WriteRequestError4(
35117
35420
  "lineage must not cite the record's own data point",
35118
35421
  { dataPointId: own, scope: derivedScope }
35119
35422
  );
@@ -35124,7 +35427,7 @@ function normalizeLineage(lineage, derivedScope) {
35124
35427
  }
35125
35428
  function assertNoLineageField(value, where) {
35126
35429
  if (Object.prototype.hasOwnProperty.call(value, LINEAGE_FIELD)) {
35127
- throw new WriteRequestError(
35430
+ throw new WriteRequestError4(
35128
35431
  `${where}.${LINEAGE_FIELD} is reserved; pass sources through the lineage option`
35129
35432
  );
35130
35433
  }
@@ -35132,7 +35435,7 @@ function assertNoLineageField(value, where) {
35132
35435
  function buildMetadataHeader(metadata, sources) {
35133
35436
  if (metadata !== void 0) {
35134
35437
  if (!isRecord4(metadata)) {
35135
- throw new WriteRequestError("metadata must be a plain object");
35438
+ throw new WriteRequestError4("metadata must be a plain object");
35136
35439
  }
35137
35440
  assertNoReservedKeys(metadata, "metadata");
35138
35441
  assertNoLineageField(metadata, "metadata");
@@ -35145,24 +35448,24 @@ function buildMetadataHeader(metadata, sources) {
35145
35448
  }
35146
35449
  function prepareWrite(params) {
35147
35450
  if (params.binary !== void 0 && params.data !== void 0) {
35148
- throw new WriteRequestError("Pass either data or binary, not both");
35451
+ throw new WriteRequestError4("Pass either data or binary, not both");
35149
35452
  }
35150
35453
  const rawLineage = params.lineage;
35151
35454
  const sources = rawLineage === void 0 || rawLineage === null ? void 0 : normalizeLineage(rawLineage, params.scope);
35152
35455
  if (params.binary !== void 0) {
35153
35456
  const { bytes, contentType, filename } = params.binary;
35154
35457
  if (!(bytes instanceof Uint8Array)) {
35155
- throw new WriteRequestError("binary.bytes must be a Uint8Array");
35458
+ throw new WriteRequestError4("binary.bytes must be a Uint8Array");
35156
35459
  }
35157
35460
  if (typeof contentType !== "string" || contentType.trim() === "") {
35158
- throw new WriteRequestError("binary.contentType is required");
35461
+ throw new WriteRequestError4("binary.contentType is required");
35159
35462
  }
35160
35463
  if (filename !== void 0) {
35161
35464
  if (typeof filename !== "string") {
35162
- throw new WriteRequestError("binary.filename must be a string");
35465
+ throw new WriteRequestError4("binary.filename must be a string");
35163
35466
  }
35164
35467
  if (filename !== filename.trim()) {
35165
- throw new WriteRequestError(
35468
+ throw new WriteRequestError4(
35166
35469
  "binary.filename must not have leading or trailing whitespace"
35167
35470
  );
35168
35471
  }
@@ -35182,13 +35485,13 @@ function prepareWrite(params) {
35182
35485
  };
35183
35486
  }
35184
35487
  if (params.data === void 0) {
35185
- throw new WriteRequestError("Pass data (a JSON object) or binary");
35488
+ throw new WriteRequestError4("Pass data (a JSON object) or binary");
35186
35489
  }
35187
35490
  if (!isRecord4(params.data)) {
35188
- throw new WriteRequestError("data must be a plain JSON object");
35491
+ throw new WriteRequestError4("data must be a plain JSON object");
35189
35492
  }
35190
35493
  if (params.metadata !== void 0) {
35191
- throw new WriteRequestError(
35494
+ throw new WriteRequestError4(
35192
35495
  "metadata applies to binary writes; put fields to store inside data"
35193
35496
  );
35194
35497
  }
@@ -35199,12 +35502,12 @@ function prepareWrite(params) {
35199
35502
  try {
35200
35503
  text = JSON.stringify(record);
35201
35504
  } catch (err) {
35202
- throw new WriteRequestError(
35505
+ throw new WriteRequestError4(
35203
35506
  `data is not JSON-serialisable: ${errorMessage(err)}`
35204
35507
  );
35205
35508
  }
35206
35509
  if (typeof text !== "string" || !text.startsWith("{")) {
35207
- throw new WriteRequestError("data must serialise to a JSON object");
35510
+ throw new WriteRequestError4("data must serialise to a JSON object");
35208
35511
  }
35209
35512
  const body = new TextEncoder().encode(text);
35210
35513
  return {
@@ -35233,11 +35536,11 @@ async function writeErrorFromResponse(response) {
35233
35536
  async function writeData(params) {
35234
35537
  const { session } = params;
35235
35538
  if (!isWriteSession(session)) {
35236
- throw new WriteRequestError("session must come from openWriteSession");
35539
+ throw new WriteRequestError4("session must come from openWriteSession");
35237
35540
  }
35238
35541
  const fetchFn = resolveFetch3(params.fetch);
35239
35542
  if (typeof params.scope !== "string" || params.scope.length === 0) {
35240
- throw new WriteRequestError("scope is required");
35543
+ throw new WriteRequestError4("scope is required");
35241
35544
  }
35242
35545
  const prepared = prepareWrite(params);
35243
35546
  if (Date.now() >= session.expiresAt) {
@@ -35333,6 +35636,21 @@ async function writePersonalServerData(params) {
35333
35636
 
35334
35637
  // src/protocol/derivative-questions.ts
35335
35638
  import { z as z5 } from "zod";
35639
+ import {
35640
+ DerivativeComputeUnavailableError,
35641
+ DerivativeCycleError,
35642
+ DerivativeDerivedScopeRequiredError,
35643
+ DerivativeQuestionFailedError,
35644
+ DerivativeQuestionInvalidError,
35645
+ DerivativeQuestionNotFoundError,
35646
+ DerivativeQuestionRejectedError,
35647
+ DerivativeQuestionTimeoutError,
35648
+ DerivativeSourceNotGrantedError,
35649
+ WriteConflictError as WriteConflictError2,
35650
+ WriteForbiddenError as WriteForbiddenError2,
35651
+ WriteRequestError as WriteRequestError5,
35652
+ WriteUnauthorizedError as WriteUnauthorizedError2
35653
+ } from "./errors.js";
35336
35654
  var DERIVATIVE_QUESTIONS_PATH = "/v1/derivatives/questions";
35337
35655
  var MAX_QUESTION_SOURCE_SCOPES = 16;
35338
35656
  var MAX_QUESTION_CHARS = 8e3;
@@ -35415,15 +35733,15 @@ function fetchIdOf(fetchFn) {
35415
35733
  }
35416
35734
  function resolveRequest(params) {
35417
35735
  if (typeof params.personalServerUrl !== "string" || params.personalServerUrl.length === 0) {
35418
- throw new WriteRequestError("personalServerUrl is required");
35736
+ throw new WriteRequestError5("personalServerUrl is required");
35419
35737
  }
35420
35738
  if (typeof params.grantId !== "string" || params.grantId.length === 0) {
35421
- throw new WriteRequestError(
35739
+ throw new WriteRequestError5(
35422
35740
  "grantId is required; a question call runs under the grant carrying write:<derivedScope>"
35423
35741
  );
35424
35742
  }
35425
35743
  if (params.signer === null || typeof params.signer !== "object") {
35426
- throw new WriteRequestError(
35744
+ throw new WriteRequestError5(
35427
35745
  "signer must be a viem LocalAccount, a viem WalletClient, or a { signMessage } object"
35428
35746
  );
35429
35747
  }
@@ -35499,13 +35817,13 @@ async function questionErrorFromResponse(response, body) {
35499
35817
  }
35500
35818
  switch (response.status) {
35501
35819
  case 401:
35502
- return new WriteUnauthorizedError(text, errorCode, details);
35820
+ return new WriteUnauthorizedError2(text, errorCode, details);
35503
35821
  case 403:
35504
- return new WriteForbiddenError(text, errorCode, details);
35822
+ return new WriteForbiddenError2(text, errorCode, details);
35505
35823
  case 404:
35506
35824
  return new DerivativeQuestionNotFoundError(text, errorCode, details);
35507
35825
  case 409:
35508
- return new WriteConflictError(text, errorCode, details);
35826
+ return new WriteConflictError2(text, errorCode, details);
35509
35827
  default:
35510
35828
  return new DerivativeQuestionRejectedError(
35511
35829
  text,
@@ -35607,22 +35925,22 @@ async function sendQuestionRequest(params, spec, schema) {
35607
35925
  }
35608
35926
  function assertQuestionId(questionId) {
35609
35927
  if (typeof questionId !== "string" || questionId.length === 0) {
35610
- throw new WriteRequestError("questionId is required");
35928
+ throw new WriteRequestError5("questionId is required");
35611
35929
  }
35612
35930
  return `${DERIVATIVE_QUESTIONS_PATH}/${encodeURIComponent(questionId)}`;
35613
35931
  }
35614
35932
  function registrationBody(params) {
35615
35933
  const { derivedScope, question } = params;
35616
35934
  if (typeof derivedScope !== "string" || derivedScope.length === 0) {
35617
- throw new WriteRequestError("derivedScope is required");
35935
+ throw new WriteRequestError5("derivedScope is required");
35618
35936
  }
35619
35937
  if (!Array.isArray(params.sourceScopes) || params.sourceScopes.length === 0) {
35620
- throw new WriteRequestError(
35938
+ throw new WriteRequestError5(
35621
35939
  "sourceScopes must be a non-empty array of scopes"
35622
35940
  );
35623
35941
  }
35624
35942
  if (params.sourceScopes.length > MAX_QUESTION_SOURCE_SCOPES) {
35625
- throw new WriteRequestError(
35943
+ throw new WriteRequestError5(
35626
35944
  `sourceScopes lists ${params.sourceScopes.length} scopes; the maximum is ${MAX_QUESTION_SOURCE_SCOPES}`,
35627
35945
  { max: MAX_QUESTION_SOURCE_SCOPES, count: params.sourceScopes.length }
35628
35946
  );
@@ -35630,15 +35948,15 @@ function registrationBody(params) {
35630
35948
  const sourceScopes = [];
35631
35949
  for (const scope of params.sourceScopes) {
35632
35950
  if (typeof scope !== "string" || scope.length === 0) {
35633
- throw new WriteRequestError("sourceScopes entries must be scope strings");
35951
+ throw new WriteRequestError5("sourceScopes entries must be scope strings");
35634
35952
  }
35635
35953
  if (sourceScopes.includes(scope)) {
35636
- throw new WriteRequestError("sourceScopes must not repeat a scope", {
35954
+ throw new WriteRequestError5("sourceScopes must not repeat a scope", {
35637
35955
  duplicate: scope
35638
35956
  });
35639
35957
  }
35640
35958
  if (scope === derivedScope) {
35641
- throw new WriteRequestError(
35959
+ throw new WriteRequestError5(
35642
35960
  "derivedScope cannot be one of its own sources",
35643
35961
  { scope }
35644
35962
  );
@@ -35646,17 +35964,17 @@ function registrationBody(params) {
35646
35964
  sourceScopes.push(scope);
35647
35965
  }
35648
35966
  if (typeof question !== "string" || question.trim() === "") {
35649
- throw new WriteRequestError("question must be a non-empty string");
35967
+ throw new WriteRequestError5("question must be a non-empty string");
35650
35968
  }
35651
35969
  if (question.length > MAX_QUESTION_CHARS) {
35652
- throw new WriteRequestError(
35970
+ throw new WriteRequestError5(
35653
35971
  `question is ${question.length} characters; the maximum is ${MAX_QUESTION_CHARS}`,
35654
35972
  { max: MAX_QUESTION_CHARS, length: question.length }
35655
35973
  );
35656
35974
  }
35657
35975
  if (params.model !== void 0) {
35658
35976
  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", {
35977
+ throw new WriteRequestError5("model must be a provider model id", {
35660
35978
  model: params.model
35661
35979
  });
35662
35980
  }
@@ -35692,7 +36010,7 @@ async function getQuestion(params) {
35692
36010
  }
35693
36011
  async function listQuestions(params) {
35694
36012
  if (typeof params.derivedScope !== "string" || params.derivedScope.length === 0) {
35695
- throw new WriteRequestError(
36013
+ throw new WriteRequestError5(
35696
36014
  "derivedScope is required; a builder may only list its own questions on a scope it may write"
35697
36015
  );
35698
36016
  }
@@ -35797,6 +36115,12 @@ async function askPersonalServer(params) {
35797
36115
 
35798
36116
  // src/protocol/derivative-status.ts
35799
36117
  import { z as z6 } from "zod";
36118
+ import {
36119
+ DerivativeQuestionRejectedError as DerivativeQuestionRejectedError2,
36120
+ DerivativeQuestionTimeoutError as DerivativeQuestionTimeoutError2,
36121
+ WriteRequestError as WriteRequestError6,
36122
+ WriteTransportError as WriteTransportError2
36123
+ } from "./errors.js";
35800
36124
  var DERIVATIVE_STATUS_PATH = "/v1/derivatives/status";
35801
36125
  var DEFAULT_DERIVATIVE_STATUS_TIMEOUT_MS = 12e4;
35802
36126
  var DEFAULT_DERIVATIVE_STATUS_POLL_INTERVAL_MS = 2e3;
@@ -35827,13 +36151,13 @@ function normalizeBaseUrl3(url) {
35827
36151
  function resolveFetch4(fetchFn) {
35828
36152
  const resolved = fetchFn ?? globalThis.fetch;
35829
36153
  if (resolved === void 0) {
35830
- throw new WriteRequestError("No fetch implementation available");
36154
+ throw new WriteRequestError6("No fetch implementation available");
35831
36155
  }
35832
36156
  return resolved;
35833
36157
  }
35834
36158
  function requireDerivedScope(derivedScope) {
35835
36159
  if (typeof derivedScope !== "string" || derivedScope.length === 0) {
35836
- throw new WriteRequestError("derivedScope is required");
36160
+ throw new WriteRequestError6("derivedScope is required");
35837
36161
  }
35838
36162
  return derivedScope;
35839
36163
  }
@@ -35852,7 +36176,7 @@ function sleep4(ms, signal) {
35852
36176
  });
35853
36177
  }
35854
36178
  function timeoutError(latest, timeoutMs) {
35855
- return new DerivativeQuestionTimeoutError(
36179
+ return new DerivativeQuestionTimeoutError2(
35856
36180
  `Derived scope ${latest.derivedScope} was still ${latest.status} after ${timeoutMs}ms`,
35857
36181
  {
35858
36182
  derivedScope: latest.derivedScope,
@@ -35865,7 +36189,7 @@ function timeoutError(latest, timeoutMs) {
35865
36189
  }
35866
36190
  function abortError2(signal) {
35867
36191
  const reason = signal?.reason;
35868
- return reason instanceof Error ? reason : new WriteRequestError("Derivative status wait was aborted");
36192
+ return reason instanceof Error ? reason : new WriteRequestError6("Derivative status wait was aborted");
35869
36193
  }
35870
36194
  function isDerivativeStatusSettled(status) {
35871
36195
  if (status.status === "ready") return true;
@@ -35898,7 +36222,7 @@ async function getDerivativeStatus(params) {
35898
36222
  }
35899
36223
  );
35900
36224
  } catch (err) {
35901
- throw new WriteTransportError(
36225
+ throw new WriteTransportError2(
35902
36226
  `Derivative status read failed: ${err instanceof Error ? err.message : String(err)}`,
35903
36227
  1,
35904
36228
  err
@@ -35913,7 +36237,7 @@ async function getDerivativeStatus(params) {
35913
36237
  try {
35914
36238
  body = await response.json();
35915
36239
  } catch (err) {
35916
- throw new DerivativeQuestionRejectedError(
36240
+ throw new DerivativeQuestionRejectedError2(
35917
36241
  "Derivative status response is not JSON",
35918
36242
  response.status,
35919
36243
  null,
@@ -35922,7 +36246,7 @@ async function getDerivativeStatus(params) {
35922
36246
  }
35923
36247
  const parsed = DerivativeStatusSchema.safeParse(body);
35924
36248
  if (!parsed.success) {
35925
- throw new DerivativeQuestionRejectedError(
36249
+ throw new DerivativeQuestionRejectedError2(
35926
36250
  "Derivative status response is not a status view",
35927
36251
  response.status,
35928
36252
  null,
@@ -35956,6 +36280,11 @@ async function waitForDerivativeStatus(params) {
35956
36280
  }
35957
36281
 
35958
36282
  // src/protocol/gateway.ts
36283
+ import {
36284
+ DataPointDeletedError as DataPointDeletedError3,
36285
+ DataPointNotFoundError as DataPointNotFoundError2,
36286
+ DataPointVersionConflictError
36287
+ } from "./errors.js";
35959
36288
  function withGrantPermissions(grant) {
35960
36289
  const stripped = { ...grant };
35961
36290
  delete stripped.permissions;
@@ -36001,7 +36330,7 @@ function createGatewayClient(baseUrl) {
36001
36330
  }
36002
36331
  async function deletedError(res, details) {
36003
36332
  const body = await readBody(res);
36004
- return new DataPointDeletedError(
36333
+ return new DataPointDeletedError3(
36005
36334
  `Data point ${details.dataPointId ?? details.scope ?? ""} has been deleted`,
36006
36335
  { ...details, deletedAt: tombstoneDeletedAt(body) }
36007
36336
  );
@@ -36074,7 +36403,7 @@ function createGatewayClient(baseUrl) {
36074
36403
  }
36075
36404
  const record = await unwrapEnvelope(res);
36076
36405
  if (!options?.includeDeleted && isDataPointTombstone(record)) {
36077
- throw new DataPointDeletedError(
36406
+ throw new DataPointDeletedError3(
36078
36407
  `Data point ${dataPointId} has been deleted`,
36079
36408
  {
36080
36409
  dataPointId,
@@ -36236,7 +36565,7 @@ function createGatewayClient(baseUrl) {
36236
36565
  })
36237
36566
  });
36238
36567
  if (res.status === 404) {
36239
- throw new DataPointNotFoundError(
36568
+ throw new DataPointNotFoundError2(
36240
36569
  `Data point ${dataPointId} (scope '${params.scope}') is not registered`,
36241
36570
  details
36242
36571
  );
@@ -36378,6 +36707,7 @@ function createGatewayClient(baseUrl) {
36378
36707
  }
36379
36708
 
36380
36709
  // src/protocol/escrow.ts
36710
+ import { isHex as isHex3 } from "viem";
36381
36711
  var GENERIC_PAYMENT_TYPES = {
36382
36712
  GenericPayment: [
36383
36713
  { name: "payerAddress", type: "address" },
@@ -36417,6 +36747,26 @@ var ESCROW_DEPOSIT_ABI2 = [
36417
36747
  }
36418
36748
  ];
36419
36749
  var NATIVE_ASSET_ADDRESS = "0x0000000000000000000000000000000000000000";
36750
+ var EscrowWithdrawalLifecycleError = class extends Error {
36751
+ constructor(httpStatus, result) {
36752
+ super(result.error);
36753
+ this.httpStatus = httpStatus;
36754
+ this.result = result;
36755
+ }
36756
+ httpStatus;
36757
+ result;
36758
+ name = "EscrowWithdrawalLifecycleError";
36759
+ };
36760
+ var EscrowWithdrawalRejectionError = class extends Error {
36761
+ constructor(httpStatus, result) {
36762
+ super(result.error);
36763
+ this.httpStatus = httpStatus;
36764
+ this.result = result;
36765
+ }
36766
+ httpStatus;
36767
+ result;
36768
+ name = "EscrowWithdrawalRejectionError";
36769
+ };
36420
36770
  function createEscrowGatewayClient(baseUrl) {
36421
36771
  const base = baseUrl.replace(/\/+$/, "");
36422
36772
  async function throwOnError(res, context) {
@@ -36432,6 +36782,27 @@ function createEscrowGatewayClient(baseUrl) {
36432
36782
  );
36433
36783
  }
36434
36784
  }
36785
+ async function throwOnWithdrawError(res) {
36786
+ if (res.ok) return;
36787
+ let body;
36788
+ try {
36789
+ body = await res.json();
36790
+ } catch {
36791
+ throw new Error(
36792
+ `Escrow gateway error (POST /v1/escrow/withdraw): ${res.status} ${res.statusText}`
36793
+ );
36794
+ }
36795
+ if (isEscrowWithdrawalFailureResult(body)) {
36796
+ throw new EscrowWithdrawalLifecycleError(res.status, body);
36797
+ }
36798
+ if (isEscrowWithdrawalRejectedResult(body)) {
36799
+ throw new EscrowWithdrawalRejectionError(res.status, body);
36800
+ }
36801
+ const error = getGatewayErrorMessage(body);
36802
+ throw new Error(
36803
+ `Escrow gateway error (POST /v1/escrow/withdraw): ${res.status} ${res.statusText}${error ? `: ${error}` : ""}`
36804
+ );
36805
+ }
36435
36806
  return {
36436
36807
  async submitDeposit({ txHash }) {
36437
36808
  const res = await fetch(`${base}/v1/escrow/deposit`, {
@@ -36487,9 +36858,108 @@ function createEscrowGatewayClient(baseUrl) {
36487
36858
  });
36488
36859
  await throwOnError(res, "POST /v1/escrow/pay");
36489
36860
  return res.json();
36861
+ },
36862
+ async withdraw({
36863
+ account,
36864
+ asset,
36865
+ amount,
36866
+ withdrawNonce,
36867
+ deadline,
36868
+ signature
36869
+ }) {
36870
+ const res = await fetch(`${base}/v1/escrow/withdraw`, {
36871
+ method: "POST",
36872
+ headers: {
36873
+ "Content-Type": "application/json",
36874
+ Authorization: `Web3Signed ${signature}`
36875
+ },
36876
+ body: JSON.stringify({
36877
+ account,
36878
+ asset,
36879
+ amount,
36880
+ withdrawNonce,
36881
+ deadline
36882
+ })
36883
+ });
36884
+ await throwOnWithdrawError(res);
36885
+ return res.json();
36886
+ },
36887
+ async getWithdrawNonce(account) {
36888
+ const res = await fetch(
36889
+ `${base}/v1/escrow/withdraw/nonce?account=${encodeURIComponent(account)}`,
36890
+ { cache: "no-store" }
36891
+ );
36892
+ await throwOnError(res, "GET /v1/escrow/withdraw/nonce");
36893
+ const body = await res.json();
36894
+ if (!isWithdrawNonceResponse(body, account)) {
36895
+ throw new Error(
36896
+ "GET /v1/escrow/withdraw/nonce: invalid response structure"
36897
+ );
36898
+ }
36899
+ return body;
36490
36900
  }
36491
36901
  };
36492
36902
  }
36903
+ function getGatewayErrorMessage(body) {
36904
+ if (typeof body === "object" && body !== null && "error" in body && typeof body.error === "string") {
36905
+ return body.error;
36906
+ }
36907
+ return void 0;
36908
+ }
36909
+ function isEscrowWithdrawalFailureResult(body) {
36910
+ if (typeof body !== "object" || body === null) return false;
36911
+ const value = body;
36912
+ 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));
36913
+ }
36914
+ function isEscrowWithdrawalRejectedResult(body) {
36915
+ if (typeof body !== "object" || body === null) return false;
36916
+ const value = body;
36917
+ 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);
36918
+ }
36919
+ function isWithdrawalRejectionCode(value) {
36920
+ return value === "below_minimum" || value === "deadline_too_far" || value === "expired" || value === "insufficient_available" || value === "stale_nonce";
36921
+ }
36922
+ function optionalUint256Decimal(value) {
36923
+ return value === void 0 || isUint256Decimal(value);
36924
+ }
36925
+ function isAddressHex(value) {
36926
+ return typeof value === "string" && isHex3(value, { strict: true }) && value.length === 42;
36927
+ }
36928
+ function isHash(value) {
36929
+ return typeof value === "string" && isHex3(value, { strict: true }) && value.length === 66;
36930
+ }
36931
+ function isUint256Decimal(value) {
36932
+ if (typeof value !== "string" || value.length === 0 || value.length > 78) {
36933
+ return false;
36934
+ }
36935
+ if (!/^(0|[1-9]\d*)$/.test(value)) return false;
36936
+ return BigInt(value) <= 2n ** 256n - 1n;
36937
+ }
36938
+ function isBlockNumber(value) {
36939
+ return value === null || isUint256Decimal(value);
36940
+ }
36941
+ function isWithdrawNonceResponse(body, requestedAccount) {
36942
+ if (typeof body !== "object" || body === null) return false;
36943
+ const value = body;
36944
+ if (value.success !== true) return false;
36945
+ if (!isAddressHex(value.account)) return false;
36946
+ if (value.account.toLowerCase() !== requestedAccount.toLowerCase())
36947
+ return false;
36948
+ if (typeof value.chainId !== "string") return false;
36949
+ if (!/^(0|[1-9]\d*)$/.test(value.chainId)) return false;
36950
+ const isLastNull = value.lastWithdrawNonce === null;
36951
+ const lastNonceValid = isLastNull || isUint256Decimal(value.lastWithdrawNonce);
36952
+ if (!lastNonceValid) return false;
36953
+ if (!isUint256Decimal(value.nextWithdrawNonce)) return false;
36954
+ if (isLastNull) {
36955
+ return value.nextWithdrawNonce === "1";
36956
+ }
36957
+ const lastNonce = BigInt(value.lastWithdrawNonce);
36958
+ const nextNonce = BigInt(value.nextWithdrawNonce);
36959
+ const expectedNextNonce = lastNonce + 1n;
36960
+ if (expectedNextNonce > 2n ** 256n - 1n) return false;
36961
+ return nextNonce === expectedNextNonce;
36962
+ }
36493
36963
 
36494
36964
  // src/direct/escrow-payment.ts
36495
36965
  var GRANT_OP_TYPE = "grant";
@@ -36526,12 +36996,12 @@ var UINT256_MAX = (1n << 256n) - 1n;
36526
36996
  var ADDRESS_RE = /^0x[0-9a-fA-F]{40}$/;
36527
36997
  var BYTES32_RE = /^0x[0-9a-fA-F]{64}$/;
36528
36998
  var SIGNATURE_RE = /^0x[0-9a-fA-F]{130}$/;
36529
- function isUint256Decimal(value, allowZero) {
36999
+ function isUint256Decimal2(value, allowZero) {
36530
37000
  const pattern = allowZero ? /^(0|[1-9]\d*)$/ : /^[1-9]\d*$/;
36531
37001
  return value.length <= UINT256_MAX.toString().length && pattern.test(value) && BigInt(value) <= UINT256_MAX;
36532
37002
  }
36533
37003
  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);
37004
+ 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
37005
  }
36536
37006
  function validateSigningOperation(payerAddress, required) {
36537
37007
  if (!ADDRESS_RE.test(payerAddress)) {
@@ -36543,10 +37013,10 @@ function validateSigningOperation(payerAddress, required) {
36543
37013
  if (!ADDRESS_RE.test(required.asset || NATIVE_ASSET_ADDRESS)) {
36544
37014
  throw new Error("Payment asset must be a 20-byte EVM address");
36545
37015
  }
36546
- if (!isUint256Decimal(required.amount, true)) {
37016
+ if (!isUint256Decimal2(required.amount, true)) {
36547
37017
  throw new Error("Payment amount must be a canonical uint256 decimal");
36548
37018
  }
36549
- if (required.paymentNonce !== void 0 && !isUint256Decimal(required.paymentNonce, false)) {
37019
+ if (required.paymentNonce !== void 0 && !isUint256Decimal2(required.paymentNonce, false)) {
36550
37020
  throw new Error("Payment nonce must be a positive uint256 decimal");
36551
37021
  }
36552
37022
  const accessRecord = required.accessRecord;
@@ -36677,7 +37147,7 @@ function paymentResponseMetadataFromHeader(header) {
36677
37147
  const registrationFee = stringField(breakdown, "registrationFee");
36678
37148
  const dataAccessFee = stringField(breakdown, "dataAccessFee");
36679
37149
  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)) {
37150
+ 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
37151
  return void 0;
36682
37152
  }
36683
37153
  return {
@@ -36726,18 +37196,9 @@ async function authorizeEscrowPayment(params) {
36726
37196
  return toDirectPaymentReceipt(result);
36727
37197
  }
36728
37198
 
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
37199
  // src/direct/personal-server-read.ts
37200
+ import { PaymentRequiredError, PersonalServerReadError } from "./direct/errors.js";
37201
+ import { DataPointDeletedError as DataPointDeletedError4 } from "./errors.js";
36741
37202
  function asRecord2(value) {
36742
37203
  return value && typeof value === "object" && !Array.isArray(value) ? value : void 0;
36743
37204
  }
@@ -36767,15 +37228,15 @@ function isBytes32Hex(value) {
36767
37228
  return /^0x[0-9a-fA-F]{64}$/.test(value);
36768
37229
  }
36769
37230
  var UINT256_MAX2 = (1n << 256n) - 1n;
36770
- function isAddressHex(value) {
37231
+ function isAddressHex2(value) {
36771
37232
  return /^0x[0-9a-fA-F]{40}$/.test(value);
36772
37233
  }
36773
- function isUint256Decimal2(value, allowZero) {
37234
+ function isUint256Decimal3(value, allowZero) {
36774
37235
  const pattern = allowZero ? /^(0|[1-9]\d*)$/ : /^[1-9]\d*$/;
36775
37236
  return value.length <= UINT256_MAX2.toString().length && pattern.test(value) && BigInt(value) <= UINT256_MAX2;
36776
37237
  }
36777
37238
  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);
37239
+ return isBytes32Hex(record.dataPointId) && isUint256Decimal3(record.version, false) && isAddressHex2(record.accessor) && isBytes32Hex(record.recordId) && /^0x[0-9a-fA-F]{130}$/.test(record.signature);
36779
37240
  }
36780
37241
  function parseLegacyGrantOperation(params) {
36781
37242
  const { challengeGrantId, challengeOpId, challengeOpType, grantId } = params;
@@ -36826,7 +37287,7 @@ function parseCanonicalDataAccessAccept(value) {
36826
37287
  const accessRecord = parseAccessRecord(accept?.accessRecord);
36827
37288
  const acceptAsset = stringField2(accept, "asset");
36828
37289
  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) {
37290
+ 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
37291
  return null;
36831
37292
  }
36832
37293
  return {
@@ -36911,7 +37372,7 @@ async function parsePersonalServerPaymentRequired(res, grantId) {
36911
37372
  const acceptAmount = stringField2(accept, "amount");
36912
37373
  const accessRecord2 = parseAccessRecord(accept.accessRecord);
36913
37374
  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) {
37375
+ 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
37376
  throw new PersonalServerReadError(
36916
37377
  "Personal Server grant payment challenge was untrusted or incomplete",
36917
37378
  402
@@ -37027,14 +37488,11 @@ export {
37027
37488
  AccountPersonalServerLiteOwnerBindingError,
37028
37489
  AccountPersonalServerRegistrationError,
37029
37490
  BUILDER_REGISTRATION_TYPES,
37030
- BlockchainError,
37031
37491
  BrowserPlatformAdapter,
37032
- BuilderUnknownError,
37033
37492
  CLAIM_POLL_FLOOR_MS,
37034
37493
  CONTRACTS,
37035
37494
  CallbackStorage,
37036
37495
  ContractFactory,
37037
- ContractNotFoundError,
37038
37496
  DATA_ACCESS_OP_TYPE,
37039
37497
  DATA_REGISTRY_STATUS_ABI,
37040
37498
  DEFAULT_DERIVATIVE_STATUS_POLL_INTERVAL_MS,
@@ -37047,21 +37505,9 @@ export {
37047
37505
  DERIVATIVE_QUESTIONS_PATH,
37048
37506
  DERIVATIVE_STATUS_PATH,
37049
37507
  DataFileEnvelopeSchema,
37050
- DataPointDeletedError,
37051
- DataPointNotFoundError,
37052
37508
  DataPointStatus,
37053
- DataPointVersionConflictError,
37054
- DerivativeComputeUnavailableError,
37055
- DerivativeCycleError,
37056
- DerivativeDerivedScopeRequiredError,
37057
37509
  DerivativeErrorCodeSchema,
37058
- DerivativeQuestionFailedError,
37059
- DerivativeQuestionInvalidError,
37060
- DerivativeQuestionNotFoundError,
37061
- DerivativeQuestionRejectedError,
37062
37510
  DerivativeQuestionSchema,
37063
- DerivativeQuestionTimeoutError,
37064
- DerivativeSourceNotGrantedError,
37065
37511
  DerivativeStatusSchema,
37066
37512
  DropboxStorage,
37067
37513
  ECIESError,
@@ -37069,42 +37515,35 @@ export {
37069
37515
  ENCLAVE_TRUST_ANCHORS,
37070
37516
  ENCLAVE_WALLET_PURPOSE,
37071
37517
  ESCROW_DEPOSIT_ABI2 as ESCROW_DEPOSIT_ABI,
37072
- ExpiredTokenError,
37518
+ EscrowWithdrawalLifecycleError,
37519
+ EscrowWithdrawalRejectionError,
37520
+ ExpiredTokenError2 as ExpiredTokenError,
37073
37521
  FEE_REGISTRY_ABI,
37074
37522
  GENERIC_PAYMENT_TYPES,
37075
37523
  GRANT_OP_TYPE,
37076
37524
  GRANT_REGISTRATION_TYPES,
37077
37525
  GRANT_REVOCATION_TYPES,
37078
37526
  GoogleDriveStorage,
37079
- GrantInvalidError,
37080
37527
  InMemoryTokenStore,
37081
37528
  IngestResponseSchema,
37082
- InvalidConfigurationError,
37083
37529
  InvalidScopeEntryError,
37084
- InvalidSignatureError,
37530
+ InvalidSignatureError2 as InvalidSignatureError,
37085
37531
  IpfsStorage,
37086
37532
  JOB_OPERATIONS,
37087
37533
  JOB_PROTOCOL_VERSION,
37534
+ JOB_RESULT_CHUNK_BYTES,
37535
+ JOB_RESULT_FORMAT_VERSION,
37088
37536
  JOB_STATES,
37089
37537
  JobEnvelopeError,
37090
- JobIdTakenError,
37091
- JobNotFoundError,
37092
- JobRejectedError,
37093
- JobRequestTooLargeError,
37094
- JobTimeoutError,
37095
- JobTransportError,
37096
- JobsClientError,
37097
37538
  LINEAGE_FIELD,
37098
37539
  LINEAGE_KEY,
37099
37540
  LineageEntrySchema,
37100
37541
  LineageGraphSchema,
37101
37542
  LineageNodeSchema,
37102
- LineageReadError,
37103
37543
  MASTER_KEY_MESSAGE,
37104
37544
  MASTER_SIGNATURE_DELIVERY_MAX_AGE_SECONDS,
37105
37545
  MASTER_SIGNATURE_DELIVERY_VERSION,
37106
37546
  MAX_ATTEMPTS,
37107
- MAX_INLINE_RESULT_BYTES,
37108
37547
  MAX_JOB_DEADLINE_SECONDS,
37109
37548
  MAX_LEASE_SECONDS,
37110
37549
  MAX_LINEAGE_SOURCES,
@@ -37112,15 +37551,12 @@ export {
37112
37551
  MAX_QUESTION_MODEL_CHARS,
37113
37552
  MAX_QUESTION_SOURCE_SCOPES,
37114
37553
  MAX_WAIT_SECONDS,
37115
- MissingAuthError,
37554
+ MissingAuthError2 as MissingAuthError,
37116
37555
  NATIVE_ASSET_ADDRESS,
37117
37556
  NATIVE_VANA_ASSET,
37118
- NetworkError,
37119
37557
  NodeECIESUint8Provider as NodeECIESProvider,
37120
37558
  NodePlatformAdapter,
37121
- NonceError,
37122
37559
  OAuthClient,
37123
- OwnerNotReadyError,
37124
37560
  PERSONAL_SERVER_LITE_OWNER_BINDING_PREFIX,
37125
37561
  PERSONAL_SERVER_LITE_OWNER_BINDING_PURPOSE,
37126
37562
  PERSONAL_SERVER_LITE_OWNER_BINDING_VERSION,
@@ -37129,9 +37565,6 @@ export {
37129
37565
  PKCE_CHALLENGE_PATTERN,
37130
37566
  PKCE_VERIFIER_PATTERN,
37131
37567
  PSError,
37132
- PermissionError,
37133
- PersonalServerError,
37134
- PersonalServerWriteError,
37135
37568
  PinataStorage,
37136
37569
  QUESTION_STATUSES,
37137
37570
  QuestionDeleteResultSchema,
@@ -37142,42 +37575,26 @@ export {
37142
37575
  RECORD_DATA_ACCESS_TYPES,
37143
37576
  REGISTRATION_KIND_FOR_OP,
37144
37577
  RESERVED_WRITE_KEYS,
37145
- ReadOnlyError,
37146
37578
  RedactedLineageNodeSchema,
37147
- RelayerError,
37148
37579
  SCOPE_ACTIONS,
37149
37580
  SEALED_ENVELOPE_VERSION,
37150
37581
  SERVER_REGISTRATION_TYPES,
37151
37582
  ScopeSchema,
37152
- SerializationError,
37153
- ServerUrlMismatchError,
37154
- SignatureError,
37155
37583
  StorageError,
37156
37584
  StorageManager,
37157
37585
  TOMBSTONE_DATA_HASH,
37158
37586
  TOMBSTONE_DATA_HASH_PREIMAGE,
37159
37587
  TOMBSTONE_METADATA_HASH,
37160
37588
  TOMBSTONE_METADATA_HASH_PREIMAGE,
37161
- TransactionPendingError,
37162
37589
  USER_PS_ID_DOMAIN,
37163
- UserRejectedRequestError,
37164
- VanaError,
37165
37590
  VanaStorage,
37591
+ WITHDRAW_AUTHORIZATION_TYPES,
37166
37592
  WRITER_ATTRIBUTION_KEY,
37167
37593
  WRITE_CONTENT_DISPOSITION_HEADER,
37168
37594
  WRITE_FILENAME_HEADER,
37169
37595
  WRITE_METADATA_HEADER,
37170
37596
  WRITE_SESSION_PATH,
37171
37597
  WRITE_SIGNATURE_HEADER,
37172
- WriteConflictError,
37173
- WriteForbiddenError,
37174
- WriteLineageError,
37175
- WriteRejectedError,
37176
- WriteRequestError,
37177
- WriteSessionError,
37178
- WriteSessionExpiredError,
37179
- WriteTransportError,
37180
- WriteUnauthorizedError,
37181
37598
  appRootPreimage,
37182
37599
  askPersonalServer,
37183
37600
  assertDerivedScopeNaming,
@@ -37200,6 +37617,7 @@ export {
37200
37617
  buildPersonalServerRegistrationTypedData,
37201
37618
  buildSetDataPointStatusRequest,
37202
37619
  buildWeb3SignedHeader,
37620
+ buildWithdrawAuthorizationTypedData,
37203
37621
  builderRegistrationDomain,
37204
37622
  canonicalJobRequestBytes,
37205
37623
  chains,
@@ -37282,6 +37700,7 @@ export {
37282
37700
  normalizeBinaryMimeType,
37283
37701
  openJobRequest,
37284
37702
  openJobResult,
37703
+ openJobResultStream,
37285
37704
  openWriteSession,
37286
37705
  parsePSError,
37287
37706
  parsePersonalServerPaymentRequired,
@@ -37307,6 +37726,7 @@ export {
37307
37726
  scopeToPathSegments,
37308
37727
  sealJobRequest,
37309
37728
  sealJobResult,
37729
+ sealJobResultStream,
37310
37730
  serializeECIES,
37311
37731
  serverRegistrationDomain,
37312
37732
  sessionCoversScope,
@@ -37325,6 +37745,7 @@ export {
37325
37745
  verifyWeb3Signed,
37326
37746
  waitForDerivativeStatus,
37327
37747
  waitForQuestion,
37748
+ withdrawAuthorizationDomain,
37328
37749
  writeData,
37329
37750
  writePersonalServerData
37330
37751
  };