import { type StorageProvider, type StorageUploadResult, type StorageFile, type StorageListOptions, type StorageProviderConfig } from "../index.js"; import { type Web3SignedSignFn } from "../../auth/web3-signed-builder.js"; import { type ProtocolNetwork } from "../../protocol/networks.js"; /** * Wallet-style signer used by {@link VanaStorage} to authenticate every * request. For Personal Server flows this can be a registered server wallet * signing requests for the owner's storage namespace. * * @category Storage */ export interface VanaStorageSigner { /** EIP-191 address (`0x...`). */ address: `0x${string}`; /** EIP-191 personal_sign callback (e.g. viem `account.signMessage`). */ signMessage: Web3SignedSignFn; } /** * Configuration for {@link VanaStorage}. * * @category Storage */ export interface VanaStorageConfig { /** * Base URL of the vana-storage Worker. Defaults to `https://storage.vana.org`. * * This selects the storage endpoint and is independent of {@link network} / * {@link chainId}. */ endpoint?: string; /** * Named Vana protocol network that scopes blob paths. Prefer this for known * Vana networks because it keeps callers on the SDK's typed network registry. * * When set, uploads use chain-scoped routes derived from the network's chain * ID (`/v1/chains/1480/...` for mainnet, `/v1/chains/14800/...` for Moksha). */ network?: ProtocolNetwork; /** * Explicit numeric chain ID for custom or future networks not yet represented * by {@link ProtocolNetwork}. * * When set, uploads use chain-scoped routes * (`/v1/chains/{chainId}/blobs/...`) so data for different chains under the * same owner/scope/timestamp never collides. Reads and deletes must use the * same chain-scoped namespace; legacy blobs should be migrated or re-collected * rather than read through an ambiguous fallback. When omitted, the provider * preserves the legacy `/v1/blobs/...` routes and behavior. * * `chainId` and {@link network} are mutually consistent ways to select the * namespace. If both are provided, they must resolve to the same chain ID. * `endpoint` remains orthogonal: it picks the storage host, not the protocol * namespace. */ chainId?: number; /** * Wallet signer used to authenticate writes and reads. */ signer: VanaStorageSigner; /** * Owner namespace under which blobs are stored. Defaults to the signer address. */ ownerAddress?: `0x${string}`; /** * Optional `fetch` implementation. Defaults to the global `fetch`. * Useful for tests and for environments that need a custom HTTP client. */ fetchImpl?: typeof fetch; } /** * Response of {@link VanaStorage.deleteScope} -- the worker's * `DELETE /:owner/:scope` body. `count` is the number of blobs removed (0 is * a success: nothing was stored under that scope). * * @category Storage */ export interface VanaStorageScopeDeleteResult { deleted: boolean; scope: string; count: number; totalBytes: number; } /** * Storage provider that talks to the vana-storage Worker * (`https://storage.vana.org` by default). All requests are authenticated * with Web3Signed headers signed by the configured wallet. * * @remarks * Filenames passed to {@link VanaStorage.upload} must be of the form * `"{scope}/{collectedAt}"` (e.g. `"instagram.profile/2026-05-08T20:00:00.000Z"`). * The owner address is prepended automatically to produce the canonical * blob path `/v1/blobs/{owner}/{scope}/{collectedAt}`. * * When {@link VanaStorageConfig.network} or {@link VanaStorageConfig.chainId} * is set, paths are chain-scoped as * `/v1/chains/{chainId}/blobs/{owner}/{scope}/{collectedAt}` so different chains * never collide on the same host. The Web3Signed audience remains the endpoint * origin regardless of network. * * @category Storage * * @example * ```typescript * import { privateKeyToAccount } from "viem/accounts"; * import { VanaStorage } from "@opendatalabs/vana-sdk/node"; * * const account = privateKeyToAccount(process.env.PRIVATE_KEY as `0x${string}`); * const storage = new VanaStorage({ * signer: { * address: account.address, * signMessage: (msg) => account.signMessage({ message: msg }), * }, * }); * * const result = await storage.upload( * new Blob([ciphertext]), * "instagram.profile/2026-05-08T20:00:00.000Z", * ); * ``` */ export declare class VanaStorage implements StorageProvider { private readonly endpoint; private readonly network?; private readonly chainId?; private readonly blobPathPrefix; private readonly signer; private readonly ownerAddress; private readonly fetchImpl; constructor(config: VanaStorageConfig); /** * Upload an encrypted blob to vana-storage. * * @param file - The blob to upload. * @param filename - Required relative key in the form `"{scope}/{collectedAt}"`. * The owner address is prepended automatically. */ upload(file: Blob, filename?: string): Promise; /** * Download a blob by URL. The URL must point at a path under this * provider's endpoint. */ download(url: string): Promise; /** * Listing is not supported by vana-storage — file discovery is handled by * the Gateway DataRegistry, not the storage layer. */ list(_options?: StorageListOptions): Promise; delete(url: string): Promise; /** * Delete every version's blob under `(owner, scope)` -- * `DELETE {prefix}/{owner}/{scope}` on vana-storage, signed with the same * Web3Signed header as uploads (aud = endpoint origin, empty bodyHash). * The worker accepts the owner's own signature or a personal server the * owner registered with the gateway. * * @param ownerAddress - Must equal the provider's configured owner; a * mismatch throws before anything is signed so this wallet can never be * induced to sign a delete for another namespace. * @param scope - The scope segment, e.g. `"instagram.profile"`. */ deleteScope(ownerAddress: `0x${string}`, scope: string): Promise; getConfig(): StorageProviderConfig; private signRequest; private pathFromUrl; private namespaceDescription; }