ox
Version:
Ethereum Standard Library
932 lines • 31.9 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 Hex from '../core/Hex.js';
import type { Assign, Compute, IsNarrowable, OneOf, PartialBy, UnionPartialBy } from '../core/internal/types.js';
import type * as PublicKey from '../core/PublicKey.js';
import * as Rlp from '../core/Rlp.js';
import * as ox_Secp256k1 from '../core/Secp256k1.js';
import * as Signature from '../core/Signature.js';
import type * as WebAuthnP256 from '../core/WebAuthnP256.js';
import * as MultisigConfig from './MultisigConfig.js';
/** Serialized magic identifier for Tempo signature envelopes. */
export declare const magicBytes = "0x7777777777777777777777777777777777777777777777777777777777777777";
/**
* Statically determines the signature type of an envelope at compile time.
*
* @example
* ```ts twoslash
* import type { SignatureEnvelope } from 'ox/tempo'
*
* type Type = SignatureEnvelope.GetType<{
* r: `0x${string}`
* s: `0x${string}`
* yParity: number
* }>
* // @log: 'secp256k1'
* ```
*/
export type GetType<envelope extends PartialBy<SignatureEnvelope, 'type'> | unknown> = unknown extends envelope ? envelope extends unknown ? Type : never : envelope extends {
type: infer T extends Type;
} ? T : envelope extends {
signature: {
r: `0x${string}`;
s: `0x${string}`;
};
prehash: boolean;
publicKey: PublicKey.PublicKey;
} ? 'p256' : envelope extends {
signature: {
r: `0x${string}`;
s: `0x${string}`;
};
metadata: any;
publicKey: PublicKey.PublicKey;
} ? 'webAuthn' : envelope extends {
r: `0x${string}`;
s: `0x${string}`;
yParity: number;
} ? 'secp256k1' : envelope extends {
signature: {
r: `0x${string}`;
s: `0x${string}`;
yParity: number;
};
} ? 'secp256k1' : envelope extends {
userAddress: Address.Address;
} ? 'keychain' : envelope extends {
account: Address.Address;
signatures: any;
} | {
init: MultisigConfig.Config;
signatures: any;
} ? 'multisig' : never;
/**
* Represents a signature envelope that can contain different signature types.
*
* Tempo transactions support multiple signature types, each with different wire formats:
*
* - **secp256k1** (no type prefix, 65 bytes): Standard Ethereum ECDSA signature. The sender
* address is recovered via `ecrecover`. Base transaction cost: 21,000 gas.
*
* - **p256** (type `0x01`, 130 bytes): P256/secp256r1 curve signature for passkey accounts.
* Includes embedded public key (64 bytes) and prehash flag. Enables native WebCrypto
* key support. Additional gas cost: +5,000 gas over secp256k1.
*
* - **webAuthn** (type `0x02`, 129-2049 bytes): WebAuthn signature with authenticator data
* and clientDataJSON. Enables browser passkey authentication. The signature is also
* charged as calldata (16 gas/non-zero byte, 4 gas/zero byte).
*
* - **keychain** (type `0x03` V1, `0x04` V2): Access key signature that wraps an inner signature
* (secp256k1, p256, or webAuthn). Format: type byte + user_address (20 bytes) + inner signature.
* V2 binds the signature to the user account via `keccak256(sigHash || userAddress)`.
* The protocol validates the access key authorization via the AccountKeychain precompile.
*
* [Signature Types Specification](https://docs.tempo.xyz/protocol/transactions/spec-tempo-transaction#signature-types)
*/
export type SignatureEnvelope<numberType = number> = OneOf<Secp256k1<numberType> | P256<numberType> | WebAuthn<numberType> | Keychain<numberType> | Multisig<numberType>>;
/**
* RPC-formatted signature envelope.
*/
export type SignatureEnvelopeRpc = OneOf<Secp256k1Rpc | P256Rpc | WebAuthnRpc | KeychainRpc | MultisigRpc>;
/** Primitive signature envelope accepted by protocol sidecars. */
export type Primitive<numberType = number> = OneOf<Secp256k1<numberType> | P256<numberType> | WebAuthn<numberType>>;
/** RPC-formatted primitive signature envelope. */
export type PrimitiveRpc = OneOf<Secp256k1Rpc | P256Rpc | WebAuthnRpc>;
/**
* Keychain signature version.
*
* - `'v1'`: Legacy format. Inner signature signs the raw `sig_hash` directly. Deprecated at T1C.
* - `'v2'`: Inner signature signs `keccak256(sig_hash || user_address)`, binding the signature
* to the specific user account.
*/
export type KeychainVersion = 'v1' | 'v2';
export type Keychain<numberType = number> = {
/** Root account address that this transaction is being executed for */
userAddress: Address.Address;
/** The actual signature from the access key (can be Secp256k1, P256, or WebAuthn) */
inner: SignatureEnvelope<numberType>;
/** The access key address (recovered address of the access key signer). */
keyId?: Address.Address | undefined;
type: 'keychain';
/** Keychain signature version. @default 'v1' */
version?: KeychainVersion | undefined;
};
export type KeychainRpc = {
type: 'keychain';
userAddress: Address.Address;
keyId?: Address.Address | undefined;
signature: SignatureEnvelopeRpc;
version?: KeychainVersion | undefined;
};
/**
* Native multisig signature (type `0x05`).
*
* Wraps a set of owner approvals (secp256k1, p256, webAuthn, or nested
* multisig) over the multisig owner approval digest. The transaction sender is
* the derived `account`, authorized once the recovered owner weights meet the
* configured threshold.
*
* [TIP-1061](https://tips.sh/1061)
*/
export type Multisig<numberType = number> = {
type: 'multisig';
/** Native multisig account address. */
account: Address.Address;
/**
* Owner approvals over the multisig owner approval digest. Each approval is
* either a primitive signature or a nested multisig signature (keychain
* approvals are invalid).
*/
signatures: readonly SignatureEnvelope<numberType>[];
/**
* Initial native multisig config for bootstrapping this account. Present only on
* the first (bootstrap) transaction from the derived account; absent on every
* subsequent transaction.
*/
init?: MultisigConfig.Config<numberType> | undefined;
};
/** RPC-formatted native multisig signature. */
export type MultisigRpc = OneOf<{
/** Existing native multisig account. */
account: Address.Address;
/** Structured owner approvals. */
signatures: readonly SignatureEnvelopeRpc[];
/** Multisig RPC signatures are untagged. */
type?: undefined;
} | {
/** Initial config for bootstrapping a native multisig account. */
init: MultisigConfig.Config;
/** Structured owner approvals. */
signatures: readonly SignatureEnvelopeRpc[];
/** Multisig RPC signatures are untagged. */
type?: undefined;
}>;
export type P256<numberType = number> = {
prehash: boolean;
publicKey: PublicKey.PublicKey;
signature: Signature.Signature<false, numberType>;
type: 'p256';
};
export type P256Rpc = {
preHash: boolean;
pubKeyX: Hex.Hex;
pubKeyY: Hex.Hex;
r: Hex.Hex;
s: Hex.Hex;
type: 'p256';
};
export type Secp256k1<numberType = number> = {
signature: Signature.Signature<true, numberType>;
type: 'secp256k1';
};
export type Secp256k1Rpc = Compute<Signature.Rpc<true> & {
v?: Hex.Hex | undefined;
type: 'secp256k1';
}>;
export type Secp256k1Flat<numberType = number> = Signature.Signature<true, numberType> & {
type?: 'secp256k1' | undefined;
};
export type WebAuthn<numberType = number> = {
metadata: Pick<WebAuthnP256.SignMetadata, 'authenticatorData' | 'clientDataJSON'>;
signature: Signature.Signature<false, numberType>;
publicKey: PublicKey.PublicKey;
type: 'webAuthn';
};
export type WebAuthnRpc = {
pubKeyX: Hex.Hex;
pubKeyY: Hex.Hex;
r: Hex.Hex;
s: Hex.Hex;
type: 'webAuthn';
webauthnData: Hex.Hex;
};
/** Hex-encoded serialized signature envelope. */
export type Serialized = Hex.Hex;
/** List of supported signature types. */
export declare const types: readonly ["secp256k1", "p256", "webAuthn"];
/** Union type of supported signature types. */
export type Type = (typeof types)[number];
/**
* Asserts that a {@link ox#SignatureEnvelope.SignatureEnvelope} is valid.
*
* @example
* ```ts twoslash
* import { SignatureEnvelope } from 'ox/tempo'
*
* SignatureEnvelope.assert({
* type: 'secp256k1',
* signature: {
* r: '0x0000000000000000000000000000000000000000000000000000000000000000',
* s: '0x0000000000000000000000000000000000000000000000000000000000000000',
* yParity: 0
* }
* })
* ```
*
* @param envelope - The signature envelope to assert.
* @throws `CoercionError` if the envelope type cannot be determined.
*/
export declare function assert(envelope: PartialBy<SignatureEnvelope, 'type'>): void;
export declare namespace assert {
type ErrorType = CoercionError | InvalidMultisigApprovalError | MissingPropertiesError | MultisigConfig.assert.ErrorType | MultisigConfig.getAddress.ErrorType | Signature.assert.ErrorType | Errors.GlobalErrorType;
}
/**
* Extracts the address of the signer from a {@link ox#SignatureEnvelope.SignatureEnvelope}.
*
* - **secp256k1**: Recovers the address from the payload via `ecrecover`.
* - **p256** / **webAuthn**: Derives the address from the embedded public key.
* - **keychain**: Extracts from the inner signature (or returns `userAddress` if `user` is `true`).
*
* @example
* ```ts twoslash
* import { Secp256k1 } from 'ox'
* import { SignatureEnvelope } from 'ox/tempo'
*
* const payload = '0xdeadbeef'
* const signature = Secp256k1.sign({
* payload,
* privateKey: '0x...'
* })
* const envelope = SignatureEnvelope.from(signature)
*
* const address = SignatureEnvelope.extractAddress({
* // [!code focus]
* payload, // [!code focus]
* signature: envelope // [!code focus]
* }) // [!code focus]
* ```
*
* @param options - The extraction options.
* @returns The signer address.
*/
export declare function extractAddress(options: extractAddress.Options): extractAddress.ReturnType;
export declare namespace extractAddress {
type Options = {
/** The sign payload that was signed (only required for secp256k1 signatures). */
payload: Hex.Hex | Bytes.Bytes;
/** The signature envelope. */
signature: SignatureEnvelope;
/** Whether to return the root `userAddress` for keychain signatures instead of extracting from the inner signature. */
root?: boolean | undefined;
};
type ReturnType = Address.Address;
type ErrorType = Address.fromPublicKey.ErrorType | extractPublicKey.ErrorType | Errors.GlobalErrorType;
}
/**
* Extracts the public key of the signer from a {@link ox#SignatureEnvelope.SignatureEnvelope}.
*
* - **secp256k1**: Recovers the public key from the payload via `ecrecover`.
* - **p256** / **webAuthn**: Returns the embedded public key.
* - **keychain**: Extracts from the inner signature.
*
* @example
* ```ts twoslash
* import { Secp256k1 } from 'ox'
* import { SignatureEnvelope } from 'ox/tempo'
*
* const payload = '0xdeadbeef'
* const signature = Secp256k1.sign({
* payload,
* privateKey: '0x...'
* })
* const envelope = SignatureEnvelope.from(signature)
*
* const publicKey = SignatureEnvelope.extractPublicKey({
* // [!code focus]
* payload, // [!code focus]
* signature: envelope // [!code focus]
* }) // [!code focus]
* ```
*
* @param options - The extraction options.
* @returns The signer's public key.
*/
export declare function extractPublicKey(options: extractPublicKey.Options): extractPublicKey.ReturnType;
export declare namespace extractPublicKey {
type Options = {
/** The sign payload that was signed (only required for secp256k1 signatures). */
payload: Hex.Hex | Bytes.Bytes;
/** The signature envelope. */
signature: SignatureEnvelope;
};
type ReturnType = PublicKey.PublicKey;
type ErrorType = CoercionError | ox_Secp256k1.recoverPublicKey.ErrorType | Errors.GlobalErrorType;
}
/**
* Deserializes a hex-encoded signature envelope into a typed signature object.
*
* Wire format detection:
* - 65 bytes (no prefix): secp256k1 signature
* - Type `0x01` + 129 bytes: P256 signature (r, s, pubKeyX, pubKeyY, prehash)
* - Type `0x02` + variable: WebAuthn signature (webauthnData, r, s, pubKeyX, pubKeyY)
* - Type `0x03` + 20 bytes + inner: Keychain V1 signature (userAddress + inner signature)
* - Type `0x04` + 20 bytes + inner: Keychain V2 signature (userAddress + inner signature)
*
* [Signature Types](https://docs.tempo.xyz/protocol/transactions/spec-tempo-transaction#signature-types)
*
* @example
* ```ts twoslash
* import { SignatureEnvelope } from 'ox/tempo'
*
* const envelope = SignatureEnvelope.deserialize('0x...')
* ```
*
* @param serialized - The hex-encoded signature envelope to deserialize.
* @returns The deserialized signature envelope.
* @throws `CoercionError` if the serialized value cannot be coerced to a valid signature envelope.
*/
export declare function deserialize(value: Serialized): SignatureEnvelope;
/**
* Coerces a value to a signature envelope.
*
* Accepts either a serialized hex string or an existing signature envelope object.
* Use this to wrap raw signatures from {@link ox#Secp256k1.(sign:function)}, {@link ox#P256.(sign:function)},
* {@link ox#WebCryptoP256.(sign:function)}, or {@link ox#WebAuthnP256.(sign:function)} into the envelope format
* required by Tempo transactions.
*
* [Signature Types](https://docs.tempo.xyz/protocol/transactions/spec-tempo-transaction#signature-types)
*
* @example
* ### Secp256k1
*
* Standard Ethereum ECDSA signature using the secp256k1 curve.
*
* ```ts twoslash
* import { Secp256k1 } from 'ox'
* import { SignatureEnvelope } from 'ox/tempo'
*
* const privateKey = Secp256k1.randomPrivateKey()
* const signature = Secp256k1.sign({
* payload: '0xdeadbeef',
* privateKey
* })
*
* const envelope = SignatureEnvelope.from(signature)
* ```
*
* @example
* ### P256
*
* ECDSA signature using the P-256 (secp256r1) curve. Requires embedding the
* public key.
*
* ```ts twoslash
* import { P256 } from 'ox'
* import { SignatureEnvelope } from 'ox/tempo'
*
* const { privateKey, publicKey } = P256.createKeyPair()
* const signature = P256.sign({
* payload: '0xdeadbeef',
* privateKey
* })
*
* const envelope = SignatureEnvelope.from({
* signature,
* publicKey
* })
* ```
*
* @example
* ### P256 (WebCrypto)
*
* When using WebCrypto keys, `prehash` must be `true` since WebCrypto always
* SHA256 hashes the digest before signing.
*
* ```ts twoslash
* // @noErrors
* import { WebCryptoP256 } from 'ox'
* import { SignatureEnvelope } from 'ox/tempo'
*
* const { privateKey, publicKey } =
* await WebCryptoP256.createKeyPair()
* const signature = await WebCryptoP256.sign({
* payload: '0xdeadbeef',
* privateKey
* })
*
* const envelope = SignatureEnvelope.from({
* signature,
* publicKey,
* prehash: true
* })
* ```
*
* @example
* ### WebAuthn
*
* Passkey-based signature using WebAuthn. Includes authenticator metadata
* (authenticatorData and clientDataJSON) along with the P-256 signature and
* public key.
*
* ```ts twoslash
* // @noErrors
* import { WebAuthnP256 } from 'ox'
* import { SignatureEnvelope } from 'ox/tempo'
*
* const credential = await WebAuthnP256.createCredential({
* name: 'Example'
* })
*
* const { metadata, signature } = await WebAuthnP256.sign({
* challenge: '0xdeadbeef',
* credentialId: credential.id
* })
*
* const envelope = SignatureEnvelope.from({
* signature,
* publicKey: credential.publicKey,
* metadata
* })
* ```
*
* @example
* ### Keychain
*
* Wraps another signature type with a user address, used for delegated signing
* via access keys on behalf of a root account.
*
* ```ts twoslash
* import { Secp256k1 } from 'ox'
* import { SignatureEnvelope } from 'ox/tempo'
*
* const privateKey = Secp256k1.randomPrivateKey()
* const signature = Secp256k1.sign({
* payload: '0xdeadbeef',
* privateKey
* })
*
* const envelope = SignatureEnvelope.from({
* userAddress: '0x1234567890123456789012345678901234567890',
* inner: SignatureEnvelope.from(signature)
* })
* ```
*
* @example
* ### Multisig (from genesis config)
*
* Pass `genesisConfig` to derive `account` automatically. Set `init: true` to
* opt into bootstrap (uses `genesisConfig` as the bootstrap `init`); omit
* `init` for subsequent (non-bootstrap) transactions.
*
* ```ts twoslash
* import { Secp256k1 } from 'ox'
* import { MultisigConfig, SignatureEnvelope } from 'ox/tempo'
*
* const genesisConfig = MultisigConfig.from({
* threshold: 1,
* owners: [
* {
* owner: '0x1111111111111111111111111111111111111111',
* weight: 1
* }
* ]
* })
*
* const privateKey = Secp256k1.randomPrivateKey()
* const signature = SignatureEnvelope.from(
* Secp256k1.sign({ payload: '0xdeadbeef', privateKey })
* )
*
* // Bootstrap transaction
* const bootstrap = SignatureEnvelope.from({
* genesisConfig,
* signatures: [signature],
* init: true
* })
*
* // Subsequent (non-bootstrap) transactions
* const subsequent = SignatureEnvelope.from({
* genesisConfig,
* signatures: [signature]
* })
* ```
*
* @param value - The value to coerce (either a hex string or signature envelope).
* @returns The signature envelope.
*/
export declare function from<const value extends from.Value>(value: value | from.Value, options?: from.Options): from.ReturnValue<value>;
export declare namespace from {
type Options = {
/** Payload that was signed. Used to recover `keyId` for keychain envelopes with secp256k1 inner signatures. */
payload?: Hex.Hex | Bytes.Bytes | undefined;
};
/**
* Multisig envelope input variant where `account` is derived from the
* supplied `genesisConfig`. Pass `init: true` to opt into bootstrap (uses
* `genesisConfig` as the bootstrap `init`); omit `init` for subsequent
* (non-bootstrap) transactions.
*/
type MultisigFromGenesisConfig = {
type?: 'multisig' | undefined;
genesisConfig: MultisigConfig.Config;
signatures: readonly SignatureEnvelope[];
init?: MultisigConfig.Config | boolean | undefined;
};
type Value = UnionPartialBy<SignatureEnvelope, 'prehash' | 'type'> | Secp256k1Flat | Serialized | MultisigFromGenesisConfig;
type ReturnValue<value extends Value> = Compute<OneOf<value extends Serialized ? SignatureEnvelope : value extends Secp256k1Flat ? Secp256k1 : value extends MultisigFromGenesisConfig ? Multisig : IsNarrowable<value, SignatureEnvelope> extends true ? SignatureEnvelope : Assign<value, {
readonly type: GetType<value>;
} & (GetType<value> extends 'keychain' ? {
keyId?: Address.Address | undefined;
} : {})>>>;
}
/**
* Converts an RPC-formatted signature envelope to a typed signature envelope.
*
* @example
* ```ts twoslash
* import { SignatureEnvelope } from 'ox/tempo'
*
* const envelope = SignatureEnvelope.fromRpc({
* r: '0x0',
* s: '0x0',
* yParity: '0x0',
* type: 'secp256k1'
* })
* ```
*
* @param envelope - The RPC signature envelope to convert.
* @returns The signature envelope with bigint values.
*/
export declare function fromRpc(envelope: SignatureEnvelopeRpc): SignatureEnvelope;
export declare namespace fromRpc {
type ErrorType = assert.ErrorType | CoercionError | InvalidSerializedError | MultisigConfig.getAddress.ErrorType | Signature.fromRpc.ErrorType | Errors.GlobalErrorType;
}
/**
* Determines the signature type of an envelope.
*
* @example
* ```ts twoslash
* import { SignatureEnvelope } from 'ox/tempo'
*
* const type = SignatureEnvelope.getType({
* signature: {
* r: '0x0000000000000000000000000000000000000000000000000000000000000000',
* s: '0x0000000000000000000000000000000000000000000000000000000000000000',
* yParity: 0
* }
* })
* // @log: 'secp256k1'
* ```
*
* @param envelope - The signature envelope to inspect.
* @returns The signature type ('secp256k1', 'p256', or 'webAuthn').
* @throws `CoercionError` if the envelope type cannot be determined.
*/
export declare function getType<envelope extends PartialBy<SignatureEnvelope, 'type'> | Secp256k1Flat | unknown>(envelope: envelope): GetType<envelope>;
/**
* Serializes a signature envelope to a hex-encoded string.
*
* Wire format:
* - secp256k1: 65 bytes (no type prefix, for backward compatibility)
* - P256: `0x01` + r (32) + s (32) + pubKeyX (32) + pubKeyY (32) + prehash (1) = 130 bytes
* - WebAuthn: `0x02` + webauthnData (variable) + r (32) + s (32) + pubKeyX (32) + pubKeyY (32)
* - Keychain V1: `0x03` + userAddress (20) + inner signature (recursive)
* - Keychain V2: `0x04` + userAddress (20) + inner signature (recursive)
* - Multisig: `0x05` + RLP `[account | init, signatures]`
*
* [Signature Types](https://docs.tempo.xyz/protocol/transactions/spec-tempo-transaction#signature-types)
*
* @example
* ```ts twoslash
* import { SignatureEnvelope } from 'ox/tempo'
*
* const serialized = SignatureEnvelope.serialize({
* signature: {
* r: '0x0000000000000000000000000000000000000000000000000000000000000000',
* s: '0x0000000000000000000000000000000000000000000000000000000000000000',
* yParity: 0
* },
* type: 'secp256k1'
* })
* ```
*
* @param envelope - The signature envelope to serialize.
* @returns The hex-encoded serialized signature.
* @throws `CoercionError` if the envelope cannot be serialized.
*/
export declare function serialize(envelope: UnionPartialBy<SignatureEnvelope, 'prehash'>, options?: serialize.Options): Serialized;
export declare namespace serialize {
type Options = {
/**
* Whether to serialize the signature envelope with the Tempo magic identifier.
* This is useful for being able to distinguish between Tempo and non-Tempo (e.g. ERC-1271) signatures.
*/
magic?: boolean | undefined;
};
type ErrorType = assert.ErrorType | CoercionError | Hex.concat.ErrorType | Hex.fromNumber.ErrorType | Hex.fromString.ErrorType | Rlp.fromHex.ErrorType | Signature.toHex.ErrorType | Errors.GlobalErrorType;
}
/**
* Orders native multisig owner approvals into the strictly-ascending
* recovered-owner order the Tempo node requires for the multisig `signatures`
* array (the node enforces "recovered owners must be strictly ascending").
*
* Each approval is signed over the multisig owner approval digest
* ({@link ox#MultisigConfig.(getSignPayload:function)}), so the signer of
* every approval is recovered against that digest and the list is sorted by the
* recovered owner address. Works for any owner key type (secp256k1, p256,
* webAuthn).
*
* Config updates never change `account`, so the genesis config is the correct
* input even for post-update transactions.
*
* @example
* ```ts twoslash
* import { Secp256k1 } from 'ox'
* import {
* MultisigConfig,
* SignatureEnvelope,
* TxEnvelopeTempo
* } from 'ox/tempo'
*
* const genesisConfig = MultisigConfig.from({
* threshold: 2,
* owners: [
* {
* owner: '0x1111111111111111111111111111111111111111',
* weight: 1
* },
* {
* owner: '0x2222222222222222222222222222222222222222',
* weight: 1
* }
* ]
* })
*
* const tx = TxEnvelopeTempo.from({ chainId: 1, calls: [] })
* const payload = TxEnvelopeTempo.getSignPayload(tx)
*
* const privateKeys = [
* Secp256k1.randomPrivateKey(),
* Secp256k1.randomPrivateKey()
* ]
* const digest = MultisigConfig.getSignPayload({
* payload,
* genesisConfig
* })
* const signatures = privateKeys.map((privateKey) =>
* SignatureEnvelope.from(
* Secp256k1.sign({ payload: digest, privateKey })
* )
* )
*
* const ordered = SignatureEnvelope.sortMultisigApprovals({
* // [!code focus]
* genesisConfig, // [!code focus]
* payload, // [!code focus]
* signatures // [!code focus]
* }) // [!code focus]
* ```
*
* @param value - The approval ordering parameters.
* @returns The owner approvals ordered ascending by recovered owner address.
*/
export declare function sortMultisigApprovals(value: sortMultisigApprovals.Value): readonly SignatureEnvelope[];
export declare namespace sortMultisigApprovals {
type Value = {
/** The inner transaction sign payload (`tx.signature_hash()`). */
payload: Hex.Hex | Bytes.Bytes;
/** The owner approvals to order. */
signatures: readonly SignatureEnvelope[];
} & 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.
*/
genesisConfig: MultisigConfig.Config;
}>;
type ErrorType = MultisigConfig.getSignPayload.ErrorType | extractAddress.ErrorType | Errors.GlobalErrorType;
}
/**
* Converts a signature envelope to RPC format.
*
* @example
* ```ts twoslash
* import { SignatureEnvelope } from 'ox/tempo'
*
* const rpc = SignatureEnvelope.toRpc({
* signature: {
* r: '0x0000000000000000000000000000000000000000000000000000000000000000',
* s: '0x0000000000000000000000000000000000000000000000000000000000000000',
* yParity: 0
* },
* type: 'secp256k1'
* })
* ```
*
* @param envelope - The signature envelope to convert.
* @returns The RPC signature envelope with hex values.
*/
export declare function toRpc<const envelope extends toRpc.Input>(envelope: envelope): toRpc.ReturnType<envelope>;
export declare namespace toRpc {
/** Numberish input accepted by {@link ox#SignatureEnvelope.(toRpc:function)}. */
type Input = SignatureEnvelope<Hex.Hex | number>;
/** RPC signature envelope inferred from the input type. */
type ReturnType<envelope extends Input = Input> = GetType<envelope> extends 'secp256k1' ? Secp256k1Rpc : GetType<envelope> extends 'p256' ? P256Rpc : GetType<envelope> extends 'webAuthn' ? WebAuthnRpc : GetType<envelope> extends 'keychain' ? KeychainRpc : GetType<envelope> extends 'multisig' ? MultisigRpc : SignatureEnvelopeRpc;
type ErrorType = assert.ErrorType | CoercionError | Signature.toRpc.ErrorType | Errors.GlobalErrorType;
}
/**
* Validates a signature envelope. Returns `true` if the envelope is valid, `false` otherwise.
*
* @example
* ```ts twoslash
* import { SignatureEnvelope } from 'ox/tempo'
*
* const valid = SignatureEnvelope.validate({
* signature: {
* r: '0x0000000000000000000000000000000000000000000000000000000000000000',
* s: '0x0000000000000000000000000000000000000000000000000000000000000000',
* yParity: 0
* },
* type: 'secp256k1'
* })
* // @log: true
* ```
*
* @param envelope - The signature envelope to validate.
* @returns `true` if valid, `false` otherwise.
*/
export declare function validate(envelope: PartialBy<SignatureEnvelope, 'type'>): boolean;
export declare namespace validate {
type ErrorType = Errors.GlobalErrorType;
}
/**
* Verifies a signature envelope against a digest/payload.
*
* Supports `secp256k1`, `p256`, and `webAuthn` signature types.
*
* :::warning
* `keychain` signatures are not supported and will throw an error.
* :::
*
* @example
* ### Secp256k1
*
* ```ts twoslash
* import { SignatureEnvelope } from 'ox/tempo'
* import { Secp256k1 } from 'ox'
*
* const privateKey = Secp256k1.randomPrivateKey()
* const publicKey = Secp256k1.getPublicKey({ privateKey })
* const payload = '0xdeadbeef'
*
* const signature = Secp256k1.sign({ payload, privateKey })
* const envelope = SignatureEnvelope.from(signature)
*
* const valid = SignatureEnvelope.verify(envelope, {
* payload,
* publicKey
* })
* // @log: true
* ```
*
* @example
* ### P256
*
* For P256 signatures, the `address` or `publicKey` must match the embedded
* public key in the signature envelope.
*
* ```ts twoslash
* import { SignatureEnvelope } from 'ox/tempo'
* import { P256 } from 'ox'
*
* const privateKey = P256.randomPrivateKey()
* const publicKey = P256.getPublicKey({ privateKey })
* const payload = '0xdeadbeef'
*
* const signature = P256.sign({ payload, privateKey })
* const envelope = SignatureEnvelope.from({
* prehash: false,
* publicKey,
* signature
* })
*
* const valid = SignatureEnvelope.verify(envelope, {
* payload,
* publicKey
* })
* // @log: true
* ```
*
* @example
* ### WebCryptoP256
*
* ```ts twoslash
* import { SignatureEnvelope } from 'ox/tempo'
* import { WebCryptoP256 } from 'ox'
*
* const { privateKey, publicKey } =
* await WebCryptoP256.createKeyPair()
* const payload = '0xdeadbeef'
*
* const signature = await WebCryptoP256.sign({
* payload,
* privateKey
* })
* const envelope = SignatureEnvelope.from({
* prehash: true,
* publicKey,
* signature
* })
*
* const valid = SignatureEnvelope.verify(envelope, {
* payload,
* publicKey
* })
* // @log: true
* ```
*
* @example
* ### WebAuthnP256
*
* ```ts twoslash
* import { SignatureEnvelope } from 'ox/tempo'
* import { WebAuthnP256 } from 'ox'
*
* const credential = await WebAuthnP256.createCredential({
* name: 'Example'
* })
* const payload = '0xdeadbeef'
*
* const { metadata, signature } = await WebAuthnP256.sign({
* challenge: payload,
* credentialId: credential.id
* })
* const envelope = SignatureEnvelope.from({
* metadata,
* signature,
* publicKey: credential.publicKey
* })
*
* const valid = SignatureEnvelope.verify(envelope, {
* payload,
* publicKey: credential.publicKey
* })
* // @log: true
* ```
*
* @param parameters - Verification parameters.
* @returns `true` if the signature is valid, `false` otherwise.
*/
export declare function verify(signature: SignatureEnvelope, parameters: verify.Parameters): boolean;
export declare namespace verify {
type Parameters = {
/** Payload that was signed. */
payload: Hex.Hex | Bytes.Bytes;
} & OneOf<{
/** Public key that signed the payload. */
publicKey: PublicKey.PublicKey;
} | {
/** Address that signed the payload. */
address: Address.Address;
}>;
}
/**
* Error thrown when a signature envelope cannot be coerced to a valid type.
*/
export declare class CoercionError extends Errors.BaseError {
readonly name = "SignatureEnvelope.CoercionError";
constructor({ envelope }: {
envelope: unknown;
});
}
/**
* Error thrown when a signature envelope is missing required properties.
*/
export declare class MissingPropertiesError extends Errors.BaseError {
readonly name = "SignatureEnvelope.MissingPropertiesError";
constructor({ envelope, missing, type, }: {
envelope: unknown;
missing: string[];
type: Type | 'keychain' | 'multisig';
});
}
/**
* Error thrown when a serialized signature envelope cannot be deserialized.
*/
export declare class InvalidSerializedError extends Errors.BaseError {
readonly name = "SignatureEnvelope.InvalidSerializedError";
constructor({ reason, serialized }: {
reason: string;
serialized: Hex.Hex;
});
}
/**
* Error thrown when a native multisig owner approval is invalid.
*/
export declare class InvalidMultisigApprovalError extends Errors.BaseError {
readonly name = "SignatureEnvelope.InvalidMultisigApprovalError";
constructor({ reason }: {
reason: string;
});
}
/**
* Error thrown when a signature envelope fails to verify.
*/
export declare class VerificationError extends Errors.BaseError {
readonly name = "SignatureEnvelope.VerificationError";
}
//# sourceMappingURL=SignatureEnvelope.d.ts.map