ox
Version:
Ethereum Standard Library
313 lines • 9.82 kB
TypeScript
import * as Address from '../core/Address.js';
import type * as Bytes from '../core/Bytes.js';
import * as Errors from '../core/Errors.js';
import * as Hash from '../core/Hash.js';
import * as Hex from '../core/Hex.js';
import type { Compute, OneOf } from '../core/internal/types.js';
/** Maximum number of owners allowed in a native multisig config. */
export declare const maxOwners = 255;
/** Maximum threshold accepted by a native multisig config. */
export declare const maxThreshold = 8;
/** Maximum number of owner approvals in a native multisig signature. */
export declare const maxSignatures = 8;
/**
* Maximum number of native multisig signatures in one nested authorization
* path, including the top-level transaction signature.
*/
export declare const maxNestingDepth = 2;
/** Maximum encoded byte length for one owner approval. */
export declare const maxOwnerSignatureBytes = 2049;
/** Tempo signature type byte for native multisig signatures. */
export declare const signatureTypeByte: "0x05";
/** Zero 32-byte salt (the default when no salt is provided). */
export declare const zeroSalt: `0x${string}`;
/**
* Native multisig configuration. Determines the stable multisig account
* address.
*/
export type Config<numberType = number> = Compute<{
/**
* Caller-chosen 32-byte salt mixed into the derived account address.
* Defaults to the zero salt (`MultisigConfig.zeroSalt`) when omitted.
*/
salt?: Hex.Hex | undefined;
/** Minimum total owner weight required to authorize a transaction. */
threshold: numberType;
/** Weighted owner list (strictly ascending by `owner` address). */
owners: readonly Owner<numberType>[];
}>;
/** Native multisig owner entry. */
export type Owner<numberType = number> = {
/** Owner address (recovered from the owner's approval). */
owner: Address.Address;
/** Nonzero owner weight. */
weight: numberType;
};
/** RLP tuple representation of a {@link ox#MultisigConfig.Config}. */
export type Tuple = readonly [
salt: Hex.Hex,
threshold: Hex.Hex,
owners: readonly Hex.Hex[][]
];
/**
* Asserts that a native multisig {@link ox#MultisigConfig.Config} is valid.
*
* Mirrors the Tempo `InitMultisig::validate` rules: owners non-empty and
* `<= maxOwners`, strictly ascending unique nonzero owner addresses, nonzero
* integer owner weights, integer `threshold` between `1` and `maxThreshold`,
* total weight `<= 255` (u8 max), and `threshold <= total weight`.
*
* @example
* ```ts twoslash
* import { MultisigConfig } from 'ox/tempo'
*
* MultisigConfig.assert({
* threshold: 1,
* owners: [
* {
* owner: '0x1111111111111111111111111111111111111111',
* weight: 1
* }
* ]
* })
* ```
*
* @param config - The multisig config.
*/
export declare function assert<numberType = number>(config: Config<numberType>): void;
export declare namespace assert {
type ErrorType = InvalidConfigError | Errors.GlobalErrorType;
}
/**
* Normalizes a native multisig {@link ox#MultisigConfig.Config}.
*
* Sorts owners into strictly ascending `owner` address order (the canonical
* form required for account derivation) and asserts the config is valid.
*
* @example
* ```ts twoslash
* import { MultisigConfig } from 'ox/tempo'
*
* const config = MultisigConfig.from({
* threshold: 2,
* owners: [
* {
* owner: '0x2222222222222222222222222222222222222222',
* weight: 1
* },
* {
* owner: '0x1111111111111111111111111111111111111111',
* weight: 1
* }
* ]
* })
* // owners are now sorted ascending by address
* ```
*
* @param config - The multisig config.
* @returns The normalized multisig config.
*/
export declare function from<numberType = number>(config: Config<numberType>): Config<numberType>;
/**
* Converts an RLP {@link ox#MultisigConfig.Tuple} back to a
* {@link ox#MultisigConfig.Config}.
*
* @example
* ```ts twoslash
* import { MultisigConfig } from 'ox/tempo'
*
* const config = MultisigConfig.fromTuple([
* `0x${'00'.repeat(32)}`,
* '0x01',
* [['0x1111111111111111111111111111111111111111', '0x01']]
* ])
* ```
*
* @param tuple - The RLP tuple.
* @returns The multisig config.
*/
export declare function fromTuple(tuple: Tuple): Config;
/**
* Derives the stable native multisig account address.
*
* Preimage (fixed-width big-endian, **not** RLP):
* `keccak256("tempo:multisig:account" || salt || u8(threshold) || u8(owners.length) || (owner || u8(weight)) for each owner)[12:32]`.
*
* The address is derived once from the initial (bootstrap) config and never
* changes — config updates do not affect it.
*
* @example
* ```ts twoslash
* import { MultisigConfig } from 'ox/tempo'
*
* const genesisConfig = MultisigConfig.from({
* threshold: 1,
* owners: [
* {
* owner: '0x1111111111111111111111111111111111111111',
* weight: 1
* }
* ]
* })
*
* const address = MultisigConfig.getAddress(genesisConfig)
* ```
*
* @param config - The initial (bootstrap) multisig config.
* @returns The multisig account address.
*/
export declare function getAddress(config: Config): Address.Address;
export declare namespace getAddress {
type ErrorType = assert.ErrorType | Address.from.ErrorType | Hash.keccak256.ErrorType | Hex.concat.ErrorType | Hex.fromNumber.ErrorType | Hex.fromString.ErrorType | Hex.slice.ErrorType | Errors.GlobalErrorType;
}
/**
* Computes the digest a native multisig owner approves (signs).
*
* `keccak256("tempo:multisig:signature" || inner_digest || account)`,
* where `inner_digest` is the transaction sign payload
* ({@link ox#TxEnvelopeTempo.(getSignPayload:function)}).
*
* The digest is keyed on the permanent `account` derived from the genesis
* (bootstrap) config — config updates never change it, so the genesis config
* is the correct input even for post-update transactions.
*
* For a nested multisig owner approval, the parent digest becomes the nested
* approval's `payload`, with the nested multisig `account`.
*
* @example
* ```ts twoslash
* import { MultisigConfig, TxEnvelopeTempo } from 'ox/tempo'
*
* const genesisConfig = MultisigConfig.from({
* threshold: 1,
* owners: [
* {
* owner: '0x1111111111111111111111111111111111111111',
* weight: 1
* }
* ]
* })
*
* const envelope = TxEnvelopeTempo.from({
* chainId: 1,
* calls: []
* })
*
* const digest = MultisigConfig.getSignPayload({
* payload: TxEnvelopeTempo.getSignPayload(envelope),
* genesisConfig
* })
* ```
*
* @example
* ### From `account`
*
* If you already have the permanent `account` (for example, recovered from a
* stored envelope), pass it directly:
*
* ```ts twoslash
* import { MultisigConfig, TxEnvelopeTempo } from 'ox/tempo'
*
* const genesisConfig = MultisigConfig.from({
* threshold: 1,
* owners: [
* {
* owner: '0x1111111111111111111111111111111111111111',
* weight: 1
* }
* ]
* })
* const account = MultisigConfig.getAddress(genesisConfig)
*
* const envelope = TxEnvelopeTempo.from({
* chainId: 1,
* calls: []
* })
*
* const digest = MultisigConfig.getSignPayload({
* payload: TxEnvelopeTempo.getSignPayload(envelope),
* account
* })
* ```
*
* @param value - The digest derivation parameters.
* @returns The owner approval digest.
*/
export declare function getSignPayload(value: getSignPayload.Value): Hex.Hex;
export declare namespace getSignPayload {
type Value = {
/** The inner transaction sign payload (`tx.signature_hash()`). */
payload: Hex.Hex | Bytes.Bytes;
} & OneOf<{
/** The native multisig account address. */
account: Address.Address;
} | {
/**
* The initial multisig config (the bootstrap config that derived the
* permanent `account`). Used to derive the account automatically.
* Config updates never change `account`, so the genesis config is
* also the correct input for post-update transactions.
*/
genesisConfig: Config;
}>;
type ErrorType = getAddress.ErrorType | Hash.keccak256.ErrorType | Hex.concat.ErrorType | Hex.from.ErrorType | Errors.GlobalErrorType;
}
/**
* Converts a {@link ox#MultisigConfig.Config} to its RLP tuple form (carried
* by the multisig signature `init`).
*
* Tuple shape: `[salt, threshold, [[owner, weight], ...]]`. The
* 32-byte `salt` encodes as a full fixed-width string; other integers use
* canonical RLP encoding (zero values encode as `0x`).
*
* @example
* ```ts twoslash
* import { MultisigConfig } from 'ox/tempo'
*
* const tuple = MultisigConfig.toTuple({
* threshold: 1,
* owners: [
* {
* owner: '0x1111111111111111111111111111111111111111',
* weight: 1
* }
* ]
* })
* ```
*
* @param config - The multisig config.
* @returns The RLP tuple.
*/
export declare function toTuple(config: Config): Tuple;
/**
* Validates a native multisig {@link ox#MultisigConfig.Config}. Returns `true`
* if valid, `false` otherwise.
*
* @example
* ```ts twoslash
* import { MultisigConfig } from 'ox/tempo'
*
* const valid = MultisigConfig.validate({
* threshold: 1,
* owners: [
* {
* owner: '0x1111111111111111111111111111111111111111',
* weight: 1
* }
* ]
* })
* // @log: true
* ```
*
* @param config - The multisig config.
* @returns Whether the config is valid.
*/
export declare function validate(config: Config): boolean;
/** Thrown when a native multisig config is invalid. */
export declare class InvalidConfigError extends Errors.BaseError {
readonly name = "MultisigConfig.InvalidConfigError";
constructor({ reason }: {
reason: string;
});
}
//# sourceMappingURL=MultisigConfig.d.ts.map