Skip to content
LogoLogo

accessKey.authorize

Authorizes an access key by signing a key authorization and sending a transaction.

Usage

import { Account, Expiry, P256 } from 'viem/tempo'
import { client } from './viem.config'
 
// 1. Define root account
const account = Account.fromSecp256k1('0x...')
 
// 2. Define access key attached to the root account
const accessKey = Account.fromP256(P256.randomPrivateKey(), {
  access: account,
})
 
// 3. Authorize the access key
const { receipt } = await client.accessKey.authorizeSync({
  accessKey,
})
 
console.log('Transaction hash:', receipt.transactionHash)
Transaction hash: 0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef

With Expiry and Spending Limits

You can set an expiry and per-token spending limits when authorizing an access key:

import { Account, Expiry, P256 } from 'viem/tempo'
import { client } from './viem.config'
 
const account = Account.fromSecp256k1('0x...')
const accessKey = Account.fromP256(P256.randomPrivateKey(), {
  access: account,
})
 
const { receipt } = await client.accessKey.authorizeSync({
  accessKey,
  expiry: Expiry.hours(1), 
  limits: [ 
    { 
      token: '0x20c0000000000000000000000000000000000001', 
      limit: 1000000n, 
    }, 
  ], 
})

With Periodic Spending Limits

Use the period field on limits to set a recurring spending cap that resets after the given number of seconds:

import { parseUnits } from 'viem'
import { Account, Period, P256 } from 'viem/tempo'
import { client } from './viem.config'
 
const account = Account.fromSecp256k1('0x...')
const accessKey = Account.fromP256(P256.randomPrivateKey(), {
  access: account,
})
 
const { receipt } = await client.accessKey.authorizeSync({
  accessKey,
  limits: [ 
    { 
      token: '0x20c0000000000000000000000000000000000001', 
      limit: parseUnits('1000', 6), 
      period: Period.months(1), // resets every month
    }, 
  ], 
})

With Call Scopes

Use scopes to restrict which contracts and functions the access key can call:

import { parseUnits } from 'viem'
import { Account, P256 } from 'viem/tempo'
import { client } from './viem.config'
 
const account = Account.fromSecp256k1('0x...')
const accessKey = Account.fromP256(P256.randomPrivateKey(), {
  access: account,
})
 
const { receipt } = await client.accessKey.authorizeSync({
  accessKey,
  limits: [
    {
      token: '0x20c0000000000000000000000000000000000001',
      limit: parseUnits('10000', 6),
    },
  ],
  scopes: [ 
    { 
      address: '0x20c0000000000000000000000000000000000001', 
      selector: 'transfer(address,uint256)', // or "0xa9059cbb"
      recipients: ['0xcafebabecafebabecafebabecafebabecafebabe'], // optional
    }, 
  ], 
})

With a Witness

Use witness to bind a 32-byte value into the authorization's signing hash. This lets you bind a single signature to an arbitrary offchain context (e.g. a server-issued challenge), or use it as a revocation handle that can be burned onchain (via accessKey.burnWitness) to invalidate the authorization before it is submitted (TIP-1053):

import { Account, P256 } from 'viem/tempo'
import { client } from './viem.config'
 
const account = Account.fromSecp256k1('0x...')
const accessKey = Account.fromP256(P256.randomPrivateKey(), {
  access: account,
})
 
const { receipt } = await client.accessKey.authorizeSync({
  accessKey,
  witness: '0x...', 
})

Admin Keys

Set admin: true to authorize an unrestricted admin key. Admin keys can manage the account's other access keys and cannot carry expiry, limits, or scopes (they are ignored). Requires the T6 hardfork (TIP-1049):

import { Account, P256 } from 'viem/tempo'
import { client } from './viem.config'
 
const account = Account.fromSecp256k1('0x...')
const accessKey = Account.fromP256(P256.randomPrivateKey(), {
  access: account,
})
 
const { receipt } = await client.accessKey.authorizeSync({
  accessKey,
  admin: true, 
})

Once authorized, an admin key can authorize (and manage) other keys on behalf of the account. Pass the admin key as the account: viem binds the authorization to the parent account and signs it with the admin key directly.

import { Account, P256 } from 'viem/tempo'
import { client } from './viem.config'
 
const account = Account.fromSecp256k1('0x...')
 
// Admin key (previously authorized with `admin: true`)
const adminKey = Account.fromP256(P256.randomPrivateKey(), {
  access: account,
})
 
// New key to authorize on behalf of the account
const childKey = Account.fromP256(P256.randomPrivateKey(), {
  access: account,
})
 
const { receipt } = await client.accessKey.authorizeSync({
  account: adminKey, 
  accessKey: childKey,
})

Authorize Public Keys

Instead of passing an AccessKeyAccount, you can authorize a key by its public key or address directly:

import { Account, P256 } from 'viem/tempo'
import { client } from './viem.config'
 
const account = Account.fromSecp256k1('0x...')
 
// Authorize by public key
const { receipt } = await client.accessKey.authorizeSync({ 
  accessKey: { 
    publicKey: '0x...', 
    type: 'p256', 
  }, 
}) 

You can also authorize by address:

import { Account } from 'viem/tempo'
import { client } from './viem.config'
 
const account = Account.fromSecp256k1('0x...')
 
// Authorize by address
const { receipt } = await client.accessKey.authorizeSync({ 
  accessKey: { 
    address: '0x...', 
    type: 'p256', 
  }, 
}) 

Asynchronous Usage

The example above uses a *Sync variant of the action, that will wait for the transaction to be included before returning.

If you are optimizing for performance, you should use the non-sync accessKey.authorize action and wait for inclusion manually:

import { Actions, Account, Expiry, P256 } from 'viem/tempo'
import { client } from './viem.config'
 
const account = Account.fromSecp256k1('0x...')
const accessKey = Account.fromP256(P256.randomPrivateKey(), {
  access: account,
})
 
const hash = await client.accessKey.authorize({
  accessKey,
  expiry: Expiry.hours(1),
})
const receipt = await client.waitForTransactionReceipt({ hash })
 
const { args }
  = Actions.accessKey.authorize.extractEvent(receipt.logs)

Return Type

type ReturnType = {
  /** The account that authorized the key. */
  account: Address
  /** The public key that was authorized. */
  publicKey: Address
  /** The signature type. */
  signatureType: number
  /** The expiry timestamp. */
  expiry: bigint
  /** Transaction receipt */
  receipt: TransactionReceipt
}

Parameters

accessKey

  • Type: { accessKeyAddress: Address; keyType: string } | { address: Address; type: string } | { publicKey: Hex; type: string }

The access key to authorize. Accepts an AccessKeyAccount, or an object with { address, type } or { publicKey, type }.

admin (optional)

  • Type: boolean

Whether to authorize the key as an admin key. Admin keys are unrestricted and can manage the account's other access keys; expiry, limits, and scopes are ignored. Requires the T6 hardfork (TIP-1049).

expiry (optional)

  • Type: number

Unix timestamp when the key expires.

limits (optional)

  • Type: { token: Address; limit: bigint; period?: number }[]

Spending limits per token. Optionally include period (in seconds) to make the limit periodic. It resets after each period. Use Period.months(1), Period.seconds(n), etc. from ox/tempo for convenience.

scopes (optional)

  • Type: { address: Address; selector?: Hex | string; recipients?: Address[] }[]

Call scopes restricting which contracts/selectors this key can call. Each scope entry specifies a contract address, an optional 4-byte function selector, and optional recipient addresses (for transfer-like functions). If scopes is set to [] (empty array), the key cannot make any calls.

witness (optional)

  • Type: Hex

Optional 32-byte witness bound into the authorization's signing hash. Can be burned onchain via accessKey.burnWitness to invalidate the authorization before it is submitted (TIP-1053).

account (optional)

  • Type: Account | Address

Account that will be used to send the transaction.

feeToken (optional)

  • Type: Address | bigint

Fee token for the transaction.

Can be an unpaused USD-denominated TIP-20 token address or ID. Use client.fee.validateToken({ token }) to validate a token before submitting a transaction or setting it as a fee preference.

feePayer (optional)

  • Type: Account | true

Fee payer for the transaction.

Can be a Viem Account, or true if a Fee Payer Service will be used.

gas (optional)

  • Type: bigint

Gas limit for the transaction.

maxFeePerGas (optional)

  • Type: bigint

Max fee per gas for the transaction.

maxPriorityFeePerGas (optional)

  • Type: bigint

Max priority fee per gas for the transaction.

nonce (optional)

  • Type: number

Nonce for the transaction.

nonceKey (optional)

  • Type: 'expiring' | bigint

Nonce key for the transaction. Use 'expiring' to use expiring nonces (TIP-1009), which enables concurrent transaction submission without nonce ordering.

validBefore (optional)

  • Type: number

Unix timestamp before which the transaction must be included.

validAfter (optional)

  • Type: number

Unix timestamp after which the transaction can be included.

throwOnReceiptRevert (optional)

  • Type: boolean
  • Default: true

Whether to throw an error if the transaction receipt indicates a revert. Only applicable to *Sync actions.