ox
Version:
Ethereum Standard Library
507 lines • 15.8 kB
TypeScript
import type * as Abi from './Abi.js';
import * as Errors from './Errors.js';
import * as Hash from './Hash.js';
import * as Hex from './Hex.js';
import * as formatAbiItem from './internal/human-readable/formatAbiItem.js';
import * as parseAbiItem from './internal/human-readable/parseAbiItem.js';
import * as internal from './internal/abiItem.js';
import type { UnionCompute } from './internal/types.js';
/** Root type for an item on an {@link ox#Abi.Abi}. */
export type AbiItem = Abi.Abi[number];
export { InvalidAbiItemError, UnknownSolidityTypeError, UnknownTypeError, } from './internal/human-readable/errors.js';
/**
* Extracts an {@link ox#AbiItem.AbiItem} item from an {@link ox#Abi.Abi}, given a name.
*
* @example
* ```ts twoslash
* import { Abi, AbiItem } from 'ox'
*
* const abi = Abi.from([
* 'error Foo(string)',
* 'function foo(string)',
* 'event Bar(uint256)'
* ])
*
* type Foo = AbiItem.FromAbi<typeof abi, 'Foo'>
* // ^?
* ```
*/
export type FromAbi<abi extends Abi.Abi, name extends ExtractNames<abi>> = Extract<abi[number], {
name: name;
}>;
/**
* Extracts the names of all {@link ox#AbiItem.AbiItem} items in an {@link ox#Abi.Abi}.
*
* @example
* ```ts twoslash
* import { Abi, AbiItem } from 'ox'
*
* const abi = Abi.from([
* 'error Foo(string)',
* 'function foo(string)',
* 'event Bar(uint256)'
* ])
*
* type names = AbiItem.Name<typeof abi>
* // ^?
* ```
*/
export type Name<abi extends Abi.Abi | readonly unknown[] = Abi.Abi> = abi extends Abi.Abi ? ExtractNames<abi> : string;
export type ExtractNames<abi extends Abi.Abi> = Extract<abi[number], {
name: string;
}>['name'];
/**
* Formats an {@link ox#AbiItem.AbiItem} into a **Human Readable ABI Item**.
*
* @example
* ```ts twoslash
* import { AbiItem } from 'ox'
*
* const formatted = AbiItem.format({
* type: 'function',
* name: 'approve',
* stateMutability: 'nonpayable',
* inputs: [
* {
* name: 'spender',
* type: 'address'
* },
* {
* name: 'amount',
* type: 'uint256'
* }
* ],
* outputs: [{ type: 'bool' }]
* })
*
* formatted
* // ^?
* ```
*
* @param abiItem - The ABI Item to format.
* @returns The formatted ABI Item .
*/
export declare function format<const abiItem extends AbiItem>(abiItem: abiItem | AbiItem): format.ReturnType<abiItem>;
export declare namespace format {
type ReturnType<abiItem extends AbiItem = AbiItem> = formatAbiItem.FormatAbiItem<abiItem>;
type ErrorType = Errors.GlobalErrorType;
}
/**
* Parses an arbitrary **JSON ABI Item** or **Human Readable ABI Item** into a typed {@link ox#AbiItem.AbiItem}.
*
* @example
* ### JSON ABIs
*
* ```ts twoslash
* import { AbiItem } from 'ox'
*
* const abiItem = AbiItem.from({
* type: 'function',
* name: 'approve',
* stateMutability: 'nonpayable',
* inputs: [
* {
* name: 'spender',
* type: 'address'
* },
* {
* name: 'amount',
* type: 'uint256'
* }
* ],
* outputs: [{ type: 'bool' }]
* })
*
* abiItem
* //^?
* ```
*
* @example
* ### Human Readable ABIs
*
* A Human Readable ABI can be parsed into a typed ABI object:
*
* ```ts twoslash
* import { AbiItem } from 'ox'
*
* const abiItem = AbiItem.from(
* 'function approve(address spender, uint256 amount) returns (bool)' // [!code hl]
* )
*
* abiItem
* //^?
* ```
*
* @example
* It is possible to specify `struct`s along with your definitions:
*
* ```ts twoslash
* import { AbiItem } from 'ox'
*
* const abiItem = AbiItem.from([
* 'struct Foo { address spender; uint256 amount; }', // [!code hl]
* 'function approve(Foo foo) returns (bool)'
* ])
*
* abiItem
* //^?
* ```
*
*
*
* @param abiItem - The ABI Item to parse.
* @returns The typed ABI Item.
*/
export declare function from<const abiItem extends AbiItem | string | readonly string[]>(abiItem: (abiItem | AbiItem | string | readonly string[]) & ((abiItem extends string ? internal.Signature<abiItem> : never) | (abiItem extends readonly string[] ? internal.Signatures<abiItem> : never) | AbiItem), options?: from.Options): from.ReturnType<abiItem>;
export declare namespace from {
type Options = {
/**
* Whether or not to prepare the extracted item (optimization for encoding performance).
* When `true`, the `hash` property is computed and included in the returned value.
*
* @default true
*/
prepare?: boolean | undefined;
};
type ReturnType<abiItem extends AbiItem | string | readonly string[]> = abiItem extends string ? parseAbiItem.ParseAbiItem<abiItem> : abiItem extends readonly string[] ? parseAbiItem.ParseAbiItem<abiItem> : abiItem;
type ErrorType = Errors.GlobalErrorType;
}
/**
* Extracts an {@link ox#AbiItem.AbiItem} from an {@link ox#Abi.Abi} given a name and optional arguments.
*
* @example
* ABI Items can be extracted by their name using the `name` option:
*
* ```ts twoslash
* import { Abi, AbiItem } from 'ox'
*
* const abi = Abi.from([
* 'function foo()',
* 'event Transfer(address owner, address to, uint256 tokenId)',
* 'function bar(string a) returns (uint256 x)'
* ])
*
* const item = AbiItem.fromAbi(abi, 'Transfer') // [!code focus]
* // ^?
* ```
*
* @example
* ### Extracting by Selector
*
* ABI Items can be extract by their selector when {@link ox#Hex.Hex} is provided to `name`.
*
* ```ts twoslash
* import { Abi, AbiItem } from 'ox'
*
* const abi = Abi.from([
* 'function foo()',
* 'event Transfer(address owner, address to, uint256 tokenId)',
* 'function bar(string a) returns (uint256 x)'
* ])
* const item = AbiItem.fromAbi(abi, '0x095ea7b3') // [!code focus]
* // ^?
* ```
*
* :::note
*
* Extracting via a hex selector is useful when extracting an ABI Item from an `eth_call` RPC response,
* a Transaction `input`, or from Event Log `topics`.
*
* :::
*
* @param abi - The ABI to extract from.
* @param name - The name (or selector) of the ABI item to extract.
* @param options - Extraction options.
* @returns The ABI item.
*/
export declare function fromAbi<const abi extends Abi.Abi | readonly unknown[], name extends Name<abi>, const args extends internal.ExtractArgs<abi, name> | undefined = undefined, allNames = Name<abi>>(abi: abi | Abi.Abi | readonly unknown[], name: Hex.Hex | (name extends allNames ? name : never), options?: fromAbi.Options<abi, name, args>): fromAbi.ReturnType<abi, name, args>;
export declare namespace fromAbi {
type Options<abi extends Abi.Abi | readonly unknown[] = Abi.Abi, name extends Name<abi> = Name<abi>, args extends internal.ExtractArgs<abi, name> | undefined = internal.ExtractArgs<abi, name>, allArgs = internal.ExtractArgs<abi, name>> = {
/**
* Whether or not to prepare the extracted item (optimization for encoding performance).
* When `true`, the `hash` property is computed and included in the returned value.
*
* @default true
*/
prepare?: boolean | undefined;
} & UnionCompute<readonly [] extends allArgs ? {
args?: allArgs | (abi extends Abi.Abi ? args extends allArgs ? internal.Widen<args> : never : never) | undefined;
} : {
args?: allArgs | (internal.Widen<args> & (args extends allArgs ? unknown : never)) | undefined;
}>;
type ReturnType<abi extends Abi.Abi | readonly unknown[] = Abi.Abi, name extends Name<abi> = Name<abi>, args extends internal.ExtractArgs<abi, name> | undefined = internal.ExtractArgs<abi, name>, fallback = AbiItem> = abi extends Abi.Abi ? Abi.Abi extends abi ? fallback : internal.ExtractForArgs<abi, name, args extends internal.ExtractArgs<abi, name> ? args : internal.ExtractArgs<abi, name>> : fallback;
type ErrorType = Errors.GlobalErrorType;
}
/**
* Computes the [4-byte selector](https://solidity-by-example.org/function-selector/) for an {@link ox#AbiItem.AbiItem}.
*
* Useful for computing function selectors for calldata.
*
* @example
* ```ts twoslash
* import { AbiItem } from 'ox'
*
* const selector = AbiItem.getSelector(
* 'function ownerOf(uint256 tokenId)'
* )
* // @log: '0x6352211e'
* ```
*
* @example
* ```ts twoslash
* // @noErrors
* import { Abi, AbiItem } from 'ox'
*
* const erc20Abi = Abi.from([...])
*
* const selector = AbiItem.getSelector(erc20Abi, 'ownerOf')
* // @log: '0x6352211e'
* ```
*
* @example
* ```ts twoslash
* import { AbiItem } from 'ox'
*
* const selector = AbiItem.getSelector({
* inputs: [{ type: 'uint256' }],
* name: 'ownerOf',
* outputs: [],
* stateMutability: 'view',
* type: 'function'
* })
* // @log: '0x6352211e'
* ```
*
* @param abiItem - The ABI item to compute the selector for. Can be a signature or an ABI item for an error, event, function, etc.
* @returns The first 4 bytes of the {@link ox#Hash.(keccak256:function)} hash of the function signature.
*/
export declare function getSelector<abi extends Abi.Abi | readonly unknown[], name extends Name<abi>>(abi: abi | Abi.Abi | readonly unknown[], name: name): Hex.Hex;
export declare function getSelector(abiItem: string | AbiItem): Hex.Hex;
export declare namespace getSelector {
type ErrorType = getSignatureHash.ErrorType | Hex.slice.ErrorType | Errors.GlobalErrorType;
}
/**
* Computes the stringified signature for a given {@link ox#AbiItem.AbiItem}.
*
* @example
* ```ts twoslash
* import { AbiItem } from 'ox'
*
* const signature = AbiItem.getSignature(
* 'function ownerOf(uint256 tokenId)'
* )
* // @log: 'ownerOf(uint256)'
* ```
*
* @example
* ```ts twoslash
* // @noErrors
* import { Abi, AbiItem } from 'ox'
*
* const erc20Abi = Abi.from([...])
*
* const signature = AbiItem.getSignature(erc20Abi, 'ownerOf')
* // @log: 'ownerOf(uint256)'
* ```
*
* @example
* ```ts twoslash
* import { AbiItem } from 'ox'
*
* const signature = AbiItem.getSignature({
* name: 'ownerOf',
* type: 'function',
* inputs: [{ name: 'tokenId', type: 'uint256' }],
* outputs: [],
* stateMutability: 'view'
* })
* // @log: 'ownerOf(uint256)'
* ```
*
* @param abiItem - The ABI Item to compute the signature for.
* @returns The stringified signature of the ABI Item.
*/
export declare function getSignature<abi extends Abi.Abi | readonly unknown[], name extends Name<abi>>(abi: abi | Abi.Abi | readonly unknown[], name: name): string;
export declare function getSignature(abiItem: string | AbiItem): string;
export declare namespace getSignature {
type ErrorType = internal.normalizeSignature.ErrorType | Errors.GlobalErrorType;
}
/**
* Computes the signature hash for an {@link ox#AbiItem.AbiItem}.
*
* Useful for computing Event Topic values.
*
* @example
* ```ts twoslash
* import { AbiItem } from 'ox'
*
* const hash = AbiItem.getSignatureHash(
* 'event Transfer(address indexed from, address indexed to, uint256 amount)'
* )
* // @log: '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef'
* ```
*
* @example
* ```ts twoslash
* // @noErrors
* import { Abi, AbiItem } from 'ox'
*
* const erc20Abi = Abi.from([...])
*
* const hash = AbiItem.getSignatureHash(erc20Abi, 'Transfer')
* // @log: '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef'
* ```
*
* @example
* ```ts twoslash
* import { AbiItem } from 'ox'
*
* const hash = AbiItem.getSignatureHash({
* name: 'Transfer',
* type: 'event',
* inputs: [
* { name: 'from', type: 'address', indexed: true },
* { name: 'to', type: 'address', indexed: true },
* { name: 'amount', type: 'uint256', indexed: false }
* ]
* })
* // @log: '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef'
* ```
*
* @param abiItem - The ABI Item to compute the signature hash for.
* @returns The {@link ox#Hash.(keccak256:function)} hash of the ABI item's signature.
*/
export declare function getSignatureHash<abi extends Abi.Abi | readonly unknown[], name extends Name<abi>>(abi: abi | Abi.Abi | readonly unknown[], name: name): Hex.Hex;
export declare function getSignatureHash(abiItem: string | AbiItem): Hex.Hex;
export declare namespace getSignatureHash {
type ErrorType = getSignature.ErrorType | Hash.keccak256.ErrorType | Hex.fromString.ErrorType | Errors.GlobalErrorType;
}
/**
* Throws when ambiguous types are found on overloaded ABI items.
*
* @example
* ```ts twoslash
* import { Abi, AbiFunction } from 'ox'
*
* const foo = Abi.from([
* 'function foo(address)',
* 'function foo(bytes20)'
* ])
* AbiFunction.fromAbi(foo, 'foo', {
* args: ['0xA0Cf798816D4b9b9866b5330EEa46a18382f251e']
* })
* // @error: AbiItem.AmbiguityError: Found ambiguous types in overloaded ABI Items.
* // @error: `bytes20` in `foo(bytes20)`, and
* // @error: `address` in `foo(address)`
* // @error: These types encode differently and cannot be distinguished at runtime.
* // @error: Remove one of the ambiguous items in the ABI.
* ```
*
* ### Solution
*
* Remove one of the ambiguous types from the ABI.
*
* ```ts twoslash
* import { Abi, AbiFunction } from 'ox'
*
* const foo = Abi.from([
* 'function foo(address)',
* 'function foo(bytes20)' // [!code --]
* ])
* AbiFunction.fromAbi(foo, 'foo', {
* args: ['0xA0Cf798816D4b9b9866b5330EEa46a18382f251e']
* })
* // @error: AbiItem.AmbiguityError: Found ambiguous types in overloaded ABI Items.
* // @error: `bytes20` in `foo(bytes20)`, and
* // @error: `address` in `foo(address)`
* // @error: These types encode differently and cannot be distinguished at runtime.
* // @error: Remove one of the ambiguous items in the ABI.
* ```
*/
export declare class AmbiguityError extends Errors.BaseError {
readonly name = "AbiItem.AmbiguityError";
constructor(x: {
abiItem: Abi.Abi[number];
type: string;
}, y: {
abiItem: Abi.Abi[number];
type: string;
});
}
/**
* Throws when an ABI item is not found in the ABI.
*
* @example
* ```ts twoslash
* // @noErrors
* import { Abi, AbiFunction } from 'ox'
*
* const foo = Abi.from([
* 'function foo(address)',
* 'function bar(uint)'
* ])
* AbiFunction.fromAbi(foo, 'baz')
* // @error: AbiItem.NotFoundError: ABI function with name "baz" not found.
* ```
*
* ### Solution
*
* Ensure the ABI item exists on the ABI.
*
* ```ts twoslash
* // @noErrors
* import { Abi, AbiFunction } from 'ox'
*
* const foo = Abi.from([
* 'function foo(address)',
* 'function bar(uint)',
* 'function baz(bool)' // [!code ++]
* ])
* AbiFunction.fromAbi(foo, 'baz')
* ```
*/
export declare class NotFoundError extends Errors.BaseError {
readonly name = "AbiItem.NotFoundError";
constructor({ name, data, type, }: {
name?: string | undefined;
data?: Hex.Hex | undefined;
type?: string | undefined;
});
}
/**
* Throws when the selector size is invalid.
*
* @example
* ```ts twoslash
* import { Abi, AbiFunction } from 'ox'
*
* const foo = Abi.from([
* 'function foo(address)',
* 'function bar(uint)'
* ])
* AbiFunction.fromAbi(foo, '0xaaa')
* // @error: AbiItem.InvalidSelectorSizeError: Selector size is invalid. Expected 4 bytes. Received 2 bytes ("0xaaa").
* ```
*
* ### Solution
*
* Ensure the selector size is 4 bytes.
*
* ```ts twoslash
* // @noErrors
* import { Abi, AbiFunction } from 'ox'
*
* const foo = Abi.from([
* 'function foo(address)',
* 'function bar(uint)'
* ])
* AbiFunction.fromAbi(foo, '0x7af82b1a')
* ```
*/
export declare class InvalidSelectorSizeError extends Errors.BaseError {
readonly name = "AbiItem.InvalidSelectorSizeError";
constructor({ data }: {
data: Hex.Hex;
});
}
//# sourceMappingURL=AbiItem.d.ts.map