hollowdb
Version:
A decentralized privacy-preserving key-value database
292 lines (290 loc) • 11 kB
TypeScript
import { Warp, Contract, ArWallet, CustomSignature, SortKeyCacheResult } from "warp-contracts";
import { SortKeyCacheRangeOptions } from "warp-contracts/lib/types/cache/SortKeyCacheRangeOptions";
/**
* A type-utility to convert an array of `T`s into a mapped type,
* that can be used for example as a mapping key type.
*
* If the array is empty, defaults to `T`.
*/
type OpitonalArray<A extends T[], T> = A extends [] ? T : A[number];
/**
* A type to describe whitelists and proofs (circuits) used within a contract.
*/
type ContractMode = {
whitelists: string[];
proofs: string[];
};
/**
* A generic contract input.
*/
type ContractInputGeneric = {
function: string;
value: any;
};
/**
* A contract state. For example, HollowDB state is defined as:
*
* ```ts
* ContractState<{circuits: ['auth']; whitelists: ['put', 'update']}>
* ```
*
* because we have an `auth` circuit, and we have two whitelists names `put` and `update`.
*
* @template M a type where whitelists and circuit names are specified. If none, pass in empty array `[]` to each.
*/
type ContractState<M extends ContractMode = ContractMode> = {
version: string;
canEvolve: boolean;
evolve?: string;
owner: string;
isProofRequired: {
[name in OpitonalArray<M['proofs'], string>]: boolean;
};
verificationKeys: {
[name in OpitonalArray<M['proofs'], string>]: any;
};
whitelists: {
[name in OpitonalArray<M['whitelists'], string>]: {
[address: string]: boolean;
};
};
isWhitelistRequired: {
[name in OpitonalArray<M['whitelists'], string>]: boolean;
};
};
declare class Base<M extends ContractMode> {
readonly contract: Contract<ContractState<M>>;
readonly warp: Warp;
readonly signer: ArWallet | CustomSignature;
constructor(signer: ArWallet | CustomSignature, contractTxId: string, warp: Warp);
/**
* Return the latest contract state.
*
* This is a good way to trigger Warp to fetch the latest data from Arweave.
* Note that if the contract has many transactions, fetching up to the latest
* state may take some time.
*
* @returns contract state along with corresponding sort key
*/
readState(): Promise<import("warp-contracts").SortKeyCacheResult<import("warp-contracts").EvalStateResult<ContractState<M>>>>;
/**
* A typed wrapper around `dryWrite`, which evaluates a given input
* on the local state, without creating a transaction. This may provide
* better UX for some use-cases.
* @param input input in the form of `{function, value}`
* @returns interaction result
*/
dryWrite<I extends ContractInputGeneric>(input: I): Promise<import("warp-contracts").InteractionResult<ContractState<M>, unknown>>;
/**
* A typed wrapper around `writeInteraction`, which creates a
* transaction. You are likely to use this after `dryWrite`, or you
* may directly call this function.
* @param input input in the form of `{function, value}`
* @returns interaction response
*/
writeInteraction<I extends ContractInputGeneric>(input: I): Promise<import("warp-contracts").WriteInteractionResponse | null>;
/**
* A typed wrapper around `dryWrite` followed by `writeInteraction`. This
* function first executes the interaction locally via `dryWrite`, and if
* there is an error, throws an error with an optional prefix in the message.
* @param input input in the form of `{function, value}`
* @param errorPrefix optional prefix for the error message
*/
dryWriteInteraction<I extends ContractInputGeneric>(input: I): Promise<void>;
/**
* A typed wrapper around `viewState` followed with a repsonse type check.
* If response type is not `ok`, it will throw an error.
* @param input input in the form of `{function, value}`
* @returns interaction result
*/
safeReadInteraction<I extends ContractInputGeneric, V>(input: I): Promise<V>;
/**
* A typed wrapper around `viewState`, which is a read interaction.
* @param input input in the form of `{function, value}`
* @returns interaction result
*/
viewState<I extends ContractInputGeneric, R>(input: I): Promise<import("warp-contracts").InteractionResult<ContractState<M>, R>>;
}
declare class Admin<M extends ContractMode = ContractMode> {
constructor(base: Base<M>);
/**
* Sets the owner as the given wallet address.
* @param newOwner address of the new owner, make sure that this is correct!
*/
updateOwner(newOwner: string): Promise<void>;
/**
* Changes the whitelist for the selected list.
* @param users an array of user addresses
* @param name name of the list to be updated
* @param op whether to `add` the users to whitelist or `remove` them
*/
updateWhitelist(users: string[], name: OpitonalArray<M['whitelists'], string>, op: 'add' | 'remove'): Promise<void>;
/**
* Update a verification key.
* @param name name of the circuit that the verification key belongs to
* @param verificationKey verification key
*/
updateVerificationKey(name: OpitonalArray<M['proofs'], string>, verificationKey: any): Promise<void>;
/**
* Disable or enable whitelist checks for a specific whitelist.
* @param name name of the list
* @param value a boolean
*/
updateWhitelistRequirement(name: OpitonalArray<M['whitelists'], string>, value: boolean): Promise<void>;
/**
* Disable or enable proof checks for a specific circuit.
* @param name name of the circuit
* @param value a boolean
*/
updateProofRequirement(name: OpitonalArray<M['proofs'], string>, value: boolean): Promise<void>;
}
export class BaseSDK<V = unknown, M extends ContractMode = ContractMode> {
readonly base: Base<M>;
readonly admin: Admin<M>;
/**
* Connects to the given contract via the provided Warp instance using the provided signer.
* @param signer a Signer, such as Arweave wallet or Ethereum CustomSignature
* @param contractTxId contract txId to connect to
* @param warp a Warp instace, such as `WarpFactory.forMainnet()`
*/
constructor(signer: ArWallet | CustomSignature, contractTxId: string, warp: Warp);
/** The smart-contract that we are connected to. */
get contract(): Contract<ContractState<M>>;
/** Warp instance. */
get warp(): Warp;
/** Contract transaction id. */
get contractTxId(): string;
/** Signer. */
get signer(): ArWallet | CustomSignature;
/**
* Returns the latest contract state.
*
* For a more fine-grained state data, use `base.readState()`.
*
* @returns contract state object
*/
getState(): Promise<ContractState<M>>;
/**
* Alternative method of getting key values. Uses the underlying `getStorageValues`
* function, returns a Map instead of an array.
*
* @param keys an array of keys
* @returns `SortKeyCacheResult` of a key-value `Map`
*/
getStorageValues(keys: string[]): Promise<SortKeyCacheResult<Map<string, V | null>>>;
/**
* Returns keys with respect to a range option.
*
* If no option is provided, it will get all keys.
*
* @param options optional range
* @returns an array of keys
*/
getKeys(options?: SortKeyCacheRangeOptions): Promise<string[]>;
/**
* Returns all keys in the database.
*
* @returns an array of all keys
*/
getAllKeys(): Promise<string[]>;
/**
* Returns a mapping of keys and values with respect to a range option.
* If no option is provided, all values are returned.
*
* @param options optional range
* @returns a key-value `Map`
*/
getKVMap(options?: SortKeyCacheRangeOptions): Promise<Map<string, V | null>>;
/**
* Gets the value of the given key.
* @param key the key of the value to be returned
* @returns the value of the given key
*/
get(key: string): Promise<V | null>;
/**
* Gets the values at the given keys as an array.
*
* If a value does not exist, it is returned as `null`.
*
* Note that the transaction limit may become a problem for too many keys.
*
* @param keys an array of keys
* @returns an array of corresponding values
*/
getMany(keys: string[]): Promise<(V | null)[]>;
/**
* Inserts the given value into database.
*
* There must not be a value at the given key.
*
* @param key the key of the value to be inserted
* @param value the value to be inserted
*/
put(key: string, value: V): Promise<void>;
/**
* Inserts an array of value into database.
*
* There must not be a value at the given key.
*
* @param keys the keys of the values to be inserted
* @param values the values to be inserted
*/
putMany(keys: string[], values: V[]): Promise<void>;
/**
* Updates the value of given key.
* @param key key of the value to be updated
* @param value new value
* @param proof optional zero-knowledge proof
*/
update(key: string, value: V, proof?: object): Promise<void>;
/**
* Removes the value of given key along with the key.
* Checks if the proof is valid.
* @param key key of the value to be removed
* @param proof optional zero-knowledge proof
*/
remove(key: string, proof?: object): Promise<void>;
}
export class SDK<V = unknown> extends BaseSDK<V, {
proofs: ['auth'];
whitelists: ['put', 'update'];
}> {
}
/** Just like HollowDB SDK, but supports `Set` and `SetMany` operations.
* The user must be whitelisted for `set` separately to use them.
*
* A `set` operation is like a `put` but the key can exist already and will be overwritten.
*/
export class SetSDK<V = unknown> extends BaseSDK<V, {
proofs: ['auth'];
whitelists: ['put', 'update', 'set'];
}> {
/**
* Inserts the given value into database.
*
* Overwrites the existing values at the given key.
*
* @param key the key of the value to be inserted
* @param value the value to be inserted
*/
set(key: string, value: V): Promise<void>;
/**
* Inserts an array of value into database.
*
* Overwrites the existing values at the given keys.
*
* @param keys the keys of the values to be inserted
* @param values the values to be inserted
*/
setMany(keys: string[], values: V[]): Promise<void>;
/**
* Overwrites the contract state.
*
* Note that this is an owner-only operation, and a wrongfully
* overwritten state may break some of the contract methods.
*
* @param state the key of the value to be inserted
*/
setState(state: Awaited<ReturnType<this['getState']>>): Promise<void>;
}
//# sourceMappingURL=index.d.ts.map