UNPKG

ox

Version:

Ethereum Standard Library

512 lines 18.4 kB
import type * as abitype from 'abitype'; import * as AbiParameters from './AbiParameters.js'; import * as Address from './Address.js'; import * as Bytes from './Bytes.js'; import * as Errors from './Errors.js'; import * as Hash from './Hash.js'; import * as Hex from './Hex.js'; import type { Compute } from './internal/types.js'; import * as Json from './Json.js'; export type TypedData = abitype.TypedData; export type Domain = abitype.TypedDataDomain; export type Parameter = abitype.TypedDataParameter; export type Definition<typedData extends TypedData | Record<string, unknown> = TypedData, primaryType extends keyof typedData | 'EIP712Domain' = keyof typedData, primaryTypes = typedData extends TypedData ? keyof typedData : string> = primaryType extends 'EIP712Domain' ? EIP712DomainDefinition<typedData, primaryType> : MessageDefinition<typedData, primaryType, primaryTypes>; export type EIP712DomainDefinition<typedData extends TypedData | Record<string, unknown> = TypedData, primaryType extends 'EIP712Domain' = 'EIP712Domain', schema extends Record<string, unknown> = typedData extends TypedData ? abitype.TypedDataToPrimitiveTypes<typedData> : Record<string, unknown>> = { types?: typedData | undefined; } & { primaryType: 'EIP712Domain' | (primaryType extends 'EIP712Domain' ? primaryType : never); domain: schema extends { EIP712Domain: infer domain; } ? domain : Compute<Domain>; message?: undefined; }; export type MessageDefinition<typedData extends TypedData | Record<string, unknown> = TypedData, primaryType extends keyof typedData = keyof typedData, primaryTypes = typedData extends TypedData ? keyof typedData : string, schema extends Record<string, unknown> = typedData extends TypedData ? abitype.TypedDataToPrimitiveTypes<typedData> : Record<string, unknown>, message = schema[primaryType extends keyof schema ? primaryType : keyof schema]> = { types: typedData; } & { primaryType: primaryTypes | (primaryType extends primaryTypes ? primaryType : never); domain?: (schema extends { EIP712Domain: infer domain; } ? domain : Compute<Domain>) | undefined; message: { [_: string]: any; } extends message ? Record<string, unknown> : message; }; /** * Asserts that [EIP-712 Typed Data](https://eips.ethereum.org/EIPS/eip-712) is valid. * * @example * ```ts twoslash * import { TypedData } from 'ox' * * TypedData.assert({ * domain: { * name: 'Ether!', * version: '1', * chainId: 1, * verifyingContract: * '0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC' * }, * primaryType: 'Foo', * types: { * Foo: [ * { name: 'address', type: 'address' }, * { name: 'name', type: 'string' }, * { name: 'foo', type: 'string' } * ] * }, * message: { * address: '0xb9CAB4F0E46F7F6b1024b5A7463734fa68E633f9', * name: 'jxom', * foo: '0xb9CAB4F0E46F7F6b1024b5A7463734fa68E633f9' * } * }) * ``` * * @param value - The Typed Data to validate. */ export declare function assert<const typedData extends TypedData | Record<string, unknown>, primaryType extends keyof typedData | 'EIP712Domain'>(value: assert.Value<typedData, primaryType>): void; export declare namespace assert { type Value<typedData extends TypedData | Record<string, unknown> = TypedData, primaryType extends keyof typedData | 'EIP712Domain' = keyof typedData> = Definition<typedData, primaryType>; type ErrorType = Address.InvalidAddressError | BytesSizeMismatchError | InvalidArrayError | InvalidArrayLengthError | InvalidPrimaryTypeError | Hex.fromNumber.ErrorType | Hex.size.ErrorType | Errors.GlobalErrorType; } /** * Creates [EIP-712 Typed Data](https://eips.ethereum.org/EIPS/eip-712) [`domainSeparator`](https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator) for the provided domain. * * @example * ```ts twoslash * import { TypedData } from 'ox' * * TypedData.domainSeparator({ * name: 'Ether!', * version: '1', * chainId: 1, * verifyingContract: * '0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC' * }) * // @log: '0x9911ee4f58a7059a8f5385248040e6984d80e2c849500fe6a4d11c4fa98c2af3' * ``` * * @param domain - The domain for which to create the domain separator. * @returns The domain separator. */ export declare function domainSeparator(domain: Domain): Hex.Hex; export declare namespace domainSeparator { type ErrorType = hashDomain.ErrorType | Errors.GlobalErrorType; } /** * Encodes typed data in [EIP-712 format](https://eips.ethereum.org/EIPS/eip-712): `0x19 ‖ 0x01 ‖ domainSeparator ‖ hashStruct(message)`. * * @example * ```ts twoslash * import { TypedData, Hash } from 'ox' * * const data = TypedData.encode({ * // [!code focus:33] * domain: { * name: 'Ether Mail', * version: '1', * chainId: 1, * verifyingContract: * '0x0000000000000000000000000000000000000000' * }, * types: { * Person: [ * { name: 'name', type: 'string' }, * { name: 'wallet', type: 'address' } * ], * Mail: [ * { name: 'from', type: 'Person' }, * { name: 'to', type: 'Person' }, * { name: 'contents', type: 'string' } * ] * }, * primaryType: 'Mail', * message: { * from: { * name: 'Cow', * wallet: '0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826' * }, * to: { * name: 'Bob', * wallet: '0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB' * }, * contents: 'Hello, Bob!' * } * }) * // @log: '0x19012fdf3441fcaf4f30c7e16292b258a5d7054a4e2e00dbd7b7d2f467f2b8fb9413c52c0ee5d84264471806290a3f2c4cecfc5490626bf912d01f240d7a274b371e' * // @log: (0x19 ‖ 0x01 ‖ domainSeparator ‖ hashStruct(message)) * * const hash = Hash.keccak256(data) * ``` * * @param value - The Typed Data to encode. * @returns The encoded Typed Data. */ export declare function encode<const typedData extends TypedData | Record<string, unknown>, primaryType extends keyof typedData | 'EIP712Domain'>(value: encode.Value<typedData, primaryType>): Hex.Hex; export declare namespace encode { type Value<typedData extends TypedData | Record<string, unknown> = TypedData, primaryType extends keyof typedData | 'EIP712Domain' = keyof typedData> = Definition<typedData, primaryType>; type ErrorType = extractEip712DomainTypes.ErrorType | hashDomain.ErrorType | hashStruct.ErrorType | assert.ErrorType | Errors.GlobalErrorType; } /** * Encodes [EIP-712 Typed Data](https://eips.ethereum.org/EIPS/eip-712) schema for the provided primaryType. * * @example * ```ts twoslash * import { TypedData } from 'ox' * * TypedData.encodeType({ * types: { * Foo: [ * { name: 'address', type: 'address' }, * { name: 'name', type: 'string' }, * { name: 'foo', type: 'string' } * ] * }, * primaryType: 'Foo' * }) * // @log: 'Foo(address address,string name,string foo)' * ``` * * @param value - The Typed Data schema. * @returns The encoded type. */ export declare function encodeType(value: encodeType.Value): string; export declare namespace encodeType { type Value = { primaryType: string; types: TypedData; }; type ErrorType = findTypeDependencies.ErrorType | Errors.GlobalErrorType; } /** * Gets [EIP-712 Typed Data](https://eips.ethereum.org/EIPS/eip-712) schema for EIP-721 domain. * * @example * ```ts twoslash * import { TypedData } from 'ox' * * TypedData.extractEip712DomainTypes({ * name: 'Ether!', * version: '1', * chainId: 1, * verifyingContract: * '0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC' * }) * // @log: [ * // @log: { 'name': 'name', 'type': 'string' }, * // @log: { 'name': 'version', 'type': 'string' }, * // @log: { 'name': 'chainId', 'type': 'uint256' }, * // @log: { 'name': 'verifyingContract', 'type': 'address' }, * // @log: ] * ``` * * @param domain - The EIP-712 domain. * @returns The EIP-712 domain schema. */ export declare function extractEip712DomainTypes(domain: Domain | undefined): Parameter[]; export declare namespace extractEip712DomainTypes { type ErrorType = Errors.GlobalErrorType; } /** * Gets the payload to use for signing typed data in [EIP-712 format](https://eips.ethereum.org/EIPS/eip-712). * * @example * ```ts twoslash * import { Secp256k1, TypedData, Hash } from 'ox' * * const payload = TypedData.getSignPayload({ * // [!code focus:99] * domain: { * name: 'Ether Mail', * version: '1', * chainId: 1, * verifyingContract: * '0x0000000000000000000000000000000000000000' * }, * types: { * Person: [ * { name: 'name', type: 'string' }, * { name: 'wallet', type: 'address' } * ], * Mail: [ * { name: 'from', type: 'Person' }, * { name: 'to', type: 'Person' }, * { name: 'contents', type: 'string' } * ] * }, * primaryType: 'Mail', * message: { * from: { * name: 'Cow', * wallet: '0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826' * }, * to: { * name: 'Bob', * wallet: '0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB' * }, * contents: 'Hello, Bob!' * } * }) * * const signature = Secp256k1.sign({ * payload, * privateKey: '0x...' * }) * ``` * * @param value - The typed data to get the sign payload for. * @returns The payload to use for signing. */ export declare function getSignPayload<const typedData extends TypedData | Record<string, unknown>, primaryType extends keyof typedData | 'EIP712Domain'>(value: encode.Value<typedData, primaryType>): Hex.Hex; export declare namespace getSignPayload { type ErrorType = Hash.keccak256.ErrorType | encode.ErrorType | Errors.GlobalErrorType; } /** * Hashes [EIP-712 Typed Data](https://eips.ethereum.org/EIPS/eip-712) domain. * * @example * ```ts twoslash * import { TypedData } from 'ox' * * TypedData.hashDomain({ * domain: { * name: 'Ether Mail', * version: '1', * chainId: 1, * verifyingContract: * '0x0000000000000000000000000000000000000000' * } * }) * // @log: '0x6192106f129ce05c9075d319c1fa6ea9b3ae37cbd0c1ef92e2be7137bb07baa1' * ``` * * @param value - The Typed Data domain and types. * @returns The hashed domain. */ export declare function hashDomain(value: hashDomain.Value): Hex.Hex; export declare namespace hashDomain { type Value = { /** The Typed Data domain. */ domain: Domain; /** The Typed Data types. */ types?: { EIP712Domain?: readonly Parameter[] | undefined; [key: string]: readonly Parameter[] | undefined; } | undefined; /** Optional cache of `keccak256(encodeType(t))` keyed by type name, shared across nested struct/array calls. */ typeHashes?: Map<string, Hex.Hex> | undefined; }; type ErrorType = hashStruct.ErrorType | Errors.GlobalErrorType; } /** * Hashes [EIP-712 Typed Data](https://eips.ethereum.org/EIPS/eip-712) struct. * * @example * ```ts twoslash * import { TypedData } from 'ox' * * TypedData.hashStruct({ * types: { * Foo: [ * { name: 'address', type: 'address' }, * { name: 'name', type: 'string' }, * { name: 'foo', type: 'string' } * ] * }, * primaryType: 'Foo', * data: { * address: '0xb9CAB4F0E46F7F6b1024b5A7463734fa68E633f9', * name: 'jxom', * foo: '0xb9CAB4F0E46F7F6b1024b5A7463734fa68E633f9' * } * }) * // @log: '0x996fb3b6d48c50312d69abdd4c1b6fb02057c85aa86bb8d04c6f023326a168ce' * ``` * * @param value - The Typed Data struct to hash. * @returns The hashed Typed Data struct. */ export declare function hashStruct(value: hashStruct.Value): Hex.Hex; export declare namespace hashStruct { type Value = { /** The Typed Data struct to hash. */ data: Record<string, unknown>; /** The primary type of the Typed Data struct. */ primaryType: string; /** The types of the Typed Data struct. */ types: TypedData; /** Optional cache of `keccak256(encodeType(t))` keyed by type name, shared across nested struct/array calls. */ typeHashes?: Map<string, Hex.Hex> | undefined; }; type ErrorType = encodeData.ErrorType | Hash.keccak256.ErrorType | Errors.GlobalErrorType; } /** * Serializes [EIP-712 Typed Data](https://eips.ethereum.org/EIPS/eip-712) schema into string. * * @example * ```ts twoslash * import { TypedData } from 'ox' * * TypedData.serialize({ * domain: { * name: 'Ether!', * version: '1', * chainId: 1, * verifyingContract: * '0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC' * }, * primaryType: 'Foo', * types: { * Foo: [ * { name: 'address', type: 'address' }, * { name: 'name', type: 'string' }, * { name: 'foo', type: 'string' } * ] * }, * message: { * address: '0xb9CAB4F0E46F7F6b1024b5A7463734fa68E633f9', * name: 'jxom', * foo: '0xb9CAB4F0E46F7F6b1024b5A7463734fa68E633f9' * } * }) * // @log: "{"domain":{},"message":{"address":"0xb9cab4f0e46f7f6b1024b5a7463734fa68e633f9","name":"jxom","foo":"0xb9CAB4F0E46F7F6b1024b5A7463734fa68E633f9"},"primaryType":"Foo","types":{"Foo":[{"name":"address","type":"address"},{"name":"name","type":"string"},{"name":"foo","type":"string"}]}}" * ``` * * @param value - The Typed Data schema to serialize. * @returns The serialized Typed Data schema. w */ export declare function serialize<const typedData extends TypedData | Record<string, unknown>, primaryType extends keyof typedData | 'EIP712Domain'>(value: serialize.Value<typedData, primaryType>): string; export declare namespace serialize { type Value<typedData extends TypedData | Record<string, unknown> = TypedData, primaryType extends keyof typedData | 'EIP712Domain' = keyof typedData> = Definition<typedData, primaryType>; type ErrorType = Json.stringify.ErrorType | Errors.GlobalErrorType; } /** * Checks if [EIP-712 Typed Data](https://eips.ethereum.org/EIPS/eip-712) is valid. * * @example * ```ts twoslash * import { TypedData } from 'ox' * * const valid = TypedData.validate({ * domain: { * name: 'Ether!', * version: '1', * chainId: 1, * verifyingContract: * '0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC' * }, * primaryType: 'Foo', * types: { * Foo: [ * { name: 'address', type: 'address' }, * { name: 'name', type: 'string' }, * { name: 'foo', type: 'string' } * ] * }, * message: { * address: '0xb9CAB4F0E46F7F6b1024b5A7463734fa68E633f9', * name: 'jxom', * foo: '0xb9CAB4F0E46F7F6b1024b5A7463734fa68E633f9' * } * }) * // @log: true * ``` * * @param value - The Typed Data to validate. */ export declare function validate<const typedData extends TypedData | Record<string, unknown>, primaryType extends keyof typedData | 'EIP712Domain'>(value: assert.Value<typedData, primaryType>): boolean; export declare namespace validate { type ErrorType = assert.ErrorType | Errors.GlobalErrorType; } /** Thrown when the bytes size of a typed data value does not match the expected size. */ export declare class BytesSizeMismatchError extends Errors.BaseError { readonly name = "TypedData.BytesSizeMismatchError"; constructor({ expectedSize, givenSize, }: { expectedSize: number; givenSize: number; }); } /** Thrown when the domain is invalid. */ export declare class InvalidDomainError extends Errors.BaseError { readonly name = "TypedData.InvalidDomainError"; constructor({ domain }: { domain: unknown; }); } /** Thrown when the primary type of a typed data value is invalid. */ export declare class InvalidPrimaryTypeError extends Errors.BaseError { readonly name = "TypedData.InvalidPrimaryTypeError"; constructor({ primaryType, types, }: { primaryType: string; types: TypedData | Record<string, unknown>; }); } /** Thrown when the struct type is not a valid type. */ export declare class InvalidStructTypeError extends Errors.BaseError { readonly name = "TypedData.InvalidStructTypeError"; constructor({ type }: { type: string; }); } /** Thrown when an array-typed value is not an array. */ export declare class InvalidArrayError extends Errors.BaseError { readonly name = "TypedData.InvalidArrayError"; constructor({ name, type, value, }: { name: string; type: string; value: unknown; }); } /** Thrown when a fixed-length array does not match its declared length. */ export declare class InvalidArrayLengthError extends Errors.BaseError { readonly name = "TypedData.InvalidArrayLengthError"; constructor({ name, type, expectedLength, givenLength, }: { name: string; type: string; expectedLength: number; givenLength: number; }); } /** @internal */ export declare function encodeData(value: { data: Record<string, unknown>; primaryType: string; types: TypedData; typeHashes?: Map<string, Hex.Hex> | undefined; }): Hex.Hex; /** @internal */ export declare namespace encodeData { type ErrorType = AbiParameters.encode.ErrorType | encodeField.ErrorType | hashType.ErrorType | Errors.GlobalErrorType; } /** @internal */ export declare function hashType(value: { primaryType: string; types: TypedData; typeHashes?: Map<string, Hex.Hex> | undefined; }): Hex.Hex; /** @internal */ export declare namespace hashType { type ErrorType = Hex.fromString.ErrorType | encodeType.ErrorType | Hash.keccak256.ErrorType | Errors.GlobalErrorType; } /** @internal */ export declare function encodeField(properties: { types: TypedData; name: string; type: string; value: any; typeHashes?: Map<string, Hex.Hex> | undefined; }): [type: AbiParameters.Parameter, value: Hex.Hex]; /** @internal */ export declare namespace encodeField { type ErrorType = AbiParameters.encode.ErrorType | Hash.keccak256.ErrorType | Bytes.fromString.ErrorType | InvalidArrayError | InvalidArrayLengthError | Errors.GlobalErrorType; } /** @internal */ export declare function findTypeDependencies(value: { primaryType: string; types: TypedData; }, results?: Set<string>): Set<string>; /** @internal */ export declare namespace findTypeDependencies { type ErrorType = Errors.GlobalErrorType; } //# sourceMappingURL=TypedData.d.ts.map