UNPKG

@opendatalabs/vana-sdk

Version:

A TypeScript library for interacting with Vana Network smart contracts.

123 lines 3.82 kB
import { verifyTypedData } from "viem"; import { GRANT_REGISTRATION_TYPES, grantRegistrationDomain } from "./eip712.js"; function isHexString(value) { return typeof value === "string" && value.startsWith("0x"); } function isDataPortabilityGatewayConfig(value) { if (value === null || typeof value !== "object" || Array.isArray(value)) { return false; } const config = value; const contracts = config["contracts"]; if (typeof config["chainId"] !== "number" || !Number.isInteger(config["chainId"]) || config["chainId"] <= 0 || contracts === null || typeof contracts !== "object" || Array.isArray(contracts)) { return false; } const c = contracts; return isHexString(c["dataRegistry"]) && isHexString(c["dataPortabilityPermissions"]) && isHexString(c["dataPortabilityServer"]) && isHexString(c["dataPortabilityGrantees"]); } function parseGrantRegistrationPayload(grant) { let parsed; try { parsed = JSON.parse(grant); } catch { return null; } if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) { return null; } const value = parsed; if (!Array.isArray(value["scopes"]) || value["scopes"].length === 0) { return null; } if (!value["scopes"].every((scope) => typeof scope === "string")) { return null; } if (typeof value["expiresAt"] !== "number" || !Number.isFinite(value["expiresAt"])) { return null; } if (value["user"] !== void 0 && !isHexString(value["user"])) { return null; } if (value["builder"] !== void 0 && !isHexString(value["builder"])) { return null; } if (value["nonce"] !== void 0 && (typeof value["nonce"] !== "number" || !Number.isFinite(value["nonce"]))) { return null; } return { user: value["user"], builder: value["builder"], scopes: value["scopes"], expiresAt: value["expiresAt"], nonce: value["nonce"] }; } function parseFileIds(fileIds) { try { const values = (fileIds ?? []).map((fileId) => BigInt(fileId)); return { values, display: values.map((fileId) => fileId.toString()) }; } catch { return null; } } async function verifyGrantRegistration(input) { const payload = parseGrantRegistrationPayload(input.grant); if (!payload) { return { valid: false, error: "Grant must be JSON with scopes and expiresAt" }; } const fileIds = parseFileIds(input.fileIds); if (!fileIds) { return { valid: false, error: "fileIds must contain integer values" }; } let valid; try { valid = await verifyTypedData({ address: input.grantorAddress, domain: grantRegistrationDomain(input.gatewayConfig), types: GRANT_REGISTRATION_TYPES, primaryType: "GrantRegistration", message: { grantorAddress: input.grantorAddress, granteeId: input.granteeId, grant: input.grant, fileIds: fileIds.values }, signature: input.signature }); } catch { return { valid: false, error: "EIP-712 signature verification failed" }; } if (!valid) { return { valid: false, error: "Grant signature does not match grantor" }; } const nowSeconds = input.nowSeconds ?? Math.floor(Date.now() / 1e3); if (payload.expiresAt > 0 && payload.expiresAt < nowSeconds) { return { valid: false, error: "Grant has expired" }; } if (payload.user !== void 0 && payload.user.toLowerCase() !== input.grantorAddress.toLowerCase()) { return { valid: false, error: "Grant user does not match grantorAddress" }; } return { valid: true, grantorAddress: input.grantorAddress, granteeId: input.granteeId, grant: input.grant, payload, fileIds: fileIds.display }; } export { isDataPortabilityGatewayConfig, parseGrantRegistrationPayload, verifyGrantRegistration }; //# sourceMappingURL=grants.js.map