@opendatalabs/vana-sdk
Version:
A TypeScript library for interacting with Vana Network smart contracts.
434 lines • 14.9 kB
JavaScript
;
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
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 __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
// If the importer is in node compatibility mode or this is not an ESM
// file that has been converted to a CommonJS file using a Babel-
// compatible transform (i.e. "__esModule" has not been set), then set
// "default" to the CommonJS "module.exports" for node compatibility.
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
mod
));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var node_exports = {};
__export(node_exports, {
NodePlatformAdapter: () => NodePlatformAdapter,
nodePlatformAdapter: () => nodePlatformAdapter
});
module.exports = __toCommonJS(node_exports);
var import_pgp_utils = require("./shared/pgp-utils");
var import_error_utils = require("./shared/error-utils");
var import_stream_utils = require("./shared/stream-utils");
var import_lazy_import = require("../utils/lazy-import");
var import_WalletKeyEncryptionService = require("../crypto/services/WalletKeyEncryptionService");
var import_crypto_utils = require("../utils/crypto-utils");
var import_node = require("../crypto/ecies/node");
var import_interface = require("../crypto/ecies/interface");
var import_crypto = require("crypto");
var import_secp256k1 = __toESM(require("secp256k1"), 1);
const getOpenPGP = (0, import_lazy_import.lazyImport)(() => import("openpgp"));
class NodeCryptoAdapter {
eciesProvider = new import_node.NodeECIESUint8Provider();
walletService = new import_WalletKeyEncryptionService.WalletKeyEncryptionService({
eciesProvider: this.eciesProvider
});
/**
* Encrypts data using ECIES with a public key.
*
* @param data - The plaintext string to encrypt.
* Typically user data or sensitive information.
* @param publicKeyHex - The recipient's public key in hex format.
* Obtain from key generation or user profile.
* @returns Encrypted data as a hex string containing IV, ephemeral key, ciphertext, and MAC
*
* @throws {Error} If encryption fails or public key is invalid
*/
async encryptWithPublicKey(data, publicKeyHex) {
try {
const publicKeyBytes = (0, import_crypto_utils.processWalletPublicKey)(publicKeyHex);
const publicKey = Buffer.from(publicKeyBytes);
const message = Buffer.from(data, "utf8");
const encrypted = await this.eciesProvider.encrypt(publicKey, message);
const result = Buffer.concat([
encrypted.iv,
encrypted.ephemPublicKey,
encrypted.ciphertext,
encrypted.mac
]);
return result.toString("hex");
} catch (error) {
if (error instanceof import_interface.ECIESError) {
throw error;
}
throw new Error(
`Encryption failed: ${error instanceof Error ? error.message : String(error)}`
);
}
}
/**
* Decrypts ECIES-encrypted data using a private key.
*
* @param encryptedData - Hex string containing encrypted data.
* Must include IV, ephemeral public key, ciphertext, and MAC.
* @param privateKeyHex - The private key in hex format.
* Must correspond to the public key used for encryption.
* @returns The decrypted plaintext string
*
* @throws {Error} If decryption fails or MAC verification fails
* @throws {ECIESError} If using custom ECIES and specific error occurs
*/
async decryptWithPrivateKey(encryptedData, privateKeyHex) {
try {
const privateKeyBuffer = (0, import_crypto_utils.processWalletPrivateKey)(privateKeyHex);
const encryptedHex = encryptedData.startsWith("0x") ? encryptedData.slice(2) : encryptedData;
const encryptedBuffer = Buffer.from(encryptedHex, "hex");
const { iv, ephemPublicKey, ciphertext, mac } = (0, import_crypto_utils.parseEncryptedDataBuffer)(encryptedBuffer);
const encryptedObj = {
iv,
ephemPublicKey,
ciphertext,
mac
};
const decrypted = await this.eciesProvider.decrypt(
privateKeyBuffer,
encryptedObj
);
return new TextDecoder().decode(decrypted);
} catch (error) {
if (error instanceof import_interface.ECIESError) {
throw error;
}
throw new Error(
`Decryption failed: ${error instanceof Error ? error.message : String(error)}`
);
}
}
/**
* Generates a new secp256k1 key pair for ECIES operations.
*
* @returns Object containing hex-encoded public and private keys
* @returns returns.publicKey - Compressed public key in hex format
* @returns returns.privateKey - Private key in hex format
*
* @throws {Error} If key generation fails
*/
async generateKeyPair() {
try {
const secp256k1 = import_secp256k1.default;
let privateKey;
do {
privateKey = (0, import_crypto.randomBytes)(32);
} while (!secp256k1.privateKeyVerify(privateKey));
const publicKey = Buffer.from(
secp256k1.publicKeyCreate(privateKey, true)
);
return {
privateKey: privateKey.toString("hex"),
publicKey: publicKey.toString("hex")
};
} catch (error) {
throw (0, import_error_utils.wrapCryptoError)("key generation", error);
}
}
/**
* Encrypts data using a wallet's public key.
*
* @param data - The plaintext string to encrypt.
* Typically permission data or DLP metadata.
* @param publicKey - The wallet's public key (with or without 0x prefix).
* Obtain from wallet connection or user profile.
* @returns Encrypted data as a hex string
*
* @throws {Error} If encryption fails or key processing fails
*/
async encryptWithWalletPublicKey(data, publicKey) {
try {
return await this.walletService.encryptWithWalletPublicKey(
data,
publicKey
);
} catch (error) {
throw (0, import_error_utils.wrapCryptoError)("encrypt with wallet public key", error);
}
}
/**
* Decrypts data using a wallet's private key.
*
* @param encryptedData - Hex string containing encrypted data.
* Must be encrypted with corresponding wallet public key.
* @param privateKey - The wallet's private key.
* Obtain from wallet connection (handle with care).
* @returns The decrypted plaintext string
*
* @throws {Error} If decryption fails or key is invalid
*/
async decryptWithWalletPrivateKey(encryptedData, privateKey) {
try {
return await this.walletService.decryptWithWalletPrivateKey(
encryptedData,
privateKey
);
} catch (error) {
throw (0, import_error_utils.wrapCryptoError)("decrypt with wallet private key", error);
}
}
/**
* Encrypts binary data using password-based encryption.
*
* @param data - Binary data to encrypt.
* Typically file contents or serialized objects.
* @param password - Password for encryption.
* Often derived from wallet signatures.
* @returns Encrypted data as Uint8Array
*
* @remarks
* Uses OpenPGP for password-based encryption. Note that this is not
* deterministic due to OpenPGP's random salt generation.
*
* @throws {Error} If encryption fails
*/
async encryptWithPassword(data, password) {
try {
const openpgp = await getOpenPGP();
const message = await openpgp.createMessage({
binary: data
});
const encrypted = await openpgp.encrypt({
message,
passwords: [password],
format: "binary"
});
if (encrypted instanceof Uint8Array) {
return encrypted;
}
if (encrypted && typeof encrypted === "object" && "getReader" in encrypted) {
return await (0, import_stream_utils.streamToUint8Array)(
encrypted
);
}
throw new Error("Unexpected encrypted data format");
} catch (error) {
throw (0, import_error_utils.wrapCryptoError)("encrypt with password", error);
}
}
/**
* Decrypts password-encrypted binary data.
*
* @param encryptedData - Password-encrypted data as Uint8Array.
* Must be encrypted with the same password.
* @param password - Password for decryption.
* Must match the encryption password.
* @returns Decrypted data as Uint8Array
*
* @throws {Error} If decryption fails or password is incorrect
*/
async decryptWithPassword(encryptedData, password) {
try {
const openpgp = await getOpenPGP();
const message = await openpgp.readMessage({
binaryMessage: encryptedData
});
const { data: decrypted } = await openpgp.decrypt({
message,
passwords: [password],
format: "binary"
});
return new Uint8Array(decrypted);
} catch (error) {
throw (0, import_error_utils.wrapCryptoError)("decrypt with password", error);
}
}
}
class NodePGPAdapter {
/**
* Encrypts data using PGP public key encryption.
*
* @param data - The plaintext string to encrypt.
* Typically messages or structured data.
* @param publicKeyArmored - ASCII-armored PGP public key.
* Obtain from PGP key generation or key servers.
* @returns ASCII-armored encrypted message
*
* @throws {Error} If encryption fails or public key is invalid
*/
async encrypt(data, publicKeyArmored) {
try {
const openpgp = await getOpenPGP();
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 (0, import_error_utils.wrapCryptoError)("PGP encryption", error);
}
}
/**
* Decrypts PGP-encrypted data using a private key.
*
* @param encryptedData - ASCII-armored encrypted message.
* Must be encrypted with corresponding public key.
* @param privateKeyArmored - ASCII-armored PGP private key.
* Must correspond to the public key used for encryption.
* @returns The decrypted plaintext string
*
* @throws {Error} If decryption fails or private key is invalid
*/
async decrypt(encryptedData, privateKeyArmored) {
try {
const openpgp = await getOpenPGP();
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 (0, import_error_utils.wrapCryptoError)("PGP decryption", error);
}
}
/**
* Generates a new PGP key pair.
*
* @param options - Key generation options
* @param options.name - Name for the key identity.
* Defaults to 'Vana User'.
* @param options.email - Email for the key identity.
* Defaults to 'user@vana.com'.
* @param options.passphrase - Passphrase to protect the private key.
* If not provided, key is unprotected.
* @returns ASCII-armored public and private keys
*
* @throws {Error} If key generation fails
*/
async generateKeyPair(options) {
try {
const openpgp = await getOpenPGP();
const keyGenParams = (0, import_pgp_utils.getPGPKeyGenParams)(options);
const { privateKey, publicKey } = await openpgp.generateKey(keyGenParams);
return { publicKey, privateKey };
} catch (error) {
throw (0, import_error_utils.wrapCryptoError)("PGP key generation", error);
}
}
}
class NodeHttpAdapter {
/**
* Performs an HTTP request using fetch.
*
* @param url - The URL to fetch.
* Must be a valid HTTP/HTTPS URL.
* @param options - Standard fetch options.
* See MDN fetch documentation for details.
* @returns Standard fetch Response object
*
* @throws {Error} If fetch is not available in the environment
*/
async fetch(url, options) {
if (typeof globalThis.fetch !== "undefined") {
return globalThis.fetch(url, options);
}
throw new Error("No fetch implementation available in Node.js environment");
}
}
class NodeCacheAdapter {
cache = /* @__PURE__ */ new Map();
defaultTtl = 2 * 60 * 60 * 1e3;
// 2 hours in milliseconds
/**
* Retrieves a cached value by key.
*
* @param key - The cache key to look up.
* Typically derived from operation parameters.
* @returns The cached value or null if not found/expired
*/
get(key) {
const entry = this.cache.get(key);
if (!entry) {
return null;
}
if (Date.now() > entry.expires) {
this.cache.delete(key);
return null;
}
return entry.value;
}
/**
* Stores a value in the cache with TTL.
*
* @param key - The cache key.
* Should be unique per operation.
* @param value - The value to cache.
* Typically serialized data or signatures.
*/
set(key, value) {
this.cache.set(key, {
value,
expires: Date.now() + this.defaultTtl
});
}
/**
* Removes a specific key from the cache.
*
* @param key - The cache key to remove.
* Use when cached data becomes invalid.
*/
delete(key) {
this.cache.delete(key);
}
/**
* Clears all cached values.
*
* @remarks
* Use with caution as this removes all cached signatures
* and other performance optimizations.
*/
clear() {
this.cache.clear();
}
}
class NodePlatformAdapter {
crypto;
pgp;
http;
cache;
platform = "node";
constructor() {
this.crypto = new NodeCryptoAdapter();
this.pgp = new NodePGPAdapter();
this.http = new NodeHttpAdapter();
this.cache = new NodeCacheAdapter();
}
}
const nodePlatformAdapter = new NodePlatformAdapter();
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
NodePlatformAdapter,
nodePlatformAdapter
});
//# sourceMappingURL=node.cjs.map