UNPKG

@opendatalabs/vana-sdk

Version:

A TypeScript library for interacting with Vana Network smart contracts.

150 lines 5.65 kB
"use strict"; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); var web3_signed_exports = {}; __export(web3_signed_exports, { parseWeb3SignedHeader: () => parseWeb3SignedHeader, verifyWeb3Signed: () => verifyWeb3Signed }); module.exports = __toCommonJS(web3_signed_exports); var import_viem = require("viem"); var import_encoding = require("../utils/encoding"); var import_errors = require("./errors"); var import_web3_signed_builder = require("./web3-signed-builder"); const WEB3_SIGNED_PREFIX = "Web3Signed "; const CLOCK_SKEW_SECONDS = 60; function base64urlDecode(input) { let base64 = input.replace(/-/g, "+").replace(/_/g, "/"); const padLength = (4 - base64.length % 4) % 4; base64 += "=".repeat(padLength); return new TextDecoder().decode((0, import_encoding.fromBase64)(base64)); } function isFiniteNumber(value) { return typeof value === "number" && Number.isFinite(value); } function parsePayload(value) { if (value === null || typeof value !== "object" || Array.isArray(value)) { throw new import_errors.InvalidSignatureError({ reason: "Invalid payload shape" }); } const payload = value; if (typeof payload["aud"] !== "string" || typeof payload["method"] !== "string" || typeof payload["uri"] !== "string" || typeof payload["bodyHash"] !== "string" || !isFiniteNumber(payload["iat"]) || !isFiniteNumber(payload["exp"])) { throw new import_errors.InvalidSignatureError({ reason: "Invalid payload claims" }); } if (payload["grantId"] !== void 0 && typeof payload["grantId"] !== "string") { throw new import_errors.InvalidSignatureError({ reason: "Invalid grantId claim" }); } return { aud: payload["aud"], method: payload["method"], uri: payload["uri"], bodyHash: payload["bodyHash"], iat: payload["iat"], exp: payload["exp"], grantId: payload["grantId"] }; } function parseWeb3SignedHeader(headerValue) { if (!headerValue) { throw new import_errors.MissingAuthError(); } if (!headerValue.startsWith(WEB3_SIGNED_PREFIX)) { throw new import_errors.InvalidSignatureError({ reason: "Missing Web3Signed prefix" }); } const value = headerValue.slice(WEB3_SIGNED_PREFIX.length); const dotIndex = value.indexOf("."); if (dotIndex === -1 || dotIndex === 0 || dotIndex === value.length - 1) { throw new import_errors.InvalidSignatureError({ reason: "Invalid header format" }); } const payloadBase64 = value.slice(0, dotIndex); const signatureStr = value.slice(dotIndex + 1); if (!signatureStr.startsWith("0x")) { throw new import_errors.InvalidSignatureError({ reason: "Invalid signature format" }); } let payload; try { const decoded = base64urlDecode(payloadBase64); payload = parsePayload(JSON.parse(decoded)); } catch (err) { if (err instanceof import_errors.InvalidSignatureError) throw err; throw new import_errors.InvalidSignatureError({ reason: "Invalid payload encoding" }); } return { payloadBase64, payload, signature: signatureStr }; } async function verifyWeb3Signed(params) { const { payloadBase64, payload, signature } = parseWeb3SignedHeader( params.headerValue ); let signer; try { signer = await (0, import_viem.recoverMessageAddress)({ message: payloadBase64, signature }); } catch { throw new import_errors.InvalidSignatureError({ reason: "Signature recovery failed" }); } if (payload.aud !== params.expectedOrigin) { throw new import_errors.InvalidSignatureError({ reason: "Audience mismatch", expected: params.expectedOrigin, actual: payload.aud }); } if (payload.method !== params.expectedMethod) { throw new import_errors.InvalidSignatureError({ reason: "Method mismatch", expected: params.expectedMethod, actual: payload.method }); } if (payload.uri !== params.expectedPath) { throw new import_errors.InvalidSignatureError({ reason: "URI mismatch", expected: params.expectedPath, actual: payload.uri }); } if (params.bodyBytes !== void 0) { const expectedBodyHash = (0, import_web3_signed_builder.computeBodyHash)(params.bodyBytes); if (payload.bodyHash !== expectedBodyHash) { throw new import_errors.InvalidSignatureError({ reason: "Body hash mismatch", expected: expectedBodyHash, actual: payload.bodyHash }); } } const now = params.now ?? Math.floor(Date.now() / 1e3); if (payload.exp < now - CLOCK_SKEW_SECONDS) { throw new import_errors.ExpiredTokenError({ reason: "Token expired" }); } if (payload.iat > now + CLOCK_SKEW_SECONDS) { throw new import_errors.ExpiredTokenError({ reason: "Token issued in the future" }); } return { signer, payload }; } // Annotate the CommonJS export names for ESM import in node: 0 && (module.exports = { parseWeb3SignedHeader, verifyWeb3Signed }); //# sourceMappingURL=web3-signed.cjs.map