@opendatalabs/vana-sdk 3.15.0 → 3.17.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +107 -0
- package/dist/errors.cjs +94 -2
- package/dist/errors.cjs.map +1 -1
- package/dist/errors.d.ts +123 -0
- package/dist/errors.js +82 -1
- package/dist/errors.js.map +1 -1
- package/dist/index.browser.d.ts +4 -0
- package/dist/index.browser.js +1155 -14
- package/dist/index.browser.js.map +4 -4
- package/dist/index.node.cjs +1205 -15
- package/dist/index.node.cjs.map +4 -4
- package/dist/index.node.d.ts +4 -0
- package/dist/index.node.js +1155 -14
- package/dist/index.node.js.map +4 -4
- package/dist/protocol/gateway.cjs +16 -2
- package/dist/protocol/gateway.cjs.map +1 -1
- package/dist/protocol/gateway.d.ts +2 -0
- package/dist/protocol/gateway.js +16 -2
- package/dist/protocol/gateway.js.map +1 -1
- package/dist/protocol/lineage.cjs +287 -0
- package/dist/protocol/lineage.cjs.map +1 -0
- package/dist/protocol/lineage.d.ts +228 -0
- package/dist/protocol/lineage.js +258 -0
- package/dist/protocol/lineage.js.map +1 -0
- package/dist/protocol/lineage.test.d.ts +1 -0
- package/dist/protocol/personal-server-error-body.cjs +57 -0
- package/dist/protocol/personal-server-error-body.cjs.map +1 -0
- package/dist/protocol/personal-server-error-body.d.ts +18 -0
- package/dist/protocol/personal-server-error-body.js +32 -0
- package/dist/protocol/personal-server-error-body.js.map +1 -0
- package/dist/protocol/personal-server-write.cjs +623 -0
- package/dist/protocol/personal-server-write.cjs.map +1 -0
- package/dist/protocol/personal-server-write.d.ts +284 -0
- package/dist/protocol/personal-server-write.js +601 -0
- package/dist/protocol/personal-server-write.js.map +1 -0
- package/dist/protocol/personal-server-write.test.d.ts +1 -0
- package/dist/protocol/scope-actions.cjs +185 -0
- package/dist/protocol/scope-actions.cjs.map +1 -0
- package/dist/protocol/scope-actions.d.ts +145 -0
- package/dist/protocol/scope-actions.js +154 -0
- package/dist/protocol/scope-actions.js.map +1 -0
- package/dist/protocol/scope-actions.test.d.ts +1 -0
- package/dist/protocol/write-signer.cjs +67 -0
- package/dist/protocol/write-signer.cjs.map +1 -0
- package/dist/protocol/write-signer.d.ts +59 -0
- package/dist/protocol/write-signer.js +43 -0
- package/dist/protocol/write-signer.js.map +1 -0
- package/dist/protocol/write-signer.test.d.ts +1 -0
- package/dist/tests/mock-personal-server.d.ts +127 -0
- package/package.json +1 -1
package/dist/index.node.cjs
CHANGED
|
@@ -1201,9 +1201,17 @@ __export(index_node_exports, {
|
|
|
1201
1201
|
InMemoryTokenStore: () => InMemoryTokenStore,
|
|
1202
1202
|
IngestResponseSchema: () => IngestResponseSchema,
|
|
1203
1203
|
InvalidConfigurationError: () => InvalidConfigurationError,
|
|
1204
|
+
InvalidScopeEntryError: () => InvalidScopeEntryError,
|
|
1204
1205
|
InvalidSignatureError: () => InvalidSignatureError,
|
|
1205
1206
|
IpfsStorage: () => IpfsStorage,
|
|
1207
|
+
LINEAGE_FIELD: () => LINEAGE_FIELD,
|
|
1208
|
+
LINEAGE_KEY: () => LINEAGE_KEY,
|
|
1209
|
+
LineageEntrySchema: () => LineageEntrySchema,
|
|
1210
|
+
LineageGraphSchema: () => LineageGraphSchema,
|
|
1211
|
+
LineageNodeSchema: () => LineageNodeSchema,
|
|
1212
|
+
LineageReadError: () => LineageReadError,
|
|
1206
1213
|
MASTER_KEY_MESSAGE: () => MASTER_KEY_MESSAGE,
|
|
1214
|
+
MAX_LINEAGE_SOURCES: () => MAX_LINEAGE_SOURCES,
|
|
1207
1215
|
MissingAuthError: () => MissingAuthError,
|
|
1208
1216
|
NATIVE_ASSET_ADDRESS: () => NATIVE_ASSET_ADDRESS,
|
|
1209
1217
|
NATIVE_VANA_ASSET: () => NATIVE_VANA_ASSET,
|
|
@@ -1222,12 +1230,16 @@ __export(index_node_exports, {
|
|
|
1222
1230
|
PSError: () => PSError,
|
|
1223
1231
|
PermissionError: () => PermissionError,
|
|
1224
1232
|
PersonalServerError: () => PersonalServerError,
|
|
1233
|
+
PersonalServerWriteError: () => PersonalServerWriteError,
|
|
1225
1234
|
PinataStorage: () => PinataStorage,
|
|
1226
1235
|
R2Storage: () => R2Storage,
|
|
1227
1236
|
RECORD_DATA_ACCESS_TYPES: () => RECORD_DATA_ACCESS_TYPES,
|
|
1228
1237
|
REGISTRATION_KIND_FOR_OP: () => REGISTRATION_KIND_FOR_OP,
|
|
1238
|
+
RESERVED_WRITE_KEYS: () => RESERVED_WRITE_KEYS,
|
|
1229
1239
|
ReadOnlyError: () => ReadOnlyError,
|
|
1240
|
+
RedactedLineageNodeSchema: () => RedactedLineageNodeSchema,
|
|
1230
1241
|
RelayerError: () => RelayerError,
|
|
1242
|
+
SCOPE_ACTIONS: () => SCOPE_ACTIONS,
|
|
1231
1243
|
SERVER_REGISTRATION_TYPES: () => SERVER_REGISTRATION_TYPES,
|
|
1232
1244
|
ScopeSchema: () => ScopeSchema,
|
|
1233
1245
|
SerializationError: () => SerializationError,
|
|
@@ -1239,9 +1251,26 @@ __export(index_node_exports, {
|
|
|
1239
1251
|
UserRejectedRequestError: () => UserRejectedRequestError,
|
|
1240
1252
|
VanaError: () => VanaError,
|
|
1241
1253
|
VanaStorage: () => VanaStorage,
|
|
1254
|
+
WRITER_ATTRIBUTION_KEY: () => WRITER_ATTRIBUTION_KEY,
|
|
1255
|
+
WRITE_CONTENT_DISPOSITION_HEADER: () => WRITE_CONTENT_DISPOSITION_HEADER,
|
|
1256
|
+
WRITE_FILENAME_HEADER: () => WRITE_FILENAME_HEADER,
|
|
1257
|
+
WRITE_METADATA_HEADER: () => WRITE_METADATA_HEADER,
|
|
1258
|
+
WRITE_SESSION_PATH: () => WRITE_SESSION_PATH,
|
|
1259
|
+
WRITE_SIGNATURE_HEADER: () => WRITE_SIGNATURE_HEADER,
|
|
1260
|
+
WriteConflictError: () => WriteConflictError,
|
|
1261
|
+
WriteForbiddenError: () => WriteForbiddenError,
|
|
1262
|
+
WriteLineageError: () => WriteLineageError,
|
|
1263
|
+
WriteRejectedError: () => WriteRejectedError,
|
|
1264
|
+
WriteRequestError: () => WriteRequestError,
|
|
1265
|
+
WriteSessionError: () => WriteSessionError,
|
|
1266
|
+
WriteSessionExpiredError: () => WriteSessionExpiredError,
|
|
1267
|
+
WriteTransportError: () => WriteTransportError,
|
|
1268
|
+
WriteUnauthorizedError: () => WriteUnauthorizedError,
|
|
1269
|
+
assertDerivedScopeNaming: () => assertDerivedScopeNaming,
|
|
1242
1270
|
assertValidPkceVerifier: () => assertValidPkceVerifier,
|
|
1243
1271
|
authorizeEscrowPayment: () => authorizeEscrowPayment,
|
|
1244
1272
|
authorizeGrantPayment: () => authorizeGrantPayment,
|
|
1273
|
+
binaryWriteSignedBytes: () => binaryWriteSignedBytes,
|
|
1245
1274
|
buildDepositNativeRequest: () => buildDepositNativeRequest,
|
|
1246
1275
|
buildDepositTokenRequest: () => buildDepositTokenRequest,
|
|
1247
1276
|
buildEscrowPaymentHeader: () => buildEscrowPaymentHeader,
|
|
@@ -1275,16 +1304,21 @@ __export(index_node_exports, {
|
|
|
1275
1304
|
dataRegistryContractAddress: () => dataRegistryContractAddress,
|
|
1276
1305
|
dataRegistryDomain: () => dataRegistryDomain,
|
|
1277
1306
|
decryptWithPassword: () => decryptWithPassword,
|
|
1307
|
+
deriveDataPointId: () => deriveDataPointId,
|
|
1278
1308
|
deriveMasterKey: () => deriveMasterKey,
|
|
1279
1309
|
deriveScopeKey: () => deriveScopeKey,
|
|
1310
|
+
derivedScopeViolatesNaming: () => derivedScopeViolatesNaming,
|
|
1280
1311
|
deserializeECIES: () => deserializeECIES,
|
|
1281
1312
|
detectPlatform: () => detectPlatform,
|
|
1282
1313
|
encodeDepositNativeData: () => encodeDepositNativeData,
|
|
1283
1314
|
encodeDepositTokenData: () => encodeDepositTokenData,
|
|
1284
1315
|
encodeSetDataPointStatusData: () => encodeSetDataPointStatusData,
|
|
1316
|
+
encodeWriteMetadataHeader: () => encodeWriteMetadataHeader,
|
|
1285
1317
|
encryptWithPassword: () => encryptWithPassword,
|
|
1286
1318
|
escrowContractAddress: () => escrowContractAddress,
|
|
1287
1319
|
escrowPaymentDomain: () => escrowPaymentDomain,
|
|
1320
|
+
formatScopeEntry: () => formatScopeEntry,
|
|
1321
|
+
gatewayLineagePath: () => gatewayLineagePath,
|
|
1288
1322
|
generatePkceVerifier: () => generatePkceVerifier,
|
|
1289
1323
|
genericPaymentDomain: () => genericPaymentDomain,
|
|
1290
1324
|
getAbi: () => getAbi,
|
|
@@ -1294,43 +1328,62 @@ __export(index_node_exports, {
|
|
|
1294
1328
|
getContractController: () => getContractController,
|
|
1295
1329
|
getContractInfo: () => getContractInfo,
|
|
1296
1330
|
getFee: () => getFee,
|
|
1331
|
+
getGatewayLineage: () => getGatewayLineage,
|
|
1332
|
+
getLineage: () => getLineage,
|
|
1297
1333
|
getOpFee: () => getOpFee,
|
|
1334
|
+
getPersonalServerLineage: () => getPersonalServerLineage,
|
|
1298
1335
|
getPlatformCapabilities: () => getPlatformCapabilities,
|
|
1299
1336
|
getServiceEndpoints: () => getServiceEndpoints,
|
|
1337
|
+
grantPermissions: () => grantPermissions,
|
|
1300
1338
|
grantRegistrationDomain: () => grantRegistrationDomain,
|
|
1301
1339
|
grantRevocationDomain: () => grantRevocationDomain,
|
|
1340
|
+
hasAction: () => hasAction,
|
|
1341
|
+
isDataPointId: () => isDataPointId,
|
|
1302
1342
|
isDataPortabilityGatewayConfig: () => isDataPortabilityGatewayConfig,
|
|
1303
1343
|
isECIESEncrypted: () => isECIESEncrypted,
|
|
1304
1344
|
isPlatformSupported: () => isPlatformSupported,
|
|
1345
|
+
isRedactedLineageNode: () => isRedactedLineageNode,
|
|
1305
1346
|
mainnetServices: () => mainnetServices,
|
|
1306
1347
|
moksha: () => moksha,
|
|
1307
1348
|
mokshaServices: () => mokshaServices,
|
|
1308
1349
|
mokshaTestnet: () => mokshaTestnet2,
|
|
1350
|
+
normalizeBinaryMimeType: () => normalizeBinaryMimeType,
|
|
1351
|
+
openWriteSession: () => openWriteSession,
|
|
1309
1352
|
parsePSError: () => parsePSError,
|
|
1310
1353
|
parsePersonalServerPaymentRequired: () => parsePersonalServerPaymentRequired,
|
|
1311
1354
|
parseScope: () => parseScope,
|
|
1355
|
+
parseScopeEntry: () => parseScopeEntry,
|
|
1312
1356
|
parseWeb3SignedHeader: () => parseWeb3SignedHeader,
|
|
1357
|
+
parseWriteMetadataHeader: () => parseWriteMetadataHeader,
|
|
1313
1358
|
paymentReceiptFromHeader: () => paymentReceiptFromHeader,
|
|
1314
1359
|
paymentResponseMetadataFromHeader: () => paymentResponseMetadataFromHeader,
|
|
1360
|
+
permissionsToScopes: () => permissionsToScopes,
|
|
1315
1361
|
personalServerDataReadPath: () => personalServerDataReadPath,
|
|
1362
|
+
personalServerLineagePath: () => personalServerLineagePath,
|
|
1316
1363
|
personalServerRegistrationDomain: () => personalServerRegistrationDomain,
|
|
1317
1364
|
readPersonalServerData: () => readPersonalServerData,
|
|
1318
1365
|
recoverServerOwner: () => recoverServerOwner,
|
|
1319
1366
|
registerPersonalServerSignature: () => registerPersonalServerSignature,
|
|
1367
|
+
resolveWriteSigner: () => resolveWriteSigner,
|
|
1320
1368
|
scopeCoveredByGrant: () => scopeCoveredByGrant,
|
|
1321
1369
|
scopeMatchesPattern: () => scopeMatchesPattern,
|
|
1370
|
+
scopeNamespace: () => scopeNamespace,
|
|
1322
1371
|
scopeToPathSegments: () => scopeToPathSegments,
|
|
1323
1372
|
serializeECIES: () => serializeECIES,
|
|
1324
1373
|
serverRegistrationDomain: () => serverRegistrationDomain,
|
|
1374
|
+
sessionCoversScope: () => sessionCoversScope,
|
|
1325
1375
|
signPersonalServerLiteOwnerBinding: () => signPersonalServerLiteOwnerBinding,
|
|
1326
1376
|
signPersonalServerLiteOwnerBindingWithAccountClient: () => signPersonalServerLiteOwnerBindingWithAccountClient,
|
|
1327
1377
|
signPersonalServerRegistrationWithAccount: () => signPersonalServerRegistrationWithAccount,
|
|
1328
1378
|
toDirectFeeBreakdown: () => toDirectFeeBreakdown,
|
|
1329
1379
|
toDirectPaymentReceipt: () => toDirectPaymentReceipt,
|
|
1380
|
+
tryGrantPermissions: () => tryGrantPermissions,
|
|
1330
1381
|
vanaMainnet: () => vanaMainnet2,
|
|
1331
1382
|
verifyGrantRegistration: () => verifyGrantRegistration,
|
|
1332
1383
|
verifyPkceChallenge: () => verifyPkceChallenge,
|
|
1333
|
-
verifyWeb3Signed: () => verifyWeb3Signed
|
|
1384
|
+
verifyWeb3Signed: () => verifyWeb3Signed,
|
|
1385
|
+
writeData: () => writeData,
|
|
1386
|
+
writePersonalServerData: () => writePersonalServerData
|
|
1334
1387
|
});
|
|
1335
1388
|
module.exports = __toCommonJS(index_node_exports);
|
|
1336
1389
|
|
|
@@ -1475,6 +1528,76 @@ var TransactionPendingError = class extends VanaError {
|
|
|
1475
1528
|
};
|
|
1476
1529
|
}
|
|
1477
1530
|
};
|
|
1531
|
+
var PersonalServerWriteError = class extends VanaError {
|
|
1532
|
+
constructor(message, code, status, errorCode = null, details) {
|
|
1533
|
+
super(message, code);
|
|
1534
|
+
this.status = status;
|
|
1535
|
+
this.errorCode = errorCode;
|
|
1536
|
+
this.details = details;
|
|
1537
|
+
}
|
|
1538
|
+
status;
|
|
1539
|
+
errorCode;
|
|
1540
|
+
details;
|
|
1541
|
+
};
|
|
1542
|
+
var WriteRequestError = class extends PersonalServerWriteError {
|
|
1543
|
+
constructor(message, details) {
|
|
1544
|
+
super(message, "WRITE_INVALID_REQUEST", void 0, null, details);
|
|
1545
|
+
}
|
|
1546
|
+
};
|
|
1547
|
+
var WriteTransportError = class extends PersonalServerWriteError {
|
|
1548
|
+
constructor(message, attempts, cause) {
|
|
1549
|
+
super(message, "WRITE_TRANSPORT_ERROR", void 0, null, { attempts });
|
|
1550
|
+
this.attempts = attempts;
|
|
1551
|
+
this.cause = cause;
|
|
1552
|
+
}
|
|
1553
|
+
attempts;
|
|
1554
|
+
};
|
|
1555
|
+
var WriteSessionError = class extends PersonalServerWriteError {
|
|
1556
|
+
constructor(message, status, errorCode = null, details) {
|
|
1557
|
+
super(message, "WRITE_SESSION_REJECTED", status, errorCode, details);
|
|
1558
|
+
}
|
|
1559
|
+
};
|
|
1560
|
+
var WriteSessionExpiredError = class extends PersonalServerWriteError {
|
|
1561
|
+
constructor(message, details) {
|
|
1562
|
+
super(message, "WRITE_SESSION_EXPIRED", void 0, null, details);
|
|
1563
|
+
}
|
|
1564
|
+
};
|
|
1565
|
+
var WriteUnauthorizedError = class extends PersonalServerWriteError {
|
|
1566
|
+
constructor(message, errorCode = null, details) {
|
|
1567
|
+
super(message, "WRITE_UNAUTHORIZED", 401, errorCode, details);
|
|
1568
|
+
}
|
|
1569
|
+
};
|
|
1570
|
+
var WriteForbiddenError = class extends PersonalServerWriteError {
|
|
1571
|
+
constructor(message, errorCode = null, details) {
|
|
1572
|
+
super(message, "WRITE_FORBIDDEN", 403, errorCode, details);
|
|
1573
|
+
}
|
|
1574
|
+
};
|
|
1575
|
+
var WriteConflictError = class extends PersonalServerWriteError {
|
|
1576
|
+
constructor(message, errorCode = null, details) {
|
|
1577
|
+
super(message, "WRITE_CONFLICT", 409, errorCode, details);
|
|
1578
|
+
}
|
|
1579
|
+
};
|
|
1580
|
+
var WriteLineageError = class extends PersonalServerWriteError {
|
|
1581
|
+
constructor(message, status = 422, errorCode = null, details) {
|
|
1582
|
+
super(message, "WRITE_LINEAGE_REJECTED", status, errorCode, details);
|
|
1583
|
+
}
|
|
1584
|
+
};
|
|
1585
|
+
var WriteRejectedError = class extends PersonalServerWriteError {
|
|
1586
|
+
constructor(message, status, errorCode = null, details) {
|
|
1587
|
+
super(message, "WRITE_REJECTED", status, errorCode, details);
|
|
1588
|
+
}
|
|
1589
|
+
};
|
|
1590
|
+
var LineageReadError = class extends VanaError {
|
|
1591
|
+
constructor(message, status, errorCode = null, details) {
|
|
1592
|
+
super(message, "LINEAGE_READ_ERROR");
|
|
1593
|
+
this.status = status;
|
|
1594
|
+
this.errorCode = errorCode;
|
|
1595
|
+
this.details = details;
|
|
1596
|
+
}
|
|
1597
|
+
status;
|
|
1598
|
+
errorCode;
|
|
1599
|
+
details;
|
|
1600
|
+
};
|
|
1478
1601
|
|
|
1479
1602
|
// src/contracts/contractController.ts
|
|
1480
1603
|
var import_viem3 = require("viem");
|
|
@@ -32972,13 +33095,13 @@ function createViemPersonalServerRegistrationSigner(source, options = {}) {
|
|
|
32972
33095
|
if (isPersonalServerRegistrationSigner(source)) {
|
|
32973
33096
|
return source;
|
|
32974
33097
|
}
|
|
32975
|
-
const
|
|
32976
|
-
if (
|
|
33098
|
+
const accountAddress2 = getAccountAddress(options.account) ?? getAccountAddress(source.account);
|
|
33099
|
+
if (accountAddress2) {
|
|
32977
33100
|
return {
|
|
32978
|
-
address:
|
|
33101
|
+
address: accountAddress2,
|
|
32979
33102
|
signTypedData: (typedData) => source.signTypedData({
|
|
32980
33103
|
...typedData,
|
|
32981
|
-
account: options.account ?? source.account ??
|
|
33104
|
+
account: options.account ?? source.account ?? accountAddress2
|
|
32982
33105
|
})
|
|
32983
33106
|
};
|
|
32984
33107
|
}
|
|
@@ -33061,12 +33184,12 @@ function createViemPersonalServerLiteOwnerBindingSigner(source, options = {}) {
|
|
|
33061
33184
|
if (isPersonalServerLiteOwnerBindingSigner(source)) {
|
|
33062
33185
|
return source;
|
|
33063
33186
|
}
|
|
33064
|
-
const
|
|
33065
|
-
if (
|
|
33187
|
+
const accountAddress2 = getAccountAddress2(options.account) ?? getAccountAddress2(source.account);
|
|
33188
|
+
if (accountAddress2) {
|
|
33066
33189
|
return {
|
|
33067
|
-
address:
|
|
33190
|
+
address: accountAddress2,
|
|
33068
33191
|
signMessage: ({ message }) => source.signMessage({
|
|
33069
|
-
account: options.account ?? source.account ??
|
|
33192
|
+
account: options.account ?? source.account ?? accountAddress2,
|
|
33070
33193
|
message
|
|
33071
33194
|
})
|
|
33072
33195
|
};
|
|
@@ -33745,7 +33868,1018 @@ function scopeCoveredByGrant(requestedScope, grantedScopes) {
|
|
|
33745
33868
|
);
|
|
33746
33869
|
}
|
|
33747
33870
|
|
|
33871
|
+
// src/protocol/scope-actions.ts
|
|
33872
|
+
var SCOPE_ACTIONS = ["read", "write"];
|
|
33873
|
+
var InvalidScopeEntryError = class extends Error {
|
|
33874
|
+
/** The offending entry, verbatim (unknown because it may not be a string). */
|
|
33875
|
+
entry;
|
|
33876
|
+
constructor(entry, reason) {
|
|
33877
|
+
super(`Invalid scope entry ${describeValue(entry)}: ${reason}`);
|
|
33878
|
+
this.name = "InvalidScopeEntryError";
|
|
33879
|
+
this.entry = entry;
|
|
33880
|
+
}
|
|
33881
|
+
};
|
|
33882
|
+
var OPERATION_SEPARATOR = ":";
|
|
33883
|
+
function describeValue(value) {
|
|
33884
|
+
if (typeof value === "string") return JSON.stringify(value);
|
|
33885
|
+
if (value === null) return "null";
|
|
33886
|
+
return `[${typeof value}]`;
|
|
33887
|
+
}
|
|
33888
|
+
var OPERATION_BY_PREFIX = {
|
|
33889
|
+
write: "write"
|
|
33890
|
+
};
|
|
33891
|
+
function assertScopePart(entry, scope) {
|
|
33892
|
+
if (scope.length === 0) {
|
|
33893
|
+
throw new InvalidScopeEntryError(entry, "scope part is empty");
|
|
33894
|
+
}
|
|
33895
|
+
if (scope.includes(OPERATION_SEPARATOR)) {
|
|
33896
|
+
throw new InvalidScopeEntryError(
|
|
33897
|
+
entry,
|
|
33898
|
+
`scope part must not contain "${OPERATION_SEPARATOR}"`
|
|
33899
|
+
);
|
|
33900
|
+
}
|
|
33901
|
+
}
|
|
33902
|
+
function parseScopeEntry(entry) {
|
|
33903
|
+
const raw = entry;
|
|
33904
|
+
if (typeof raw !== "string") {
|
|
33905
|
+
throw new InvalidScopeEntryError(raw, "entry must be a string");
|
|
33906
|
+
}
|
|
33907
|
+
const separatorIndex = entry.indexOf(OPERATION_SEPARATOR);
|
|
33908
|
+
if (separatorIndex === -1) {
|
|
33909
|
+
assertScopePart(entry, entry);
|
|
33910
|
+
return { scope: entry, action: "read" };
|
|
33911
|
+
}
|
|
33912
|
+
const prefix = entry.slice(0, separatorIndex);
|
|
33913
|
+
const scope = entry.slice(separatorIndex + 1);
|
|
33914
|
+
const action = Object.hasOwn(OPERATION_BY_PREFIX, prefix) ? OPERATION_BY_PREFIX[prefix] : void 0;
|
|
33915
|
+
if (action === void 0) {
|
|
33916
|
+
throw new InvalidScopeEntryError(
|
|
33917
|
+
entry,
|
|
33918
|
+
`unknown operation "${prefix}" (known: ${Object.keys(OPERATION_BY_PREFIX).join(", ")}; read has no prefix)`
|
|
33919
|
+
);
|
|
33920
|
+
}
|
|
33921
|
+
assertScopePart(entry, scope);
|
|
33922
|
+
return { scope, action };
|
|
33923
|
+
}
|
|
33924
|
+
function formatScopeEntry(parsed) {
|
|
33925
|
+
const { scope, action } = parsed;
|
|
33926
|
+
assertScopePart(scope, scope);
|
|
33927
|
+
if (action === "read") return scope;
|
|
33928
|
+
const prefix = Object.entries(OPERATION_BY_PREFIX).find(
|
|
33929
|
+
([, candidate]) => candidate === action
|
|
33930
|
+
)?.[0];
|
|
33931
|
+
if (prefix === void 0) {
|
|
33932
|
+
throw new InvalidScopeEntryError(
|
|
33933
|
+
scope,
|
|
33934
|
+
`unknown action ${describeValue(action)} (known: ${SCOPE_ACTIONS.join(", ")})`
|
|
33935
|
+
);
|
|
33936
|
+
}
|
|
33937
|
+
return `${prefix}${OPERATION_SEPARATOR}${scope}`;
|
|
33938
|
+
}
|
|
33939
|
+
function compareScopes(a, b) {
|
|
33940
|
+
if (a < b) return -1;
|
|
33941
|
+
if (a > b) return 1;
|
|
33942
|
+
return 0;
|
|
33943
|
+
}
|
|
33944
|
+
function sortActions(actions) {
|
|
33945
|
+
const present = new Set(actions);
|
|
33946
|
+
return SCOPE_ACTIONS.filter((action) => present.has(action));
|
|
33947
|
+
}
|
|
33948
|
+
function grantPermissions(scopes) {
|
|
33949
|
+
const byScope = /* @__PURE__ */ new Map();
|
|
33950
|
+
for (const entry of scopes) {
|
|
33951
|
+
const { scope, action } = parseScopeEntry(entry);
|
|
33952
|
+
let actions = byScope.get(scope);
|
|
33953
|
+
if (actions === void 0) {
|
|
33954
|
+
actions = /* @__PURE__ */ new Set();
|
|
33955
|
+
byScope.set(scope, actions);
|
|
33956
|
+
}
|
|
33957
|
+
actions.add(action);
|
|
33958
|
+
}
|
|
33959
|
+
return [...byScope.keys()].sort(compareScopes).map((scope) => ({
|
|
33960
|
+
scope,
|
|
33961
|
+
actions: sortActions(byScope.get(scope) ?? [])
|
|
33962
|
+
}));
|
|
33963
|
+
}
|
|
33964
|
+
function permissionsToScopes(permissions) {
|
|
33965
|
+
const byScope = /* @__PURE__ */ new Map();
|
|
33966
|
+
for (const { scope, actions } of permissions) {
|
|
33967
|
+
let merged = byScope.get(scope);
|
|
33968
|
+
if (merged === void 0) {
|
|
33969
|
+
merged = /* @__PURE__ */ new Set();
|
|
33970
|
+
byScope.set(scope, merged);
|
|
33971
|
+
}
|
|
33972
|
+
for (const action of actions) {
|
|
33973
|
+
if (!SCOPE_ACTIONS.includes(action)) {
|
|
33974
|
+
throw new InvalidScopeEntryError(
|
|
33975
|
+
scope,
|
|
33976
|
+
`unknown action ${describeValue(action)} (known: ${SCOPE_ACTIONS.join(", ")})`
|
|
33977
|
+
);
|
|
33978
|
+
}
|
|
33979
|
+
merged.add(action);
|
|
33980
|
+
}
|
|
33981
|
+
}
|
|
33982
|
+
const entries = [];
|
|
33983
|
+
for (const scope of [...byScope.keys()].sort(compareScopes)) {
|
|
33984
|
+
for (const action of sortActions(byScope.get(scope) ?? [])) {
|
|
33985
|
+
entries.push(formatScopeEntry({ scope, action }));
|
|
33986
|
+
}
|
|
33987
|
+
}
|
|
33988
|
+
return entries;
|
|
33989
|
+
}
|
|
33990
|
+
function hasAction(scopes, scope, action) {
|
|
33991
|
+
if (scope.includes(OPERATION_SEPARATOR)) return false;
|
|
33992
|
+
for (const entry of scopes) {
|
|
33993
|
+
let parsed;
|
|
33994
|
+
try {
|
|
33995
|
+
parsed = parseScopeEntry(entry);
|
|
33996
|
+
} catch (error) {
|
|
33997
|
+
if (error instanceof InvalidScopeEntryError) continue;
|
|
33998
|
+
throw error;
|
|
33999
|
+
}
|
|
34000
|
+
if (parsed.action === action && scopeMatchesPattern(scope, parsed.scope)) {
|
|
34001
|
+
return true;
|
|
34002
|
+
}
|
|
34003
|
+
}
|
|
34004
|
+
return false;
|
|
34005
|
+
}
|
|
34006
|
+
function tryGrantPermissions(scopes) {
|
|
34007
|
+
try {
|
|
34008
|
+
return grantPermissions(scopes);
|
|
34009
|
+
} catch (error) {
|
|
34010
|
+
if (error instanceof InvalidScopeEntryError) return void 0;
|
|
34011
|
+
throw error;
|
|
34012
|
+
}
|
|
34013
|
+
}
|
|
34014
|
+
|
|
34015
|
+
// src/protocol/personal-server-write.ts
|
|
34016
|
+
var import_sha25 = require("@noble/hashes/sha2");
|
|
34017
|
+
var import_viem22 = require("viem");
|
|
34018
|
+
var import_zod4 = require("zod");
|
|
34019
|
+
|
|
34020
|
+
// src/protocol/lineage.ts
|
|
34021
|
+
var import_viem21 = require("viem");
|
|
34022
|
+
var import_zod3 = require("zod");
|
|
34023
|
+
|
|
34024
|
+
// src/protocol/personal-server-error-body.ts
|
|
34025
|
+
function isRecord2(value) {
|
|
34026
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
34027
|
+
}
|
|
34028
|
+
async function readPersonalServerErrorBody(response) {
|
|
34029
|
+
let body;
|
|
34030
|
+
try {
|
|
34031
|
+
body = await response.json();
|
|
34032
|
+
} catch {
|
|
34033
|
+
return { errorCode: null, message: null };
|
|
34034
|
+
}
|
|
34035
|
+
if (!isRecord2(body)) return { errorCode: null, message: null };
|
|
34036
|
+
const nested = isRecord2(body.error) ? body.error : null;
|
|
34037
|
+
const gatewayShape = typeof body.error === "string" && typeof body.code === "string";
|
|
34038
|
+
const code = nested?.errorCode ?? nested?.code ?? body.errorCode ?? (gatewayShape ? body.code : void 0) ?? (typeof body.error === "string" ? body.error : void 0) ?? body.code;
|
|
34039
|
+
const message = nested?.message ?? body.message ?? (gatewayShape ? body.error : void 0);
|
|
34040
|
+
const gatewayDetails = {};
|
|
34041
|
+
for (const key of ["unknown", "scope", "sourceScope"]) {
|
|
34042
|
+
if (gatewayShape && body[key] !== void 0)
|
|
34043
|
+
gatewayDetails[key] = body[key];
|
|
34044
|
+
}
|
|
34045
|
+
const details = nested?.details ?? body.details ?? (Object.keys(gatewayDetails).length > 0 ? gatewayDetails : void 0);
|
|
34046
|
+
return {
|
|
34047
|
+
errorCode: typeof code === "string" ? code : null,
|
|
34048
|
+
message: typeof message === "string" ? message : null,
|
|
34049
|
+
...isRecord2(details) ? { details } : {}
|
|
34050
|
+
};
|
|
34051
|
+
}
|
|
34052
|
+
|
|
34053
|
+
// src/protocol/write-signer.ts
|
|
34054
|
+
function isRecord3(value) {
|
|
34055
|
+
return value !== null && typeof value === "object";
|
|
34056
|
+
}
|
|
34057
|
+
function isViemWriteAccount(source) {
|
|
34058
|
+
return isRecord3(source) && source.type === "local" && typeof source.address === "string" && typeof source.signMessage === "function";
|
|
34059
|
+
}
|
|
34060
|
+
function isViemWriteWalletClient(source) {
|
|
34061
|
+
return isRecord3(source) && typeof source.signMessage === "function" && source.type !== "local" && (source.type === "walletClient" || "transport" in source);
|
|
34062
|
+
}
|
|
34063
|
+
function accountAddress(account) {
|
|
34064
|
+
return typeof account === "string" ? account : account.address;
|
|
34065
|
+
}
|
|
34066
|
+
function resolveWriteSigner(source, options = {}) {
|
|
34067
|
+
if (isViemWriteWalletClient(source)) {
|
|
34068
|
+
const account = options.account ?? source.account;
|
|
34069
|
+
if (account === void 0) {
|
|
34070
|
+
throw new WriteRequestError(
|
|
34071
|
+
"Viem wallet client requires an account option or account property"
|
|
34072
|
+
);
|
|
34073
|
+
}
|
|
34074
|
+
return {
|
|
34075
|
+
address: accountAddress(account),
|
|
34076
|
+
signMessage: (message) => source.signMessage({ account, message })
|
|
34077
|
+
};
|
|
34078
|
+
}
|
|
34079
|
+
if (isViemWriteAccount(source)) {
|
|
34080
|
+
return {
|
|
34081
|
+
address: source.address,
|
|
34082
|
+
signMessage: (message) => source.signMessage({ message })
|
|
34083
|
+
};
|
|
34084
|
+
}
|
|
34085
|
+
if (!isRecord3(source) || typeof source.signMessage !== "function") {
|
|
34086
|
+
throw new WriteRequestError(
|
|
34087
|
+
"signer must be a viem LocalAccount, a viem WalletClient, or a { signMessage } object"
|
|
34088
|
+
);
|
|
34089
|
+
}
|
|
34090
|
+
return source;
|
|
34091
|
+
}
|
|
34092
|
+
|
|
34093
|
+
// src/protocol/lineage.ts
|
|
34094
|
+
var DATA_POINT_ID_PATTERN = /^0x[0-9a-fA-F]{64}$/;
|
|
34095
|
+
function isDataPointId(value) {
|
|
34096
|
+
return typeof value === "string" && DATA_POINT_ID_PATTERN.test(value);
|
|
34097
|
+
}
|
|
34098
|
+
function deriveDataPointId(ownerAddress, scope) {
|
|
34099
|
+
if (!(0, import_viem21.isAddress)(ownerAddress, { strict: false })) {
|
|
34100
|
+
throw new Error(
|
|
34101
|
+
`ownerAddress is not an EVM address: ${String(ownerAddress)}`
|
|
34102
|
+
);
|
|
34103
|
+
}
|
|
34104
|
+
return (0, import_viem21.keccak256)(
|
|
34105
|
+
(0, import_viem21.encodeAbiParameters)(
|
|
34106
|
+
[
|
|
34107
|
+
{ name: "ownerAddress", type: "address" },
|
|
34108
|
+
{ name: "scope", type: "string" }
|
|
34109
|
+
],
|
|
34110
|
+
[ownerAddress, scope]
|
|
34111
|
+
)
|
|
34112
|
+
);
|
|
34113
|
+
}
|
|
34114
|
+
var DataPointIdSchema = import_zod3.z.string().regex(DATA_POINT_ID_PATTERN).transform((value) => value.toLowerCase());
|
|
34115
|
+
var VERSION_PATTERN = /^[1-9]\d*$/;
|
|
34116
|
+
var NODE_VERSION_PATTERN = /^(0|[1-9]\d*)$/;
|
|
34117
|
+
var VersionSchema = import_zod3.z.union([import_zod3.z.string(), import_zod3.z.number()]).transform(String).refine((value) => NODE_VERSION_PATTERN.test(value), {
|
|
34118
|
+
message: "version must be a decimal integer"
|
|
34119
|
+
});
|
|
34120
|
+
var ViewVersionSchema = VersionSchema.refine(
|
|
34121
|
+
(value) => VERSION_PATTERN.test(value),
|
|
34122
|
+
{ message: "version must be a positive decimal integer" }
|
|
34123
|
+
);
|
|
34124
|
+
function scopeNamespace(scope) {
|
|
34125
|
+
const dot = scope.indexOf(".");
|
|
34126
|
+
return dot === -1 ? scope : scope.slice(0, dot);
|
|
34127
|
+
}
|
|
34128
|
+
function derivedScopeViolatesNaming(derivedScope, sourceScope) {
|
|
34129
|
+
return scopeNamespace(derivedScope) === scopeNamespace(sourceScope);
|
|
34130
|
+
}
|
|
34131
|
+
function assertDerivedScopeNaming(derivedScope, sourceScopes) {
|
|
34132
|
+
for (const sourceScope of sourceScopes) {
|
|
34133
|
+
if (derivedScopeViolatesNaming(derivedScope, sourceScope)) {
|
|
34134
|
+
throw new WriteRequestError(
|
|
34135
|
+
`Derived scope ${derivedScope} must not share its first segment with source scope ${sourceScope}; put derivatives in the app's own namespace`,
|
|
34136
|
+
{ scope: derivedScope, sourceScope }
|
|
34137
|
+
);
|
|
34138
|
+
}
|
|
34139
|
+
}
|
|
34140
|
+
}
|
|
34141
|
+
var LineageNodeSchema = import_zod3.z.object({
|
|
34142
|
+
dataPointId: DataPointIdSchema,
|
|
34143
|
+
scope: import_zod3.z.string(),
|
|
34144
|
+
/**
|
|
34145
|
+
* The node's current version, decimal string; `"0"` for a source that no
|
|
34146
|
+
* longer resolves to a registered data point.
|
|
34147
|
+
*/
|
|
34148
|
+
version: VersionSchema,
|
|
34149
|
+
/** The node's tombstone time, or `null` when live. */
|
|
34150
|
+
deletedAt: import_zod3.z.string().nullable()
|
|
34151
|
+
});
|
|
34152
|
+
var RedactedLineageNodeSchema = import_zod3.z.object({
|
|
34153
|
+
dataPointId: DataPointIdSchema,
|
|
34154
|
+
redacted: import_zod3.z.literal(true)
|
|
34155
|
+
});
|
|
34156
|
+
var LineageEntrySchema = import_zod3.z.union([
|
|
34157
|
+
RedactedLineageNodeSchema,
|
|
34158
|
+
LineageNodeSchema
|
|
34159
|
+
]);
|
|
34160
|
+
var LineageGraphSchema = import_zod3.z.object({
|
|
34161
|
+
dataPointId: DataPointIdSchema,
|
|
34162
|
+
/** The data point owner; every node in the view belongs to it. */
|
|
34163
|
+
ownerAddress: import_zod3.z.string().optional(),
|
|
34164
|
+
scope: import_zod3.z.string(),
|
|
34165
|
+
/**
|
|
34166
|
+
* The derived record's version whose lineage is shown: the requested one,
|
|
34167
|
+
* else the current one, else (current is a tombstone) the last version
|
|
34168
|
+
* that carried lineage.
|
|
34169
|
+
*/
|
|
34170
|
+
version: ViewVersionSchema,
|
|
34171
|
+
deletedAt: import_zod3.z.string().nullable(),
|
|
34172
|
+
sources: import_zod3.z.array(LineageEntrySchema),
|
|
34173
|
+
derivatives: import_zod3.z.array(LineageEntrySchema),
|
|
34174
|
+
/** `true` when `derivatives` was cut at the server's cap (1000). */
|
|
34175
|
+
derivativesTruncated: import_zod3.z.boolean().optional()
|
|
34176
|
+
});
|
|
34177
|
+
function isRedactedLineageNode(entry) {
|
|
34178
|
+
return "redacted" in entry && entry.redacted === true;
|
|
34179
|
+
}
|
|
34180
|
+
function personalServerLineagePath(scope, version) {
|
|
34181
|
+
return `/v1/data/${encodeURIComponent(scope)}/lineage${version === void 0 ? "" : `/${String(version)}`}`;
|
|
34182
|
+
}
|
|
34183
|
+
function gatewayLineagePath(dataPointId, version) {
|
|
34184
|
+
return `/v1/data/${dataPointId.toLowerCase()}/lineage${version === void 0 ? "" : `/${String(version)}`}`;
|
|
34185
|
+
}
|
|
34186
|
+
function normalizeBaseUrl(url) {
|
|
34187
|
+
return url.replace(/\/+$/, "");
|
|
34188
|
+
}
|
|
34189
|
+
function resolveFetch(fetchFn) {
|
|
34190
|
+
const resolved = fetchFn ?? globalThis.fetch;
|
|
34191
|
+
if (resolved === void 0) {
|
|
34192
|
+
throw new LineageReadError("No fetch implementation available");
|
|
34193
|
+
}
|
|
34194
|
+
return resolved;
|
|
34195
|
+
}
|
|
34196
|
+
function normalizeVersion(version) {
|
|
34197
|
+
if (version === void 0) return void 0;
|
|
34198
|
+
const text = String(version);
|
|
34199
|
+
if (!VERSION_PATTERN.test(text)) {
|
|
34200
|
+
throw new LineageReadError(
|
|
34201
|
+
"version must be a positive decimal integer",
|
|
34202
|
+
void 0,
|
|
34203
|
+
"INVALID_VERSION",
|
|
34204
|
+
{ version }
|
|
34205
|
+
);
|
|
34206
|
+
}
|
|
34207
|
+
return text;
|
|
34208
|
+
}
|
|
34209
|
+
async function lineageReadFailure(source, response) {
|
|
34210
|
+
const { errorCode, message, details } = await readPersonalServerErrorBody(response);
|
|
34211
|
+
return new LineageReadError(
|
|
34212
|
+
message ?? `${source} lineage read failed: ${response.status} ${response.statusText}`,
|
|
34213
|
+
response.status,
|
|
34214
|
+
errorCode,
|
|
34215
|
+
details
|
|
34216
|
+
);
|
|
34217
|
+
}
|
|
34218
|
+
async function parseLineageGraph(source, response) {
|
|
34219
|
+
let body;
|
|
34220
|
+
try {
|
|
34221
|
+
body = await response.json();
|
|
34222
|
+
} catch (err) {
|
|
34223
|
+
throw new LineageReadError(
|
|
34224
|
+
`${source} lineage response is not JSON`,
|
|
34225
|
+
response.status,
|
|
34226
|
+
null,
|
|
34227
|
+
{ cause: err instanceof Error ? err.message : String(err) }
|
|
34228
|
+
);
|
|
34229
|
+
}
|
|
34230
|
+
const envelope = isRecord2(body) && isRecord2(body.data) ? body : void 0;
|
|
34231
|
+
const parsed = LineageGraphSchema.safeParse(envelope?.data ?? body);
|
|
34232
|
+
if (!parsed.success) {
|
|
34233
|
+
throw new LineageReadError(
|
|
34234
|
+
`${source} lineage response is not a lineage view`,
|
|
34235
|
+
response.status,
|
|
34236
|
+
null,
|
|
34237
|
+
{ issues: parsed.error.issues }
|
|
34238
|
+
);
|
|
34239
|
+
}
|
|
34240
|
+
const proof = isRecord2(envelope?.proof) ? envelope.proof : void 0;
|
|
34241
|
+
return proof === void 0 ? parsed.data : { ...parsed.data, proof };
|
|
34242
|
+
}
|
|
34243
|
+
async function sendLineageRead(source, fetchFn, url, headers) {
|
|
34244
|
+
let response;
|
|
34245
|
+
try {
|
|
34246
|
+
response = await fetchFn(url, { method: "GET", headers });
|
|
34247
|
+
} catch (err) {
|
|
34248
|
+
throw new LineageReadError(
|
|
34249
|
+
`${source} lineage read failed: ${err instanceof Error ? err.message : String(err)}`,
|
|
34250
|
+
void 0,
|
|
34251
|
+
null,
|
|
34252
|
+
{ cause: err instanceof Error ? err.message : String(err) }
|
|
34253
|
+
);
|
|
34254
|
+
}
|
|
34255
|
+
if (!response.ok) {
|
|
34256
|
+
throw await lineageReadFailure(source, response);
|
|
34257
|
+
}
|
|
34258
|
+
return parseLineageGraph(source, response);
|
|
34259
|
+
}
|
|
34260
|
+
async function getPersonalServerLineage(params) {
|
|
34261
|
+
const fetchFn = resolveFetch(params.fetch);
|
|
34262
|
+
const baseUrl = normalizeBaseUrl(params.personalServerUrl);
|
|
34263
|
+
const audience = params.audience ?? baseUrl;
|
|
34264
|
+
const signer = resolveWriteSigner(params.signer, { account: params.account });
|
|
34265
|
+
const path = personalServerLineagePath(
|
|
34266
|
+
params.scope,
|
|
34267
|
+
normalizeVersion(params.version)
|
|
34268
|
+
);
|
|
34269
|
+
const headers = new Headers(params.headers);
|
|
34270
|
+
headers.set(
|
|
34271
|
+
"Authorization",
|
|
34272
|
+
await buildWeb3SignedHeader({
|
|
34273
|
+
signMessage: signer.signMessage,
|
|
34274
|
+
aud: audience,
|
|
34275
|
+
method: "GET",
|
|
34276
|
+
uri: path,
|
|
34277
|
+
grantId: params.grantId
|
|
34278
|
+
})
|
|
34279
|
+
);
|
|
34280
|
+
return sendLineageRead(
|
|
34281
|
+
"Personal Server",
|
|
34282
|
+
fetchFn,
|
|
34283
|
+
`${baseUrl}${path}`,
|
|
34284
|
+
headers
|
|
34285
|
+
);
|
|
34286
|
+
}
|
|
34287
|
+
async function getGatewayLineage(params) {
|
|
34288
|
+
if (!isDataPointId(params.dataPointId)) {
|
|
34289
|
+
throw new LineageReadError(
|
|
34290
|
+
"dataPointId must be a 32-byte hex string (see deriveDataPointId)",
|
|
34291
|
+
void 0,
|
|
34292
|
+
"INVALID_DATA_POINT_ID",
|
|
34293
|
+
{ dataPointId: params.dataPointId }
|
|
34294
|
+
);
|
|
34295
|
+
}
|
|
34296
|
+
const fetchFn = resolveFetch(params.fetch);
|
|
34297
|
+
const baseUrl = normalizeBaseUrl(params.gatewayUrl);
|
|
34298
|
+
const signer = resolveWriteSigner(params.signer, { account: params.account });
|
|
34299
|
+
const uri = gatewayLineagePath(
|
|
34300
|
+
params.dataPointId,
|
|
34301
|
+
normalizeVersion(params.version)
|
|
34302
|
+
);
|
|
34303
|
+
const headers = new Headers(params.headers);
|
|
34304
|
+
headers.set(
|
|
34305
|
+
"Authorization",
|
|
34306
|
+
await buildWeb3SignedHeader({
|
|
34307
|
+
signMessage: signer.signMessage,
|
|
34308
|
+
aud: baseUrl,
|
|
34309
|
+
method: "GET",
|
|
34310
|
+
uri,
|
|
34311
|
+
grantId: params.grantId?.toLowerCase()
|
|
34312
|
+
})
|
|
34313
|
+
);
|
|
34314
|
+
return sendLineageRead("Gateway", fetchFn, `${baseUrl}${uri}`, headers);
|
|
34315
|
+
}
|
|
34316
|
+
function getLineage(params) {
|
|
34317
|
+
return "personalServerUrl" in params ? getPersonalServerLineage(params) : getGatewayLineage(params);
|
|
34318
|
+
}
|
|
34319
|
+
|
|
34320
|
+
// src/protocol/personal-server-write.ts
|
|
34321
|
+
var WRITE_SESSION_PATH = "/v1/write/session";
|
|
34322
|
+
var WRITE_SIGNATURE_HEADER = "X-Vana-Write-Signature";
|
|
34323
|
+
var WRITE_METADATA_HEADER = "X-Vana-Metadata";
|
|
34324
|
+
var LINEAGE_FIELD = "lineage";
|
|
34325
|
+
var MAX_LINEAGE_SOURCES = 256;
|
|
34326
|
+
var WRITE_FILENAME_HEADER = "X-Filename";
|
|
34327
|
+
var WRITE_CONTENT_DISPOSITION_HEADER = "Content-Disposition";
|
|
34328
|
+
var WRITER_ATTRIBUTION_KEY = "$writtenBy";
|
|
34329
|
+
var LINEAGE_KEY = "$lineage";
|
|
34330
|
+
var RESERVED_WRITE_KEYS = [
|
|
34331
|
+
WRITER_ATTRIBUTION_KEY,
|
|
34332
|
+
LINEAGE_KEY
|
|
34333
|
+
];
|
|
34334
|
+
var WriteDataResultSchema = IngestResponseSchema.extend({
|
|
34335
|
+
// Present when the write carried lineage: the validated, lowercased ids.
|
|
34336
|
+
lineage: import_zod4.z.object({ sources: import_zod4.z.array(import_zod4.z.string()) }).optional()
|
|
34337
|
+
});
|
|
34338
|
+
var WriteSessionResponseSchema = import_zod4.z.object({
|
|
34339
|
+
access_token: import_zod4.z.string().min(1),
|
|
34340
|
+
token_type: import_zod4.z.string(),
|
|
34341
|
+
expires_in: import_zod4.z.number().nonnegative(),
|
|
34342
|
+
scope: import_zod4.z.string()
|
|
34343
|
+
});
|
|
34344
|
+
function normalizeBaseUrl2(url) {
|
|
34345
|
+
return url.replace(/\/+$/, "");
|
|
34346
|
+
}
|
|
34347
|
+
function resolveFetch2(fetchFn) {
|
|
34348
|
+
const resolved = fetchFn ?? globalThis.fetch;
|
|
34349
|
+
if (resolved === void 0) {
|
|
34350
|
+
throw new WriteRequestError("No fetch implementation available");
|
|
34351
|
+
}
|
|
34352
|
+
return resolved;
|
|
34353
|
+
}
|
|
34354
|
+
function dataPath(scope) {
|
|
34355
|
+
return `/v1/data/${encodeURIComponent(scope)}`;
|
|
34356
|
+
}
|
|
34357
|
+
function errorMessage(err) {
|
|
34358
|
+
return err instanceof Error ? err.message : String(err);
|
|
34359
|
+
}
|
|
34360
|
+
function finiteOr(value, fallback) {
|
|
34361
|
+
return typeof value === "number" && Number.isFinite(value) ? value : fallback;
|
|
34362
|
+
}
|
|
34363
|
+
function sleep2(ms) {
|
|
34364
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
34365
|
+
}
|
|
34366
|
+
var issuedProofIats = /* @__PURE__ */ new Map();
|
|
34367
|
+
var issuedProofBuckets = /* @__PURE__ */ new Map();
|
|
34368
|
+
var issuedProofIatsPrunedAtSec = 0;
|
|
34369
|
+
var WEB3_SIGNED_PROOF_LIFETIME_SECONDS = 300;
|
|
34370
|
+
var WEB3_SIGNED_CLOCK_SKEW_SECONDS = 60;
|
|
34371
|
+
var PROOF_IAT_RETENTION_SECONDS = WEB3_SIGNED_PROOF_LIFETIME_SECONDS + WEB3_SIGNED_CLOCK_SKEW_SECONDS;
|
|
34372
|
+
var PROOF_IAT_MAX_AHEAD_SECONDS = 30;
|
|
34373
|
+
function pruneIssuedProofIats(nowSec) {
|
|
34374
|
+
if (issuedProofIatsPrunedAtSec === nowSec) return;
|
|
34375
|
+
issuedProofIatsPrunedAtSec = nowSec;
|
|
34376
|
+
const cutoff = nowSec - PROOF_IAT_RETENTION_SECONDS;
|
|
34377
|
+
for (const [sec, keys] of issuedProofBuckets) {
|
|
34378
|
+
if (sec >= cutoff) continue;
|
|
34379
|
+
for (const key of keys) issuedProofIats.delete(key);
|
|
34380
|
+
issuedProofBuckets.delete(sec);
|
|
34381
|
+
}
|
|
34382
|
+
}
|
|
34383
|
+
function setIssuedProofIat(key, iat, previous) {
|
|
34384
|
+
if (previous !== void 0) {
|
|
34385
|
+
const bucket2 = issuedProofBuckets.get(previous);
|
|
34386
|
+
bucket2?.delete(key);
|
|
34387
|
+
if (bucket2?.size === 0) issuedProofBuckets.delete(previous);
|
|
34388
|
+
}
|
|
34389
|
+
issuedProofIats.set(key, iat);
|
|
34390
|
+
let bucket = issuedProofBuckets.get(iat);
|
|
34391
|
+
if (bucket === void 0) {
|
|
34392
|
+
bucket = /* @__PURE__ */ new Set();
|
|
34393
|
+
issuedProofBuckets.set(iat, bucket);
|
|
34394
|
+
}
|
|
34395
|
+
bucket.add(key);
|
|
34396
|
+
}
|
|
34397
|
+
function nextProofIat(proofKey) {
|
|
34398
|
+
const nowSec = Math.floor(Date.now() / 1e3);
|
|
34399
|
+
pruneIssuedProofIats(nowSec);
|
|
34400
|
+
const last = issuedProofIats.get(proofKey);
|
|
34401
|
+
const iat = last === void 0 ? nowSec : Math.max(nowSec, last + 1);
|
|
34402
|
+
setIssuedProofIat(proofKey, iat, last);
|
|
34403
|
+
const waitSec = iat - nowSec - PROOF_IAT_MAX_AHEAD_SECONDS;
|
|
34404
|
+
if (waitSec <= 0) return Promise.resolve(iat);
|
|
34405
|
+
return sleep2(waitSec * 1e3).then(() => iat);
|
|
34406
|
+
}
|
|
34407
|
+
function proofKeyFor(parts) {
|
|
34408
|
+
return (0, import_viem22.bytesToHex)(
|
|
34409
|
+
(0, import_sha25.sha256)(
|
|
34410
|
+
new TextEncoder().encode(
|
|
34411
|
+
JSON.stringify([
|
|
34412
|
+
parts.aud,
|
|
34413
|
+
parts.method,
|
|
34414
|
+
parts.uri,
|
|
34415
|
+
parts.grantId,
|
|
34416
|
+
parts.signedBytes ? (0, import_viem22.bytesToHex)((0, import_sha25.sha256)(parts.signedBytes)) : ""
|
|
34417
|
+
])
|
|
34418
|
+
)
|
|
34419
|
+
)
|
|
34420
|
+
);
|
|
34421
|
+
}
|
|
34422
|
+
async function sendWithFreshProof(label, fetchFn, options, proofKey, build) {
|
|
34423
|
+
const attempts = Math.max(1, Math.floor(finiteOr(options?.attempts, 3)));
|
|
34424
|
+
let delayMs = Math.max(0, finiteOr(options?.initialDelayMs, 1e3));
|
|
34425
|
+
let lastError;
|
|
34426
|
+
for (let attempt = 0; attempt < attempts; attempt++) {
|
|
34427
|
+
const { url, init } = await build(await nextProofIat(proofKey));
|
|
34428
|
+
try {
|
|
34429
|
+
return await fetchFn(url, init);
|
|
34430
|
+
} catch (err) {
|
|
34431
|
+
lastError = err;
|
|
34432
|
+
}
|
|
34433
|
+
if (attempt < attempts - 1) {
|
|
34434
|
+
await sleep2(delayMs);
|
|
34435
|
+
delayMs *= 2;
|
|
34436
|
+
}
|
|
34437
|
+
}
|
|
34438
|
+
throw new WriteTransportError(
|
|
34439
|
+
`${label} failed after ${attempts} attempt(s): ${errorMessage(lastError)}`,
|
|
34440
|
+
attempts,
|
|
34441
|
+
lastError
|
|
34442
|
+
);
|
|
34443
|
+
}
|
|
34444
|
+
async function openWriteSession(params) {
|
|
34445
|
+
const fetchFn = resolveFetch2(params.fetch);
|
|
34446
|
+
const personalServerUrl = normalizeBaseUrl2(params.personalServerUrl);
|
|
34447
|
+
const audience = params.audience ?? personalServerUrl;
|
|
34448
|
+
const signer = resolveWriteSigner(params.signer, { account: params.account });
|
|
34449
|
+
const response = await sendWithFreshProof(
|
|
34450
|
+
"Write session handshake",
|
|
34451
|
+
fetchFn,
|
|
34452
|
+
params.retry,
|
|
34453
|
+
proofKeyFor({
|
|
34454
|
+
aud: audience,
|
|
34455
|
+
method: "POST",
|
|
34456
|
+
uri: WRITE_SESSION_PATH,
|
|
34457
|
+
grantId: params.grantId
|
|
34458
|
+
}),
|
|
34459
|
+
async (iat) => {
|
|
34460
|
+
const headers = new Headers(params.headers);
|
|
34461
|
+
headers.set(
|
|
34462
|
+
"Authorization",
|
|
34463
|
+
await buildWeb3SignedHeader({
|
|
34464
|
+
signMessage: signer.signMessage,
|
|
34465
|
+
aud: audience,
|
|
34466
|
+
method: "POST",
|
|
34467
|
+
uri: WRITE_SESSION_PATH,
|
|
34468
|
+
grantId: params.grantId,
|
|
34469
|
+
iat
|
|
34470
|
+
})
|
|
34471
|
+
);
|
|
34472
|
+
return {
|
|
34473
|
+
url: `${personalServerUrl}${WRITE_SESSION_PATH}`,
|
|
34474
|
+
init: { method: "POST", headers }
|
|
34475
|
+
};
|
|
34476
|
+
}
|
|
34477
|
+
);
|
|
34478
|
+
const mintedAt = Date.now();
|
|
34479
|
+
if (!response.ok) {
|
|
34480
|
+
const { errorCode, message, details } = await readPersonalServerErrorBody(response);
|
|
34481
|
+
throw new WriteSessionError(
|
|
34482
|
+
message ?? `Write session handshake failed: ${response.status} ${response.statusText}`,
|
|
34483
|
+
response.status,
|
|
34484
|
+
errorCode,
|
|
34485
|
+
details
|
|
34486
|
+
);
|
|
34487
|
+
}
|
|
34488
|
+
let body;
|
|
34489
|
+
try {
|
|
34490
|
+
body = await response.json();
|
|
34491
|
+
} catch (err) {
|
|
34492
|
+
throw new WriteSessionError(
|
|
34493
|
+
"Write session response is not JSON",
|
|
34494
|
+
response.status,
|
|
34495
|
+
null,
|
|
34496
|
+
{ cause: errorMessage(err) }
|
|
34497
|
+
);
|
|
34498
|
+
}
|
|
34499
|
+
const parsed = WriteSessionResponseSchema.safeParse(body);
|
|
34500
|
+
if (!parsed.success) {
|
|
34501
|
+
throw new WriteSessionError(
|
|
34502
|
+
"Write session response is not a session",
|
|
34503
|
+
response.status,
|
|
34504
|
+
null,
|
|
34505
|
+
{ issues: parsed.error.issues }
|
|
34506
|
+
);
|
|
34507
|
+
}
|
|
34508
|
+
if (parsed.data.token_type.toLowerCase() !== "bearer") {
|
|
34509
|
+
throw new WriteSessionError(
|
|
34510
|
+
`Write session token type is not Bearer: ${parsed.data.token_type}`,
|
|
34511
|
+
response.status
|
|
34512
|
+
);
|
|
34513
|
+
}
|
|
34514
|
+
return {
|
|
34515
|
+
personalServerUrl,
|
|
34516
|
+
audience,
|
|
34517
|
+
grantId: params.grantId,
|
|
34518
|
+
accessToken: parsed.data.access_token,
|
|
34519
|
+
expiresAt: mintedAt + parsed.data.expires_in * 1e3,
|
|
34520
|
+
writeScopes: parsed.data.scope.split(" ").filter((s) => s.length > 0),
|
|
34521
|
+
signer
|
|
34522
|
+
};
|
|
34523
|
+
}
|
|
34524
|
+
function isWriteSession(value) {
|
|
34525
|
+
if (!isRecord2(value)) return false;
|
|
34526
|
+
const signer = value.signer;
|
|
34527
|
+
return typeof value.personalServerUrl === "string" && typeof value.audience === "string" && typeof value.grantId === "string" && typeof value.accessToken === "string" && value.accessToken.length > 0 && typeof value.expiresAt === "number" && Number.isFinite(value.expiresAt) && Array.isArray(value.writeScopes) && value.writeScopes.every((scope) => typeof scope === "string") && isRecord2(signer) && typeof signer.signMessage === "function";
|
|
34528
|
+
}
|
|
34529
|
+
function sessionCoversScope(session, scope) {
|
|
34530
|
+
if (!isRecord2(session) || !Array.isArray(session.writeScopes) || !session.writeScopes.every((pattern) => typeof pattern === "string")) {
|
|
34531
|
+
throw new WriteRequestError("session must come from openWriteSession");
|
|
34532
|
+
}
|
|
34533
|
+
return session.writeScopes.some(
|
|
34534
|
+
(pattern) => scopeMatchesPattern(scope, pattern)
|
|
34535
|
+
);
|
|
34536
|
+
}
|
|
34537
|
+
function normalizeBinaryMimeType(contentType) {
|
|
34538
|
+
if (!contentType) return "application/octet-stream";
|
|
34539
|
+
return contentType.split(";")[0].trim() || "application/octet-stream";
|
|
34540
|
+
}
|
|
34541
|
+
function parseWriteMetadataHeader(value) {
|
|
34542
|
+
if (value === null) return void 0;
|
|
34543
|
+
const trimmed = value.trim();
|
|
34544
|
+
if (trimmed === "") return void 0;
|
|
34545
|
+
try {
|
|
34546
|
+
return JSON.parse(trimmed);
|
|
34547
|
+
} catch {
|
|
34548
|
+
return value;
|
|
34549
|
+
}
|
|
34550
|
+
}
|
|
34551
|
+
function encodeWriteMetadataHeader(metadata) {
|
|
34552
|
+
let json;
|
|
34553
|
+
try {
|
|
34554
|
+
json = JSON.stringify(metadata);
|
|
34555
|
+
} catch (err) {
|
|
34556
|
+
throw new WriteRequestError(
|
|
34557
|
+
`metadata is not JSON-serialisable: ${errorMessage(err)}`
|
|
34558
|
+
);
|
|
34559
|
+
}
|
|
34560
|
+
if (typeof json !== "string") {
|
|
34561
|
+
throw new WriteRequestError("metadata must serialise to JSON");
|
|
34562
|
+
}
|
|
34563
|
+
return json.replace(
|
|
34564
|
+
/[\u007f-\uffff]/g,
|
|
34565
|
+
(c) => `\\u${c.charCodeAt(0).toString(16).padStart(4, "0")}`
|
|
34566
|
+
);
|
|
34567
|
+
}
|
|
34568
|
+
function binaryWriteSignedBytes(input) {
|
|
34569
|
+
const metadata = parseWriteMetadataHeader(input.metadataHeader ?? null);
|
|
34570
|
+
const record = {
|
|
34571
|
+
$binary: true,
|
|
34572
|
+
mimeType: normalizeBinaryMimeType(input.contentType),
|
|
34573
|
+
...input.filename ? { filename: input.filename } : {},
|
|
34574
|
+
sizeBytes: input.bytes.length,
|
|
34575
|
+
contentHash: (0, import_viem22.bytesToHex)((0, import_sha25.sha256)(input.bytes)),
|
|
34576
|
+
encoding: "base64",
|
|
34577
|
+
content: toBase64(input.bytes),
|
|
34578
|
+
...metadata !== void 0 ? { metadata } : {}
|
|
34579
|
+
};
|
|
34580
|
+
return new TextEncoder().encode(JSON.stringify(record));
|
|
34581
|
+
}
|
|
34582
|
+
var PRINTABLE_ASCII = /^[\x20-\x7e]*$/;
|
|
34583
|
+
function setFilenameHeader(headers, filename) {
|
|
34584
|
+
if (PRINTABLE_ASCII.test(filename)) {
|
|
34585
|
+
headers.set(WRITE_FILENAME_HEADER, filename);
|
|
34586
|
+
return;
|
|
34587
|
+
}
|
|
34588
|
+
headers.set(
|
|
34589
|
+
WRITE_CONTENT_DISPOSITION_HEADER,
|
|
34590
|
+
`attachment; filename*=UTF-8''${encodeURIComponent(filename)}`
|
|
34591
|
+
);
|
|
34592
|
+
}
|
|
34593
|
+
function assertNoReservedKeys(value, where) {
|
|
34594
|
+
for (const key of RESERVED_WRITE_KEYS) {
|
|
34595
|
+
if (Object.prototype.hasOwnProperty.call(value, key)) {
|
|
34596
|
+
throw new WriteRequestError(
|
|
34597
|
+
`${where} must not contain the reserved ${key} key; the Personal Server stamps it`,
|
|
34598
|
+
{ key }
|
|
34599
|
+
);
|
|
34600
|
+
}
|
|
34601
|
+
}
|
|
34602
|
+
}
|
|
34603
|
+
function isLineagePair(value) {
|
|
34604
|
+
return isRecord2(value) && typeof value.ownerAddress === "string" && typeof value.scope === "string";
|
|
34605
|
+
}
|
|
34606
|
+
function normalizeLineage(lineage, derivedScope) {
|
|
34607
|
+
if (!Array.isArray(lineage)) {
|
|
34608
|
+
throw new WriteRequestError("lineage must be an array of data point ids");
|
|
34609
|
+
}
|
|
34610
|
+
if (lineage.length > MAX_LINEAGE_SOURCES) {
|
|
34611
|
+
throw new WriteRequestError(
|
|
34612
|
+
`lineage lists ${lineage.length} sources; the maximum is ${MAX_LINEAGE_SOURCES}`,
|
|
34613
|
+
{ max: MAX_LINEAGE_SOURCES, count: lineage.length }
|
|
34614
|
+
);
|
|
34615
|
+
}
|
|
34616
|
+
const seen = /* @__PURE__ */ new Set();
|
|
34617
|
+
const sources = [];
|
|
34618
|
+
const sourceScopes = [];
|
|
34619
|
+
const ownIds = /* @__PURE__ */ new Set();
|
|
34620
|
+
for (const entry of lineage) {
|
|
34621
|
+
let id;
|
|
34622
|
+
if (isLineagePair(entry)) {
|
|
34623
|
+
if (!(0, import_viem22.isAddress)(entry.ownerAddress, { strict: false })) {
|
|
34624
|
+
throw new WriteRequestError(
|
|
34625
|
+
"lineage source ownerAddress must be an EVM address",
|
|
34626
|
+
{ ownerAddress: entry.ownerAddress }
|
|
34627
|
+
);
|
|
34628
|
+
}
|
|
34629
|
+
if (entry.scope.length === 0) {
|
|
34630
|
+
throw new WriteRequestError("lineage source scope is required");
|
|
34631
|
+
}
|
|
34632
|
+
id = deriveDataPointId(entry.ownerAddress, entry.scope);
|
|
34633
|
+
sourceScopes.push(entry.scope);
|
|
34634
|
+
ownIds.add(deriveDataPointId(entry.ownerAddress, derivedScope));
|
|
34635
|
+
} else if (isDataPointId(entry)) {
|
|
34636
|
+
id = entry;
|
|
34637
|
+
} else {
|
|
34638
|
+
throw new WriteRequestError(
|
|
34639
|
+
"lineage entries must be 32-byte hex data point ids or { ownerAddress, scope } pairs",
|
|
34640
|
+
{ entry }
|
|
34641
|
+
);
|
|
34642
|
+
}
|
|
34643
|
+
const normalized = id.toLowerCase();
|
|
34644
|
+
if (seen.has(normalized)) {
|
|
34645
|
+
throw new WriteRequestError("lineage must not repeat a data point id", {
|
|
34646
|
+
dataPointId: normalized
|
|
34647
|
+
});
|
|
34648
|
+
}
|
|
34649
|
+
seen.add(normalized);
|
|
34650
|
+
sources.push(normalized);
|
|
34651
|
+
}
|
|
34652
|
+
for (const own of ownIds) {
|
|
34653
|
+
if (seen.has(own)) {
|
|
34654
|
+
throw new WriteRequestError(
|
|
34655
|
+
"lineage must not cite the record's own data point",
|
|
34656
|
+
{ dataPointId: own, scope: derivedScope }
|
|
34657
|
+
);
|
|
34658
|
+
}
|
|
34659
|
+
}
|
|
34660
|
+
assertDerivedScopeNaming(derivedScope, sourceScopes);
|
|
34661
|
+
return sources;
|
|
34662
|
+
}
|
|
34663
|
+
function assertNoLineageField(value, where) {
|
|
34664
|
+
if (Object.prototype.hasOwnProperty.call(value, LINEAGE_FIELD)) {
|
|
34665
|
+
throw new WriteRequestError(
|
|
34666
|
+
`${where}.${LINEAGE_FIELD} is reserved; pass sources through the lineage option`
|
|
34667
|
+
);
|
|
34668
|
+
}
|
|
34669
|
+
}
|
|
34670
|
+
function buildMetadataHeader(metadata, sources) {
|
|
34671
|
+
if (metadata !== void 0) {
|
|
34672
|
+
if (!isRecord2(metadata)) {
|
|
34673
|
+
throw new WriteRequestError("metadata must be a plain object");
|
|
34674
|
+
}
|
|
34675
|
+
assertNoReservedKeys(metadata, "metadata");
|
|
34676
|
+
assertNoLineageField(metadata, "metadata");
|
|
34677
|
+
}
|
|
34678
|
+
if (metadata === void 0 && sources === void 0) return void 0;
|
|
34679
|
+
return encodeWriteMetadataHeader({
|
|
34680
|
+
...metadata ?? {},
|
|
34681
|
+
...sources !== void 0 ? { [LINEAGE_FIELD]: sources } : {}
|
|
34682
|
+
});
|
|
34683
|
+
}
|
|
34684
|
+
function prepareWrite(params) {
|
|
34685
|
+
if (params.binary !== void 0 && params.data !== void 0) {
|
|
34686
|
+
throw new WriteRequestError("Pass either data or binary, not both");
|
|
34687
|
+
}
|
|
34688
|
+
const rawLineage = params.lineage;
|
|
34689
|
+
const sources = rawLineage === void 0 || rawLineage === null ? void 0 : normalizeLineage(rawLineage, params.scope);
|
|
34690
|
+
if (params.binary !== void 0) {
|
|
34691
|
+
const { bytes, contentType, filename } = params.binary;
|
|
34692
|
+
if (!(bytes instanceof Uint8Array)) {
|
|
34693
|
+
throw new WriteRequestError("binary.bytes must be a Uint8Array");
|
|
34694
|
+
}
|
|
34695
|
+
if (typeof contentType !== "string" || contentType.trim() === "") {
|
|
34696
|
+
throw new WriteRequestError("binary.contentType is required");
|
|
34697
|
+
}
|
|
34698
|
+
if (filename !== void 0) {
|
|
34699
|
+
if (typeof filename !== "string") {
|
|
34700
|
+
throw new WriteRequestError("binary.filename must be a string");
|
|
34701
|
+
}
|
|
34702
|
+
if (filename !== filename.trim()) {
|
|
34703
|
+
throw new WriteRequestError(
|
|
34704
|
+
"binary.filename must not have leading or trailing whitespace"
|
|
34705
|
+
);
|
|
34706
|
+
}
|
|
34707
|
+
}
|
|
34708
|
+
const metadataHeader = buildMetadataHeader(params.metadata, sources);
|
|
34709
|
+
return {
|
|
34710
|
+
body: bytes,
|
|
34711
|
+
signedBytes: binaryWriteSignedBytes({
|
|
34712
|
+
bytes,
|
|
34713
|
+
contentType,
|
|
34714
|
+
filename,
|
|
34715
|
+
metadataHeader
|
|
34716
|
+
}),
|
|
34717
|
+
contentType,
|
|
34718
|
+
filename,
|
|
34719
|
+
metadataHeader
|
|
34720
|
+
};
|
|
34721
|
+
}
|
|
34722
|
+
if (params.data === void 0) {
|
|
34723
|
+
throw new WriteRequestError("Pass data (a JSON object) or binary");
|
|
34724
|
+
}
|
|
34725
|
+
if (!isRecord2(params.data)) {
|
|
34726
|
+
throw new WriteRequestError("data must be a plain JSON object");
|
|
34727
|
+
}
|
|
34728
|
+
if (params.metadata !== void 0) {
|
|
34729
|
+
throw new WriteRequestError(
|
|
34730
|
+
"metadata applies to binary writes; put fields to store inside data"
|
|
34731
|
+
);
|
|
34732
|
+
}
|
|
34733
|
+
assertNoReservedKeys(params.data, "data");
|
|
34734
|
+
assertNoLineageField(params.data, "data");
|
|
34735
|
+
const record = sources === void 0 ? params.data : { ...params.data, [LINEAGE_FIELD]: sources };
|
|
34736
|
+
let text;
|
|
34737
|
+
try {
|
|
34738
|
+
text = JSON.stringify(record);
|
|
34739
|
+
} catch (err) {
|
|
34740
|
+
throw new WriteRequestError(
|
|
34741
|
+
`data is not JSON-serialisable: ${errorMessage(err)}`
|
|
34742
|
+
);
|
|
34743
|
+
}
|
|
34744
|
+
if (typeof text !== "string" || !text.startsWith("{")) {
|
|
34745
|
+
throw new WriteRequestError("data must serialise to a JSON object");
|
|
34746
|
+
}
|
|
34747
|
+
const body = new TextEncoder().encode(text);
|
|
34748
|
+
return {
|
|
34749
|
+
body,
|
|
34750
|
+
signedBytes: body,
|
|
34751
|
+
contentType: "application/json"
|
|
34752
|
+
};
|
|
34753
|
+
}
|
|
34754
|
+
async function writeErrorFromResponse(response) {
|
|
34755
|
+
const { errorCode, message, details } = await readPersonalServerErrorBody(response);
|
|
34756
|
+
const text = message ?? `Personal Server write failed: ${response.status} ${response.statusText}`;
|
|
34757
|
+
if (response.status === 422 || errorCode?.startsWith("LINEAGE_")) {
|
|
34758
|
+
return new WriteLineageError(text, response.status, errorCode, details);
|
|
34759
|
+
}
|
|
34760
|
+
switch (response.status) {
|
|
34761
|
+
case 401:
|
|
34762
|
+
return new WriteUnauthorizedError(text, errorCode, details);
|
|
34763
|
+
case 403:
|
|
34764
|
+
return new WriteForbiddenError(text, errorCode, details);
|
|
34765
|
+
case 409:
|
|
34766
|
+
return new WriteConflictError(text, errorCode, details);
|
|
34767
|
+
default:
|
|
34768
|
+
return new WriteRejectedError(text, response.status, errorCode, details);
|
|
34769
|
+
}
|
|
34770
|
+
}
|
|
34771
|
+
async function writeData(params) {
|
|
34772
|
+
const { session } = params;
|
|
34773
|
+
if (!isWriteSession(session)) {
|
|
34774
|
+
throw new WriteRequestError("session must come from openWriteSession");
|
|
34775
|
+
}
|
|
34776
|
+
const fetchFn = resolveFetch2(params.fetch);
|
|
34777
|
+
if (typeof params.scope !== "string" || params.scope.length === 0) {
|
|
34778
|
+
throw new WriteRequestError("scope is required");
|
|
34779
|
+
}
|
|
34780
|
+
const prepared = prepareWrite(params);
|
|
34781
|
+
if (Date.now() >= session.expiresAt) {
|
|
34782
|
+
throw new WriteSessionExpiredError(
|
|
34783
|
+
"Write session has expired; open a new session",
|
|
34784
|
+
{ grantId: session.grantId, expiresAt: session.expiresAt }
|
|
34785
|
+
);
|
|
34786
|
+
}
|
|
34787
|
+
const path = dataPath(params.scope);
|
|
34788
|
+
const response = await sendWithFreshProof(
|
|
34789
|
+
`Write to ${params.scope}`,
|
|
34790
|
+
fetchFn,
|
|
34791
|
+
params.retry,
|
|
34792
|
+
proofKeyFor({
|
|
34793
|
+
aud: session.audience,
|
|
34794
|
+
method: "POST",
|
|
34795
|
+
uri: path,
|
|
34796
|
+
grantId: session.grantId,
|
|
34797
|
+
signedBytes: prepared.signedBytes
|
|
34798
|
+
}),
|
|
34799
|
+
async (iat) => {
|
|
34800
|
+
const headers = new Headers(params.headers);
|
|
34801
|
+
headers.set("Content-Type", prepared.contentType);
|
|
34802
|
+
headers.set("Authorization", `Bearer ${session.accessToken}`);
|
|
34803
|
+
if (prepared.filename) {
|
|
34804
|
+
setFilenameHeader(headers, prepared.filename);
|
|
34805
|
+
}
|
|
34806
|
+
if (prepared.metadataHeader !== void 0) {
|
|
34807
|
+
headers.set(WRITE_METADATA_HEADER, prepared.metadataHeader);
|
|
34808
|
+
}
|
|
34809
|
+
headers.set(
|
|
34810
|
+
WRITE_SIGNATURE_HEADER,
|
|
34811
|
+
await buildWeb3SignedHeader({
|
|
34812
|
+
signMessage: session.signer.signMessage,
|
|
34813
|
+
aud: session.audience,
|
|
34814
|
+
method: "POST",
|
|
34815
|
+
uri: path,
|
|
34816
|
+
body: prepared.signedBytes,
|
|
34817
|
+
grantId: session.grantId,
|
|
34818
|
+
iat
|
|
34819
|
+
})
|
|
34820
|
+
);
|
|
34821
|
+
return {
|
|
34822
|
+
url: `${session.personalServerUrl}${path}`,
|
|
34823
|
+
init: {
|
|
34824
|
+
method: "POST",
|
|
34825
|
+
headers,
|
|
34826
|
+
body: prepared.body
|
|
34827
|
+
}
|
|
34828
|
+
};
|
|
34829
|
+
}
|
|
34830
|
+
);
|
|
34831
|
+
if (!response.ok) {
|
|
34832
|
+
throw await writeErrorFromResponse(response);
|
|
34833
|
+
}
|
|
34834
|
+
let body;
|
|
34835
|
+
try {
|
|
34836
|
+
body = await response.json();
|
|
34837
|
+
} catch (err) {
|
|
34838
|
+
throw new WriteRejectedError(
|
|
34839
|
+
"Personal Server write response is not JSON",
|
|
34840
|
+
response.status,
|
|
34841
|
+
null,
|
|
34842
|
+
{ cause: errorMessage(err) }
|
|
34843
|
+
);
|
|
34844
|
+
}
|
|
34845
|
+
const parsed = WriteDataResultSchema.safeParse(body);
|
|
34846
|
+
if (!parsed.success) {
|
|
34847
|
+
throw new WriteRejectedError(
|
|
34848
|
+
"Personal Server write response is not an ingest result",
|
|
34849
|
+
response.status,
|
|
34850
|
+
null,
|
|
34851
|
+
{ issues: parsed.error.issues }
|
|
34852
|
+
);
|
|
34853
|
+
}
|
|
34854
|
+
return parsed.data;
|
|
34855
|
+
}
|
|
34856
|
+
async function writePersonalServerData(params) {
|
|
34857
|
+
const session = await openWriteSession({
|
|
34858
|
+
personalServerUrl: params.personalServerUrl,
|
|
34859
|
+
signer: params.signer,
|
|
34860
|
+
grantId: params.grantId,
|
|
34861
|
+
account: params.account,
|
|
34862
|
+
audience: params.audience,
|
|
34863
|
+
fetch: params.fetch,
|
|
34864
|
+
headers: params.headers,
|
|
34865
|
+
retry: params.retry
|
|
34866
|
+
});
|
|
34867
|
+
const writeParams = { ...params, session };
|
|
34868
|
+
const result = await writeData(writeParams);
|
|
34869
|
+
return { ...result, session };
|
|
34870
|
+
}
|
|
34871
|
+
|
|
33748
34872
|
// src/protocol/gateway.ts
|
|
34873
|
+
function withGrantPermissions(grant) {
|
|
34874
|
+
const stripped = { ...grant };
|
|
34875
|
+
delete stripped.permissions;
|
|
34876
|
+
const scopes = stripped.scopes;
|
|
34877
|
+
if (!Array.isArray(scopes)) {
|
|
34878
|
+
return stripped;
|
|
34879
|
+
}
|
|
34880
|
+
const permissions = tryGrantPermissions(scopes);
|
|
34881
|
+
return permissions === void 0 ? stripped : { ...stripped, permissions };
|
|
34882
|
+
}
|
|
33749
34883
|
function createGatewayClient(baseUrl) {
|
|
33750
34884
|
const base = baseUrl.replace(/\/+$/, "");
|
|
33751
34885
|
async function unwrapEnvelope(res) {
|
|
@@ -33775,7 +34909,9 @@ function createGatewayClient(baseUrl) {
|
|
|
33775
34909
|
if (!res.ok) {
|
|
33776
34910
|
throw new Error(`Gateway error: ${res.status} ${res.statusText}`);
|
|
33777
34911
|
}
|
|
33778
|
-
return
|
|
34912
|
+
return withGrantPermissions(
|
|
34913
|
+
await unwrapEnvelope(res)
|
|
34914
|
+
);
|
|
33779
34915
|
},
|
|
33780
34916
|
async listGrantsByUser(userAddress) {
|
|
33781
34917
|
const res = await fetch(`${base}/v1/grants?user=${userAddress}`);
|
|
@@ -33783,7 +34919,8 @@ function createGatewayClient(baseUrl) {
|
|
|
33783
34919
|
if (!res.ok) {
|
|
33784
34920
|
throw new Error(`Gateway error: ${res.status} ${res.statusText}`);
|
|
33785
34921
|
}
|
|
33786
|
-
|
|
34922
|
+
const grants = await unwrapEnvelope(res);
|
|
34923
|
+
return grants.map(withGrantPermissions);
|
|
33787
34924
|
},
|
|
33788
34925
|
async getSchemaForScope(scope) {
|
|
33789
34926
|
const res = await fetch(`${base}/v1/schemas?scope=${scope}`);
|
|
@@ -34652,7 +35789,7 @@ var KNOWN_CODES = /* @__PURE__ */ new Set([
|
|
|
34652
35789
|
"server_not_configured",
|
|
34653
35790
|
"content_too_large"
|
|
34654
35791
|
]);
|
|
34655
|
-
function
|
|
35792
|
+
function isRecord4(value) {
|
|
34656
35793
|
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
34657
35794
|
}
|
|
34658
35795
|
function normalizeCode(value) {
|
|
@@ -34663,10 +35800,10 @@ function normalizeCode(value) {
|
|
|
34663
35800
|
return KNOWN_CODES.has(code) ? code : null;
|
|
34664
35801
|
}
|
|
34665
35802
|
function extractPSErrorBody(body) {
|
|
34666
|
-
if (!
|
|
35803
|
+
if (!isRecord4(body)) {
|
|
34667
35804
|
return null;
|
|
34668
35805
|
}
|
|
34669
|
-
const nested =
|
|
35806
|
+
const nested = isRecord4(body.error) ? body.error : null;
|
|
34670
35807
|
const code = normalizeCode(
|
|
34671
35808
|
nested?.errorCode ?? nested?.code ?? body.errorCode ?? body.code
|
|
34672
35809
|
);
|
|
@@ -34719,9 +35856,17 @@ async function parsePSError(response) {
|
|
|
34719
35856
|
InMemoryTokenStore,
|
|
34720
35857
|
IngestResponseSchema,
|
|
34721
35858
|
InvalidConfigurationError,
|
|
35859
|
+
InvalidScopeEntryError,
|
|
34722
35860
|
InvalidSignatureError,
|
|
34723
35861
|
IpfsStorage,
|
|
35862
|
+
LINEAGE_FIELD,
|
|
35863
|
+
LINEAGE_KEY,
|
|
35864
|
+
LineageEntrySchema,
|
|
35865
|
+
LineageGraphSchema,
|
|
35866
|
+
LineageNodeSchema,
|
|
35867
|
+
LineageReadError,
|
|
34724
35868
|
MASTER_KEY_MESSAGE,
|
|
35869
|
+
MAX_LINEAGE_SOURCES,
|
|
34725
35870
|
MissingAuthError,
|
|
34726
35871
|
NATIVE_ASSET_ADDRESS,
|
|
34727
35872
|
NATIVE_VANA_ASSET,
|
|
@@ -34740,12 +35885,16 @@ async function parsePSError(response) {
|
|
|
34740
35885
|
PSError,
|
|
34741
35886
|
PermissionError,
|
|
34742
35887
|
PersonalServerError,
|
|
35888
|
+
PersonalServerWriteError,
|
|
34743
35889
|
PinataStorage,
|
|
34744
35890
|
R2Storage,
|
|
34745
35891
|
RECORD_DATA_ACCESS_TYPES,
|
|
34746
35892
|
REGISTRATION_KIND_FOR_OP,
|
|
35893
|
+
RESERVED_WRITE_KEYS,
|
|
34747
35894
|
ReadOnlyError,
|
|
35895
|
+
RedactedLineageNodeSchema,
|
|
34748
35896
|
RelayerError,
|
|
35897
|
+
SCOPE_ACTIONS,
|
|
34749
35898
|
SERVER_REGISTRATION_TYPES,
|
|
34750
35899
|
ScopeSchema,
|
|
34751
35900
|
SerializationError,
|
|
@@ -34757,9 +35906,26 @@ async function parsePSError(response) {
|
|
|
34757
35906
|
UserRejectedRequestError,
|
|
34758
35907
|
VanaError,
|
|
34759
35908
|
VanaStorage,
|
|
35909
|
+
WRITER_ATTRIBUTION_KEY,
|
|
35910
|
+
WRITE_CONTENT_DISPOSITION_HEADER,
|
|
35911
|
+
WRITE_FILENAME_HEADER,
|
|
35912
|
+
WRITE_METADATA_HEADER,
|
|
35913
|
+
WRITE_SESSION_PATH,
|
|
35914
|
+
WRITE_SIGNATURE_HEADER,
|
|
35915
|
+
WriteConflictError,
|
|
35916
|
+
WriteForbiddenError,
|
|
35917
|
+
WriteLineageError,
|
|
35918
|
+
WriteRejectedError,
|
|
35919
|
+
WriteRequestError,
|
|
35920
|
+
WriteSessionError,
|
|
35921
|
+
WriteSessionExpiredError,
|
|
35922
|
+
WriteTransportError,
|
|
35923
|
+
WriteUnauthorizedError,
|
|
35924
|
+
assertDerivedScopeNaming,
|
|
34760
35925
|
assertValidPkceVerifier,
|
|
34761
35926
|
authorizeEscrowPayment,
|
|
34762
35927
|
authorizeGrantPayment,
|
|
35928
|
+
binaryWriteSignedBytes,
|
|
34763
35929
|
buildDepositNativeRequest,
|
|
34764
35930
|
buildDepositTokenRequest,
|
|
34765
35931
|
buildEscrowPaymentHeader,
|
|
@@ -34793,16 +35959,21 @@ async function parsePSError(response) {
|
|
|
34793
35959
|
dataRegistryContractAddress,
|
|
34794
35960
|
dataRegistryDomain,
|
|
34795
35961
|
decryptWithPassword,
|
|
35962
|
+
deriveDataPointId,
|
|
34796
35963
|
deriveMasterKey,
|
|
34797
35964
|
deriveScopeKey,
|
|
35965
|
+
derivedScopeViolatesNaming,
|
|
34798
35966
|
deserializeECIES,
|
|
34799
35967
|
detectPlatform,
|
|
34800
35968
|
encodeDepositNativeData,
|
|
34801
35969
|
encodeDepositTokenData,
|
|
34802
35970
|
encodeSetDataPointStatusData,
|
|
35971
|
+
encodeWriteMetadataHeader,
|
|
34803
35972
|
encryptWithPassword,
|
|
34804
35973
|
escrowContractAddress,
|
|
34805
35974
|
escrowPaymentDomain,
|
|
35975
|
+
formatScopeEntry,
|
|
35976
|
+
gatewayLineagePath,
|
|
34806
35977
|
generatePkceVerifier,
|
|
34807
35978
|
genericPaymentDomain,
|
|
34808
35979
|
getAbi,
|
|
@@ -34812,42 +35983,61 @@ async function parsePSError(response) {
|
|
|
34812
35983
|
getContractController,
|
|
34813
35984
|
getContractInfo,
|
|
34814
35985
|
getFee,
|
|
35986
|
+
getGatewayLineage,
|
|
35987
|
+
getLineage,
|
|
34815
35988
|
getOpFee,
|
|
35989
|
+
getPersonalServerLineage,
|
|
34816
35990
|
getPlatformCapabilities,
|
|
34817
35991
|
getServiceEndpoints,
|
|
35992
|
+
grantPermissions,
|
|
34818
35993
|
grantRegistrationDomain,
|
|
34819
35994
|
grantRevocationDomain,
|
|
35995
|
+
hasAction,
|
|
35996
|
+
isDataPointId,
|
|
34820
35997
|
isDataPortabilityGatewayConfig,
|
|
34821
35998
|
isECIESEncrypted,
|
|
34822
35999
|
isPlatformSupported,
|
|
36000
|
+
isRedactedLineageNode,
|
|
34823
36001
|
mainnetServices,
|
|
34824
36002
|
moksha,
|
|
34825
36003
|
mokshaServices,
|
|
34826
36004
|
mokshaTestnet,
|
|
36005
|
+
normalizeBinaryMimeType,
|
|
36006
|
+
openWriteSession,
|
|
34827
36007
|
parsePSError,
|
|
34828
36008
|
parsePersonalServerPaymentRequired,
|
|
34829
36009
|
parseScope,
|
|
36010
|
+
parseScopeEntry,
|
|
34830
36011
|
parseWeb3SignedHeader,
|
|
36012
|
+
parseWriteMetadataHeader,
|
|
34831
36013
|
paymentReceiptFromHeader,
|
|
34832
36014
|
paymentResponseMetadataFromHeader,
|
|
36015
|
+
permissionsToScopes,
|
|
34833
36016
|
personalServerDataReadPath,
|
|
36017
|
+
personalServerLineagePath,
|
|
34834
36018
|
personalServerRegistrationDomain,
|
|
34835
36019
|
readPersonalServerData,
|
|
34836
36020
|
recoverServerOwner,
|
|
34837
36021
|
registerPersonalServerSignature,
|
|
36022
|
+
resolveWriteSigner,
|
|
34838
36023
|
scopeCoveredByGrant,
|
|
34839
36024
|
scopeMatchesPattern,
|
|
36025
|
+
scopeNamespace,
|
|
34840
36026
|
scopeToPathSegments,
|
|
34841
36027
|
serializeECIES,
|
|
34842
36028
|
serverRegistrationDomain,
|
|
36029
|
+
sessionCoversScope,
|
|
34843
36030
|
signPersonalServerLiteOwnerBinding,
|
|
34844
36031
|
signPersonalServerLiteOwnerBindingWithAccountClient,
|
|
34845
36032
|
signPersonalServerRegistrationWithAccount,
|
|
34846
36033
|
toDirectFeeBreakdown,
|
|
34847
36034
|
toDirectPaymentReceipt,
|
|
36035
|
+
tryGrantPermissions,
|
|
34848
36036
|
vanaMainnet,
|
|
34849
36037
|
verifyGrantRegistration,
|
|
34850
36038
|
verifyPkceChallenge,
|
|
34851
|
-
verifyWeb3Signed
|
|
36039
|
+
verifyWeb3Signed,
|
|
36040
|
+
writeData,
|
|
36041
|
+
writePersonalServerData
|
|
34852
36042
|
});
|
|
34853
36043
|
//# sourceMappingURL=index.node.cjs.map
|