@opendatalabs/vana-sdk 3.0.0 → 3.0.1

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.
@@ -35,6 +35,7 @@ export { MissingAuthError, InvalidSignatureError, ExpiredTokenError, } from "./a
35
35
  export { generatePkceVerifier, computePkceChallenge, verifyPkceChallenge, assertValidPkceVerifier, PKCE_VERIFIER_PATTERN, PKCE_CHALLENGE_PATTERN, } from "./auth/pkce";
36
36
  export { InMemoryTokenStore, type TokenStore, type TokenRecord, } from "./auth/token-store";
37
37
  export { fileRegistrationDomain, grantRegistrationDomain, grantRevocationDomain, serverRegistrationDomain, builderRegistrationDomain, FILE_REGISTRATION_TYPES, GRANT_REGISTRATION_TYPES, GRANT_REVOCATION_TYPES, SERVER_REGISTRATION_TYPES, BUILDER_REGISTRATION_TYPES, type DataPortabilityContracts, type DataPortabilityGatewayConfig, type FileRegistrationMessage, type GrantRegistrationMessage, type GrantRevocationMessage, type ServerRegistrationMessage, type BuilderRegistrationMessage, } from "./protocol/eip712";
38
+ export { isDataPortabilityGatewayConfig, parseGrantRegistrationPayload, verifyGrantRegistration, type DataPortabilityGrantPayload, type VerifyGrantRegistrationInput, type VerifyGrantRegistrationResult, } from "./protocol/grants";
38
39
  export { ScopeSchema, parseScope, scopeToPathSegments, scopeMatchesPattern, scopeCoveredByGrant, type Scope, type ParsedScope, } from "./protocol/scopes";
39
40
  export { DataFileEnvelopeSchema, createDataFileEnvelope, IngestResponseSchema, type DataFileEnvelope, type IngestResponse, } from "./protocol/data-file";
40
41
  export { createGatewayClient, type GatewayEnvelope, type GatewayProof, type Builder, type Schema, type ServerInfo, type GatewayGrantResponse, type GrantListItem, type FileRecord, type FileListResult, type RegisterServerParams, type RegisterServerResult, type RegisterFileParams, type CreateGrantParams, type RevokeGrantParams, type GatewayClient, } from "./protocol/gateway";
@@ -32078,6 +32078,30 @@ function base64urlDecode(input) {
32078
32078
  base64 += "=".repeat(padLength);
32079
32079
  return new TextDecoder().decode(fromBase64(base64));
32080
32080
  }
32081
+ function isFiniteNumber(value) {
32082
+ return typeof value === "number" && Number.isFinite(value);
32083
+ }
32084
+ function parsePayload(value) {
32085
+ if (value === null || typeof value !== "object" || Array.isArray(value)) {
32086
+ throw new InvalidSignatureError({ reason: "Invalid payload shape" });
32087
+ }
32088
+ const payload = value;
32089
+ if (typeof payload["aud"] !== "string" || typeof payload["method"] !== "string" || typeof payload["uri"] !== "string" || typeof payload["bodyHash"] !== "string" || !isFiniteNumber(payload["iat"]) || !isFiniteNumber(payload["exp"])) {
32090
+ throw new InvalidSignatureError({ reason: "Invalid payload claims" });
32091
+ }
32092
+ if (payload["grantId"] !== void 0 && typeof payload["grantId"] !== "string") {
32093
+ throw new InvalidSignatureError({ reason: "Invalid grantId claim" });
32094
+ }
32095
+ return {
32096
+ aud: payload["aud"],
32097
+ method: payload["method"],
32098
+ uri: payload["uri"],
32099
+ bodyHash: payload["bodyHash"],
32100
+ iat: payload["iat"],
32101
+ exp: payload["exp"],
32102
+ grantId: payload["grantId"]
32103
+ };
32104
+ }
32081
32105
  function parseWeb3SignedHeader(headerValue) {
32082
32106
  if (!headerValue) {
32083
32107
  throw new MissingAuthError();
@@ -32098,8 +32122,9 @@ function parseWeb3SignedHeader(headerValue) {
32098
32122
  let payload;
32099
32123
  try {
32100
32124
  const decoded = base64urlDecode(payloadBase64);
32101
- payload = JSON.parse(decoded);
32102
- } catch {
32125
+ payload = parsePayload(JSON.parse(decoded));
32126
+ } catch (err) {
32127
+ if (err instanceof InvalidSignatureError) throw err;
32103
32128
  throw new InvalidSignatureError({ reason: "Invalid payload encoding" });
32104
32129
  }
32105
32130
  return {
@@ -32142,7 +32167,7 @@ async function verifyWeb3Signed(params) {
32142
32167
  actual: payload.uri
32143
32168
  });
32144
32169
  }
32145
- if (params.bodyBytes !== void 0 && params.bodyBytes.length > 0) {
32170
+ if (params.bodyBytes !== void 0) {
32146
32171
  const expectedBodyHash = computeBodyHash(params.bodyBytes);
32147
32172
  if (payload.bodyHash !== expectedBodyHash) {
32148
32173
  throw new InvalidSignatureError({
@@ -32338,6 +32363,121 @@ var BUILDER_REGISTRATION_TYPES = {
32338
32363
  ]
32339
32364
  };
32340
32365
 
32366
+ // src/protocol/grants.ts
32367
+ import { verifyTypedData } from "viem";
32368
+ function isHexString(value) {
32369
+ return typeof value === "string" && value.startsWith("0x");
32370
+ }
32371
+ function isDataPortabilityGatewayConfig(value) {
32372
+ if (value === null || typeof value !== "object" || Array.isArray(value)) {
32373
+ return false;
32374
+ }
32375
+ const config = value;
32376
+ const contracts = config["contracts"];
32377
+ if (typeof config["chainId"] !== "number" || !Number.isInteger(config["chainId"]) || config["chainId"] <= 0 || contracts === null || typeof contracts !== "object" || Array.isArray(contracts)) {
32378
+ return false;
32379
+ }
32380
+ const c = contracts;
32381
+ return isHexString(c["dataRegistry"]) && isHexString(c["dataPortabilityPermissions"]) && isHexString(c["dataPortabilityServer"]) && isHexString(c["dataPortabilityGrantees"]);
32382
+ }
32383
+ function parseGrantRegistrationPayload(grant) {
32384
+ let parsed;
32385
+ try {
32386
+ parsed = JSON.parse(grant);
32387
+ } catch {
32388
+ return null;
32389
+ }
32390
+ if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
32391
+ return null;
32392
+ }
32393
+ const value = parsed;
32394
+ if (!Array.isArray(value["scopes"]) || value["scopes"].length === 0) {
32395
+ return null;
32396
+ }
32397
+ if (!value["scopes"].every((scope) => typeof scope === "string")) {
32398
+ return null;
32399
+ }
32400
+ if (typeof value["expiresAt"] !== "number" || !Number.isFinite(value["expiresAt"])) {
32401
+ return null;
32402
+ }
32403
+ if (value["user"] !== void 0 && !isHexString(value["user"])) {
32404
+ return null;
32405
+ }
32406
+ if (value["builder"] !== void 0 && !isHexString(value["builder"])) {
32407
+ return null;
32408
+ }
32409
+ if (value["nonce"] !== void 0 && (typeof value["nonce"] !== "number" || !Number.isFinite(value["nonce"]))) {
32410
+ return null;
32411
+ }
32412
+ return {
32413
+ user: value["user"],
32414
+ builder: value["builder"],
32415
+ scopes: value["scopes"],
32416
+ expiresAt: value["expiresAt"],
32417
+ nonce: value["nonce"]
32418
+ };
32419
+ }
32420
+ function parseFileIds(fileIds) {
32421
+ try {
32422
+ const values = (fileIds ?? []).map((fileId) => BigInt(fileId));
32423
+ return {
32424
+ values,
32425
+ display: values.map((fileId) => fileId.toString())
32426
+ };
32427
+ } catch {
32428
+ return null;
32429
+ }
32430
+ }
32431
+ async function verifyGrantRegistration(input) {
32432
+ const payload = parseGrantRegistrationPayload(input.grant);
32433
+ if (!payload) {
32434
+ return {
32435
+ valid: false,
32436
+ error: "Grant must be JSON with scopes and expiresAt"
32437
+ };
32438
+ }
32439
+ const fileIds = parseFileIds(input.fileIds);
32440
+ if (!fileIds) {
32441
+ return { valid: false, error: "fileIds must contain integer values" };
32442
+ }
32443
+ let valid;
32444
+ try {
32445
+ valid = await verifyTypedData({
32446
+ address: input.grantorAddress,
32447
+ domain: grantRegistrationDomain(input.gatewayConfig),
32448
+ types: GRANT_REGISTRATION_TYPES,
32449
+ primaryType: "GrantRegistration",
32450
+ message: {
32451
+ grantorAddress: input.grantorAddress,
32452
+ granteeId: input.granteeId,
32453
+ grant: input.grant,
32454
+ fileIds: fileIds.values
32455
+ },
32456
+ signature: input.signature
32457
+ });
32458
+ } catch {
32459
+ return { valid: false, error: "EIP-712 signature verification failed" };
32460
+ }
32461
+ if (!valid) {
32462
+ return { valid: false, error: "Grant signature does not match grantor" };
32463
+ }
32464
+ const nowSeconds = input.nowSeconds ?? Math.floor(Date.now() / 1e3);
32465
+ if (payload.expiresAt > 0 && payload.expiresAt < nowSeconds) {
32466
+ return { valid: false, error: "Grant has expired" };
32467
+ }
32468
+ if (payload.user !== void 0 && payload.user.toLowerCase() !== input.grantorAddress.toLowerCase()) {
32469
+ return { valid: false, error: "Grant user does not match grantorAddress" };
32470
+ }
32471
+ return {
32472
+ valid: true,
32473
+ grantorAddress: input.grantorAddress,
32474
+ granteeId: input.granteeId,
32475
+ grant: input.grant,
32476
+ payload,
32477
+ fileIds: fileIds.display
32478
+ };
32479
+ }
32480
+
32341
32481
  // src/protocol/scopes.ts
32342
32482
  import { z } from "zod";
32343
32483
  var SEGMENT_RE = /^[a-z0-9][a-z0-9_]*$/;
@@ -32618,32 +32758,57 @@ var PSError = class extends Error {
32618
32758
  code;
32619
32759
  };
32620
32760
  var KNOWN_CODES = /* @__PURE__ */ new Set([
32761
+ "missing_auth",
32762
+ "invalid_signature",
32763
+ "unregistered_builder",
32764
+ "not_owner",
32765
+ "expired_token",
32621
32766
  "grant_invalid",
32767
+ "grant_required",
32768
+ "grant_expired",
32622
32769
  "grant_revoked",
32770
+ "scope_mismatch",
32623
32771
  "fee_required",
32624
- "ps_unavailable"
32772
+ "ps_unavailable",
32773
+ "server_not_configured",
32774
+ "content_too_large"
32625
32775
  ]);
32626
- async function parsePSError(response) {
32627
- if (response.ok) {
32776
+ function isRecord(value) {
32777
+ return value !== null && typeof value === "object" && !Array.isArray(value);
32778
+ }
32779
+ function normalizeCode(value) {
32780
+ if (typeof value !== "string") {
32628
32781
  return null;
32629
32782
  }
32630
- let body;
32631
- try {
32632
- body = await response.json();
32633
- } catch {
32783
+ const code = value.toLowerCase();
32784
+ return KNOWN_CODES.has(code) ? code : null;
32785
+ }
32786
+ function extractPSErrorBody(body) {
32787
+ if (!isRecord(body)) {
32634
32788
  return null;
32635
32789
  }
32636
- if (typeof body !== "object" || body === null) {
32790
+ const nested = isRecord(body.error) ? body.error : null;
32791
+ const code = normalizeCode(
32792
+ nested?.errorCode ?? nested?.code ?? body.errorCode ?? body.code
32793
+ );
32794
+ const message = nested?.message ?? body.message;
32795
+ if (!code || typeof message !== "string") {
32637
32796
  return null;
32638
32797
  }
32639
- const { code, message } = body;
32640
- if (typeof code !== "string" || typeof message !== "string") {
32798
+ return { code, message };
32799
+ }
32800
+ async function parsePSError(response) {
32801
+ if (response.ok) {
32641
32802
  return null;
32642
32803
  }
32643
- if (!KNOWN_CODES.has(code)) {
32804
+ let body;
32805
+ try {
32806
+ body = await response.json();
32807
+ } catch {
32644
32808
  return null;
32645
32809
  }
32646
- return new PSError(code, message);
32810
+ const errorBody = extractPSErrorBody(body);
32811
+ return errorBody ? new PSError(errorBody.code, errorBody.message) : null;
32647
32812
  }
32648
32813
  export {
32649
32814
  BUILDER_REGISTRATION_TYPES,
@@ -32726,12 +32891,14 @@ export {
32726
32891
  getServiceEndpoints,
32727
32892
  grantRegistrationDomain,
32728
32893
  grantRevocationDomain,
32894
+ isDataPortabilityGatewayConfig,
32729
32895
  isECIESEncrypted,
32730
32896
  isPlatformSupported,
32731
32897
  mainnetServices,
32732
32898
  moksha,
32733
32899
  mokshaServices,
32734
32900
  mokshaTestnet2 as mokshaTestnet,
32901
+ parseGrantRegistrationPayload,
32735
32902
  parsePSError,
32736
32903
  parseScope,
32737
32904
  parseWeb3SignedHeader,
@@ -32742,6 +32909,7 @@ export {
32742
32909
  serializeECIES,
32743
32910
  serverRegistrationDomain,
32744
32911
  vanaMainnet2 as vanaMainnet,
32912
+ verifyGrantRegistration,
32745
32913
  verifyPkceChallenge,
32746
32914
  verifyWeb3Signed
32747
32915
  };