@opendatalabs/vana-sdk
Version:
A TypeScript library for interacting with Vana Network smart contracts.
150 lines • 5.65 kB
JavaScript
;
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