import type * as Address from '../core/Address.js'; import type * as Errors from '../core/Errors.js'; import * as Hash from '../core/Hash.js'; import * as Hex from '../core/Hex.js'; import type { Compute } from '../core/internal/types.js'; import * as Rlp from '../core/Rlp.js'; import * as SignatureEnvelope from './SignatureEnvelope.js'; import * as TempoAddress from './TempoAddress.js'; /** * Key authorization for provisioning access keys. * * Access keys allow a root key (e.g., a passkey) to delegate transaction signing to secondary * keys with customizable permissions including expiry timestamps and per-TIP-20 token spending * limits. This enables a user to sign transactions without repeated passkey prompts. * * The root key signs a `KeyAuthorization` to grant an access key permission to sign transactions * on its behalf. The authorization is attached to a transaction (which can be signed by the access * key itself), and the protocol validates the authorization before storing the key in the * AccountKeychain precompile. * * Key authorization fields: * - `address`: Address derived from the access key's public key (the "key ID") * - `chainId`: Chain ID for replay protection (0 = valid on any chain) * - `expiry`: Unix timestamp when the key expires (undefined = never expires) * - `limits`: Per-TIP-20 token spending limits (only applies to `transfer()` and `approve()` calls) * - `type`: Key type (`secp256k1`, `p256`, or `webAuthn`) * * [Access Keys Specification](https://docs.tempo.xyz/protocol/transactions/spec-tempo-transaction#access-keys) */ export type KeyAuthorization = { /** Address derived from the public key of the key type. */ address: addressType; /** Chain ID for replay protection. */ chainId: bigintType; /** Unix timestamp when key expires (undefined = never expires). */ expiry?: numberType | null | undefined; /** TIP20 spending limits for this key. */ limits?: readonly TokenLimit[] | undefined; /** * Call scopes restricting which contracts/selectors this key can call. * * - `undefined` = unrestricted key (any call allowed) * - `[]` = scoped mode with no calls allowed * - `[...]` = only listed contract+selector combinations allowed */ scopes?: readonly Scope[] | undefined; /** Key type. (secp256k1, P256, WebAuthn). */ type: SignatureEnvelope.Type; } & (signed extends true ? { signature: SignatureEnvelope.SignatureEnvelope; } : { signature?: SignatureEnvelope.SignatureEnvelope | undefined; }); /** Input type for a Key Authorization. */ export type Input = KeyAuthorization; /** RPC representation matching the node's wire format. */ export type Rpc = { /** Allowed call scopes (node field: `allowedCalls`). */ allowedCalls?: readonly RpcCallScope[] | undefined; /** Chain ID (hex quantity). */ chainId: Hex.Hex; /** Expiry timestamp (hex quantity or null). */ expiry: Hex.Hex | null | undefined; /** Key identifier. */ keyId: Address.Address; /** Key type. */ keyType: SignatureEnvelope.Type; /** Token spending limits. */ limits?: readonly RpcTokenLimit[] | undefined; /** Signature envelope. */ signature: SignatureEnvelope.SignatureEnvelopeRpc; }; /** RPC representation of a token limit (matches node's `TokenLimit` serde). */ export type RpcTokenLimit = { token: Address.Address; limit: Hex.Hex; period?: Hex.Hex | undefined; }; /** RPC representation of a call scope (matches node's `CallScope` serde). */ export type RpcCallScope = { target: Address.Address; selectorRules?: readonly RpcSelectorRule[]; }; /** RPC representation of a selector rule (matches node's `SelectorRule` serde). */ export type RpcSelectorRule = { selector: Hex.Hex; recipients?: readonly Address.Address[]; }; /** Signed representation of a Key Authorization. */ export type Signed = KeyAuthorization; type BaseTuple = readonly [ chainId: Hex.Hex, keyType: Hex.Hex, keyId: Address.Address ]; type TokenLimitTuple = readonly [token: Address.Address, limit: Hex.Hex] | readonly [token: Address.Address, limit: Hex.Hex, period: Hex.Hex]; type SelectorRuleTuple = readonly [ selector: Hex.Hex, recipients: readonly Address.Address[] ]; type CallScopeTuple = readonly [ target: Address.Address, selectorRules: readonly SelectorRuleTuple[] ]; type AuthorizationTuple = BaseTuple | readonly [...BaseTuple, expiry: Hex.Hex] | readonly [...BaseTuple, expiry: Hex.Hex, limits: readonly TokenLimitTuple[]] | readonly [ ...BaseTuple, expiry: Hex.Hex, limits: readonly TokenLimitTuple[], calls: readonly CallScopeTuple[] ]; /** Tuple representation of a Key Authorization. */ export type Tuple = signed extends true ? readonly [authorization: AuthorizationTuple, signature: Hex.Hex] : readonly [authorization: AuthorizationTuple]; /** * Call scope entry restricting which contract, selector, and recipients an access key can use. * * Multiple entries with the same `address` are grouped by target on the wire. * * - `{ address }` = any selector on this contract * - `{ address, selector }` = specific selector * - `{ address, selector, recipients }` = selector + recipient constraint * * [TIP-1011 Specification](https://docs.tempo.xyz/protocol/transactions/tip-1011) */ export type Scope = { /** Target contract address. */ address: addressType; /** * 4-byte function selector, or a human-readable ABI signature * (e.g. `'transfer(address,uint256)'` or `'function transfer(address,uint256)'`). * * Signatures are encoded into a 4-byte selector automatically. * Omit to allow any selector on this contract. */ selector?: Hex.Hex | string | undefined; /** * Recipient allowlist for this selector (first ABI `address` argument). * * - `undefined` or `[]` = any recipient allowed * - `[...]` = only listed recipients allowed * * Only valid for constrained selectors: `transfer`, `approve`, `transferWithMemo`. */ recipients?: readonly addressType[] | undefined; }; /** * Token spending limit for access keys. * * Defines a per-TIP-20 token spending limit for an access key. Limits deplete as tokens * are spent and can be updated by the root key via `updateSpendingLimit()`. * * [Access Keys Specification](https://docs.tempo.xyz/protocol/transactions/spec-tempo-transaction#access-keys) */ export type TokenLimit = { /** Address of the TIP-20 token. */ token: addressType; /** Maximum spending amount for this token (enforced over the key's lifetime, or per period if `period` \> 0). */ limit: bigintType; /** * Period duration in seconds for recurring spending limits. * * - `0` or `undefined` = one-time limit * - `\> 0` = periodic limit that resets every `period` seconds */ period?: numberType | undefined; }; /** * Converts a Key Authorization object into a typed {@link ox#KeyAuthorization.KeyAuthorization}. * * Use this to create an unsigned key authorization, then sign it with the root key using * {@link ox#KeyAuthorization.(getSignPayload:function)} and attach the signature. The signed authorization * can be included in a {@link ox#TxEnvelopeTempo.TxEnvelopeTempo} via the * `keyAuthorization` field to provision the access key on-chain. * * [Access Keys Specification](https://docs.tempo.xyz/protocol/transactions/spec-tempo-transaction#access-keys) * * @example * ### Secp256k1 Key * * Standard Ethereum ECDSA key using the secp256k1 curve. * * ```ts twoslash * import { Address, Secp256k1, Value } from 'ox' * import { KeyAuthorization } from 'ox/tempo' * * const privateKey = Secp256k1.randomPrivateKey() * const address = Address.fromPublicKey(Secp256k1.getPublicKey({ privateKey })) * * const authorization = KeyAuthorization.from({ * address, * chainId: 4217n, * expiry: 1234567890, * type: 'secp256k1', * limits: [{ * token: '0x20c0000000000000000000000000000000000001', * limit: Value.from('10', 6), * }], * }) * ``` * * @example * ### WebCryptoP256 Key * * ```ts twoslash * import { Address, WebCryptoP256, Value } from 'ox' * import { KeyAuthorization } from 'ox/tempo' * * const keyPair = await WebCryptoP256.createKeyPair() * const address = Address.fromPublicKey(keyPair.publicKey) * * const authorization = KeyAuthorization.from({ * address, * chainId: 4217n, * expiry: 1234567890, * type: 'p256', * limits: [{ * token: '0x20c0000000000000000000000000000000000001', * limit: Value.from('10', 6), * }], * }) * ``` * * @example * ### Attaching Signatures (Secp256k1) * * Attach a signature to a Key Authorization using a Secp256k1 private key to * authorize another Secp256k1 key on the account. * * ```ts twoslash * import { Address, Secp256k1, Value } from 'ox' * import { KeyAuthorization } from 'ox/tempo' * * const privateKey = '0x...' * const address = Address.fromPublicKey(Secp256k1.getPublicKey({ privateKey })) * * const authorization = KeyAuthorization.from({ * address, * chainId: 4217n, * expiry: 1234567890, * type: 'secp256k1', * limits: [{ * token: '0x20c0000000000000000000000000000000000001', * limit: Value.from('10', 6), * }], * }) * * const rootPrivateKey = '0x...' * const signature = Secp256k1.sign({ * payload: KeyAuthorization.getSignPayload(authorization), * privateKey: rootPrivateKey, * }) * * const authorization_signed = KeyAuthorization.from(authorization, { signature }) * ``` * * @example * ### Attaching Signatures (WebAuthn) * * Attach a signature to a Key Authorization using a WebAuthn credential to * authorize a new WebCryptoP256 key on the account. * * ```ts twoslash * // @noErrors * import { Address, Value, WebCryptoP256, WebAuthnP256 } from 'ox' * import { KeyAuthorization, SignatureEnvelope } from 'ox/tempo' * * const keyPair = await WebCryptoP256.createKeyPair() * const address = Address.fromPublicKey(keyPair.publicKey) * * const authorization = KeyAuthorization.from({ * address, * chainId: 4217n, * expiry: 1234567890, * type: 'p256', * limits: [{ * token: '0x20c0000000000000000000000000000000000001', * limit: Value.from('10', 6), * }], * }) * * const credential = await WebAuthnP256.createCredential({ name: 'Example' }) * * const { metadata, signature } = await WebAuthnP256.sign({ * challenge: KeyAuthorization.getSignPayload(authorization), * credentialId: credential.id, * }) * * const signatureEnvelope = SignatureEnvelope.from({ // [!code focus] * signature, // [!code focus] * publicKey: credential.publicKey, // [!code focus] * metadata, // [!code focus] * }) * const authorization_signed = KeyAuthorization.from( * authorization, * { signature: signatureEnvelope }, // [!code focus] * ) * ``` * * @param authorization - A Key Authorization tuple in object format. * @param options - Key Authorization options. * @returns The {@link ox#KeyAuthorization.KeyAuthorization}. */ export declare function from(authorization: authorization | KeyAuthorization, options?: from.Options): from.ReturnType; export declare namespace from { type Options = { /** The {@link ox#SignatureEnvelope.SignatureEnvelope} to attach to the Key Authorization. */ signature?: signature | SignatureEnvelope.SignatureEnvelope | undefined; }; type ReturnType = Compute; } : {})>>; type ErrorType = Errors.GlobalErrorType; } /** * Converts an {@link ox#AuthorizationTempo.Rpc} to an {@link ox#AuthorizationTempo.AuthorizationTempo}. * * @example * ```ts twoslash * import { KeyAuthorization } from 'ox/tempo' * * const keyAuthorization = KeyAuthorization.fromRpc({ * chainId: '0x1079', * expiry: '0x174876e800', * keyId: '0xbe95c3f554e9fc85ec51be69a3d807a0d55bcf2c', * keyType: 'secp256k1', * limits: [{ token: '0x20c0000000000000000000000000000000000001', limit: '0xf4240' }], * signature: { * type: 'secp256k1', * r: '0x635dc2033e60185bb36709c29c75d64ea51dfbd91c32ef4be198e4ceb169fb4d', * s: '0x50c2667ac4c771072746acfdcf1f1483336dcca8bd2df47cd83175dbe60f0540', * yParity: '0x0' * }, * }) * ``` * * @param authorization - The RPC-formatted Key Authorization. * @returns A signed {@link ox#AuthorizationTempo.AuthorizationTempo}. */ export declare function fromRpc(authorization: Rpc): Signed; export declare namespace fromRpc { type ErrorType = Errors.GlobalErrorType; } /** * Converts an {@link ox#KeyAuthorization.Tuple} to an {@link ox#KeyAuthorization.KeyAuthorization}. * * @example * ```ts twoslash * import { KeyAuthorization } from 'ox/tempo' * * const authorization = KeyAuthorization.fromTuple([ * [ * '0x', * '0x00', * '0xbe95c3f554e9fc85ec51be69a3d807a0d55bcf2c', * '0x174876e800', * [['0x20c0000000000000000000000000000000000001', '0xf4240']], * ], * '0x01a068a020a209d3d56c46f38cc50a33f704f4a9a10a59377f8dd762ac66910e9b907e865ad05c4035ab5792787d4a0297a43617ae897930a6fe4d822b8faea52064', * ]) * ``` * * @example * Unsigned Key Authorization tuple (no signature): * * ```ts twoslash * import { KeyAuthorization } from 'ox/tempo' * * const authorization = KeyAuthorization.fromTuple([ * [ * '0x', * '0x00', * '0xbe95c3f554e9fc85ec51be69a3d807a0d55bcf2c', * '0x174876e800', * [['0x20c0000000000000000000000000000000000001', '0xf4240']], * ], * ]) * ``` * * @param tuple - The Key Authorization tuple. * @returns The {@link ox#KeyAuthorization.KeyAuthorization}. */ export declare function fromTuple(tuple: tuple): fromTuple.ReturnType; export declare namespace fromTuple { type ReturnType = Compute ? true : false>>; type ErrorType = Errors.GlobalErrorType; } /** * Computes the sign payload for an {@link ox#KeyAuthorization.KeyAuthorization}. * * The root key must sign this payload to authorize the access key. The resulting signature * is attached to the key authorization via {@link ox#KeyAuthorization.(from:function)} with the * `signature` option. * * [Access Keys Specification](https://docs.tempo.xyz/protocol/transactions/spec-tempo-transaction#access-keys) * * @example * ```ts twoslash * import { Address, Secp256k1, Value } from 'ox' * import { KeyAuthorization } from 'ox/tempo' * * const privateKey = '0x...' * const address = Address.fromPublicKey(Secp256k1.getPublicKey({ privateKey })) * * const authorization = KeyAuthorization.from({ * address, * chainId: 4217n, * expiry: 1234567890, * type: 'secp256k1', * limits: [{ * token: '0x20c0000000000000000000000000000000000001', * limit: Value.from('10', 6), * }], * }) * * const payload = KeyAuthorization.getSignPayload(authorization) // [!code focus] * ``` * * @param authorization - The {@link ox#KeyAuthorization.KeyAuthorization}. * @returns The sign payload. */ export declare function getSignPayload(authorization: KeyAuthorization): Hex.Hex; export declare namespace getSignPayload { type ErrorType = hash.ErrorType | Errors.GlobalErrorType; } /** * Deserializes an RLP-encoded {@link ox#KeyAuthorization.KeyAuthorization}. * * @example * ```ts twoslash * import { KeyAuthorization } from 'ox/tempo' * import { Value } from 'ox' * * const authorization = KeyAuthorization.from({ * address: '0xbe95c3f554e9fc85ec51be69a3d807a0d55bcf2c', * chainId: 4217n, * expiry: 1234567890, * type: 'secp256k1', * limits: [{ * token: '0x20c0000000000000000000000000000000000001', * limit: Value.from('10', 6) * }], * }) * * const serialized = KeyAuthorization.serialize(authorization) * const deserialized = KeyAuthorization.deserialize(serialized) // [!code focus] * ``` * * @param serialized - The RLP-encoded Key Authorization. * @returns The {@link ox#KeyAuthorization.KeyAuthorization}. */ export declare function deserialize(serialized: Hex.Hex): KeyAuthorization; export declare namespace deserialize { type ErrorType = Rlp.toHex.ErrorType | fromTuple.ErrorType | Errors.GlobalErrorType; } /** * Computes the hash for an {@link ox#KeyAuthorization.KeyAuthorization}. * * @example * ```ts twoslash * import { KeyAuthorization } from 'ox/tempo' * import { Value } from 'ox' * * const authorization = KeyAuthorization.from({ * address: '0xbe95c3f554e9fc85ec51be69a3d807a0d55bcf2c', * chainId: 4217n, * expiry: 1234567890, * type: 'secp256k1', * limits: [{ * token: '0x20c0000000000000000000000000000000000001', * limit: Value.from('10', 6) * }], * }) * * const hash = KeyAuthorization.hash(authorization) // [!code focus] * ``` * * @param authorization - The {@link ox#KeyAuthorization.KeyAuthorization}. * @returns The hash. */ export declare function hash(authorization: KeyAuthorization): Hex.Hex; export declare namespace hash { type ErrorType = toTuple.ErrorType | Hash.keccak256.ErrorType | Hex.concat.ErrorType | Rlp.fromHex.ErrorType | Errors.GlobalErrorType; } /** * Serializes a {@link ox#KeyAuthorization.KeyAuthorization} to RLP-encoded hex. * * @example * ```ts twoslash * import { KeyAuthorization } from 'ox/tempo' * import { Value } from 'ox' * * const authorization = KeyAuthorization.from({ * address: '0xbe95c3f554e9fc85ec51be69a3d807a0d55bcf2c', * chainId: 4217n, * expiry: 1234567890, * type: 'secp256k1', * limits: [{ * token: '0x20c0000000000000000000000000000000000001', * limit: Value.from('10', 6) * }], * }) * * const serialized = KeyAuthorization.serialize(authorization) // [!code focus] * ``` * * @param authorization - The {@link ox#KeyAuthorization.KeyAuthorization}. * @returns The RLP-encoded Key Authorization. */ export declare function serialize(authorization: KeyAuthorization): Hex.Hex; export declare namespace serialize { type ErrorType = toTuple.ErrorType | Rlp.fromHex.ErrorType | Errors.GlobalErrorType; } /** * Converts an {@link ox#KeyAuthorization.KeyAuthorization} to an {@link ox#KeyAuthorization.Rpc}. * * @example * ```ts twoslash * import { KeyAuthorization } from 'ox/tempo' * import { Value } from 'ox' * * const authorization = KeyAuthorization.toRpc({ * address: '0xbe95c3f554e9fc85ec51be69a3d807a0d55bcf2c', * chainId: 4217n, * expiry: 1234567890, * type: 'secp256k1', * limits: [{ * token: '0x20c0000000000000000000000000000000000001', * limit: Value.from('10', 6) * }], * signature: { * type: 'secp256k1', * signature: { * r: 44944627813007772897391531230081695102703289123332187696115181104739239197517n, * s: 36528503505192438307355164441104001310566505351980369085208178712678799181120n, * yParity: 0, * }, * }, * }) * ``` * * @param authorization - A Key Authorization. * @returns An RPC-formatted Key Authorization. */ export declare function toRpc(authorization: Signed): Rpc; export declare namespace toRpc { type ErrorType = Errors.GlobalErrorType; } /** * Converts an {@link ox#KeyAuthorization.KeyAuthorization} to an {@link ox#KeyAuthorization.Tuple}. * * @example * ```ts twoslash * import { KeyAuthorization } from 'ox/tempo' * import { Value } from 'ox' * * const authorization = KeyAuthorization.from({ * address: '0xbe95c3f554e9fc85ec51be69a3d807a0d55bcf2c', * chainId: 4217n, * expiry: 1234567890, * type: 'secp256k1', * limits: [{ * token: '0x20c0000000000000000000000000000000000001', * limit: Value.from('10', 6) * }], * }) * * const tuple = KeyAuthorization.toTuple(authorization) // [!code focus] * // @log: [ * // @log: '0x174876e800', * // @log: [['0x20c0000000000000000000000000000000000001', '0xf4240']], * // @log: '0xbe95c3f554e9fc85ec51be69a3d807a0d55bcf2c', * // @log: 'secp256k1', * // @log: ] * ``` * * @param authorization - The {@link ox#KeyAuthorization.KeyAuthorization}. * @returns A Tempo Key Authorization tuple. */ export declare function toTuple(authorization: authorization): toTuple.ReturnType; export declare namespace toTuple { type ReturnType = Compute ? true : false>>; type ErrorType = Errors.GlobalErrorType; } export {}; //# sourceMappingURL=KeyAuthorization.d.ts.map