evm-randomness
Version:
Minimal, typed SDK skeleton for HyperEVM VRF
269 lines (263 loc) • 8.93 kB
TypeScript
interface HyperevmVrfConfig {
rpcUrl?: string;
vrfAddress?: string;
chainId?: number;
account: {
privateKey: string;
};
policy?: {
mode: "strict" | "window";
window?: number;
};
drand?: {
baseUrl?: string;
fetchTimeoutMs?: number;
beacon?: string;
};
gas?: {
maxFeePerGasGwei?: number;
maxPriorityFeePerGasGwei?: number;
};
}
type FulfillResult = {
requestId: bigint;
round: bigint;
signature: [bigint, bigint];
txHash: `0x${string}`;
};
type RequestResult = {
requestId: bigint;
txHash: `0x${string}`;
};
type RequestAndFulfillResult = {
requestId: bigint;
round: bigint;
signature: [bigint, bigint];
requestTxHash: `0x${string}`;
fulfillTxHash: `0x${string}`;
};
type EphemeralCreateOptions = Omit<HyperevmVrfConfig, 'account'> & {
minBalanceWei?: bigint;
waitTimeoutMs?: number;
pollIntervalMs?: number;
};
type EphemeralCreateResult = {
vrf: HyperEVMVRF;
address: `0x${string}`;
};
declare class HyperEVMVRF {
private readonly cfg;
constructor(cfg: HyperevmVrfConfig);
/**
* Create an instance with an in-memory ephemeral account.
* Returns the address to fund with gas; waits until funded if minBalanceWei provided.
*/
static createEphemeral(options: EphemeralCreateOptions): Promise<EphemeralCreateResult>;
/**
* Validates the VRF request against the configured policy
* @param requestId The VRF request ID
* @param targetRound The target DRAND round
* @param latestRound The latest available DRAND round
* @throws VrfPolicyViolationError if policy is violated
*/
private validatePolicy;
private sleep;
fulfill(requestId: bigint): Promise<FulfillResult>;
/**
* Repeatedly attempts fulfill until the target round is published, with optional timeout.
*/
fulfillWithWait(requestId: bigint, opts?: {
intervalMs?: number;
timeoutMs?: number;
}): Promise<FulfillResult>;
/**
* Requests randomness directly on the VRF contract.
* If consumer is omitted, uses address(0) (no callback).
*/
requestRandomness(args: {
deadline: bigint;
consumer?: string;
salt?: `0x${string}`;
}): Promise<RequestResult>;
/**
* One-shot: request a VRF and then fulfill it when the round is available.
*/
requestAndFulfill(args: {
deadline: bigint;
consumer?: string;
salt?: `0x${string}`;
wait?: {
intervalMs?: number;
timeoutMs?: number;
};
}): Promise<RequestAndFulfillResult>;
}
/**
* Typed error classes for HyperEVM VRF SDK
*/
declare class HyperEVMVrfError extends Error {
readonly code: string;
readonly details?: Record<string, any> | undefined;
constructor(message: string, code: string, details?: Record<string, any> | undefined);
}
declare class VrfRequestError extends HyperEVMVrfError {
readonly requestId: bigint;
constructor(message: string, requestId: bigint, details?: Record<string, any>);
}
declare class VrfRequestAlreadyFulfilledError extends VrfRequestError {
constructor(requestId: bigint);
}
declare class VrfTargetRoundNotPublishedError extends VrfRequestError {
readonly targetRound: bigint;
readonly latestRound: bigint;
readonly secondsLeft: bigint;
constructor(requestId: bigint, targetRound: bigint, latestRound: bigint, secondsLeft: bigint);
}
declare class VrfPolicyViolationError extends VrfRequestError {
readonly policyMode: string;
readonly policyWindow: number;
readonly currentRound: bigint;
readonly targetRound: bigint;
readonly roundDifference: bigint;
constructor(requestId: bigint, policyMode: string, policyWindow: number, currentRound: bigint, targetRound: bigint, roundDifference: bigint);
}
declare class DrandError extends HyperEVMVrfError {
readonly operation: string;
constructor(message: string, operation: string, details?: Record<string, any>);
}
declare class DrandRoundMismatchError extends DrandError {
readonly expectedRound: bigint;
readonly receivedRound: string;
constructor(expectedRound: bigint, receivedRound: string);
}
declare class DrandSignatureError extends DrandError {
readonly signature: string;
readonly expectedLength: number;
readonly actualLength: number;
constructor(signature: string, expectedLength: number, actualLength: number);
}
declare class NetworkError extends HyperEVMVrfError {
readonly url: string;
readonly statusCode?: number | undefined;
constructor(message: string, url: string, statusCode?: number | undefined, details?: Record<string, any>);
}
declare class HttpError extends NetworkError {
readonly statusCode: number;
readonly responseData: string;
constructor(url: string, statusCode: number, responseData: string);
}
declare class JsonParseError extends NetworkError {
readonly responseData: string;
readonly parseError: string;
constructor(url: string, responseData: string, parseError: string);
}
declare class ConfigurationError extends HyperEVMVrfError {
readonly field?: string | undefined;
constructor(message: string, field?: string | undefined, details?: Record<string, any>);
}
declare class ContractError extends HyperEVMVrfError {
readonly contractAddress: string;
readonly operation: string;
constructor(message: string, contractAddress: string, operation: string, details?: Record<string, any>);
}
declare class TransactionError extends HyperEVMVrfError {
readonly txHash: string;
readonly operation: string;
constructor(message: string, txHash: string, operation: string, details?: Record<string, any>);
}
declare const ERROR_CODES: {
readonly VRF_REQUEST_ERROR: "VRF_REQUEST_ERROR";
readonly DRAND_ERROR: "DRAND_ERROR";
readonly NETWORK_ERROR: "NETWORK_ERROR";
readonly CONFIGURATION_ERROR: "CONFIGURATION_ERROR";
readonly CONTRACT_ERROR: "CONTRACT_ERROR";
readonly TRANSACTION_ERROR: "TRANSACTION_ERROR";
};
type ErrorCode = typeof ERROR_CODES[keyof typeof ERROR_CODES];
declare const defaultConfig: Required<Pick<HyperevmVrfConfig, "rpcUrl" | "vrfAddress" | "chainId" | "policy" | "drand">>;
declare function validateConfig(config: Partial<HyperevmVrfConfig>): void;
declare const defaultVRFABI: ({
inputs: {
internalType: string;
name: string;
type: string;
}[];
stateMutability: string;
type: string;
name?: undefined;
anonymous?: undefined;
outputs?: undefined;
} | {
inputs: {
internalType: string;
name: string;
type: string;
}[];
name: string;
type: string;
stateMutability?: undefined;
anonymous?: undefined;
outputs?: undefined;
} | {
anonymous: boolean;
inputs: {
indexed: boolean;
internalType: string;
name: string;
type: string;
}[];
name: string;
type: string;
stateMutability?: undefined;
outputs?: undefined;
} | {
inputs: {
internalType: string;
name: string;
type: string;
}[];
name: string;
outputs: {
components: {
internalType: string;
name: string;
type: string;
}[];
internalType: string;
name: string;
type: string;
}[];
stateMutability: string;
type: string;
anonymous?: undefined;
} | {
inputs: {
internalType: string;
name: string;
type: string;
}[];
name: string;
outputs: {
internalType: string;
name: string;
type: string;
}[];
stateMutability: string;
type: string;
anonymous?: undefined;
})[];
type ChainConfig = {
name: string;
chainId: number;
rpcUrl: string;
drandBeacon: string;
vrfAddress?: string;
};
/**
* Minimal chain registry. Extend as needed.
*/
declare const CHAINS: Record<number, ChainConfig>;
declare function resolveChain(chainId?: number): ChainConfig | undefined;
type CreateEphemeralWalletOptions = Parameters<typeof HyperEVMVRF.createEphemeral>[0];
declare function createEphemeralWallet(options: CreateEphemeralWalletOptions): Promise<EphemeralCreateResult>;
export { CHAINS, type ChainConfig, ConfigurationError, ContractError, type CreateEphemeralWalletOptions, DrandError, DrandRoundMismatchError, DrandSignatureError, ERROR_CODES, type EphemeralCreateOptions, type EphemeralCreateResult, type ErrorCode, HttpError, HyperEVMVRF, HyperEVMVrfError, type HyperevmVrfConfig, JsonParseError, NetworkError, type RequestAndFulfillResult, type RequestResult, TransactionError, VrfPolicyViolationError, VrfRequestAlreadyFulfilledError, VrfRequestError, VrfTargetRoundNotPublishedError, createEphemeralWallet, defaultConfig, defaultVRFABI, resolveChain, validateConfig };