Skip to content

wallet_prepareUpgradeAccount

Prepares an account for upgrade by generating initialization data and an EIP-7702 authorization item.

Upgrading an account is different from creating an account. Upgrading an account generates an EIP-7702 authorization for an existing EOA, whereas creating an account using the RPC server generates a new EOA using PREP.

The returned EIP-7702 authorization item must be signed by the EOA root key, as well as the intent digest.

Keys

There exists three different key roles:

  • Admin keys are capable of adding and modifying other keys, and capable of spending an unlimited amount of tokens and calling any contract and selector.
  • Normal keys can only call contracts as defined by the permissions set on it, and spend the amount of tokens afforded to it by permissions.
  • Session keys are like normal keys, except they also have an expiry.

Setting permissions on an admin key is not allowed and will return an error.

For complete details on keys, including their signature encoding, public key encoding, and key hashes, refer to the Key section.

Request

type Request = {
  method: 'wallet_prepareUpgradeAccount',
  params: [{
    address: Address,
    chainId: Hex,
    capabilities: {
      authorizeKeys: {
        // See "Keys"
        key: {
          expiry?: number,
          type: 'p256' | 'webauthnp256' | 'secp256k1',
          role: 'admin' | 'normal' | 'session',
          publicKey: Hex,
        },
        permissions: ({
          type: 'call',
          // See "Selectors"
          selector: string,
          to: Address,
        } | {
          type: 'spend',
          limit: number,
          period: 'minute' | 'hour' | 'day' | 'week' | 'month' | 'year',
          // defaults to the native token (address zero)
          token?: Address,
        })[],
      }[],
      delegation: Address,
      // defaults to the EOA
      feePayer?: Address,
      // defaults to the native token
      feeToken?: Address,
    },
  }],
}

Response

Please refer to wallet_prepareCalls for a detailed explanation of the response.

type Response = {
  // The context returned depending on whether
  // a precall or normal bundle was prepared.
  //
  // In the case of a precall, the precall itself
  // is returned, otherwise a quote signed by the
  // relay is returned.
  context: {
    quote: {
      chainId: Hex,
      intent: {
        eoa: Address,
        executionData: Hex,
        nonce: Hex,
        payer: Address,
        paymentToken: Address,
        prePaymentMaxAmount: Hex,
        totalPaymentMaxAmount: Hex,
        combinedGas: Hex,
        encodedPreCalls: Hex[],
        initData: Hex,
        prePaymentAmount: Hex,
        totalPaymentAmount: Hex,
        paymentRecipient: Address,
        signature: Hex,
        paymentSignature: Hex,
        supportedAccountImplementation: Address,
      },
      txGas: Hex,
      nativeFeeEstimate: {
        maxFeePerGas: number,
        maxPriorityFeePerGas: number,
      },
      // UNIX timestamp the quote expires at.
      ttl: number,
      authorizationAddress?: Address,
      entrypoint: Address,
      // The RPC servers signature over the quote.
      signature: {
        y_parity: boolean,
        r: Hex,
        s: Hex,
      },
      // The hash of the quote.
      hash: Hash,
    },
  },
  // the digest of the bundle that the user needs to sign
  digest: Hash,
  // EIP-712 typed data of the precall or bundle.
  typedData: TypedData,
  // capabilities assigned to the account
  capabilities: {
    authorizeKeys: {
      // key hash
      hash: Hash,
      // See "Keys"
      key: {
        expiry?: number,
        type: 'p256' | 'webauthnp256' | 'secp256k1',
        role: 'admin' | 'normal' | 'session',
        publicKey: Hex,
      },
      permissions: ({
        type: 'call',
        // See "Selectors"
        selector: string,
        to: Address,
      } | {
        type: 'spend',
        limit: number,
        period: 'minute' | 'hour' | 'day' | 'week' | 'month' | 'year',
        // defaults to the native token (address zero)
        token?: Address,
      })[],
    }[],
    // Key revocations.
    revokeKeys: {
      hash: Hash,
      id?: Address
    }[],
    // Simulated asset diffs, where the first element of the tuple is the recipient or sender.
    assetDiff: [
       Address,
       {
         // Omitted if this is the native token.
         address?: Address,
         decimals?: number,
         direction: 'incoming' | 'outgoing',
         name?: string,
         symbol?: string,
         type?: 'erc20' | 'erc721',
         uri?: string,
         // For ERC721, the asset ID. For ERC20 the value moved.
         value: number,
       }[]
    ][],
  }
}