@opendatalabs/vana-sdk
Version:
A TypeScript library for interacting with Vana Network smart contracts.
1,997 lines (1,980 loc) • 854 kB
JavaScript
var __defProp = Object.defineProperty;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __esm = (fn, res) => function __init() {
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
};
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
// src/utils/ipfs.ts
var ipfs_exports = {};
__export(ipfs_exports, {
DEFAULT_IPFS_GATEWAY: () => DEFAULT_IPFS_GATEWAY,
IPFS_GATEWAYS: () => IPFS_GATEWAYS,
convertIpfsUrl: () => convertIpfsUrl,
convertIpfsUrlWithFallbacks: () => convertIpfsUrlWithFallbacks,
extractIpfsHash: () => extractIpfsHash,
fetchWithFallbacks: () => fetchWithFallbacks,
getGatewayUrls: () => getGatewayUrls,
isIpfsUrl: () => isIpfsUrl
});
function isIpfsUrl(url) {
return url.startsWith("ipfs://");
}
function convertIpfsUrl(url, gateway = DEFAULT_IPFS_GATEWAY) {
if (isIpfsUrl(url)) {
const hash = url.replace("ipfs://", "");
return `${gateway}${hash}`;
}
return url;
}
function extractIpfsHash(url) {
const patterns = [
/ipfs\/([a-zA-Z0-9]+)/,
// https://gateway.pinata.cloud/ipfs/HASH
/^ipfs:\/\/([a-zA-Z0-9]+)$/,
// ipfs://HASH
/^([a-zA-Z0-9]{46,})$/
// Just the hash (46+ chars for IPFS hashes)
];
for (const pattern of patterns) {
const match = url.match(pattern);
if (match) {
return match[1];
}
}
return null;
}
function getGatewayUrls(hash) {
return IPFS_GATEWAYS.map((gateway) => `${gateway}${hash}`);
}
function convertIpfsUrlWithFallbacks(url) {
const hash = extractIpfsHash(url);
if (hash) {
return getGatewayUrls(hash);
}
return [url];
}
async function fetchWithFallbacks(url, options) {
const hash = extractIpfsHash(url);
if (!hash) {
return fetch(url, options);
}
const gatewayUrls = getGatewayUrls(hash);
let lastError = null;
for (let i = 0; i < gatewayUrls.length; i++) {
const gatewayUrl = gatewayUrls[i];
try {
const response = await fetch(gatewayUrl, {
...options,
// Add timeout to avoid hanging on slow gateways
signal: AbortSignal.timeout(1e4)
// 10 second timeout
});
if (response.ok) {
return response;
}
if (response.status === 429) {
lastError = new Error(`Gateway rate limited: ${gatewayUrl}`);
continue;
}
lastError = new Error(`Gateway error ${response.status}: ${gatewayUrl}`);
} catch (error) {
lastError = error instanceof Error ? error : new Error(String(error));
if (lastError.message.includes("429") || lastError.name === "TimeoutError") {
continue;
}
}
if (i < gatewayUrls.length - 1) {
await new Promise((resolve) => setTimeout(resolve, 1e3 * (i + 1)));
}
}
throw new Error(
`All IPFS gateways failed for hash ${hash}. Last error: ${lastError?.message}`
);
}
var DEFAULT_IPFS_GATEWAY, IPFS_GATEWAYS;
var init_ipfs = __esm({
"src/utils/ipfs.ts"() {
"use strict";
DEFAULT_IPFS_GATEWAY = "https://dweb.link/ipfs/";
IPFS_GATEWAYS = [
"https://dweb.link/ipfs/",
// Interplanetary Shipyard - highly reliable
"https://ipfs.io/ipfs/",
// IPFS Foundation - reliable
"https://cloudflare-ipfs.com/ipfs/",
// Cloudflare - good performance
"https://gateway.pinata.cloud/ipfs/",
// Pinata - backup option (has rate limits)
"https://ipfs.filebase.io/ipfs/"
// Filebase - emerging reliable option
];
}
});
// src/platform/browser.ts
import * as openpgp from "openpgp";
// src/platform/shared/crypto-utils.ts
function processWalletPublicKey(publicKey) {
const publicKeyHex = publicKey.startsWith("0x") ? publicKey.slice(2) : publicKey;
const publicKeyBytes = Buffer.from(publicKeyHex, "hex");
return publicKeyBytes.length === 64 ? Buffer.concat([Buffer.from([4]), publicKeyBytes]) : publicKeyBytes;
}
function processWalletPrivateKey(privateKey) {
const privateKeyHex = privateKey.startsWith("0x") ? privateKey.slice(2) : privateKey;
return Buffer.from(privateKeyHex, "hex");
}
function parseEncryptedDataBuffer(encryptedBuffer) {
return {
iv: encryptedBuffer.slice(0, 16),
ephemPublicKey: encryptedBuffer.slice(16, 81),
// 65 bytes for uncompressed public key
ciphertext: encryptedBuffer.slice(81, -32),
mac: encryptedBuffer.slice(-32)
};
}
function uint8ArrayToHex(array) {
return Array.from(array, (byte) => byte.toString(16).padStart(2, "0")).join(
""
);
}
// src/platform/shared/pgp-utils.ts
var STANDARD_PGP_CONFIG = {
preferredCompressionAlgorithm: 2,
// zlib (openpgp.enums.compression.zlib)
preferredSymmetricAlgorithm: 7
// aes256 (openpgp.enums.symmetric.aes256)
};
function processPGPKeyOptions(options) {
return {
name: options?.name || "Vana User",
email: options?.email || "user@vana.org",
passphrase: options?.passphrase
};
}
function getPGPKeyGenParams(options) {
const { name, email, passphrase } = processPGPKeyOptions(options);
return {
type: "rsa",
rsaBits: 2048,
userIDs: [{ name, email }],
passphrase,
config: STANDARD_PGP_CONFIG
};
}
// src/platform/shared/error-utils.ts
function wrapCryptoError(operation, error) {
const message = error instanceof Error ? error.message : "Unknown error";
return new Error(`${operation} failed: ${message}`);
}
// src/platform/browser.ts
var BrowserECDH = class {
async generateKeyPair() {
const keyPair = await crypto.subtle.generateKey(
{
name: "ECDH",
namedCurve: "P-256"
},
true,
["deriveKey", "deriveBits"]
);
return keyPair;
}
async encrypt(publicKeyHex, message) {
const ephemeralKeyPair = await this.generateKeyPair();
const publicKeyData = hexToUint8Array(publicKeyHex);
const importedPublicKey = await crypto.subtle.importKey(
"raw",
publicKeyData,
{ name: "ECDH", namedCurve: "P-256" },
false,
[]
);
const sharedKey = await crypto.subtle.deriveKey(
{ name: "ECDH", public: importedPublicKey },
ephemeralKeyPair.privateKey,
{ name: "AES-GCM", length: 256 },
false,
["encrypt"]
);
const iv = crypto.getRandomValues(new Uint8Array(12));
const encoder = new TextEncoder();
const data = encoder.encode(message);
const encrypted = await crypto.subtle.encrypt(
{ name: "AES-GCM", iv },
sharedKey,
data
);
const ephemeralPublicKeyData = await crypto.subtle.exportKey(
"raw",
ephemeralKeyPair.publicKey
);
return JSON.stringify({
encrypted: Array.from(new Uint8Array(encrypted)),
iv: Array.from(iv),
ephemeralPublicKey: Array.from(new Uint8Array(ephemeralPublicKeyData)),
publicKey: publicKeyHex
});
}
async decrypt(privateKeyHex, encryptedData) {
try {
const data = JSON.parse(encryptedData);
if (!data.encrypted || !data.iv || !data.ephemeralPublicKey) {
throw new Error("Invalid encrypted data format");
}
const privateKeyData = hexToUint8Array(privateKeyHex);
const importedPrivateKey = await crypto.subtle.importKey(
"pkcs8",
privateKeyData,
{ name: "ECDH", namedCurve: "P-256" },
false,
["deriveKey"]
);
const ephemeralPublicKey = await crypto.subtle.importKey(
"raw",
new Uint8Array(data.ephemeralPublicKey),
{ name: "ECDH", namedCurve: "P-256" },
false,
[]
);
const sharedKey = await crypto.subtle.deriveKey(
{ name: "ECDH", public: ephemeralPublicKey },
importedPrivateKey,
{ name: "AES-GCM", length: 256 },
false,
["decrypt"]
);
const decrypted = await crypto.subtle.decrypt(
{ name: "AES-GCM", iv: new Uint8Array(data.iv) },
sharedKey,
new Uint8Array(data.encrypted)
);
return new TextDecoder().decode(decrypted);
} catch (error) {
throw new Error(
`Decryption failed: ${error instanceof Error ? error.message : "Unknown error"}`
);
}
}
};
function hexToUint8Array(hex) {
const result = new Uint8Array(hex.length / 2);
for (let i = 0; i < hex.length; i += 2) {
result[i / 2] = parseInt(hex.substr(i, 2), 16);
}
return result;
}
var BrowserCryptoAdapter = class {
async encryptWithPublicKey(data, publicKeyHex) {
try {
const ecdh = new BrowserECDH();
return await ecdh.encrypt(publicKeyHex, data);
} catch (error) {
throw new Error(`Encryption failed: ${error}`);
}
}
async decryptWithPrivateKey(encryptedData, privateKeyHex) {
try {
const ecdh = new BrowserECDH();
return await ecdh.decrypt(privateKeyHex, encryptedData);
} catch (error) {
throw new Error(`Decryption failed: ${error}`);
}
}
async generateKeyPair() {
try {
const keyPair = await crypto.subtle.generateKey(
{
name: "ECDH",
namedCurve: "P-256"
},
true,
["deriveKey", "deriveBits"]
);
const publicKeyBuffer = await crypto.subtle.exportKey(
"raw",
keyPair.publicKey
);
const privateKeyBuffer = await crypto.subtle.exportKey(
"pkcs8",
keyPair.privateKey
);
return {
publicKey: uint8ArrayToHex(new Uint8Array(publicKeyBuffer)),
privateKey: uint8ArrayToHex(new Uint8Array(privateKeyBuffer))
};
} catch (error) {
throw wrapCryptoError("key generation", error);
}
}
async encryptWithWalletPublicKey(data, publicKey) {
try {
const eccrypto = await import("eccrypto-js");
const uncompressedKey = processWalletPublicKey(publicKey);
const iv = Buffer.from([
1,
2,
3,
4,
5,
6,
7,
8,
9,
10,
11,
12,
13,
14,
15,
16
]);
const ephemeralKey = Buffer.from([
17,
34,
51,
68,
85,
102,
119,
136,
153,
170,
187,
204,
221,
238,
255,
0,
16,
32,
48,
64,
80,
96,
112,
128,
144,
160,
176,
192,
208,
224,
240,
0
]);
const encryptedBuffer = await eccrypto.encrypt(
uncompressedKey,
Buffer.from(data),
{
iv,
ephemPrivateKey: ephemeralKey
}
);
const result = Buffer.concat([
encryptedBuffer.iv,
encryptedBuffer.ephemPublicKey,
encryptedBuffer.ciphertext,
encryptedBuffer.mac
]);
return result.toString("hex");
} catch (error) {
throw wrapCryptoError("encrypt with wallet public key", error);
}
}
async decryptWithWalletPrivateKey(encryptedData, privateKey) {
try {
const eccrypto = await import("eccrypto-js");
const privateKeyBuffer = processWalletPrivateKey(privateKey);
const encryptedBuffer = Buffer.from(encryptedData, "hex");
const { iv, ephemPublicKey, ciphertext, mac } = parseEncryptedDataBuffer(encryptedBuffer);
const encryptedObj = { iv, ephemPublicKey, ciphertext, mac };
const decryptedBuffer = await eccrypto.decrypt(
privateKeyBuffer,
encryptedObj
);
return decryptedBuffer.toString("utf8");
} catch (error) {
throw wrapCryptoError("decrypt with wallet private key", error);
}
}
async encryptWithPassword(data, password) {
try {
const openpgp2 = await import("openpgp");
const message = await openpgp2.createMessage({
binary: data
});
const encrypted = await openpgp2.encrypt({
message,
passwords: [password],
format: "binary"
});
const response = new Response(encrypted);
const arrayBuffer = await response.arrayBuffer();
return new Uint8Array(arrayBuffer);
} catch (error) {
throw new Error(`Failed to encrypt with password: ${error}`);
}
}
async decryptWithPassword(encryptedData, password) {
try {
const openpgp2 = await import("openpgp");
const message = await openpgp2.readMessage({
binaryMessage: encryptedData
});
const { data: decrypted } = await openpgp2.decrypt({
message,
passwords: [password],
format: "binary"
});
return new Uint8Array(decrypted);
} catch (error) {
throw new Error(`Failed to decrypt with password: ${error}`);
}
}
};
var BrowserPGPAdapter = class {
async encrypt(data, publicKeyArmored) {
try {
const publicKey = await openpgp.readKey({ armoredKey: publicKeyArmored });
const encrypted = await openpgp.encrypt({
message: await openpgp.createMessage({ text: data }),
encryptionKeys: publicKey,
config: {
preferredCompressionAlgorithm: openpgp.enums.compression.zlib
}
});
return encrypted;
} catch (error) {
throw new Error(`PGP encryption failed: ${error}`);
}
}
async decrypt(encryptedData, privateKeyArmored) {
try {
const privateKey = await openpgp.readPrivateKey({
armoredKey: privateKeyArmored
});
const message = await openpgp.readMessage({
armoredMessage: encryptedData
});
const { data: decrypted } = await openpgp.decrypt({
message,
decryptionKeys: privateKey
});
return decrypted;
} catch (error) {
throw new Error(`PGP decryption failed: ${error}`);
}
}
async generateKeyPair(options) {
try {
const keyGenParams = getPGPKeyGenParams(options);
const { privateKey, publicKey } = await openpgp.generateKey(keyGenParams);
return { publicKey, privateKey };
} catch (error) {
throw wrapCryptoError("PGP key generation", error);
}
}
};
var BrowserHttpAdapter = class {
async fetch(url, options) {
if (typeof fetch === "undefined") {
throw new Error("Fetch API not available in this browser environment");
}
return fetch(url, options);
}
};
var BrowserPlatformAdapter = class {
constructor() {
__publicField(this, "crypto");
__publicField(this, "pgp");
__publicField(this, "http");
__publicField(this, "platform", "browser");
this.crypto = new BrowserCryptoAdapter();
this.pgp = new BrowserPGPAdapter();
this.http = new BrowserHttpAdapter();
}
};
var browserPlatformAdapter = new BrowserPlatformAdapter();
// src/types/config.ts
function isWalletConfig(config) {
return "walletClient" in config;
}
function isChainConfig(config) {
return "chainId" in config && !("walletClient" in config);
}
// src/types/chains.ts
function isVanaChainId(chainId) {
return chainId === 14800 || chainId === 1480;
}
// src/types/storage.ts
var StorageError = class extends Error {
// The 'cause' property is now inherited from the base Error class
constructor(message, code, provider, options) {
super(message, options);
__publicField(this, "code");
__publicField(this, "provider");
this.name = "StorageError";
this.code = code;
this.provider = provider;
}
};
// src/utils/schemaValidation.ts
import Ajv from "ajv";
import addFormats from "ajv-formats";
// src/schemas/dataContract.schema.json
var dataContract_schema_default = {
$id: "https://vana.org/data-schema.json",
$schema: "http://json-schema.org/draft-07/schema#",
title: "Schema",
description: "Meta\u2011schema that validates a schema object containing a dataset schema and related metadata.",
type: "object",
required: ["name", "version", "dialect", "schema"],
properties: {
name: {
type: "string",
description: "Human\u2011readable name of the contract."
},
version: {
type: "string",
description: "Semantic version of the contract's business logic (e.g. 1.1.0)."
},
description: {
type: "string",
description: "Long\u2011form description of the dataset or API."
},
dialect: {
type: "string",
description: "Primary language/format of the data schema.",
enum: ["sqlite", "json"]
},
dialectVersion: {
type: "string",
description: "Optional: The version of the dialect's engine or specification the schema targets (e.g., '3' for SQLite v3). Omit for self-describing dialects like json."
},
schema: {
description: "The actual schema definition. For 'sqlite', supply a DDL string; for 'json', embed a JSON Schema object."
}
},
additionalProperties: false,
allOf: [
{
if: {
properties: { dialect: { const: "sqlite" } }
},
then: {
properties: { schema: { type: "string" } }
}
},
{
if: {
properties: { dialect: { const: "json" } }
},
then: {
properties: { schema: { type: "object" } }
}
}
]
};
// src/utils/schemaValidation.ts
var SchemaValidationError = class extends Error {
constructor(message, errors) {
super(message);
this.errors = errors;
this.name = "SchemaValidationError";
}
};
var SchemaValidator = class {
constructor() {
__publicField(this, "ajv");
__publicField(this, "dataSchemaValidator");
this.ajv = new Ajv({
allErrors: true,
verbose: true,
strict: false
});
addFormats(this.ajv);
this.dataSchemaValidator = this.ajv.compile(dataContract_schema_default);
}
/**
* Validates a data schema against the Vana meta-schema
*
* @param schema - The data schema to validate
* @throws SchemaValidationError if invalid
* @example
* ```typescript
* const validator = new SchemaValidator();
*
* const schema = {
* name: "User Profile",
* version: "1.0.0",
* dialect: "json",
* schema: {
* type: "object",
* properties: {
* name: { type: "string" },
* age: { type: "number" }
* }
* }
* };
*
* validator.validateDataSchema(schema); // throws if invalid
* ```
*/
validateDataSchema(schema) {
const isValid = this.dataSchemaValidator(schema);
if (!isValid) {
const errors = this.dataSchemaValidator.errors || [];
const errorMessage = `Data schema validation failed: ${errors.map((e) => `${e.instancePath} ${e.message}`).join(", ")}`;
throw new SchemaValidationError(errorMessage, errors);
}
const typedSchema = schema;
if (typedSchema.dialect === "json" && typeof typedSchema.schema === "object") {
try {
this.ajv.compile(typedSchema.schema);
} catch (error) {
const errorMessage = `Invalid JSON Schema in data schema: ${error instanceof Error ? error.message : "Unknown schema compilation error"}`;
throw new SchemaValidationError(errorMessage, []);
}
} else if (typedSchema.dialect === "sqlite" && typeof typedSchema.schema === "string") {
this.validateSQLiteDDL(typedSchema.schema, typedSchema.dialectVersion);
}
}
/**
* Validates data against a JSON Schema from a data schema
*
* @param data - The data to validate
* @param schema - The data schema containing the schema
* @throws SchemaValidationError if invalid
* @example
* ```typescript
* const validator = new SchemaValidator();
*
* const schema = {
* name: "User Profile",
* version: "1.0.0",
* dialect: "json",
* schema: {
* type: "object",
* properties: {
* name: { type: "string" },
* age: { type: "number" }
* },
* required: ["name"]
* }
* };
*
* const userData = { name: "Alice", age: 30 };
* validator.validateDataAgainstSchema(userData, schema);
* ```
*/
validateDataAgainstSchema(data, schema) {
this.validateDataSchema(schema);
if (schema.dialect !== "json") {
throw new SchemaValidationError(
`Data validation only supported for JSON dialect, got: ${schema.dialect}`,
[]
);
}
if (typeof schema.schema !== "object") {
throw new SchemaValidationError(
"JSON dialect schemas must have an object schema",
[]
);
}
const dataValidator = this.ajv.compile(schema.schema);
const isValid = dataValidator(data);
if (!isValid) {
const errors = dataValidator.errors || [];
const errorMessage = `Data validation failed: ${errors.map((e) => `${e.instancePath} ${e.message}`).join(", ")}`;
throw new SchemaValidationError(errorMessage, errors);
}
}
/**
* Validates a SQLite DDL string for basic syntax
* Note: This is a basic validation, full SQL parsing would require a proper SQL parser
*
* @param ddl - The DDL string to validate
* @param dialectVersion - Optional SQLite version (e.g., "3" for SQLite v3)
* @throws SchemaValidationError if invalid
*/
validateSQLiteDDL(ddl, dialectVersion) {
if (typeof ddl !== "string" || ddl.trim().length === 0) {
throw new SchemaValidationError(
"SQLite DDL must be a non-empty string",
[]
);
}
if (dialectVersion !== void 0) {
const supportedVersions = ["3"];
if (!supportedVersions.includes(dialectVersion)) {
throw new SchemaValidationError(
`Unsupported SQLite dialect version: ${dialectVersion}. Supported versions: ${supportedVersions.join(", ")}`,
[]
);
}
}
const normalizedDDL = ddl.trim().toUpperCase();
if (!normalizedDDL.includes("CREATE TABLE")) {
throw new SchemaValidationError(
"SQLite DDL must contain at least one CREATE TABLE statement",
[]
);
}
let parenCount = 0;
for (const char of ddl) {
if (char === "(") parenCount++;
if (char === ")") parenCount--;
if (parenCount < 0) {
throw new SchemaValidationError(
"SQLite DDL has unbalanced parentheses",
[]
);
}
}
if (parenCount !== 0) {
throw new SchemaValidationError(
"SQLite DDL has unbalanced parentheses",
[]
);
}
}
/**
* Fetches and validates a schema from a URL
*
* @param url - The URL to fetch the schema from
* @returns The validated data schema
* @throws SchemaValidationError if invalid or fetch fails
* @example
* ```typescript
* const validator = new SchemaValidator();
* const schema = await validator.fetchAndValidateSchema("https://example.com/schema.json");
* ```
*/
async fetchAndValidateSchema(url) {
try {
const response = await fetch(url);
if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
}
const schema = await response.json();
this.validateDataSchema(schema);
if (schema.dialect === "sqlite" && typeof schema.schema === "string") {
this.validateSQLiteDDL(schema.schema, schema.dialectVersion);
}
return schema;
} catch (error) {
if (error instanceof SchemaValidationError) {
throw error;
}
throw new SchemaValidationError(
`Failed to fetch and validate schema from ${url}: ${error instanceof Error ? error.message : "Unknown error"}`,
[]
);
}
}
};
var schemaValidator = new SchemaValidator();
function validateDataSchema(schema) {
return schemaValidator.validateDataSchema(schema);
}
function validateDataAgainstSchema(data, schema) {
return schemaValidator.validateDataAgainstSchema(data, schema);
}
function fetchAndValidateSchema(url) {
return schemaValidator.fetchAndValidateSchema(url);
}
// src/types/external-apis.ts
function isReplicateAPIResponse(value) {
if (typeof value !== "object" || value === null) return false;
const obj = value;
return "id" in obj && "status" in obj && "urls" in obj && typeof obj.id === "string" && ["starting", "processing", "succeeded", "failed", "canceled"].includes(
obj.status
);
}
function isIdentityServerOutput(value) {
console.debug("\u{1F50D} Type Guard: Checking value:", value);
console.debug("\u{1F50D} Type Guard: Value type:", typeof value);
if (typeof value !== "object" || value === null) {
console.debug("\u{1F50D} Type Guard: Failed - not object or null");
return false;
}
const obj = value;
console.debug("\u{1F50D} Type Guard: Object keys:", Object.keys(obj));
console.debug(
"\u{1F50D} Type Guard: user_address:",
obj.user_address,
typeof obj.user_address
);
if (typeof obj.user_address !== "string") {
console.debug("\u{1F50D} Type Guard: Failed - user_address not string");
return false;
}
console.debug(
"\u{1F50D} Type Guard: personal_server:",
obj.personal_server,
typeof obj.personal_server
);
if (typeof obj.personal_server !== "object" || obj.personal_server === null) {
console.debug("\u{1F50D} Type Guard: Failed - personal_server not object or null");
return false;
}
const personalServer = obj.personal_server;
console.debug(
"\u{1F50D} Type Guard: Personal server keys:",
Object.keys(personalServer)
);
console.debug("\u{1F50D} Type Guard: address:", personalServer.address);
console.debug("\u{1F50D} Type Guard: public_key:", personalServer.public_key);
const hasAddress = "address" in personalServer;
const hasPublicKey = "public_key" in personalServer;
console.debug(
"\u{1F50D} Type Guard: Has address:",
hasAddress,
"Has public_key:",
hasPublicKey
);
return hasAddress && hasPublicKey;
}
function isPersonalServerOutput(value) {
if (typeof value !== "object" || value === null) return false;
const obj = value;
return "user_address" in obj && "identity" in obj && typeof obj.user_address === "string" && typeof obj.identity === "object";
}
function isAPIResponse(value) {
if (typeof value !== "object" || value === null) return false;
const obj = value;
return "success" in obj && typeof obj.success === "boolean";
}
function safeParseJSON(jsonString, typeGuard) {
try {
const parsed = JSON.parse(jsonString);
return typeGuard(parsed) ? parsed : null;
} catch {
return null;
}
}
function parseReplicateOutput(response, typeGuard) {
if (!response.output) return null;
if (typeof response.output === "string") {
return safeParseJSON(response.output, typeGuard);
}
return typeGuard(response.output) ? response.output : null;
}
// src/errors.ts
var VanaError = class extends Error {
constructor(message, code) {
super(message);
this.code = code;
this.name = this.constructor.name;
if (Error.captureStackTrace) {
Error.captureStackTrace(this, this.constructor);
}
}
};
var RelayerError = class extends VanaError {
constructor(message, statusCode, response) {
super(message, "RELAYER_ERROR");
this.statusCode = statusCode;
this.response = response;
}
};
var UserRejectedRequestError = class extends VanaError {
constructor(message = "User rejected the signature request") {
super(message, "USER_REJECTED_REQUEST");
}
};
var InvalidConfigurationError = class extends VanaError {
constructor(message) {
super(message, "INVALID_CONFIGURATION");
}
};
var ContractNotFoundError = class extends VanaError {
constructor(contractName, chainId) {
super(
`Contract ${contractName} not found on chain ${chainId}`,
"CONTRACT_NOT_FOUND"
);
}
};
var BlockchainError = class extends VanaError {
constructor(message, originalError) {
super(message, "BLOCKCHAIN_ERROR");
this.originalError = originalError;
}
};
var SerializationError = class extends VanaError {
constructor(message) {
super(message, "SERIALIZATION_ERROR");
}
};
var SignatureError = class extends VanaError {
constructor(message, originalError) {
super(message, "SIGNATURE_ERROR");
this.originalError = originalError;
}
};
var NetworkError = class extends VanaError {
constructor(message, originalError) {
super(message, "NETWORK_ERROR");
this.originalError = originalError;
}
};
var NonceError = class extends VanaError {
constructor(message) {
super(message, "NONCE_ERROR");
}
};
var PersonalServerError = class extends VanaError {
constructor(message, originalError) {
super(message, "PERSONAL_SERVER_ERROR");
this.originalError = originalError;
}
};
var ServerUrlMismatchError = class extends VanaError {
constructor(existingUrl, providedUrl, serverId) {
super(
`Server ${serverId} is already registered with URL "${existingUrl}". Cannot change to "${providedUrl}".`,
"SERVER_URL_MISMATCH"
);
__publicField(this, "existingUrl");
__publicField(this, "providedUrl");
__publicField(this, "serverId");
this.existingUrl = existingUrl;
this.providedUrl = providedUrl;
this.serverId = serverId;
}
};
var PermissionError = class extends VanaError {
constructor(message, originalError) {
super(message, "PERMISSION_ERROR");
this.originalError = originalError;
}
};
// src/config/addresses.ts
var CONTRACTS = {
// Core Platform Contracts
DataPermissions: {
addresses: {
14800: "0x31fb1D48f6B2265A4cAD516BC39E96a18fb7c8de",
1480: "0x31fb1D48f6B2265A4cAD516BC39E96a18fb7c8de"
}
},
DataRegistry: {
addresses: {
14800: "0x8C8788f98385F6ba1adD4234e551ABba0f82Cb7C",
1480: "0x8C8788f98385F6ba1adD4234e551ABba0f82Cb7C"
}
},
TeePoolPhala: {
addresses: {
14800: "0xE8EC6BD73b23Ad40E6B9a6f4bD343FAc411bD99A",
1480: "0xE8EC6BD73b23Ad40E6B9a6f4bD343FAc411bD99A"
}
},
ComputeEngine: {
addresses: {
14800: "0xb2BFe33FA420c45F1Cf1287542ad81ae935447bd",
1480: "0xb2BFe33FA420c45F1Cf1287542ad81ae935447bd"
}
},
// Data Access Infrastructure
DataRefinerRegistry: {
addresses: {
14800: "0x93c3EF89369fDcf08Be159D9DeF0F18AB6Be008c",
1480: "0x93c3EF89369fDcf08Be159D9DeF0F18AB6Be008c"
}
},
QueryEngine: {
addresses: {
14800: "0xd25Eb66EA2452cf3238A2eC6C1FD1B7F5B320490",
1480: "0xd25Eb66EA2452cf3238A2eC6C1FD1B7F5B320490"
}
},
VanaTreasury: {
addresses: {
14800: "0x94a1E56e555ac48d092f490fB10CDFaB434915eD",
1480: "0x94a1E56e555ac48d092f490fB10CDFaB434915eD"
}
},
ComputeInstructionRegistry: {
addresses: {
14800: "0x5786B12b4c6Ba2bFAF0e77Ed30Bf6d32805563A5",
1480: "0x5786B12b4c6Ba2bFAF0e77Ed30Bf6d32805563A5"
}
},
// TEE Pool Variants
TeePoolEphemeralStandard: {
addresses: {
14800: "0xe124bae846D5ec157f75Bd9e68ca87C4d2AB835A",
1480: "0xe124bae846D5ec157f75Bd9e68ca87C4d2AB835A"
}
},
TeePoolPersistentStandard: {
addresses: {
14800: "0xe8bB8d0629651Cf33e0845d743976Dc1f0971d76",
1480: "0xe8bB8d0629651Cf33e0845d743976Dc1f0971d76"
}
},
TeePoolPersistentGpu: {
addresses: {
14800: "0x1c346Cd74f8551f8fa13f3F4b6b8dAE22338E6a9",
1480: "0x1c346Cd74f8551f8fa13f3F4b6b8dAE22338E6a9"
}
},
TeePoolDedicatedStandard: {
addresses: {
14800: "0xf024b7ac5E8417416f53B41ecfa58C8e9396687d",
1480: "0xf024b7ac5E8417416f53B41ecfa58C8e9396687d"
}
},
TeePoolDedicatedGpu: {
addresses: {
14800: "0xB1686FA9620bBf851714d1cB47b8a4Bf4664644E",
1480: "0xB1686FA9620bBf851714d1cB47b8a4Bf4664644E"
}
},
// DLP Reward System
VanaEpoch: {
addresses: {
14800: "0x2063cFF0609D59bCCc196E20Eb58A8696a6b15A0",
1480: "0x2063cFF0609D59bCCc196E20Eb58A8696a6b15A0"
}
},
DLPRegistry: {
addresses: {
14800: "0x4D59880a924526d1dD33260552Ff4328b1E18a43",
1480: "0x4D59880a924526d1dD33260552Ff4328b1E18a43"
}
},
DLPRegistryTreasury: {
addresses: {
14800: "0xb12ce1d27bEeFe39b6F0110b1AB77C21Aa0c9F9a",
1480: "0xb12ce1d27bEeFe39b6F0110b1AB77C21Aa0c9F9a"
}
},
DLPPerformance: {
addresses: {
14800: "0x847715C7DB37cF286611182Be0bD333cbfa29cc1",
1480: "0x847715C7DB37cF286611182Be0bD333cbfa29cc1"
}
},
DLPRewardDeployer: {
addresses: {
14800: "0xEFD0F9Ba9De70586b7c4189971cF754adC923B04",
1480: "0xEFD0F9Ba9De70586b7c4189971cF754adC923B04"
}
},
DLPRewardDeployerTreasury: {
addresses: {
14800: "0xb547ca8Fe4990fe330FeAeb1C2EBb42F925Af5b8",
1480: "0xb547ca8Fe4990fe330FeAeb1C2EBb42F925Af5b8"
}
},
DLPRewardSwap: {
addresses: {
14800: "0x7c6862C46830F0fc3bF3FF509EA1bD0EE7267fB0",
1480: "0x7c6862C46830F0fc3bF3FF509EA1bD0EE7267fB0"
}
},
SwapHelper: {
addresses: {
14800: "0x55D5e6F73326315bF2E091e97F04f0770e5C54e2",
1480: "0x55D5e6F73326315bF2E091e97F04f0770e5C54e2"
}
},
// VanaPool (Staking)
VanaPoolStaking: {
addresses: {
14800: "0x641C18E2F286c86f96CE95C8ec1EB9fC0415Ca0e",
1480: "0x641C18E2F286c86f96CE95C8ec1EB9fC0415Ca0e"
}
},
VanaPoolEntity: {
addresses: {
14800: "0x44f20490A82e1f1F1cC25Dd3BA8647034eDdce30",
1480: "0x44f20490A82e1f1F1cC25Dd3BA8647034eDdce30"
}
},
VanaPoolTreasury: {
addresses: {
14800: "0x143BE72CF2541604A7691933CAccd6D9cC17c003",
1480: "0x143BE72CF2541604A7691933CAccd6D9cC17c003"
}
},
// DLP Deployment Contracts
DAT: {
addresses: {
14800: "0xA706b93ccED89f13340673889e29F0a5cd84212d",
1480: "0xA706b93ccED89f13340673889e29F0a5cd84212d"
}
},
DATFactory: {
addresses: {
14800: "0x40f8bccF35a75ecef63BC3B1B3E06ffEB9220644",
1480: "0x40f8bccF35a75ecef63BC3B1B3E06ffEB9220644"
}
},
DATPausable: {
addresses: {
14800: "0xe69FE86f0B95cC2f8416Fe22815c85DC8887e76e",
1480: "0xe69FE86f0B95cC2f8416Fe22815c85DC8887e76e"
}
},
DATVotes: {
addresses: {
14800: "0xaE04c8A77E9B27869eb563720524A9aE0baf1831",
1480: "0xaE04c8A77E9B27869eb563720524A9aE0baf1831"
}
},
// Utility Contracts (no ABIs in SDK)
Multicall3: {
addresses: {
14800: "0xD8d2dFca27E8797fd779F8547166A2d3B29d360E",
1480: "0xD8d2dFca27E8797fd779F8547166A2d3B29d360E"
}
},
Multisend: {
addresses: {
14800: "0x8807e8BCDFbaA8c2761760f3FBA37F6f7F2C5b2d",
1480: "0x8807e8BCDFbaA8c2761760f3FBA37F6f7F2C5b2d"
}
}
};
var LEGACY_CONTRACTS = {
// DEPRECATED: Original Intel SGX TeePool (PRO-347)
TeePool: {
addresses: {
14800: "0x3c92fD91639b41f13338CE62f19131e7d19eaa0D",
1480: "0x3c92fD91639b41f13338CE62f19131e7d19eaa0D"
}
},
// DEPRECATED: DLPRoot system (replaced by VanaPool + DLPRewards)
DLPRootEpoch: {
addresses: {
14800: "0xc3d176cF6BccFCB9225b53B87a95147218e1537F",
1480: "0xc3d176cF6BccFCB9225b53B87a95147218e1537F"
}
},
DLPRootCore: {
addresses: {
14800: "0x0aBa5e28228c323A67712101d61a54d4ff5720FD",
1480: "0x0aBa5e28228c323A67712101d61a54d4ff5720FD"
}
},
DLPRoot: {
addresses: {
14800: "0xff14346dF2B8Fd0c95BF34f1c92e49417b508AD5",
1480: "0xff14346dF2B8Fd0c95BF34f1c92e49417b508AD5"
}
},
DLPRootMetrics: {
addresses: {
14800: "0xbb532917B6407c060Afd9Cb7d53527eCb91d6662",
1480: "0xbb532917B6407c060Afd9Cb7d53527eCb91d6662"
}
},
DLPRootStakesTreasury: {
addresses: {
14800: "0x52c3260ED5C235fcA43524CF508e29c897318775",
1480: "0x52c3260ED5C235fcA43524CF508e29c897318775"
}
},
DLPRootRewardsTreasury: {
addresses: {
14800: "0xDBFb6B8b9E2eCAEbdE64d665cD553dB81e524479",
1480: "0xDBFb6B8b9E2eCAEbdE64d665cD553dB81e524479"
}
}
};
var CONTRACT_ADDRESSES = {
14800: Object.fromEntries(
Object.entries(CONTRACTS).map(([name, info]) => [name, info.addresses[14800]]).filter(([, addr]) => addr)
),
1480: Object.fromEntries(
Object.entries(CONTRACTS).map(([name, info]) => [name, info.addresses[1480]]).filter(([, addr]) => addr)
)
};
var UTILITY_ADDRESSES = {
14800: {
Multicall3: CONTRACTS.Multicall3.addresses[14800],
Multisend: CONTRACTS.Multisend.addresses[14800]
},
1480: {
Multicall3: CONTRACTS.Multicall3.addresses[1480],
Multisend: CONTRACTS.Multisend.addresses[1480]
}
};
var LEGACY_ADDRESSES = {
14800: Object.fromEntries(
Object.entries(LEGACY_CONTRACTS).map(([name, info]) => [name, info.addresses[14800]]).filter(([, addr]) => addr)
),
1480: Object.fromEntries(
Object.entries(LEGACY_CONTRACTS).map(([name, info]) => [name, info.addresses[1480]]).filter(([, addr]) => addr)
)
};
var getContractAddress = (chainId, contract) => {
const contractAddress = CONTRACT_ADDRESSES[chainId]?.[contract];
if (!contractAddress) {
throw new Error(
`Contract address not found for ${contract} on chain ${chainId}`
);
}
return contractAddress;
};
// src/abi/ComputeEngineImplementation.ts
var ComputeEngineABI = [
{
inputs: [],
stateMutability: "nonpayable",
type: "constructor"
},
{
inputs: [],
name: "AccessControlBadConfirmation",
type: "error"
},
{
inputs: [
{
internalType: "address",
name: "account",
type: "address"
},
{
internalType: "bytes32",
name: "neededRole",
type: "bytes32"
}
],
name: "AccessControlUnauthorizedAccount",
type: "error"
},
{
inputs: [
{
internalType: "address",
name: "target",
type: "address"
}
],
name: "AddressEmptyCode",
type: "error"
},
{
inputs: [
{
internalType: "address",
name: "account",
type: "address"
}
],
name: "AddressInsufficientBalance",
type: "error"
},
{
inputs: [
{
internalType: "address",
name: "implementation",
type: "address"
}
],
name: "ERC1967InvalidImplementation",
type: "error"
},
{
inputs: [],
name: "ERC1967NonPayable",
type: "error"
},
{
inputs: [],
name: "EnforcedPause",
type: "error"
},
{
inputs: [],
name: "ExpectedPause",
type: "error"
},
{
inputs: [],
name: "FailedInnerCall",
type: "error"
},
{
inputs: [],
name: "FailedToAssignTee",
type: "error"
},
{
inputs: [
{
internalType: "uint256",
name: "computeInstructionId",
type: "uint256"
}
],
name: "InstructionNotFound",
type: "error"
},
{
inputs: [],
name: "InsufficientBalance",
type: "error"
},
{
inputs: [],
name: "InvalidAmount",
type: "error"
},
{
inputs: [],
name: "InvalidInitialization",
type: "error"
},
{
inputs: [
{
internalType: "enum IComputeEngine.JobStatus",
name: "currentStatus",
type: "uint8"
},
{
internalType: "enum IComputeEngine.JobStatus",
name: "newStatus",
type: "uint8"
}
],
name: "InvalidStatusTransition",
type: "error"
},
{
inputs: [],
name: "InvalidVanaAmount",
type: "error"
},
{
inputs: [],
name: "JobAlreadyDone",
type: "error"
},
{
inputs: [],
name: "JobLifeCycleEnded",
type: "error"
},
{
inputs: [
{
internalType: "uint256",
name: "jobId",
type: "uint256"
}
],
name: "JobNotFound",
type: "error"
},
{
inputs: [
{
internalType: "uint256",
name: "jobId",
type: "uint256"
}
],
name: "JobNotSubmitted",
type: "error"
},
{
inputs: [],
name: "NotInitializing",
type: "error"
},
{
inputs: [],
name: "NotJobOwner",
type: "error"
},
{
inputs: [],
name: "NotLongRunningJob",
type: "error"
},
{
inputs: [],
name: "NotQueryEngine",
type: "error"
},
{
inputs: [],
name: "NotTee",
type: "error"
},
{
inputs: [],
name: "OnlyRegisteredJobStatus",
type: "error"
},
{
inputs: [],
name: "ReentrancyGuardReentrantCall",
type: "error"
},
{
inputs: [
{
internalType: "address",
name: "token",
type: "address"
}
],
name: "SafeERC20FailedOperation",
type: "error"
},
{
inputs: [
{
internalType: "uint256",
name: "jobId",
type: "uint256"
}
],
name: "TeeAlreadyAssigned",
type: "error"
},
{
inputs: [],
name: "TeePoolNotFound",
type: "error"
},
{
inputs: [],
name: "UUPSUnauthorizedCallContext",
type: "error"
},
{
inputs: [
{
internalType: "bytes32",
name: "slot",
type: "bytes32"
}
],
name: "UUPSUnsupportedProxiableUUID",
type: "error"
},
{
inputs: [],
name: "UnauthorizedPaymentRequestor",
type: "error"
},
{
inputs: [],
name: "UnexpectedVanaDeposit",
type: "error"
},
{
inputs: [],
name: "ZeroAddress",
type: "error"
},
{
inputs: [],
name: "ZeroTeeAddress",
type: "error"
},
{
anonymous: false,
inputs: [
{
indexed: true,
internalType: "address",
name: "account",
type: "address"
},
{
indexed: true,
internalType: "address",
name: "token",
type: "address"
},
{
indexed: false,
internalType: "uint256",
name: "amount",
type: "uint256"
}
],
name: "Deposit",
type: "event"
},
{
anonymous: false,
inputs: [
{
indexed: false,
internalType: "uint64",
name: "version",
type: "uint64"
}
],
name: "Initialized",
type: "event"
},
{
anonymous: false,
inputs: [
{
indexed: true,
internalType: "uint256",
name: "jobId",
type: "uint256"
}
],
name: "JobCanceled",
type: "event"
},
{
anonymous: false,
inputs: [
{
indexed: true,
internalType: "uint256",
name: "jobId",
type: "uint256"
},
{
indexed: true,
internalType: "address",
name: "ownerAddress",
type: "address"
}
],
name: "JobRegistered",
type: "event"
},
{
anonymous: false,
inputs: [
{
indexed: true,
internalType: "uint256",
name: "jobId",
type: "uint256"
},
{
indexed: false,
internalType: "enum IComputeEngine.JobStatus",
name: "status",
type: "uint8"
},
{
indexed: false,
internalType: "string",
name: "statusMessage",
type: "string"
}
],
name: "JobStatusUpdated",
type: "event"
},
{
anonymous: false,
inputs: [
{
indexed: false,
internalType: "address",
name: "account",
type: "address"
}
],
name: "Paused",
type: "event"
},
{
anonymous: false,
inputs: [
{
indexed: true,
internalType: "uint256",
name: "jobId",
type: "uint256"
},
{
indexed: true,
internalType: "address",
name: "token",
type: "address"
},
{
indexed: false,
internalType: "uint256",
name: "amount",
type: "uint256"
}
],
name: "PaymentExecuted",
type: "event"
},
{
anonymous: false,
inputs: [
{
indexed: true,
internalType: "bytes32",
name: "role",
type: "bytes32"
},
{
indexed: true,
internalType: "bytes32",
name: "previousAdminRole",
type: "bytes32"
},
{
indexed: true,
internalType: "bytes32",
name: "newAdminRole",
type: "bytes32"
}
],
name: "RoleAdminChanged",
type: "event"
},
{
anonymous: false,
inputs: [
{
indexed: true,
internalType: "bytes32",
name: "role",
type: "bytes32"
},
{
indexed: true,
internalType: "address",
name: "account",
type: "address"
},
{
indexed: true,
internalType: "address",
name: "sender",
type: "address"
}
],
name: "RoleGranted",
type: "event"
},
{
anonymous: false,
inputs: [
{
indexed: true,
internalType: "bytes32",
name: "role",
type: "bytes32"
},
{
indexed: true,
internalType: "address",
name: "account",
type: "address"
},
{
indexed: true,
internalType: "address",
name: "sender",
type: "address"
}
],
name: "RoleRevoked",
type: "event"
},
{
anonymous: false,
inputs: [
{
indexed: true,
internalType: "uint256",
name: "jobId",
type: "uint256"
},
{
indexed: false,
internalType: "bytes",
name: "reason",
type: "bytes"
}
],
name: "TeeAssignmentFailed",
type: "event"
},
{
anonymous: false,
inputs: [
{
indexed: true,
internalType: "uint256",
name: "jobId",
type: "uint256"
},
{
indexed: true,
internalType: "address",
name: "teePoolAddress",
type: "address"
},
{
indexed: false,
internalType: "address",
name: "teeAddress",
type: "address"
}
],
name: "TeeAssignmentSucceeded",
type: "event"
},
{
anonymous: false,
inputs: [
{
indexed: false,
internalType: "address",
name: "account",
type: "address"
}
],
name: "Unpaused",
type: "event"
},
{
anonymous: false,
inputs: [
{
indexed: true,
internalType: "address",
name: "implementation",
type: "address"
}
],
name: "Upgraded",
type: "event"
},
{
anonymous: false,
inputs: [
{
indexed: true,
internalType: "address",
name: "account",
type: "address"
},
{
indexed: true,
internalType: "address",
name: "token",
type: "address"
},
{
indexed: false,
internalType: "uint256",
name: "amount",
type: "uint256"
}
],
name: "Withdraw",
type: "event"
},
{
inputs: [],
name: "DEDICATED_TIMEOUT",
outputs: [
{
internalType: "uint80",
name: "",
type: "uint80"
}
],
stateMutability: "view",
type: "function"
},
{
inputs: [],
name: "DEFAULT_ADMIN_ROLE",
outputs: [
{
internalType: "bytes32",
name: "",
type: "bytes32"
}
],
stateMutability: "view",
type: "function"
},
{
inputs: [],
name: "MAINTAINER_ROLE",
outputs: [
{
internalType: "bytes32",
name: "",
type: "bytes32"
}
],
stateMutability: "view",
type: "function"
},
{
inputs: [],
name: "UPGRADE_INTERFACE_VERSION",
outputs: [
{
internalType: "string",
name: "",
type: "string"
}
],
stateMutability: "view",
type: "function"
},
{
inputs: [],
name: "VANA",
outputs: [
{
internalType: "address",
name: "",
type: "address"
}
],
stateMutability: "view",
type: "function"
},
{
inputs: [
{
internalType: "address",
name: "account",
type: "address"
},
{
internalType: "address",
name: "token",
type: "address"
}
],
name: "balanceOf",
outputs: [
{
internalType: "uint256",
name: "",
type: "uint256"
}
],
stateMutability: "view",
type: "function"
},
{
inputs: [
{
internalType: "uint256",
name: "jobId",
type: "uint256"
}
],
name: "cancelJob",
outputs: [],
stateMutability: "nonpayable",
type: "function"
},
{
inputs: [],
name: "computeEngineTreasury",
outputs: [
{
internalType: "contract IDataAccessTreasury",
name: "",
type: "address"
}
],
stateMutability: "view",
type: "function"
},
{
inputs: [
{
internalType: "address",
name: "token",
type: "address"
},
{
internalType: "uint256",
name: "amount",
type: "uint256"
}
],
name: "deposit",
outputs: [],
stateMutability: "payable",
type: "function"
},
{
inputs: [
{
internalType: "address",
name: "token",
type: "address"
},
{
internalType: "uint256",
name: "amount",
type: "uint256"
},
{
internalType: "bytes",
name: "metadata",
type: "bytes"
}
],
name: "executePaymentRequest",
outputs: [],
stateMutability: "nonpayable",
type: "function"
},
{
inputs: [
{
internalType: "bytes32",
name: "role",
type: "bytes32"
}
],
name: "getRoleAdmin",
outputs: [
{
internalType: "bytes32",
name: "",
type: "bytes32"
}
],
stateMutability: "view",
type: "function"
},
{
inputs: [
{
internalType: "bytes32",
name: "role",
type: "bytes32"
},
{
internalType: "address",
name: "account",
type: "address"
}